diff --git a/SOURCES/0001-Always-do-the-rungrubby-debug-after-the-normal-kerne.patch b/SOURCES/0001-Always-do-the-rungrubby-debug-after-the-normal-kerne.patch new file mode 100644 index 0000000..4e31618 --- /dev/null +++ b/SOURCES/0001-Always-do-the-rungrubby-debug-after-the-normal-kerne.patch @@ -0,0 +1,123 @@ +From b9a37e249bf279ceb0b63ad4676f03d11796cfc9 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 26 Oct 2015 14:22:39 -0400 +Subject: [PATCH] Always do the "rungrubby --debug" after the normal kernel on + install. + +This way the during an update, the right kernel is picked as "default" +for the command line arguments. + +Related: rhbz#1212128 + +Signed-off-by: Peter Jones +--- + new-kernel-pkg | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/new-kernel-pkg b/new-kernel-pkg +index 9f56c47..9574dbb 100755 +--- a/new-kernel-pkg ++++ b/new-kernel-pkg +@@ -243,8 +243,8 @@ install() { + --args=\"root=$rootdevice $kernargs \$debugargs\" \ + --remove-kernel=\"TITLE=$title\$debugtitle\"" + +- rungrubby --debug ${ARGS} + rungrubby ${ARGS} $makedefault ++ rungrubby --debug ${ARGS} + else + [ -n "$verbose" ] && echo "$grubConfig does not exist, not running grubby for grub 0.97" + fi +@@ -257,8 +257,8 @@ install() { + ${mbargs:+--mbargs=\"$mbargs\"} \ + --args=\"root=$rootdevice $kernargs \$debugargs\" \ + --remove-kernel=\"TITLE=$title\$debugtitle\"" +- rungrubby --debug ${ARGS} + rungrubby ${ARGS} $makedefault ++ rungrubby --debug ${ARGS} + else + [ -n "$verbose" ] && echo "$grub2Config does not exist, not running grubby for grub 2" + fi +@@ -272,8 +272,8 @@ install() { + ${mbargs:+--mbargs=\"$mbargs\"} \ + --args=\"root=$rootdevice $kernargs \$debugargs\" \ + --remove-kernel=\"TITLE=$title\$debugtitle\"" +- rungrubby --debug ${ARGS} + rungrubby ${ARGS} $makedefault ++ rungrubby --debug ${ARGS} + else + [ -n "$verbose" ] && echo "$grub2EfiConfig does not exist, not running grubby for grub 2 with UEFI" + fi +@@ -288,8 +288,8 @@ install() { + --args=\"root=$rootdevice $kernargs \$debugargs\" \ + --remove-kernel=\"TITLE=$version\"" + +- rungrubby --debug ${ARGS} + rungrubby ${ARGS} $makedefault ++ rungrubby --debug ${ARGS} + if [ -n "$runLilo" ]; then + [ -n "$verbose" ] && echo "running $lilo" + if [ ! -x $lilo ] ; then +@@ -313,8 +313,8 @@ install() { + --args=\"root=$rootdevice $kernargs \$debugargs\" \ + --remove-kernel=\"TITLE=$title\$debugtitle\"" + +- rungrubby --debug ${ARGS} + rungrubby ${ARGS} $makedefault ++ rungrubby --debug ${ARGS} + else + [ -n "$verbose" ] && echo "$extlinuxConfig does not exist, not running grubby for extlinux" + fi +@@ -480,8 +480,8 @@ update() { + ${mbkernel:+--add-multiboot=\"$mbkernel\"} \ + --title=\"$title\$debugtitle\"" + +- rungrubby --debug ${ARGS} + rungrubby ${ARGS} ++ rungrubby --debug ${ARGS} + else + [ -n "$verbose" ] && echo "$grubConfig does not exist, not running grubby" + fi +@@ -493,8 +493,8 @@ update() { + ${removeargs:+--remove-args=\"$removeargs\"} \ + --title=\"$title\$debugtitle\"" + +- rungrubby --debug ${ARGS} + rungrubby ${ARGS} ++ rungrubby --debug ${ARGS} + else + [ -n "$verbose" ] && echo "$grub2Config does not exist, not running grubby" + fi +@@ -506,8 +506,8 @@ update() { + ${removeargs:+--remove-args=\"$removeargs\"} \ + --title=\"$title\$debugtitle\"" + +- rungrubby --debug ${ARGS} + rungrubby ${ARGS} ++ rungrubby --debug ${ARGS} + else + [ -n "$verbose" ] && echo "$grub2EfiConfig does not exist, not running grubby" + fi +@@ -519,8 +519,8 @@ update() { + ${removeargs:+--remove-args=\"$removeargs\"} \ + --title=\"$title\$debugtitle\"" + +- rungrubby --debug ${ARGS} + rungrubby ${ARGS} ++ rungrubby --debug ${ARGS} + + if [ -n "$runLilo" ]; then + [ -n "$verbose" ] && echo "running $lilo" +@@ -571,8 +571,8 @@ update() { + ${removeargs:+--remove-args=\"$removeargs\"} \ + --title=\"$title\$debugtitle\"" + +- rungrubby --debug ${ARGS} + rungrubby ${ARGS} ++ rungrubby --debug ${ARGS} + else + [ -n "$verbose" ] && echo "$extlinuxConfig does not exist, not running grubby" + fi +-- +2.5.0 + diff --git a/SOURCES/0001-Don-t-leak-from-one-extractTitle-call.patch b/SOURCES/0001-Don-t-leak-from-one-extractTitle-call.patch new file mode 100644 index 0000000..6489935 --- /dev/null +++ b/SOURCES/0001-Don-t-leak-from-one-extractTitle-call.patch @@ -0,0 +1,85 @@ +From 7713f8e23e326dcf1258a715e2554a4bf53dec59 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 2 Jul 2015 16:26:59 -0400 +Subject: [PATCH] Don't leak from one extractTitle() call. + +Found by coverity. + +Signed-off-by: Peter Jones +--- + grubby.c | 27 +++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +diff --git a/grubby.c b/grubby.c +index 0bb4869..70477ba 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -1510,13 +1510,14 @@ static struct grubConfig * readConfig(const char * inName, + return cfg; + } + +-static void writeDefault(FILE * out, char * indent, ++static void writeDefault(FILE * out, char * indent, + char * separator, struct grubConfig * cfg) { + struct singleEntry * entry; + struct singleLine * line; + int i; + +- if (!cfg->defaultImage && cfg->flags == GRUB_CONFIG_NO_DEFAULT) return; ++ if (!cfg->defaultImage && cfg->flags == GRUB_CONFIG_NO_DEFAULT) ++ return; + + if (cfg->defaultImage == DEFAULT_SAVED) + fprintf(out, "%sdefault%ssaved\n", indent, separator); +@@ -1540,34 +1541,40 @@ static void writeDefault(FILE * out, char * indent, + fprintf(out, "%sset default=\"%d\"\n", indent, + cfg->defaultImage); + } else { +- fprintf(out, "%sdefault%s%d\n", indent, separator, ++ fprintf(out, "%sdefault%s%d\n", indent, separator, + cfg->defaultImage); + } + } else { + int image = cfg->defaultImage; + + entry = cfg->entries; +- while (entry && entry->skip) entry = entry->next; ++ while (entry && entry->skip) ++ entry = entry->next; + + i = 0; + while (entry && i < image) { + entry = entry->next; + +- while (entry && entry->skip) entry = entry->next; ++ while (entry && entry->skip) ++ entry = entry->next; + i++; + } + +- if (!entry) return; ++ if (!entry) ++ return; + + line = getLineByType(LT_TITLE, entry->lines); + + if (line && line->numElements >= 2) +- fprintf(out, "%sdefault%s%s\n", indent, separator, ++ fprintf(out, "%sdefault%s%s\n", indent, separator, + line->elements[1].item); +- else if (line && (line->numElements == 1) && ++ else if (line && (line->numElements == 1) && + cfg->cfi->titleBracketed) { +- fprintf(out, "%sdefault%s%s\n", indent, separator, +- extractTitle(cfg, line)); ++ char *title = extractTitle(cfg, line); ++ if (title) { ++ fprintf(out, "%sdefault%s%s\n", indent, separator, title); ++ free(title); ++ } + } + } + } +-- +2.4.3 + diff --git a/SOURCES/0001-Don-t-put-spaces-in-debug-entries-on-zipl-platforms.patch b/SOURCES/0001-Don-t-put-spaces-in-debug-entries-on-zipl-platforms.patch deleted file mode 100644 index e6a53f7..0000000 --- a/SOURCES/0001-Don-t-put-spaces-in-debug-entries-on-zipl-platforms.patch +++ /dev/null @@ -1,34 +0,0 @@ -From d02b178988837a37f8a9e88bcdc54f4c169ab5d7 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 11 Nov 2014 10:46:08 -0500 -Subject: [PATCH 1/2] Don't put spaces in debug entries on zipl platforms. - -Because of course zipl can't handle spaces. - -Related: rhbz#1152152 - -Signed-off-by: Peter Jones ---- - new-kernel-pkg | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/new-kernel-pkg b/new-kernel-pkg -index 9f3b192..811b989 100755 ---- a/new-kernel-pkg -+++ b/new-kernel-pkg -@@ -140,7 +140,11 @@ rungrubby() { - if [ "$1" == "--debug" ]; then - [ "$MAKEDEBUG" != "yes" ] && return 0 - [ -n "$verbose" ] && echo "- First, making a debug entry." -- declare -x debugtitle=" with debugging" -+ if [ $ARCH = 's390' -o $ARCH = 's390x' ]; then -+ declare -x debugtitle="_with_debugging" -+ else -+ declare -x debugtitle=" with debugging" -+ fi - declare -x debugargs="$DEBUGARG" - shift - else --- -1.9.3 - diff --git a/SOURCES/0001-Fix-some-coverity-concerns.patch b/SOURCES/0001-Fix-some-coverity-concerns.patch new file mode 100644 index 0000000..a00bdde --- /dev/null +++ b/SOURCES/0001-Fix-some-coverity-concerns.patch @@ -0,0 +1,613 @@ +From 916d5770b5c8fb87503a99f98c13a5232a7dafbf Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 10 Sep 2015 10:13:15 -0400 +Subject: [PATCH] Fix some coverity concerns... + +While checking on coverity's concern with kwcmp() having a loop it +really didn't need, I discovered another problem with the fix here that +made spaces not work right in grub2 variable assignment. So here's a +new version of the fix, and yet another test case. + +Resolves: rhbz#1152550 + +Signed-off-by: Peter Jones +--- + grubby.c | 204 ++++++++++++++++++++++++++++++++++++----------- + test.sh | 6 ++ + test/grub2.17 | 156 ++++++++++++++++++++++++++++++++++++ + test/results/add/g2-1.17 | 170 +++++++++++++++++++++++++++++++++++++++ + 4 files changed, 490 insertions(+), 46 deletions(-) + create mode 100644 test/grub2.17 + create mode 100644 test/results/add/g2-1.17 + +diff --git a/grubby.c b/grubby.c +index d66c1c5..2a6eedb 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -751,28 +751,30 @@ static char *sdupprintf(const char *format, ...) + static inline int + kwcmp(struct keywordTypes *kw, const char * label, int case_insensitive) + { +- int kwl = strlen(kw->key); +- int ll = strlen(label); +- int rc; +- int (*snc)(const char *s1, const char *s2, size_t n) = +- case_insensitive ? strncasecmp : strncmp; +- int (*sc)(const char *s1, const char *s2) = +- case_insensitive ? strcasecmp : strcmp; +- +- rc = snc(kw->key, label, kwl); +- if (rc) +- return rc; +- +- for (int i = kwl; i < ll; i++) { +- if (isspace(label[i])) +- return 0; +- if (kw->separatorChar && label[i] == kw->separatorChar) +- return 0; +- else if (kw->nextChar && label[i] == kw->nextChar) +- return 0; +- return sc(kw->key+kwl, label+kwl); +- } +- return 0; ++ int kwl = strlen(kw->key); ++ int ll = strlen(label); ++ int rc; ++ int (*snc)(const char *s1, const char *s2, size_t n) = ++ case_insensitive ? strncasecmp : strncmp; ++ int (*sc)(const char *s1, const char *s2) = ++ case_insensitive ? strcasecmp : strcmp; ++ ++ if (kwl > ll) ++ return ll - kwl; ++ ++ rc = snc(kw->key, label, kwl); ++ if (rc) ++ return rc; ++ ++ if (!label[kwl]) ++ return 0; ++ if (isspace(label[kwl])) ++ return 0; ++ if (kw->separatorChar && label[kwl] == kw->separatorChar) ++ return 0; ++ if (kw->nextChar && label[kwl] == kw->nextChar) ++ return 0; ++ return sc(kw->key+kwl, label+kwl); + } + + static enum lineType_e preferredLineType(enum lineType_e type, +@@ -1034,6 +1036,123 @@ static int lineWrite(FILE * out, struct singleLine *line, + return 0; + } + ++static int mergeElements(struct singleLine *line, int left, int right) ++{ ++ struct lineElement *elements = alloca(sizeof (line->elements[0]) * ++ line->numElements); ++ int i, j; ++ size_t itemsize = 0; ++ size_t newNumElements = 0; ++ char *newitem; ++ char *newindent = NULL; ++ ++ if (right >= line->numElements) ++ right = line->numElements - 1; ++ ++ if (!elements) ++ return -1; ++ for (i = 0; i < left; i++) { ++ elements[i] = line->elements[i]; ++ newNumElements++; ++ } ++ for (; i <= right; i++) { ++ itemsize += strlen(line->elements[i].item); ++ if (line->elements[i].indent && line->elements[i].indent[0]) { ++ if (i != right) ++ itemsize += strlen(line->elements[i].indent); ++ } ++ } ++ newitem = calloc (itemsize+1, 1); ++ if (!newitem) ++ return -1; ++ for (i = left; i <= right; i++) { ++ strcat(newitem, line->elements[i].item); ++ if (line->elements[i].indent) { ++ if (i != right) { ++ strcat(newitem, line->elements[i].indent); ++ free(line->elements[i].indent); ++ } else { ++ newindent = line->elements[i].indent; ++ } ++ } else { ++ newindent = strdup(""); ++ } ++ } ++ newNumElements++; ++ elements[left].item = newitem; ++ elements[left].indent = newindent; ++ if (left+1 < line->numElements && right+1 < line->numElements) { ++ for (j = left+1, i = right+1; i < line->numElements; i++) { ++ elements[j++] = line->elements[i]; ++ newNumElements++; ++ } ++ } ++ memcpy(line->elements, elements, ++ sizeof (line->elements[i]) * newNumElements); ++ line->numElements = newNumElements; ++ return 0; ++} ++ ++static int emptyElement(struct lineElement *element) ++{ ++ if (element->item && strlen(element->item) > 0) ++ return 0; ++ if (element->indent && strlen(element->indent) > 0) ++ return 0; ++ return 1; ++} ++ ++static int splitElement(struct singleLine *line, int element, int splitchar) ++{ ++ struct lineElement split[2] = {{0,0},{0,0}}; ++ struct lineElement *elements = NULL; ++ int saved_errno; ++ int i, j; ++ ++ elements = calloc(line->numElements + 1, sizeof (line->elements[0])); ++ if (!elements) ++ return -1; ++ ++ split[0].item = strndup(line->elements[element].item, splitchar); ++ if (!split[0].item) ++ goto err; ++ split[0].indent = strndup(&line->elements[element].item[splitchar], 1); ++ if (!split[0].indent) ++ goto err; ++ split[1].item = strdup(&line->elements[element].item[splitchar+1]); ++ if (!split[1].item) ++ goto err; ++ split[1].indent = line->elements[element].indent; ++ ++ for (i = j = 0; i < line->numElements; i++) { ++ if (i != element) { ++ memcpy(&elements[j++], &line->elements[i], ++ sizeof(line->elements[i])); ++ } else { ++ memcpy(&elements[j++], &split[0], sizeof(split[0])); ++ memcpy(&elements[j++], &split[1], sizeof(split[1])); ++ free(line->elements[i].item); ++ } ++ } ++ free(line->elements); ++ line->elements = elements; ++ line->numElements++; ++ ++ return 0; ++err: ++ saved_errno = errno; ++ if (split[0].item) ++ free(split[0].item); ++ if (split[0].indent) ++ free(split[0].indent); ++ if (split[1].item) ++ free(split[1].item); ++ if (elements) ++ free(elements); ++ errno = saved_errno; ++ return -1; ++} ++ + /* we've guaranteed that the buffer ends w/ \n\0 */ + static int getNextLine(char **bufPtr, struct singleLine *line, + struct configFileInfo *cfi) +@@ -1208,34 +1327,27 @@ static int getNextLine(char **bufPtr, struct singleLine *line, + * yet a third way to avoid rhbz# XXX FIXME :/ + */ + char *eq; +- int l; +- int numElements = line->numElements; +- struct lineElement *newElements; ++ int rc; ++ rc = mergeElements(line, 2, line->numElements); ++ if (rc < 0) ++ return rc; + eq = strchr(line->elements[1].item, '='); + if (!eq) + return 0; +- l = eq - line->elements[1].item; +- if (eq[1] != 0) +- numElements++; +- newElements = calloc(numElements,sizeof (*newElements)); +- memcpy(&newElements[0], &line->elements[0], +- sizeof (newElements[0])); +- newElements[1].item = +- strndup(line->elements[1].item, l); +- newElements[1].indent = "="; +- *(eq++) = '\0'; +- newElements[2].item = strdup(eq); +- free(line->elements[1].item); +- if (line->elements[1].indent) +- newElements[2].indent = line->elements[1].indent; +- for (int i = 2; i < line->numElements; i++) { +- newElements[i+1].item = line->elements[i].item; +- newElements[i+1].indent = +- line->elements[i].indent; ++ rc = splitElement(line, 1, eq-line->elements[1].item); ++ if (rc < 0) ++ return rc; ++ /* now make sure we haven't got any bogus elements at ++ * the end that don't mean anything. ++ */ ++ while (line->numElements > 1 && ++ emptyElement( ++ &line->elements[line->numElements-1])) { ++ rc = mergeElements(line, line->numElements-2, ++ line->numElements-1); ++ if (rc < 0) ++ return rc; + } +- free(line->elements); +- line->elements = newElements; +- line->numElements = numElements; + } + } + +diff --git a/test.sh b/test.sh +index ba466a5..d488333 100755 +--- a/test.sh ++++ b/test.sh +@@ -551,6 +551,12 @@ if [ "$testgrub2" == "y" ]; then + --copy-default --title 'Red Hat Enterprise Linux Server' \ + --args=root=/dev/mapper/foo-- + ++ # the same, but for: set foo = " bar=1,2 " ++ grub2Test grub2.17 add/g2-1.17 \ ++ --boot-filesystem=/boot --add-kernel=/boot/vmlinuz-foo \ ++ --copy-default --title 'Red Hat Enterprise Linux Server' \ ++ --args=root=/dev/mapper/foo-- ++ + testing="GRUB2 add initrd" + grub2Test grub2.2 add/g2-1.4 --update-kernel=/boot/new-kernel.img \ + --initrd=/boot/new-initrd --boot-filesystem=/boot/ +diff --git a/test/grub2.17 b/test/grub2.17 +new file mode 100644 +index 0000000..bd8c9c5 +--- /dev/null ++++ b/test/grub2.17 +@@ -0,0 +1,156 @@ ++# ++# DO NOT EDIT THIS FILE ++# ++# It is automatically generated by grub2-mkconfig using templates ++# from /etc/grub.d and settings from /etc/default/grub ++# ++ ++### BEGIN /etc/grub.d/00_header ### ++set pager=1 ++ ++if [ -s $prefix/grubenv ]; then ++ load_env ++fi ++if [ "${next_entry}" ] ; then ++ set default="${next_entry}" ++ set next_entry= ++ save_env next_entry ++ set boot_once=true ++else ++ set default="${saved_entry}" ++fi ++ ++if [ x"${feature_menuentry_id}" = xy ]; then ++ menuentry_id_option="--id" ++else ++ menuentry_id_option="" ++fi ++ ++export menuentry_id_option ++ ++if [ "${prev_saved_entry}" ]; then ++ set saved_entry="${prev_saved_entry}" ++ save_env saved_entry ++ set prev_saved_entry= ++ save_env prev_saved_entry ++ set boot_once=true ++fi ++ ++function savedefault { ++ if [ -z "${boot_once}" ]; then ++ saved_entry="${chosen}" ++ save_env saved_entry ++ fi ++} ++ ++function load_video { ++ if [ x$feature_all_video_module = xy ]; then ++ insmod all_video ++ else ++ insmod efi_gop ++ insmod efi_uga ++ insmod ieee1275_fb ++ insmod vbe ++ insmod vga ++ insmod video_bochs ++ insmod video_cirrus ++ fi ++} ++ ++serial --speed=115200 ++terminal_input serial console ++terminal_output serial console ++if [ x$feature_timeout_style = xy ] ; then ++ set timeout_style=menu ++ set timeout=5 ++# Fallback normal timeout code in case the timeout_style feature is ++# unavailable. ++else ++ set timeout=5 ++fi ++### END /etc/grub.d/00_header ### ++ ++### BEGIN /etc/grub.d/00_tuned ### ++set tuned_params= " isolcpus=1,3 " ++### END /etc/grub.d/00_tuned ### ++ ++### BEGIN /etc/grub.d/01_users ### ++if [ -f ${prefix}/user.cfg ]; then ++ source ${prefix}/user.cfg ++ if [ -n ${GRUB2_PASSWORD} ]; then ++ set superusers="root" ++ export superusers ++ password_pbkdf2 root ${GRUB2_PASSWORD} ++ fi ++fi ++### END /etc/grub.d/01_users ### ++ ++### BEGIN /etc/grub.d/10_linux ### ++menuentry 'Red Hat Enterprise Linux Server (3.10.0-297.el7.x86_64) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-296.el7.x86_64-advanced-ae7b3742-9092-4432-9f7f-8abdbf0dc3db' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod xfs ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' cae02b39-f239-4d26-9032-674d261c93d8 ++ else ++ search --no-floppy --fs-uuid --set=root cae02b39-f239-4d26-9032-674d261c93d8 ++ fi ++ linux16 /vmlinuz-3.10.0-297.el7.x86_64 root=/dev/mapper/rhel_hp--dl380pgen8--02--vm--10-root ro crashkernel=auto rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/root rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/swap console=ttyS0,115200n81 $tuned_params LANG=en_US.UTF-8 ++} ++menuentry 'Red Hat Enterprise Linux Server (3.10.0-296.el7.x86_64) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-296.el7.x86_64-advanced-ae7b3742-9092-4432-9f7f-8abdbf0dc3db' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod xfs ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' cae02b39-f239-4d26-9032-674d261c93d8 ++ else ++ search --no-floppy --fs-uuid --set=root cae02b39-f239-4d26-9032-674d261c93d8 ++ fi ++ linux16 /vmlinuz-3.10.0-296.el7.x86_64 root=/dev/mapper/rhel_hp--dl380pgen8--02--vm--10-root ro crashkernel=auto rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/root rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/swap console=ttyS0,115200n81 $tuned_params ++ initrd16 /initramfs-3.10.0-296.el7.x86_64.img ++} ++menuentry 'Red Hat Enterprise Linux Server (0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7-advanced-ae7b3742-9092-4432-9f7f-8abdbf0dc3db' { ++ load_video ++ insmod gzio ++ insmod part_msdos ++ insmod xfs ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' cae02b39-f239-4d26-9032-674d261c93d8 ++ else ++ search --no-floppy --fs-uuid --set=root cae02b39-f239-4d26-9032-674d261c93d8 ++ fi ++ linux16 /vmlinuz-0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7 root=/dev/mapper/rhel_hp--dl380pgen8--02--vm--10-root ro crashkernel=auto rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/root rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/swap console=ttyS0,115200n81 $tuned_params ++ initrd16 /initramfs-0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7.img ++} ++if [ "x$default" = 'Red Hat Enterprise Linux Server (3.10.0-296.el7.x86_64) 7.2 (Maipo)' ]; then default='Advanced options for Red Hat Enterprise Linux Server>Red Hat Enterprise Linux Server (3.10.0-296.el7.x86_64) 7.2 (Maipo)'; fi; ++### END /etc/grub.d/10_linux ### ++ ++### BEGIN /etc/grub.d/20_linux_xen ### ++### END /etc/grub.d/20_linux_xen ### ++ ++### BEGIN /etc/grub.d/20_ppc_terminfo ### ++### END /etc/grub.d/20_ppc_terminfo ### ++ ++### BEGIN /etc/grub.d/30_os-prober ### ++### END /etc/grub.d/30_os-prober ### ++ ++### BEGIN /etc/grub.d/40_custom ### ++# This file provides an easy way to add custom menu entries. Simply type the ++# menu entries you want to add after this comment. Be careful not to change ++# the 'exec tail' line above. ++### END /etc/grub.d/40_custom ### ++ ++### BEGIN /etc/grub.d/41_custom ### ++if [ -f ${config_directory}/custom.cfg ]; then ++ source ${config_directory}/custom.cfg ++elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then ++ source $prefix/custom.cfg; ++fi ++### END /etc/grub.d/41_custom ### +diff --git a/test/results/add/g2-1.17 b/test/results/add/g2-1.17 +new file mode 100644 +index 0000000..afb151d +--- /dev/null ++++ b/test/results/add/g2-1.17 +@@ -0,0 +1,170 @@ ++# ++# DO NOT EDIT THIS FILE ++# ++# It is automatically generated by grub2-mkconfig using templates ++# from /etc/grub.d and settings from /etc/default/grub ++# ++ ++### BEGIN /etc/grub.d/00_header ### ++set pager=1 ++ ++if [ -s $prefix/grubenv ]; then ++ load_env ++fi ++if [ "${next_entry}" ] ; then ++ set default="${next_entry}" ++ set next_entry= ++ save_env next_entry ++ set boot_once=true ++else ++ set default="${saved_entry}" ++fi ++ ++if [ x"${feature_menuentry_id}" = xy ]; then ++ menuentry_id_option="--id" ++else ++ menuentry_id_option="" ++fi ++ ++export menuentry_id_option ++ ++if [ "${prev_saved_entry}" ]; then ++ set saved_entry="${prev_saved_entry}" ++ save_env saved_entry ++ set prev_saved_entry= ++ save_env prev_saved_entry ++ set boot_once=true ++fi ++ ++function savedefault { ++ if [ -z "${boot_once}" ]; then ++ saved_entry="${chosen}" ++ save_env saved_entry ++ fi ++} ++ ++function load_video { ++ if [ x$feature_all_video_module = xy ]; then ++ insmod all_video ++ else ++ insmod efi_gop ++ insmod efi_uga ++ insmod ieee1275_fb ++ insmod vbe ++ insmod vga ++ insmod video_bochs ++ insmod video_cirrus ++ fi ++} ++ ++serial --speed=115200 ++terminal_input serial console ++terminal_output serial console ++if [ x$feature_timeout_style = xy ] ; then ++ set timeout_style=menu ++ set timeout=5 ++# Fallback normal timeout code in case the timeout_style feature is ++# unavailable. ++else ++ set timeout=5 ++fi ++### END /etc/grub.d/00_header ### ++ ++### BEGIN /etc/grub.d/00_tuned ### ++set tuned_params= " isolcpus=1,3 " ++### END /etc/grub.d/00_tuned ### ++ ++### BEGIN /etc/grub.d/01_users ### ++if [ -f ${prefix}/user.cfg ]; then ++ source ${prefix}/user.cfg ++ if [ -n ${GRUB2_PASSWORD} ]; then ++ set superusers="root" ++ export superusers ++ password_pbkdf2 root ${GRUB2_PASSWORD} ++ fi ++fi ++### END /etc/grub.d/01_users ### ++ ++### BEGIN /etc/grub.d/10_linux ### ++menuentry 'Red Hat Enterprise Linux Server' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-296.el7.x86_64-advanced-ae7b3742-9092-4432-9f7f-8abdbf0dc3db' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod xfs ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' cae02b39-f239-4d26-9032-674d261c93d8 ++ else ++ search --no-floppy --fs-uuid --set=root cae02b39-f239-4d26-9032-674d261c93d8 ++ fi ++ linux16 /vmlinuz-foo root=/dev/mapper/foo-- ro crashkernel=auto rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/root rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/swap console=ttyS0,115200n81 $tuned_params LANG=en_US.UTF-8 ++} ++menuentry 'Red Hat Enterprise Linux Server (3.10.0-297.el7.x86_64) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-296.el7.x86_64-advanced-ae7b3742-9092-4432-9f7f-8abdbf0dc3db' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod xfs ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' cae02b39-f239-4d26-9032-674d261c93d8 ++ else ++ search --no-floppy --fs-uuid --set=root cae02b39-f239-4d26-9032-674d261c93d8 ++ fi ++ linux16 /vmlinuz-3.10.0-297.el7.x86_64 root=/dev/mapper/rhel_hp--dl380pgen8--02--vm--10-root ro crashkernel=auto rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/root rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/swap console=ttyS0,115200n81 $tuned_params LANG=en_US.UTF-8 ++} ++menuentry 'Red Hat Enterprise Linux Server (3.10.0-296.el7.x86_64) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-296.el7.x86_64-advanced-ae7b3742-9092-4432-9f7f-8abdbf0dc3db' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod xfs ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' cae02b39-f239-4d26-9032-674d261c93d8 ++ else ++ search --no-floppy --fs-uuid --set=root cae02b39-f239-4d26-9032-674d261c93d8 ++ fi ++ linux16 /vmlinuz-3.10.0-296.el7.x86_64 root=/dev/mapper/rhel_hp--dl380pgen8--02--vm--10-root ro crashkernel=auto rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/root rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/swap console=ttyS0,115200n81 $tuned_params ++ initrd16 /initramfs-3.10.0-296.el7.x86_64.img ++} ++menuentry 'Red Hat Enterprise Linux Server (0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7-advanced-ae7b3742-9092-4432-9f7f-8abdbf0dc3db' { ++ load_video ++ insmod gzio ++ insmod part_msdos ++ insmod xfs ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' cae02b39-f239-4d26-9032-674d261c93d8 ++ else ++ search --no-floppy --fs-uuid --set=root cae02b39-f239-4d26-9032-674d261c93d8 ++ fi ++ linux16 /vmlinuz-0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7 root=/dev/mapper/rhel_hp--dl380pgen8--02--vm--10-root ro crashkernel=auto rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/root rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/swap console=ttyS0,115200n81 $tuned_params ++ initrd16 /initramfs-0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7.img ++} ++if [ "x$default" = 'Red Hat Enterprise Linux Server (3.10.0-296.el7.x86_64) 7.2 (Maipo)' ]; then default='Advanced options for Red Hat Enterprise Linux Server>Red Hat Enterprise Linux Server (3.10.0-296.el7.x86_64) 7.2 (Maipo)'; fi; ++### END /etc/grub.d/10_linux ### ++ ++### BEGIN /etc/grub.d/20_linux_xen ### ++### END /etc/grub.d/20_linux_xen ### ++ ++### BEGIN /etc/grub.d/20_ppc_terminfo ### ++### END /etc/grub.d/20_ppc_terminfo ### ++ ++### BEGIN /etc/grub.d/30_os-prober ### ++### END /etc/grub.d/30_os-prober ### ++ ++### BEGIN /etc/grub.d/40_custom ### ++# This file provides an easy way to add custom menu entries. Simply type the ++# menu entries you want to add after this comment. Be careful not to change ++# the 'exec tail' line above. ++### END /etc/grub.d/40_custom ### ++ ++### BEGIN /etc/grub.d/41_custom ### ++if [ -f ${config_directory}/custom.cfg ]; then ++ source ${config_directory}/custom.cfg ++elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then ++ source $prefix/custom.cfg; ++fi ++### END /etc/grub.d/41_custom ### +-- +2.4.3 + diff --git a/SOURCES/0001-Make-it-possible-to-run-test.sh-verbose-from-the-mak.patch b/SOURCES/0001-Make-it-possible-to-run-test.sh-verbose-from-the-mak.patch new file mode 100644 index 0000000..8ccf23b --- /dev/null +++ b/SOURCES/0001-Make-it-possible-to-run-test.sh-verbose-from-the-mak.patch @@ -0,0 +1,38 @@ +From 956c9b804607d1a43183514e8a18d671ab14d2fa Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 6 Aug 2015 10:06:13 -0400 +Subject: [PATCH 1/3] Make it possible to run "test.sh --verbose" from the make + command line. + +Signed-off-by: Peter Jones +--- + Makefile | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 94cef27..e021f35 100644 +--- a/Makefile ++++ b/Makefile +@@ -26,6 +26,10 @@ CC = gcc + RPM_OPT_FLAGS ?= -O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector + CFLAGS += $(RPM_OPT_FLAGS) -std=gnu99 -Wall -Werror -Wno-error=unused-function -Wno-unused-function -ggdb + LDFLAGS := ++VERBOSE_TEST := ++ifneq ($(VERBOSE_TEST),) ++ VERBOSE_TEST="--verbose" ++endif + + grubby_LIBS = -lblkid -lpopt + +@@ -39,7 +43,7 @@ debug : clean + + test: all + @export TOPDIR=$(TOPDIR) +- @./test.sh ++ @./test.sh $(VERBOSE_TEST) + + install: all + mkdir -p $(DESTDIR)$(PREFIX)/sbin +-- +2.4.3 + diff --git a/SOURCES/0001-Only-set-RPM_OPT_FLAGS-if-undefined.patch b/SOURCES/0001-Only-set-RPM_OPT_FLAGS-if-undefined.patch new file mode 100644 index 0000000..f260e9e --- /dev/null +++ b/SOURCES/0001-Only-set-RPM_OPT_FLAGS-if-undefined.patch @@ -0,0 +1,32 @@ +From d214fbcca2578677f06d2561e357eb483be93782 Mon Sep 17 00:00:00 2001 +From: "d.marlin" +Date: Mon, 24 Jun 2013 14:57:40 -0500 +Subject: [PATCH 01/41] Only set RPM_OPT_FLAGS if undefined. + +Currently RPM_OPT_FLAGS are set even if they were already defined. +This overrides any defaults set by RPM, including architecture-specific +values that may be needed to compile on some architectures. + +To avoid this issue, only set RPM_OPT_FLAGS if previously undefined. + +Signed-off-by: David A. Marlin +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 3f6370b..5dbf0f7 100644 +--- a/Makefile ++++ b/Makefile +@@ -23,7 +23,7 @@ TARGETS = grubby + OBJECTS = grubby.o log.o + + CC = gcc +-RPM_OPT_FLAGS := -O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector ++RPM_OPT_FLAGS ?= -O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector + CFLAGS += $(RPM_OPT_FLAGS) -std=gnu99 -Wall -Werror -Wno-error=unused-function -Wno-unused-function -ggdb + LDFLAGS := + +-- +2.4.3 + diff --git a/SOURCES/0001-Specify-bootloader-directory-in-the-test-case-for-11.patch b/SOURCES/0001-Specify-bootloader-directory-in-the-test-case-for-11.patch new file mode 100644 index 0000000..79639f8 --- /dev/null +++ b/SOURCES/0001-Specify-bootloader-directory-in-the-test-case-for-11.patch @@ -0,0 +1,30 @@ +From 2793c9305a1092c03d04a5fe0fa3a56811039447 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 1 Sep 2015 11:02:07 -0400 +Subject: [PATCH] Specify bootloader directory in the test case for 1152550. + +Because otherwise it blows up when built in mock without /boot mounted. + +Related: rhbz#1152550 + +Signed-off-by: Peter Jones +--- + test.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test.sh b/test.sh +index cd2d870..ba466a5 100755 +--- a/test.sh ++++ b/test.sh +@@ -547,7 +547,7 @@ if [ "$testgrub2" == "y" ]; then + # has this being emitted as: set foo="bar=1,2"=1,2" + # which is wrong. + grub2Test grub2.16 add/g2-1.16 \ +- --add-kernel=/boot/vmlinuz-foo \ ++ --boot-filesystem=/boot --add-kernel=/boot/vmlinuz-foo \ + --copy-default --title 'Red Hat Enterprise Linux Server' \ + --args=root=/dev/mapper/foo-- + +-- +2.4.3 + diff --git a/SOURCES/0001-Use-PREFIX-during-make-install.patch b/SOURCES/0001-Use-PREFIX-during-make-install.patch deleted file mode 100644 index 2759386..0000000 --- a/SOURCES/0001-Use-PREFIX-during-make-install.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 5ed33f682272c88bd6eadf91f2688a1520e28b53 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 13 Sep 2013 10:37:10 -0400 -Subject: [PATCH 01/16] Use $(PREFIX) during make install. - -Signed-off-by: Peter Jones ---- - Makefile | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/Makefile b/Makefile -index 3f6370b..5a151ce 100644 ---- a/Makefile -+++ b/Makefile -@@ -42,14 +42,14 @@ test: all - @./test.sh - - install: all -- mkdir -p $(DESTDIR)/sbin -+ mkdir -p $(DESTDIR)$(PREFIX)/sbin - mkdir -p $(DESTDIR)/$(mandir)/man8 -- install -m 755 new-kernel-pkg $(DESTDIR)/sbin -+ install -m 755 new-kernel-pkg $(DESTDIR)$(PREFIX)/sbin - install -m 644 new-kernel-pkg.8 $(DESTDIR)/$(mandir)/man8 -- install -m 755 installkernel $(DESTDIR)/sbin -+ install -m 755 installkernel $(DESTDIR)$(PREFIX)/sbin - install -m 644 installkernel.8 $(DESTDIR)/$(mandir)/man8 - if [ -f grubby ]; then \ -- install -m 755 grubby $(DESTDIR)/sbin ; \ -+ install -m 755 grubby $(DESTDIR)$(PREFIX)/sbin ; \ - install -m 644 grubby.8 $(DESTDIR)/$(mandir)/man8 ; \ - fi - --- -1.9.3 - diff --git a/SOURCES/0001-ppc64le-sync-grub.cfg-changes-to-disk-1212114.patch b/SOURCES/0001-ppc64le-sync-grub.cfg-changes-to-disk-1212114.patch new file mode 100644 index 0000000..f4971af --- /dev/null +++ b/SOURCES/0001-ppc64le-sync-grub.cfg-changes-to-disk-1212114.patch @@ -0,0 +1,42 @@ +From 8f0ef3e08aaef134ec4acfe87a6628b3fda2243c Mon Sep 17 00:00:00 2001 +From: Don Zickus +Date: Wed, 22 Jul 2015 13:58:53 -0400 +Subject: [PATCH] ppc64le sync grub.cfg changes to disk (#1212114) + +After installing a new kernel, if a panic is induced, not all the kernel +pieces are on the disk (most importantly the grub.cfg changes). This can +lead to a hung system on a reboot because the older kernel can not be found. + +Address this by forcing all the changes (mainly the fs meta data) to disk +before finishing the kernel package installation. + +Tested by 'yum install kernel-...; echo c > /proc/sysrq-trigger'. + +Before, the machine would panic and on reboot be stuck without a grub.cfg +to read. After, works as expected. + +Related: rhbz#1212114 +--- + new-kernel-pkg | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/new-kernel-pkg b/new-kernel-pkg +index 1f6ab39..90652da 100755 +--- a/new-kernel-pkg ++++ b/new-kernel-pkg +@@ -927,4 +927,12 @@ fi + # if we mounted the U-Boot directory, unmount it. + [ -n "$mounted" ] && umount $ubootDir + ++# make sure changes make it to the disk. ++# if /boot is a mountpoint, force the meta data on disk ++# to by-pass writeback delay. ++# PPC64LE-only to deal with Petitboot issues ++if [ "$ARCH" = "ppc64le" ]; then ++ sync && mountpoint -q /boot &&fsfreeze -f /boot && fsfreeze -u /boot ++fi ++ + exit 0 +-- +1.8.3.1 + diff --git a/SOURCES/0002-Better-formatting.patch b/SOURCES/0002-Better-formatting.patch new file mode 100644 index 0000000..fafdd95 --- /dev/null +++ b/SOURCES/0002-Better-formatting.patch @@ -0,0 +1,9034 @@ +From aaea1dbe7731a481a1f62b312a5dd5ac77c10926 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 10 Sep 2015 18:27:31 -0400 +Subject: [PATCH] Reformat to make this easier to work on. + +Signed-off-by: Peter Jones +--- + grubby.c | 8385 +++++++++++++++++++++++++++++++++----------------------------- + 1 file changed, 4406 insertions(+), 3979 deletions(-) + +diff --git a/grubby.c b/grubby.c +index f1af54d..8295a53 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -48,7 +48,7 @@ + #define dbgPrintf(format, args...) + #endif + +-int debug = 0; /* Currently just for template debugging */ ++int debug = 0; /* Currently just for template debugging */ + + #define _(A) (A) + +@@ -70,50 +70,50 @@ char *saved_command_line = NULL; + + /* comments get lumped in with indention */ + struct lineElement { +- char * item; +- char * indent; ++ char *item; ++ char *indent; + }; + +-enum lineType_e { +- LT_WHITESPACE = 1 << 0, +- LT_TITLE = 1 << 1, +- LT_KERNEL = 1 << 2, +- LT_INITRD = 1 << 3, +- LT_HYPER = 1 << 4, +- LT_DEFAULT = 1 << 5, +- LT_MBMODULE = 1 << 6, +- LT_ROOT = 1 << 7, +- LT_FALLBACK = 1 << 8, +- LT_KERNELARGS = 1 << 9, +- LT_BOOT = 1 << 10, +- LT_BOOTROOT = 1 << 11, +- LT_LBA = 1 << 12, +- LT_OTHER = 1 << 13, +- LT_GENERIC = 1 << 14, +- LT_ECHO = 1 << 16, +- LT_MENUENTRY = 1 << 17, +- LT_ENTRY_END = 1 << 18, +- LT_SET_VARIABLE = 1 << 19, +- LT_KERNEL_EFI = 1 << 20, +- LT_INITRD_EFI = 1 << 21, +- LT_KERNEL_16 = 1 << 22, +- LT_INITRD_16 = 1 << 23, +- LT_UNKNOWN = 1 << 24, ++enum lineType_e { ++ LT_WHITESPACE = 1 << 0, ++ LT_TITLE = 1 << 1, ++ LT_KERNEL = 1 << 2, ++ LT_INITRD = 1 << 3, ++ LT_HYPER = 1 << 4, ++ LT_DEFAULT = 1 << 5, ++ LT_MBMODULE = 1 << 6, ++ LT_ROOT = 1 << 7, ++ LT_FALLBACK = 1 << 8, ++ LT_KERNELARGS = 1 << 9, ++ LT_BOOT = 1 << 10, ++ LT_BOOTROOT = 1 << 11, ++ LT_LBA = 1 << 12, ++ LT_OTHER = 1 << 13, ++ LT_GENERIC = 1 << 14, ++ LT_ECHO = 1 << 16, ++ LT_MENUENTRY = 1 << 17, ++ LT_ENTRY_END = 1 << 18, ++ LT_SET_VARIABLE = 1 << 19, ++ LT_KERNEL_EFI = 1 << 20, ++ LT_INITRD_EFI = 1 << 21, ++ LT_KERNEL_16 = 1 << 22, ++ LT_INITRD_16 = 1 << 23, ++ LT_UNKNOWN = 1 << 24, + }; + + struct singleLine { +- char * indent; +- int numElements; +- struct lineElement * elements; +- struct singleLine * next; +- enum lineType_e type; ++ char *indent; ++ int numElements; ++ struct lineElement *elements; ++ struct singleLine *next; ++ enum lineType_e type; + }; + + struct singleEntry { +- struct singleLine * lines; +- int skip; +- int multiboot; +- struct singleEntry * next; ++ struct singleLine *lines; ++ int skip; ++ int multiboot; ++ struct singleEntry *next; + }; + + #define GRUBBY_BADIMAGE_OKAY (1 << 0) +@@ -133,1718 +133,1837 @@ struct singleEntry { + #define DEFAULT_SAVED_GRUB2 -3 + + struct keywordTypes { +- char * key; +- enum lineType_e type; +- char nextChar; +- char separatorChar; ++ char *key; ++ enum lineType_e type; ++ char nextChar; ++ char separatorChar; + }; + + struct configFileInfo; + +-typedef const char *(*findConfigFunc)(struct configFileInfo *); +-typedef const int (*writeLineFunc)(struct configFileInfo *, +- struct singleLine *line); +-typedef char *(*getEnvFunc)(struct configFileInfo *, char *name); +-typedef int (*setEnvFunc)(struct configFileInfo *, char *name, char *value); ++typedef const char *(*findConfigFunc) (struct configFileInfo *); ++typedef const int (*writeLineFunc) (struct configFileInfo *, ++ struct singleLine * line); ++typedef char *(*getEnvFunc) (struct configFileInfo *, char *name); ++typedef int (*setEnvFunc) (struct configFileInfo *, char *name, char *value); + + struct configFileInfo { +- char * defaultConfig; +- findConfigFunc findConfig; +- writeLineFunc writeLine; +- getEnvFunc getEnv; +- setEnvFunc setEnv; +- struct keywordTypes * keywords; +- int caseInsensitive; +- int defaultIsIndex; +- int defaultIsVariable; +- int defaultSupportSaved; +- int defaultIsSaved; +- int defaultIsUnquoted; +- enum lineType_e entryStart; +- enum lineType_e entryEnd; +- int needsBootPrefix; +- int argsInQuotes; +- int maxTitleLength; +- int titleBracketed; +- int titlePosition; +- int mbHyperFirst; +- int mbInitRdIsModule; +- int mbConcatArgs; +- int mbAllowExtraInitRds; +- char *envFile; ++ char *defaultConfig; ++ findConfigFunc findConfig; ++ writeLineFunc writeLine; ++ getEnvFunc getEnv; ++ setEnvFunc setEnv; ++ struct keywordTypes *keywords; ++ int caseInsensitive; ++ int defaultIsIndex; ++ int defaultIsVariable; ++ int defaultSupportSaved; ++ int defaultIsSaved; ++ int defaultIsUnquoted; ++ enum lineType_e entryStart; ++ enum lineType_e entryEnd; ++ int needsBootPrefix; ++ int argsInQuotes; ++ int maxTitleLength; ++ int titleBracketed; ++ int titlePosition; ++ int mbHyperFirst; ++ int mbInitRdIsModule; ++ int mbConcatArgs; ++ int mbAllowExtraInitRds; ++ char *envFile; + }; + + struct keywordTypes grubKeywords[] = { +- { "title", LT_TITLE, ' ' }, +- { "root", LT_BOOTROOT, ' ' }, +- { "default", LT_DEFAULT, ' ' }, +- { "fallback", LT_FALLBACK, ' ' }, +- { "kernel", LT_KERNEL, ' ' }, +- { "initrd", LT_INITRD, ' ', ' ' }, +- { "module", LT_MBMODULE, ' ' }, +- { "kernel", LT_HYPER, ' ' }, +- { NULL, 0, 0 }, ++ {"title", LT_TITLE, ' '}, ++ {"root", LT_BOOTROOT, ' '}, ++ {"default", LT_DEFAULT, ' '}, ++ {"fallback", LT_FALLBACK, ' '}, ++ {"kernel", LT_KERNEL, ' '}, ++ {"initrd", LT_INITRD, ' ', ' '}, ++ {"module", LT_MBMODULE, ' '}, ++ {"kernel", LT_HYPER, ' '}, ++ {NULL, 0, 0}, + }; + +-const char *grubFindConfig(struct configFileInfo *cfi) { +- static const char *configFiles[] = { +- "/boot/grub/menu.lst", +- "/etc/grub.conf", +- NULL +- }; +- static int i = -1; +- +- if (i == -1) { +- for (i = 0; configFiles[i] != NULL; i++) { +- dbgPrintf("Checking \"%s\": ", configFiles[i]); +- if (!access(configFiles[i], R_OK)) { +- dbgPrintf("found\n"); +- return configFiles[i]; +- } +- dbgPrintf("not found\n"); ++const char *grubFindConfig(struct configFileInfo *cfi) ++{ ++ static const char *configFiles[] = { ++ "/boot/grub/menu.lst", ++ "/etc/grub.conf", ++ NULL ++ }; ++ static int i = -1; ++ ++ if (i == -1) { ++ for (i = 0; configFiles[i] != NULL; i++) { ++ dbgPrintf("Checking \"%s\": ", configFiles[i]); ++ if (!access(configFiles[i], R_OK)) { ++ dbgPrintf("found\n"); ++ return configFiles[i]; ++ } ++ dbgPrintf("not found\n"); ++ } + } +- } +- return configFiles[i]; ++ return configFiles[i]; + } + + struct configFileInfo grubConfigType = { +- .findConfig = grubFindConfig, +- .keywords = grubKeywords, +- .defaultIsIndex = 1, +- .defaultSupportSaved = 1, +- .entryStart = LT_TITLE, +- .needsBootPrefix = 1, +- .mbHyperFirst = 1, +- .mbInitRdIsModule = 1, +- .mbAllowExtraInitRds = 1, +- .titlePosition = 1, ++ .findConfig = grubFindConfig, ++ .keywords = grubKeywords, ++ .defaultIsIndex = 1, ++ .defaultSupportSaved = 1, ++ .entryStart = LT_TITLE, ++ .needsBootPrefix = 1, ++ .mbHyperFirst = 1, ++ .mbInitRdIsModule = 1, ++ .mbAllowExtraInitRds = 1, ++ .titlePosition = 1, + }; + + struct keywordTypes grub2Keywords[] = { +- { "menuentry", LT_MENUENTRY, ' ' }, +- { "}", LT_ENTRY_END, ' ' }, +- { "echo", LT_ECHO, ' ' }, +- { "set", LT_SET_VARIABLE,' ', '=' }, +- { "root", LT_BOOTROOT, ' ' }, +- { "default", LT_DEFAULT, ' ' }, +- { "fallback", LT_FALLBACK, ' ' }, +- { "linux", LT_KERNEL, ' ' }, +- { "linuxefi", LT_KERNEL_EFI, ' ' }, +- { "linux16", LT_KERNEL_16, ' ' }, +- { "initrd", LT_INITRD, ' ', ' ' }, +- { "initrdefi", LT_INITRD_EFI, ' ', ' ' }, +- { "initrd16", LT_INITRD_16, ' ', ' ' }, +- { "module", LT_MBMODULE, ' ' }, +- { "kernel", LT_HYPER, ' ' }, +- { NULL, 0, 0 }, ++ {"menuentry", LT_MENUENTRY, ' '}, ++ {"}", LT_ENTRY_END, ' '}, ++ {"echo", LT_ECHO, ' '}, ++ {"set", LT_SET_VARIABLE, ' ', '='}, ++ {"root", LT_BOOTROOT, ' '}, ++ {"default", LT_DEFAULT, ' '}, ++ {"fallback", LT_FALLBACK, ' '}, ++ {"linux", LT_KERNEL, ' '}, ++ {"linuxefi", LT_KERNEL_EFI, ' '}, ++ {"linux16", LT_KERNEL_16, ' '}, ++ {"initrd", LT_INITRD, ' ', ' '}, ++ {"initrdefi", LT_INITRD_EFI, ' ', ' '}, ++ {"initrd16", LT_INITRD_16, ' ', ' '}, ++ {"module", LT_MBMODULE, ' '}, ++ {"kernel", LT_HYPER, ' '}, ++ {NULL, 0, 0}, + }; + +-const char *grub2FindConfig(struct configFileInfo *cfi) { +- static const char *configFiles[] = { +- "/etc/grub2-efi.cfg", +- "/etc/grub2.cfg", +- NULL +- }; +- static int i = -1; +- static const char *grub_cfg = "/boot/grub/grub.cfg"; +- int rc = -1; +- +- if (i == -1) { +- for (i = 0; configFiles[i] != NULL; i++) { +- dbgPrintf("Checking \"%s\": ", configFiles[i]); +- if ((rc = access(configFiles[i], R_OK))) { +- if (errno == EACCES) { +- printf("Unable to access bootloader configuration file " +- "\"%s\": %m\n", configFiles[i]); +- exit(1); ++const char *grub2FindConfig(struct configFileInfo *cfi) ++{ ++ static const char *configFiles[] = { ++ "/etc/grub2-efi.cfg", ++ "/etc/grub2.cfg", ++ NULL ++ }; ++ static int i = -1; ++ static const char *grub_cfg = "/boot/grub/grub.cfg"; ++ int rc = -1; ++ ++ if (i == -1) { ++ for (i = 0; configFiles[i] != NULL; i++) { ++ dbgPrintf("Checking \"%s\": ", configFiles[i]); ++ if ((rc = access(configFiles[i], R_OK))) { ++ if (errno == EACCES) { ++ printf ++ ("Unable to access bootloader configuration file " ++ "\"%s\": %m\n", configFiles[i]); ++ exit(1); ++ } ++ continue; ++ } else { ++ dbgPrintf("found\n"); ++ return configFiles[i]; ++ } + } +- continue; +- } else { +- dbgPrintf("found\n"); +- return configFiles[i]; +- } + } +- } + +- /* Ubuntu renames grub2 to grub, so check for the grub.d directory +- * that isn't in grub1, and if it exists, return the config file path +- * that they use. */ +- if (configFiles[i] == NULL && !access("/etc/grub.d/", R_OK)) { +- dbgPrintf("found\n"); +- return grub_cfg; +- } ++ /* Ubuntu renames grub2 to grub, so check for the grub.d directory ++ * that isn't in grub1, and if it exists, return the config file path ++ * that they use. */ ++ if (configFiles[i] == NULL && !access("/etc/grub.d/", R_OK)) { ++ dbgPrintf("found\n"); ++ return grub_cfg; ++ } + +- dbgPrintf("not found\n"); +- return configFiles[i]; ++ dbgPrintf("not found\n"); ++ return configFiles[i]; + } + + /* kind of hacky. It'll give the first 1024 bytes, ish. */ + static char *grub2GetEnv(struct configFileInfo *info, char *name) + { +- static char buf[1025]; +- char *s = NULL; +- char *ret = NULL; +- char *envFile = info->envFile ? info->envFile : "/boot/grub2/grubenv"; +- int rc = asprintf(&s, "grub2-editenv %s list | grep '^%s='", envFile, name); +- +- if (rc < 0) +- return NULL; +- +- FILE *f = popen(s, "r"); +- if (!f) +- goto out; +- +- memset(buf, '\0', sizeof (buf)); +- ret = fgets(buf, 1024, f); +- pclose(f); +- +- if (ret) { +- ret += strlen(name) + 1; +- ret[strlen(ret) - 1] = '\0'; +- } +- dbgPrintf("grub2GetEnv(%s): %s\n", name, ret); ++ static char buf[1025]; ++ char *s = NULL; ++ char *ret = NULL; ++ char *envFile = info->envFile ? info->envFile : "/boot/grub2/grubenv"; ++ int rc = ++ asprintf(&s, "grub2-editenv %s list | grep '^%s='", envFile, name); ++ ++ if (rc < 0) ++ return NULL; ++ ++ FILE *f = popen(s, "r"); ++ if (!f) ++ goto out; ++ ++ memset(buf, '\0', sizeof(buf)); ++ ret = fgets(buf, 1024, f); ++ pclose(f); ++ ++ if (ret) { ++ ret += strlen(name) + 1; ++ ret[strlen(ret) - 1] = '\0'; ++ } ++ dbgPrintf("grub2GetEnv(%s): %s\n", name, ret); + out: +- free(s); +- return ret; ++ free(s); ++ return ret; + } + + static int sPopCount(const char *s, const char *c) + { +- int ret = 0; +- if (!s) +- return -1; +- for (int i = 0; s[i] != '\0'; i++) +- for (int j = 0; c[j] != '\0'; j++) +- if (s[i] == c[j]) +- ret++; +- return ret; ++ int ret = 0; ++ if (!s) ++ return -1; ++ for (int i = 0; s[i] != '\0'; i++) ++ for (int j = 0; c[j] != '\0'; j++) ++ if (s[i] == c[j]) ++ ret++; ++ return ret; + } + + static char *shellEscape(const char *s) + { +- int l = strlen(s) + sPopCount(s, "'") * 2; +- +- char *ret = calloc(l+1, sizeof (*ret)); +- if (!ret) +- return NULL; +- for (int i = 0, j = 0; s[i] != '\0'; i++, j++) { +- if (s[i] == '\'') +- ret[j++] = '\\'; +- ret[j] = s[i]; +- } +- return ret; ++ int l = strlen(s) + sPopCount(s, "'") * 2; ++ ++ char *ret = calloc(l + 1, sizeof(*ret)); ++ if (!ret) ++ return NULL; ++ for (int i = 0, j = 0; s[i] != '\0'; i++, j++) { ++ if (s[i] == '\'') ++ ret[j++] = '\\'; ++ ret[j] = s[i]; ++ } ++ return ret; + } + + static void unquote(char *s) + { +- int l = strlen(s); ++ int l = strlen(s); + +- if ((s[l-1] == '\'' && s[0] == '\'') || (s[l-1] == '"' && s[0] == '"')) { +- memmove(s, s+1, l-2); +- s[l-2] = '\0'; +- } ++ if ((s[l - 1] == '\'' && s[0] == '\'') ++ || (s[l - 1] == '"' && s[0] == '"')) { ++ memmove(s, s + 1, l - 2); ++ s[l - 2] = '\0'; ++ } + } + + static int grub2SetEnv(struct configFileInfo *info, char *name, char *value) + { +- char *s = NULL; +- int rc = 0; +- char *envFile = info->envFile ? info->envFile : "/boot/grub2/grubenv"; +- +- unquote(value); +- value = shellEscape(value); +- if (!value) +- return -1; +- +- rc = asprintf(&s, "grub2-editenv %s set '%s=%s'", envFile, name, value); +- free(value); +- if (rc <0) +- return -1; +- +- dbgPrintf("grub2SetEnv(%s): %s\n", name, s); +- rc = system(s); +- free(s); +- return rc; ++ char *s = NULL; ++ int rc = 0; ++ char *envFile = info->envFile ? info->envFile : "/boot/grub2/grubenv"; ++ ++ unquote(value); ++ value = shellEscape(value); ++ if (!value) ++ return -1; ++ ++ rc = asprintf(&s, "grub2-editenv %s set '%s=%s'", envFile, name, value); ++ free(value); ++ if (rc < 0) ++ return -1; ++ ++ dbgPrintf("grub2SetEnv(%s): %s\n", name, s); ++ rc = system(s); ++ free(s); ++ return rc; + } + + /* this is a gigantic hack to avoid clobbering grub2 variables... */ + static int is_special_grub2_variable(const char *name) + { +- if (!strcmp(name,"\"${next_entry}\"")) +- return 1; +- if (!strcmp(name,"\"${prev_saved_entry}\"")) +- return 1; +- return 0; ++ if (!strcmp(name, "\"${next_entry}\"")) ++ return 1; ++ if (!strcmp(name, "\"${prev_saved_entry}\"")) ++ return 1; ++ return 0; + } + +-int sizeOfSingleLine(struct singleLine * line) { +- int count = 0; ++int sizeOfSingleLine(struct singleLine *line) ++{ ++ int count = 0; + +- for (int i = 0; i < line->numElements; i++) { +- int indentSize = 0; ++ for (int i = 0; i < line->numElements; i++) { ++ int indentSize = 0; + +- count = count + strlen(line->elements[i].item); ++ count = count + strlen(line->elements[i].item); + +- indentSize = strlen(line->elements[i].indent); +- if (indentSize > 0) +- count = count + indentSize; +- else +- /* be extra safe and add room for whitespaces */ +- count = count + 1; +- } ++ indentSize = strlen(line->elements[i].indent); ++ if (indentSize > 0) ++ count = count + indentSize; ++ else ++ /* be extra safe and add room for whitespaces */ ++ count = count + 1; ++ } + +- /* room for trailing terminator */ +- count = count + 1; ++ /* room for trailing terminator */ ++ count = count + 1; + +- return count; ++ return count; + } + + static int isquote(char q) + { +- if (q == '\'' || q == '\"') +- return 1; +- return 0; ++ if (q == '\'' || q == '\"') ++ return 1; ++ return 0; + } + +-static int iskernel(enum lineType_e type) { +- return (type == LT_KERNEL || type == LT_KERNEL_EFI || type == LT_KERNEL_16); ++static int iskernel(enum lineType_e type) ++{ ++ return (type == LT_KERNEL || type == LT_KERNEL_EFI ++ || type == LT_KERNEL_16); + } + +-static int isinitrd(enum lineType_e type) { +- return (type == LT_INITRD || type == LT_INITRD_EFI || type == LT_INITRD_16); ++static int isinitrd(enum lineType_e type) ++{ ++ return (type == LT_INITRD || type == LT_INITRD_EFI ++ || type == LT_INITRD_16); + } + +-char *grub2ExtractTitle(struct singleLine * line) { +- char * current; +- char * current_indent; +- int current_len; +- int current_indent_len; +- int i; ++char *grub2ExtractTitle(struct singleLine *line) ++{ ++ char *current; ++ char *current_indent; ++ int current_len; ++ int current_indent_len; ++ int i; + +- /* bail out if line does not start with menuentry */ +- if (strcmp(line->elements[0].item, "menuentry")) +- return NULL; ++ /* bail out if line does not start with menuentry */ ++ if (strcmp(line->elements[0].item, "menuentry")) ++ return NULL; + +- i = 1; +- current = line->elements[i].item; +- current_len = strlen(current); +- +- /* if second word is quoted, strip the quotes and return single word */ +- if (isquote(*current) && isquote(current[current_len - 1])) { +- char *tmp; +- +- tmp = strdup(current+1); +- if (!tmp) +- return NULL; +- tmp[strlen(tmp)-1] = '\0'; +- return tmp; +- } +- +- /* if no quotes, return second word verbatim */ +- if (!isquote(*current)) +- return current; +- +- /* second element start with a quote, so we have to find the element +- * whose last character is also quote (assuming it's the closing one) */ +- int resultMaxSize; +- char * result; +- /* need to ensure that ' does not match " as we search */ +- char quote_char = *current; +- +- resultMaxSize = sizeOfSingleLine(line); +- result = malloc(resultMaxSize); +- snprintf(result, resultMaxSize, "%s", ++current); +- +- i++; +- for (; i < line->numElements; ++i) { ++ i = 1; + current = line->elements[i].item; + current_len = strlen(current); +- current_indent = line->elements[i].indent; +- current_indent_len = strlen(current_indent); + +- strncat(result, current_indent, current_indent_len); +- if (current[current_len-1] != quote_char) { +- strncat(result, current, current_len); +- } else { +- strncat(result, current, current_len - 1); +- break; ++ /* if second word is quoted, strip the quotes and return single word */ ++ if (isquote(*current) && isquote(current[current_len - 1])) { ++ char *tmp; ++ ++ tmp = strdup(current + 1); ++ if (!tmp) ++ return NULL; ++ tmp[strlen(tmp) - 1] = '\0'; ++ return tmp; ++ } ++ ++ /* if no quotes, return second word verbatim */ ++ if (!isquote(*current)) ++ return current; ++ ++ /* second element start with a quote, so we have to find the element ++ * whose last character is also quote (assuming it's the closing one) */ ++ int resultMaxSize; ++ char *result; ++ /* need to ensure that ' does not match " as we search */ ++ char quote_char = *current; ++ ++ resultMaxSize = sizeOfSingleLine(line); ++ result = malloc(resultMaxSize); ++ snprintf(result, resultMaxSize, "%s", ++current); ++ ++ i++; ++ for (; i < line->numElements; ++i) { ++ current = line->elements[i].item; ++ current_len = strlen(current); ++ current_indent = line->elements[i].indent; ++ current_indent_len = strlen(current_indent); ++ ++ strncat(result, current_indent, current_indent_len); ++ if (current[current_len - 1] != quote_char) { ++ strncat(result, current, current_len); ++ } else { ++ strncat(result, current, current_len - 1); ++ break; ++ } + } +- } +- return result; ++ return result; + } + + struct configFileInfo grub2ConfigType = { +- .findConfig = grub2FindConfig, +- .getEnv = grub2GetEnv, +- .setEnv = grub2SetEnv, +- .keywords = grub2Keywords, +- .defaultIsIndex = 1, +- .defaultSupportSaved = 1, +- .defaultIsVariable = 1, +- .entryStart = LT_MENUENTRY, +- .entryEnd = LT_ENTRY_END, +- .titlePosition = 1, +- .needsBootPrefix = 1, +- .mbHyperFirst = 1, +- .mbInitRdIsModule = 1, +- .mbAllowExtraInitRds = 1, ++ .findConfig = grub2FindConfig, ++ .getEnv = grub2GetEnv, ++ .setEnv = grub2SetEnv, ++ .keywords = grub2Keywords, ++ .defaultIsIndex = 1, ++ .defaultSupportSaved = 1, ++ .defaultIsVariable = 1, ++ .entryStart = LT_MENUENTRY, ++ .entryEnd = LT_ENTRY_END, ++ .titlePosition = 1, ++ .needsBootPrefix = 1, ++ .mbHyperFirst = 1, ++ .mbInitRdIsModule = 1, ++ .mbAllowExtraInitRds = 1, + }; + + struct keywordTypes yabootKeywords[] = { +- { "label", LT_TITLE, '=' }, +- { "root", LT_ROOT, '=' }, +- { "default", LT_DEFAULT, '=' }, +- { "image", LT_KERNEL, '=' }, +- { "bsd", LT_GENERIC, '=' }, +- { "macos", LT_GENERIC, '=' }, +- { "macosx", LT_GENERIC, '=' }, +- { "magicboot", LT_GENERIC, '=' }, +- { "darwin", LT_GENERIC, '=' }, +- { "timeout", LT_GENERIC, '=' }, +- { "install", LT_GENERIC, '=' }, +- { "fstype", LT_GENERIC, '=' }, +- { "hfstype", LT_GENERIC, '=' }, +- { "delay", LT_GENERIC, '=' }, +- { "defaultos", LT_GENERIC, '=' }, +- { "init-message", LT_GENERIC, '=' }, +- { "enablecdboot", LT_GENERIC, ' ' }, +- { "enableofboot", LT_GENERIC, ' ' }, +- { "enablenetboot", LT_GENERIC, ' ' }, +- { "nonvram", LT_GENERIC, ' ' }, +- { "hide", LT_GENERIC, ' ' }, +- { "protect", LT_GENERIC, ' ' }, +- { "nobless", LT_GENERIC, ' ' }, +- { "nonvram", LT_GENERIC, ' ' }, +- { "brokenosx", LT_GENERIC, ' ' }, +- { "usemount", LT_GENERIC, ' ' }, +- { "mntpoint", LT_GENERIC, '=' }, +- { "partition", LT_GENERIC, '=' }, +- { "device", LT_GENERIC, '=' }, +- { "fstype", LT_GENERIC, '=' }, +- { "initrd", LT_INITRD, '=', ';' }, +- { "append", LT_KERNELARGS, '=' }, +- { "boot", LT_BOOT, '=' }, +- { "lba", LT_LBA, ' ' }, +- { NULL, 0, 0 }, ++ {"label", LT_TITLE, '='}, ++ {"root", LT_ROOT, '='}, ++ {"default", LT_DEFAULT, '='}, ++ {"image", LT_KERNEL, '='}, ++ {"bsd", LT_GENERIC, '='}, ++ {"macos", LT_GENERIC, '='}, ++ {"macosx", LT_GENERIC, '='}, ++ {"magicboot", LT_GENERIC, '='}, ++ {"darwin", LT_GENERIC, '='}, ++ {"timeout", LT_GENERIC, '='}, ++ {"install", LT_GENERIC, '='}, ++ {"fstype", LT_GENERIC, '='}, ++ {"hfstype", LT_GENERIC, '='}, ++ {"delay", LT_GENERIC, '='}, ++ {"defaultos", LT_GENERIC, '='}, ++ {"init-message", LT_GENERIC, '='}, ++ {"enablecdboot", LT_GENERIC, ' '}, ++ {"enableofboot", LT_GENERIC, ' '}, ++ {"enablenetboot", LT_GENERIC, ' '}, ++ {"nonvram", LT_GENERIC, ' '}, ++ {"hide", LT_GENERIC, ' '}, ++ {"protect", LT_GENERIC, ' '}, ++ {"nobless", LT_GENERIC, ' '}, ++ {"nonvram", LT_GENERIC, ' '}, ++ {"brokenosx", LT_GENERIC, ' '}, ++ {"usemount", LT_GENERIC, ' '}, ++ {"mntpoint", LT_GENERIC, '='}, ++ {"partition", LT_GENERIC, '='}, ++ {"device", LT_GENERIC, '='}, ++ {"fstype", LT_GENERIC, '='}, ++ {"initrd", LT_INITRD, '=', ';'}, ++ {"append", LT_KERNELARGS, '='}, ++ {"boot", LT_BOOT, '='}, ++ {"lba", LT_LBA, ' '}, ++ {NULL, 0, 0}, + }; + + struct keywordTypes liloKeywords[] = { +- { "label", LT_TITLE, '=' }, +- { "root", LT_ROOT, '=' }, +- { "default", LT_DEFAULT, '=' }, +- { "image", LT_KERNEL, '=' }, +- { "other", LT_OTHER, '=' }, +- { "initrd", LT_INITRD, '=' }, +- { "append", LT_KERNELARGS, '=' }, +- { "boot", LT_BOOT, '=' }, +- { "lba", LT_LBA, ' ' }, +- { NULL, 0, 0 }, ++ {"label", LT_TITLE, '='}, ++ {"root", LT_ROOT, '='}, ++ {"default", LT_DEFAULT, '='}, ++ {"image", LT_KERNEL, '='}, ++ {"other", LT_OTHER, '='}, ++ {"initrd", LT_INITRD, '='}, ++ {"append", LT_KERNELARGS, '='}, ++ {"boot", LT_BOOT, '='}, ++ {"lba", LT_LBA, ' '}, ++ {NULL, 0, 0}, + }; + + struct keywordTypes eliloKeywords[] = { +- { "label", LT_TITLE, '=' }, +- { "root", LT_ROOT, '=' }, +- { "default", LT_DEFAULT, '=' }, +- { "image", LT_KERNEL, '=' }, +- { "initrd", LT_INITRD, '=' }, +- { "append", LT_KERNELARGS, '=' }, +- { "vmm", LT_HYPER, '=' }, +- { NULL, 0, 0 }, ++ {"label", LT_TITLE, '='}, ++ {"root", LT_ROOT, '='}, ++ {"default", LT_DEFAULT, '='}, ++ {"image", LT_KERNEL, '='}, ++ {"initrd", LT_INITRD, '='}, ++ {"append", LT_KERNELARGS, '='}, ++ {"vmm", LT_HYPER, '='}, ++ {NULL, 0, 0}, + }; + + struct keywordTypes siloKeywords[] = { +- { "label", LT_TITLE, '=' }, +- { "root", LT_ROOT, '=' }, +- { "default", LT_DEFAULT, '=' }, +- { "image", LT_KERNEL, '=' }, +- { "other", LT_OTHER, '=' }, +- { "initrd", LT_INITRD, '=' }, +- { "append", LT_KERNELARGS, '=' }, +- { "boot", LT_BOOT, '=' }, +- { NULL, 0, 0 }, ++ {"label", LT_TITLE, '='}, ++ {"root", LT_ROOT, '='}, ++ {"default", LT_DEFAULT, '='}, ++ {"image", LT_KERNEL, '='}, ++ {"other", LT_OTHER, '='}, ++ {"initrd", LT_INITRD, '='}, ++ {"append", LT_KERNELARGS, '='}, ++ {"boot", LT_BOOT, '='}, ++ {NULL, 0, 0}, + }; + + struct keywordTypes ziplKeywords[] = { +- { "target", LT_BOOTROOT, '=' }, +- { "image", LT_KERNEL, '=' }, +- { "ramdisk", LT_INITRD, '=' }, +- { "parameters", LT_KERNELARGS, '=' }, +- { "default", LT_DEFAULT, '=' }, +- { NULL, 0, 0 }, ++ {"target", LT_BOOTROOT, '='}, ++ {"image", LT_KERNEL, '='}, ++ {"ramdisk", LT_INITRD, '='}, ++ {"parameters", LT_KERNELARGS, '='}, ++ {"default", LT_DEFAULT, '='}, ++ {NULL, 0, 0}, + }; + + struct keywordTypes extlinuxKeywords[] = { +- { "label", LT_TITLE, ' ' }, +- { "root", LT_ROOT, ' ' }, +- { "default", LT_DEFAULT, ' ' }, +- { "kernel", LT_KERNEL, ' ' }, +- { "initrd", LT_INITRD, ' ', ',' }, +- { "append", LT_KERNELARGS, ' ' }, +- { "prompt", LT_UNKNOWN, ' ' }, +- { NULL, 0, 0 }, ++ {"label", LT_TITLE, ' '}, ++ {"root", LT_ROOT, ' '}, ++ {"default", LT_DEFAULT, ' '}, ++ {"kernel", LT_KERNEL, ' '}, ++ {"initrd", LT_INITRD, ' ', ','}, ++ {"append", LT_KERNELARGS, ' '}, ++ {"prompt", LT_UNKNOWN, ' '}, ++ {NULL, 0, 0}, + }; ++ + int useextlinuxmenu; + struct configFileInfo eliloConfigType = { +- .defaultConfig = "/boot/efi/EFI/redhat/elilo.conf", +- .keywords = eliloKeywords, +- .entryStart = LT_KERNEL, +- .needsBootPrefix = 1, +- .argsInQuotes = 1, +- .mbConcatArgs = 1, +- .titlePosition = 1, ++ .defaultConfig = "/boot/efi/EFI/redhat/elilo.conf", ++ .keywords = eliloKeywords, ++ .entryStart = LT_KERNEL, ++ .needsBootPrefix = 1, ++ .argsInQuotes = 1, ++ .mbConcatArgs = 1, ++ .titlePosition = 1, + }; + + struct configFileInfo liloConfigType = { +- .defaultConfig = "/etc/lilo.conf", +- .keywords = liloKeywords, +- .entryStart = LT_KERNEL, +- .argsInQuotes = 1, +- .maxTitleLength = 15, +- .titlePosition = 1, ++ .defaultConfig = "/etc/lilo.conf", ++ .keywords = liloKeywords, ++ .entryStart = LT_KERNEL, ++ .argsInQuotes = 1, ++ .maxTitleLength = 15, ++ .titlePosition = 1, + }; + + struct configFileInfo yabootConfigType = { +- .defaultConfig = "/etc/yaboot.conf", +- .keywords = yabootKeywords, +- .entryStart = LT_KERNEL, +- .needsBootPrefix = 1, +- .argsInQuotes = 1, +- .maxTitleLength = 15, +- .mbAllowExtraInitRds = 1, +- .titlePosition = 1, ++ .defaultConfig = "/etc/yaboot.conf", ++ .keywords = yabootKeywords, ++ .entryStart = LT_KERNEL, ++ .needsBootPrefix = 1, ++ .argsInQuotes = 1, ++ .maxTitleLength = 15, ++ .mbAllowExtraInitRds = 1, ++ .titlePosition = 1, + }; + + struct configFileInfo siloConfigType = { +- .defaultConfig = "/etc/silo.conf", +- .keywords = siloKeywords, +- .entryStart = LT_KERNEL, +- .needsBootPrefix = 1, +- .argsInQuotes = 1, +- .maxTitleLength = 15, +- .titlePosition = 1, ++ .defaultConfig = "/etc/silo.conf", ++ .keywords = siloKeywords, ++ .entryStart = LT_KERNEL, ++ .needsBootPrefix = 1, ++ .argsInQuotes = 1, ++ .maxTitleLength = 15, ++ .titlePosition = 1, + }; + + struct configFileInfo ziplConfigType = { +- .defaultConfig = "/etc/zipl.conf", +- .keywords = ziplKeywords, +- .entryStart = LT_TITLE, +- .argsInQuotes = 1, +- .titleBracketed = 1, ++ .defaultConfig = "/etc/zipl.conf", ++ .keywords = ziplKeywords, ++ .entryStart = LT_TITLE, ++ .argsInQuotes = 1, ++ .titleBracketed = 1, + }; + + struct configFileInfo extlinuxConfigType = { +- .defaultConfig = "/boot/extlinux/extlinux.conf", +- .keywords = extlinuxKeywords, +- .caseInsensitive = 1, +- .entryStart = LT_TITLE, +- .needsBootPrefix = 1, +- .maxTitleLength = 255, +- .mbAllowExtraInitRds = 1, +- .defaultIsUnquoted = 1, +- .titlePosition = 1, ++ .defaultConfig = "/boot/extlinux/extlinux.conf", ++ .keywords = extlinuxKeywords, ++ .caseInsensitive = 1, ++ .entryStart = LT_TITLE, ++ .needsBootPrefix = 1, ++ .maxTitleLength = 255, ++ .mbAllowExtraInitRds = 1, ++ .defaultIsUnquoted = 1, ++ .titlePosition = 1, + }; + + struct grubConfig { +- struct singleLine * theLines; +- struct singleEntry * entries; +- char * primaryIndent; +- char * secondaryIndent; +- int defaultImage; /* -1 if none specified -- this value is +- * written out, overriding original */ +- int fallbackImage; /* just like defaultImage */ +- int flags; +- struct configFileInfo * cfi; ++ struct singleLine *theLines; ++ struct singleEntry *entries; ++ char *primaryIndent; ++ char *secondaryIndent; ++ int defaultImage; /* -1 if none specified -- this value is ++ * written out, overriding original */ ++ int fallbackImage; /* just like defaultImage */ ++ int flags; ++ struct configFileInfo *cfi; + }; + + blkid_cache blkid; + +-struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index); +-struct singleEntry * findEntryByPath(struct grubConfig * cfg, +- const char * path, const char * prefix, +- int * index); +-struct singleEntry * findEntryByTitle(struct grubConfig * cfg, char *title, +- int * index); +-static int readFile(int fd, char ** bufPtr); +-static void lineInit(struct singleLine * line); +-struct singleLine * lineDup(struct singleLine * line); +-static void lineFree(struct singleLine * line); +-static int lineWrite(FILE * out, struct singleLine * line, +- struct configFileInfo * cfi); +-static int getNextLine(char ** bufPtr, struct singleLine * line, +- struct configFileInfo * cfi); +-static char * getRootSpecifier(char * str); +-static void requote(struct singleLine *line, struct configFileInfo * cfi); +-static void insertElement(struct singleLine * line, +- const char * item, int insertHere, +- struct configFileInfo * cfi); +-static void removeElement(struct singleLine * line, int removeHere); +-static struct keywordTypes * getKeywordByType(enum lineType_e type, +- struct configFileInfo * cfi); +-static enum lineType_e getTypeByKeyword(char * keyword, +- struct configFileInfo * cfi); +-static struct singleLine * getLineByType(enum lineType_e type, +- struct singleLine * line); +-static int checkForExtLinux(struct grubConfig * config); +-struct singleLine * addLineTmpl(struct singleEntry * entry, +- struct singleLine * tmplLine, +- struct singleLine * prevLine, +- const char * val, +- struct configFileInfo * cfi); +-struct singleLine * addLine(struct singleEntry * entry, +- struct configFileInfo * cfi, +- enum lineType_e type, char * defaultIndent, +- const char * val); +- +-static char * sdupprintf(const char *format, ...) ++struct singleEntry *findEntryByIndex(struct grubConfig *cfg, int index); ++struct singleEntry *findEntryByPath(struct grubConfig *cfg, ++ const char *path, const char *prefix, ++ int *index); ++struct singleEntry *findEntryByTitle(struct grubConfig *cfg, char *title, ++ int *index); ++static int readFile(int fd, char **bufPtr); ++static void lineInit(struct singleLine *line); ++struct singleLine *lineDup(struct singleLine *line); ++static void lineFree(struct singleLine *line); ++static int lineWrite(FILE * out, struct singleLine *line, ++ struct configFileInfo *cfi); ++static int getNextLine(char **bufPtr, struct singleLine *line, ++ struct configFileInfo *cfi); ++static char *getRootSpecifier(char *str); ++static void requote(struct singleLine *line, struct configFileInfo *cfi); ++static void insertElement(struct singleLine *line, ++ const char *item, int insertHere, ++ struct configFileInfo *cfi); ++static void removeElement(struct singleLine *line, int removeHere); ++static struct keywordTypes *getKeywordByType(enum lineType_e type, ++ struct configFileInfo *cfi); ++static enum lineType_e getTypeByKeyword(char *keyword, ++ struct configFileInfo *cfi); ++static struct singleLine *getLineByType(enum lineType_e type, ++ struct singleLine *line); ++static int checkForExtLinux(struct grubConfig *config); ++struct singleLine *addLineTmpl(struct singleEntry *entry, ++ struct singleLine *tmplLine, ++ struct singleLine *prevLine, ++ const char *val, struct configFileInfo *cfi); ++struct singleLine *addLine(struct singleEntry *entry, ++ struct configFileInfo *cfi, ++ enum lineType_e type, char *defaultIndent, ++ const char *val); ++ ++static char *sdupprintf(const char *format, ...) + #ifdef __GNUC__ +- __attribute__ ((format (printf, 1, 2))); ++ __attribute__ ((format(printf, 1, 2))); + #else +- ; ++; + #endif + +-static char * sdupprintf(const char *format, ...) { +- char *buf = NULL; +- char c; +- va_list args; +- size_t size = 0; +- va_start(args, format); +- +- /* XXX requires C99 vsnprintf behavior */ +- size = vsnprintf(&c, 1, format, args) + 1; +- if (size == -1) { +- printf("ERROR: vsnprintf behavior is not C99\n"); +- abort(); +- } +- +- va_end(args); +- va_start(args, format); +- +- buf = malloc(size); +- if (buf == NULL) +- return NULL; +- vsnprintf(buf, size, format, args); +- va_end (args); ++static char *sdupprintf(const char *format, ...) ++{ ++ char *buf = NULL; ++ char c; ++ va_list args; ++ size_t size = 0; ++ va_start(args, format); ++ ++ /* XXX requires C99 vsnprintf behavior */ ++ size = vsnprintf(&c, 1, format, args) + 1; ++ if (size == -1) { ++ printf("ERROR: vsnprintf behavior is not C99\n"); ++ abort(); ++ } + +- return buf; ++ va_end(args); ++ va_start(args, format); ++ ++ buf = malloc(size); ++ if (buf == NULL) ++ return NULL; ++ vsnprintf(buf, size, format, args); ++ va_end(args); ++ ++ return buf; + } + + static enum lineType_e preferredLineType(enum lineType_e type, +- struct configFileInfo *cfi) { +- if (isEfi && cfi == &grub2ConfigType) { +- switch (type) { +- case LT_KERNEL: +- return isEfiOnly ? LT_KERNEL : LT_KERNEL_EFI; +- case LT_INITRD: +- return isEfiOnly ? LT_INITRD : LT_INITRD_EFI; +- default: +- return type; +- } ++ struct configFileInfo *cfi) ++{ ++ if (isEfi && cfi == &grub2ConfigType) { ++ switch (type) { ++ case LT_KERNEL: ++ return isEfiOnly ? LT_KERNEL : LT_KERNEL_EFI; ++ case LT_INITRD: ++ return isEfiOnly ? LT_INITRD : LT_INITRD_EFI; ++ default: ++ return type; ++ } + #if defined(__i386__) || defined(__x86_64__) +- } else if (cfi == &grub2ConfigType) { +- switch (type) { +- case LT_KERNEL: +- return LT_KERNEL_16; +- case LT_INITRD: +- return LT_INITRD_16; +- default: +- return type; +- } ++ } else if (cfi == &grub2ConfigType) { ++ switch (type) { ++ case LT_KERNEL: ++ return LT_KERNEL_16; ++ case LT_INITRD: ++ return LT_INITRD_16; ++ default: ++ return type; ++ } + #endif +- } +- return type; ++ } ++ return type; + } + +-static struct keywordTypes * getKeywordByType(enum lineType_e type, +- struct configFileInfo * cfi) { +- for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) { +- if (kw->type == type) +- return kw; +- } +- return NULL; ++static struct keywordTypes *getKeywordByType(enum lineType_e type, ++ struct configFileInfo *cfi) ++{ ++ for (struct keywordTypes * kw = cfi->keywords; kw->key; kw++) { ++ if (kw->type == type) ++ return kw; ++ } ++ return NULL; + } + +-static char *getKeyByType(enum lineType_e type, struct configFileInfo * cfi) { +- struct keywordTypes *kt = getKeywordByType(type, cfi); +- if (kt) +- return kt->key; +- return "unknown"; ++static char *getKeyByType(enum lineType_e type, struct configFileInfo *cfi) ++{ ++ struct keywordTypes *kt = getKeywordByType(type, cfi); ++ if (kt) ++ return kt->key; ++ return "unknown"; + } + +-static char * getpathbyspec(char *device) { +- if (!blkid) +- blkid_get_cache(&blkid, NULL); ++static char *getpathbyspec(char *device) ++{ ++ if (!blkid) ++ blkid_get_cache(&blkid, NULL); + +- return blkid_get_devname(blkid, device, NULL); ++ return blkid_get_devname(blkid, device, NULL); + } + +-static char * getuuidbydev(char *device) { +- if (!blkid) +- blkid_get_cache(&blkid, NULL); ++static char *getuuidbydev(char *device) ++{ ++ if (!blkid) ++ blkid_get_cache(&blkid, NULL); + +- return blkid_get_tag_value(blkid, "UUID", device); ++ return blkid_get_tag_value(blkid, "UUID", device); + } + +-static enum lineType_e getTypeByKeyword(char * keyword, +- struct configFileInfo * cfi) { +- for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) { +- if (cfi->caseInsensitive) { +- if (!strcasecmp(keyword, kw->key)) +- return kw->type; +- } else { +- if (!strcmp(keyword, kw->key)) +- return kw->type; ++static enum lineType_e getTypeByKeyword(char *keyword, ++ struct configFileInfo *cfi) ++{ ++ for (struct keywordTypes * kw = cfi->keywords; kw->key; kw++) { ++ if (cfi->caseInsensitive) { ++ if (!strcasecmp(keyword, kw->key)) ++ return kw->type; ++ } else { ++ if (!strcmp(keyword, kw->key)) ++ return kw->type; ++ } + } +- } +- return LT_UNKNOWN; ++ return LT_UNKNOWN; + } + +-static struct singleLine * getLineByType(enum lineType_e type, +- struct singleLine * line) { +- dbgPrintf("getLineByType(%d): ", type); +- for (; line; line = line->next) { +- dbgPrintf("%d:%s ", line->type, +- line->numElements ? line->elements[0].item : "(empty)"); +- if (line->type & type) break; +- } +- dbgPrintf(line ? "\n" : " (failed)\n"); +- return line; ++static struct singleLine *getLineByType(enum lineType_e type, ++ struct singleLine *line) ++{ ++ dbgPrintf("getLineByType(%d): ", type); ++ for (; line; line = line->next) { ++ dbgPrintf("%d:%s ", line->type, ++ line->numElements ? line->elements[0]. ++ item : "(empty)"); ++ if (line->type & type) ++ break; ++ } ++ dbgPrintf(line ? "\n" : " (failed)\n"); ++ return line; + } + +-static int isBracketedTitle(struct singleLine * line) { +- if (line->numElements == 1 && *line->elements[0].item == '[') { +- int len = strlen(line->elements[0].item); +- if (*(line->elements[0].item + len - 1) == ']') { +- /* FIXME: this is a hack... */ +- if (strcmp(line->elements[0].item, "[defaultboot]")) { +- return 1; +- } +- } +- } +- return 0; ++static int isBracketedTitle(struct singleLine *line) ++{ ++ if (line->numElements == 1 && *line->elements[0].item == '[') { ++ int len = strlen(line->elements[0].item); ++ if (*(line->elements[0].item + len - 1) == ']') { ++ /* FIXME: this is a hack... */ ++ if (strcmp(line->elements[0].item, "[defaultboot]")) { ++ return 1; ++ } ++ } ++ } ++ return 0; + } + +-static int isEntryStart(struct singleLine * line, +- struct configFileInfo * cfi) { +- return line->type == cfi->entryStart || line->type == LT_OTHER || +- (cfi->titleBracketed && isBracketedTitle(line)); ++static int isEntryStart(struct singleLine *line, struct configFileInfo *cfi) ++{ ++ return line->type == cfi->entryStart || line->type == LT_OTHER || ++ (cfi->titleBracketed && isBracketedTitle(line)); + } + + /* extract the title from within brackets (for zipl) */ +-static char * extractTitle(struct grubConfig *cfg, struct singleLine * line) { +- /* bracketed title... let's extract it */ +- char * title = NULL; +- if (line->type == LT_TITLE) { +- char *tmp = line->elements[cfg->cfi->titlePosition].item; +- if (cfg->cfi->titleBracketed) { +- tmp++; +- title = strdup(tmp); +- *(title + strlen(title) - 1) = '\0'; +- } else { +- title = strdup(tmp); +- } +- } else if (line->type == LT_MENUENTRY) +- title = strdup(line->elements[1].item); +- else +- return NULL; +- return title; ++static char *extractTitle(struct grubConfig *cfg, struct singleLine *line) ++{ ++ /* bracketed title... let's extract it */ ++ char *title = NULL; ++ if (line->type == LT_TITLE) { ++ char *tmp = line->elements[cfg->cfi->titlePosition].item; ++ if (cfg->cfi->titleBracketed) { ++ tmp++; ++ title = strdup(tmp); ++ *(title + strlen(title) - 1) = '\0'; ++ } else { ++ title = strdup(tmp); ++ } ++ } else if (line->type == LT_MENUENTRY) ++ title = strdup(line->elements[1].item); ++ else ++ return NULL; ++ return title; + } + +-static int readFile(int fd, char ** bufPtr) { +- int alloced = 0, size = 0, i = 0; +- char * buf = NULL; ++static int readFile(int fd, char **bufPtr) ++{ ++ int alloced = 0, size = 0, i = 0; ++ char *buf = NULL; ++ ++ do { ++ size += i; ++ if ((size + 1024) > alloced) { ++ alloced += 4096; ++ buf = realloc(buf, alloced + 1); ++ } ++ } while ((i = read(fd, buf + size, 1024)) > 0); + +- do { +- size += i; +- if ((size + 1024) > alloced) { +- alloced += 4096; +- buf = realloc(buf, alloced + 1); ++ if (i < 0) { ++ fprintf(stderr, _("error reading input: %s\n"), ++ strerror(errno)); ++ free(buf); ++ return 1; + } +- } while ((i = read(fd, buf + size, 1024)) > 0); +- +- if (i < 0) { +- fprintf(stderr, _("error reading input: %s\n"), strerror(errno)); +- free(buf); +- return 1; +- } + +- buf = realloc(buf, size + 2); +- if (size == 0) +- buf[size++] = '\n'; +- else +- if (buf[size - 1] != '\n') +- buf[size++] = '\n'; +- buf[size] = '\0'; ++ buf = realloc(buf, size + 2); ++ if (size == 0) ++ buf[size++] = '\n'; ++ else if (buf[size - 1] != '\n') ++ buf[size++] = '\n'; ++ buf[size] = '\0'; + +- *bufPtr = buf; ++ *bufPtr = buf; + +- return 0; ++ return 0; + } + +-static void lineInit(struct singleLine * line) { +- line->indent = NULL; +- line->elements = NULL; +- line->numElements = 0; +- line->next = NULL; ++static void lineInit(struct singleLine *line) ++{ ++ line->indent = NULL; ++ line->elements = NULL; ++ line->numElements = 0; ++ line->next = NULL; + } + +-struct singleLine * lineDup(struct singleLine * line) { +- struct singleLine * newLine = malloc(sizeof(*newLine)); +- +- newLine->indent = strdup(line->indent); +- newLine->next = NULL; +- newLine->type = line->type; +- newLine->numElements = line->numElements; +- newLine->elements = malloc(sizeof(*newLine->elements) * +- newLine->numElements); +- +- for (int i = 0; i < newLine->numElements; i++) { +- newLine->elements[i].indent = strdup(line->elements[i].indent); +- newLine->elements[i].item = strdup(line->elements[i].item); +- } ++struct singleLine *lineDup(struct singleLine *line) ++{ ++ struct singleLine *newLine = malloc(sizeof(*newLine)); ++ ++ newLine->indent = strdup(line->indent); ++ newLine->next = NULL; ++ newLine->type = line->type; ++ newLine->numElements = line->numElements; ++ newLine->elements = malloc(sizeof(*newLine->elements) * ++ newLine->numElements); ++ ++ for (int i = 0; i < newLine->numElements; i++) { ++ newLine->elements[i].indent = strdup(line->elements[i].indent); ++ newLine->elements[i].item = strdup(line->elements[i].item); ++ } + +- return newLine; ++ return newLine; + } + +-static void lineFree(struct singleLine * line) { +- if (line->indent) free(line->indent); ++static void lineFree(struct singleLine *line) ++{ ++ if (line->indent) ++ free(line->indent); + +- for (int i = 0; i < line->numElements; i++) { +- free(line->elements[i].item); +- free(line->elements[i].indent); +- } ++ for (int i = 0; i < line->numElements; i++) { ++ free(line->elements[i].item); ++ free(line->elements[i].indent); ++ } + +- if (line->elements) free(line->elements); +- lineInit(line); ++ if (line->elements) ++ free(line->elements); ++ lineInit(line); + } + +-static int lineWrite(FILE * out, struct singleLine * line, +- struct configFileInfo * cfi) { +- if (fprintf(out, "%s", line->indent) == -1) return -1; +- +- for (int i = 0; i < line->numElements; i++) { +- /* Need to handle this, because we strip the quotes from +- * menuentry when read it. */ +- if (line->type == LT_MENUENTRY && i == 1) { +- if(!isquote(*line->elements[i].item)) { +- int substring = 0; +- /* If the line contains nested quotes, we did not strip +- * the "interna" quotes and we must use the right quotes +- * again when writing the updated file. */ +- for (int j = i; j < line->numElements; j++) { +- if (strchr(line->elements[i].item, '\'') != NULL) { +- substring = 1; +- fprintf(out, "\"%s\"", line->elements[i].item); +- break; +- } +- } +- if (!substring) +- fprintf(out, "\'%s\'", line->elements[i].item); +- } else { +- fprintf(out, "%s", line->elements[i].item); +- } +- fprintf(out, "%s", line->elements[i].indent); ++static int lineWrite(FILE * out, struct singleLine *line, ++ struct configFileInfo *cfi) ++{ ++ if (fprintf(out, "%s", line->indent) == -1) ++ return -1; ++ ++ for (int i = 0; i < line->numElements; i++) { ++ /* Need to handle this, because we strip the quotes from ++ * menuentry when read it. */ ++ if (line->type == LT_MENUENTRY && i == 1) { ++ if (!isquote(*line->elements[i].item)) { ++ int substring = 0; ++ /* If the line contains nested quotes, we did not strip ++ * the "interna" quotes and we must use the right quotes ++ * again when writing the updated file. */ ++ for (int j = i; j < line->numElements; j++) { ++ if (strchr(line->elements[i].item, '\'') ++ != NULL) { ++ substring = 1; ++ fprintf(out, "\"%s\"", ++ line->elements[i].item); ++ break; ++ } ++ } ++ if (!substring) ++ fprintf(out, "\'%s\'", ++ line->elements[i].item); ++ } else { ++ fprintf(out, "%s", line->elements[i].item); ++ } ++ fprintf(out, "%s", line->elements[i].indent); + +- continue; +- } ++ continue; ++ } + +- if (i == 1 && line->type == LT_KERNELARGS && cfi->argsInQuotes) +- if (fputc('"', out) == EOF) return -1; ++ if (i == 1 && line->type == LT_KERNELARGS && cfi->argsInQuotes) ++ if (fputc('"', out) == EOF) ++ return -1; + +- if (fprintf(out, "%s", line->elements[i].item) == -1) return -1; +- if (i < line->numElements - 1) +- if (fprintf(out, "%s", line->elements[i].indent) == -1) return -1; +- } ++ if (fprintf(out, "%s", line->elements[i].item) == -1) ++ return -1; ++ if (i < line->numElements - 1) ++ if (fprintf(out, "%s", line->elements[i].indent) == -1) ++ return -1; ++ } + +- if (line->type == LT_KERNELARGS && cfi->argsInQuotes) +- if (fputc('"', out) == EOF) return -1; ++ if (line->type == LT_KERNELARGS && cfi->argsInQuotes) ++ if (fputc('"', out) == EOF) ++ return -1; + +- if (fprintf(out, "\n") == -1) return -1; ++ if (fprintf(out, "\n") == -1) ++ return -1; + +- return 0; ++ return 0; + } + + /* we've guaranteed that the buffer ends w/ \n\0 */ +-static int getNextLine(char ** bufPtr, struct singleLine * line, +- struct configFileInfo * cfi) { +- char * end; +- char * start = *bufPtr; +- char * chptr; +- int elementsAlloced = 0; +- struct lineElement * element; +- int first = 1; +- +- lineFree(line); ++static int getNextLine(char **bufPtr, struct singleLine *line, ++ struct configFileInfo *cfi) ++{ ++ char *end; ++ char *start = *bufPtr; ++ char *chptr; ++ int elementsAlloced = 0; ++ struct lineElement *element; ++ int first = 1; + +- end = strchr(start, '\n'); +- *end = '\0'; +- *bufPtr = end + 1; ++ lineFree(line); + +- for (chptr = start; *chptr && isspace(*chptr); chptr++) ; ++ end = strchr(start, '\n'); ++ *end = '\0'; ++ *bufPtr = end + 1; + +- line->indent = strndup(start, chptr - start); +- start = chptr; ++ for (chptr = start; *chptr && isspace(*chptr); chptr++) ; + +- while (start < end) { +- /* we know !isspace(*start) */ ++ line->indent = strndup(start, chptr - start); ++ start = chptr; + +- if (elementsAlloced == line->numElements) { +- elementsAlloced += 5; +- line->elements = realloc(line->elements, +- sizeof(*line->elements) * elementsAlloced); +- } ++ while (start < end) { ++ /* we know !isspace(*start) */ + +- element = line->elements + line->numElements; ++ if (elementsAlloced == line->numElements) { ++ elementsAlloced += 5; ++ line->elements = realloc(line->elements, ++ sizeof(*line->elements) * ++ elementsAlloced); ++ } + +- chptr = start; +- while (*chptr && !isspace(*chptr)) { +- if (first && *chptr == '=') break; +- chptr++; +- } +- element->item = strndup(start, chptr - start); +- start = chptr; ++ element = line->elements + line->numElements; + +- /* lilo actually accepts the pathological case of append = " foo " */ +- if (*start == '=') +- chptr = start + 1; +- else +- chptr = start; ++ chptr = start; ++ while (*chptr && !isspace(*chptr)) { ++ if (first && *chptr == '=') ++ break; ++ chptr++; ++ } ++ element->item = strndup(start, chptr - start); ++ start = chptr; + +- do { +- for (; *chptr && isspace(*chptr); chptr++); +- if (*chptr == '=') +- chptr = chptr + 1; +- } while (isspace(*chptr)); ++ /* lilo actually accepts the pathological case of append = " foo " */ ++ if (*start == '=') ++ chptr = start + 1; ++ else ++ chptr = start; + +- element->indent = strndup(start, chptr - start); +- start = chptr; ++ do { ++ for (; *chptr && isspace(*chptr); chptr++) ; ++ if (*chptr == '=') ++ chptr = chptr + 1; ++ } while (isspace(*chptr)); + +- line->numElements++; +- first = 0; +- } +- +- if (!line->numElements) +- line->type = LT_WHITESPACE; +- else { +- line->type = getTypeByKeyword(line->elements[0].item, cfi); +- if (line->type == LT_UNKNOWN) { +- /* zipl does [title] instead of something reasonable like all +- * the other boot loaders. kind of ugly */ +- if (cfi->titleBracketed && isBracketedTitle(line)) { +- line->type = LT_TITLE; +- } +- +- /* this is awkward, but we need to be able to handle keywords +- that begin with a # (specifically for #boot in grub.conf), +- but still make comments lines with no elements (everything +- stored in the indent */ +- if (*line->elements[0].item == '#') { +- char * fullLine; +- int len; +- +- len = strlen(line->indent); +- for (int i = 0; i < line->numElements; i++) +- len += strlen(line->elements[i].item) + +- strlen(line->elements[i].indent); +- +- fullLine = malloc(len + 1); +- strcpy(fullLine, line->indent); +- free(line->indent); +- line->indent = fullLine; ++ element->indent = strndup(start, chptr - start); ++ start = chptr; + +- for (int i = 0; i < line->numElements; i++) { +- strcat(fullLine, line->elements[i].item); +- strcat(fullLine, line->elements[i].indent); +- free(line->elements[i].item); +- free(line->elements[i].indent); +- } ++ line->numElements++; ++ first = 0; ++ } + ++ if (!line->numElements) + line->type = LT_WHITESPACE; +- line->numElements = 0; +- } +- } else { +- struct keywordTypes *kw; ++ else { ++ line->type = getTypeByKeyword(line->elements[0].item, cfi); ++ if (line->type == LT_UNKNOWN) { ++ /* zipl does [title] instead of something reasonable like all ++ * the other boot loaders. kind of ugly */ ++ if (cfi->titleBracketed && isBracketedTitle(line)) { ++ line->type = LT_TITLE; ++ } + +- kw = getKeywordByType(line->type, cfi); ++ /* this is awkward, but we need to be able to handle keywords ++ that begin with a # (specifically for #boot in grub.conf), ++ but still make comments lines with no elements (everything ++ stored in the indent */ ++ if (*line->elements[0].item == '#') { ++ char *fullLine; ++ int len; ++ ++ len = strlen(line->indent); ++ for (int i = 0; i < line->numElements; i++) ++ len += strlen(line->elements[i].item) + ++ strlen(line->elements[i].indent); ++ ++ fullLine = malloc(len + 1); ++ strcpy(fullLine, line->indent); ++ free(line->indent); ++ line->indent = fullLine; ++ ++ for (int i = 0; i < line->numElements; i++) { ++ strcat(fullLine, ++ line->elements[i].item); ++ strcat(fullLine, ++ line->elements[i].indent); ++ free(line->elements[i].item); ++ free(line->elements[i].indent); ++ } + +- /* space isn't the only separator, we need to split +- * elements up more +- */ +- if (!isspace(kw->separatorChar)) { +- char indent[2] = ""; +- indent[0] = kw->separatorChar; +- for (int i = 1; i < line->numElements; i++) { +- char *p; +- int numNewElements; +- +- numNewElements = 0; +- p = line->elements[i].item; +- while (*p != '\0') { +- if (*p == kw->separatorChar) +- numNewElements++; +- p++; +- } +- if (line->numElements + numNewElements >= elementsAlloced) { +- elementsAlloced += numNewElements + 5; +- line->elements = realloc(line->elements, +- sizeof(*line->elements) * elementsAlloced); ++ line->type = LT_WHITESPACE; ++ line->numElements = 0; + } ++ } else { ++ struct keywordTypes *kw; + +- for (int j = line->numElements; j > i; j--) { +- line->elements[j + numNewElements] = line->elements[j]; +- } +- line->numElements += numNewElements; ++ kw = getKeywordByType(line->type, cfi); + +- p = line->elements[i].item; +- while (*p != '\0') { ++ /* space isn't the only separator, we need to split ++ * elements up more ++ */ ++ if (!isspace(kw->separatorChar)) { ++ char indent[2] = ""; ++ indent[0] = kw->separatorChar; ++ for (int i = 1; i < line->numElements; i++) { ++ char *p; ++ int numNewElements; ++ ++ numNewElements = 0; ++ p = line->elements[i].item; ++ while (*p != '\0') { ++ if (*p == kw->separatorChar) ++ numNewElements++; ++ p++; ++ } ++ if (line->numElements + ++ numNewElements >= elementsAlloced) { ++ elementsAlloced += ++ numNewElements + 5; ++ line->elements = ++ realloc(line->elements, ++ sizeof(*line-> ++ elements) * ++ elementsAlloced); ++ } + +- while (*p != kw->separatorChar && *p != '\0') p++; +- if (*p == '\0') { +- break; ++ for (int j = line->numElements; j > i; ++ j--) { ++ line->elements[j + ++ numNewElements] = ++ line->elements[j]; ++ } ++ line->numElements += numNewElements; ++ ++ p = line->elements[i].item; ++ while (*p != '\0') { ++ ++ while (*p != kw->separatorChar ++ && *p != '\0') ++ p++; ++ if (*p == '\0') { ++ break; ++ } ++ ++ line->elements[i + 1].indent = ++ line->elements[i].indent; ++ line->elements[i].indent = ++ strdup(indent); ++ *p++ = '\0'; ++ i++; ++ line->elements[i].item = ++ strdup(p); ++ } + } +- +- line->elements[i + 1].indent = line->elements[i].indent; +- line->elements[i].indent = strdup(indent); +- *p++ = '\0'; +- i++; +- line->elements[i].item = strdup(p); + } +- } + } + } +- } + +- return 0; ++ return 0; + } + + static int isnumber(const char *s) + { +- int i; +- for (i = 0; s[i] != '\0'; i++) +- if (s[i] < '0' || s[i] > '9') +- return 0; +- return i; ++ int i; ++ for (i = 0; s[i] != '\0'; i++) ++ if (s[i] < '0' || s[i] > '9') ++ return 0; ++ return i; + } + +-static struct grubConfig * readConfig(const char * inName, +- struct configFileInfo * cfi) { +- int in; +- char * incoming = NULL, * head; +- int rc; +- int sawEntry = 0; +- int movedLine = 0; +- struct grubConfig * cfg; +- struct singleLine * last = NULL, * line, * defaultLine = NULL; +- char * end; +- struct singleEntry * entry = NULL; +- int len; +- char * buf; +- +- if (inName == NULL) { +- printf("Could not find bootloader configuration\n"); +- exit(1); +- } else if (!strcmp(inName, "-")) { +- in = 0; +- } else { +- if ((in = open(inName, O_RDONLY)) < 0) { +- fprintf(stderr, _("error opening %s for read: %s\n"), +- inName, strerror(errno)); +- return NULL; +- } +- } +- +- rc = readFile(in, &incoming); +- close(in); +- if (rc) return NULL; +- +- head = incoming; +- cfg = malloc(sizeof(*cfg)); +- cfg->primaryIndent = strdup(""); +- cfg->secondaryIndent = strdup("\t"); +- cfg->flags = GRUB_CONFIG_NO_DEFAULT; +- cfg->cfi = cfi; +- cfg->theLines = NULL; +- cfg->entries = NULL; +- cfg->fallbackImage = 0; +- +- /* copy everything we have */ +- while (*head) { +- line = malloc(sizeof(*line)); +- lineInit(line); +- +- if (getNextLine(&head, line, cfi)) { +- free(line); +- /* XXX memory leak of everything in cfg */ +- return NULL; +- } +- +- if (!sawEntry && line->numElements) { +- free(cfg->primaryIndent); +- cfg->primaryIndent = strdup(line->indent); +- } else if (line->numElements) { +- free(cfg->secondaryIndent); +- cfg->secondaryIndent = strdup(line->indent); ++static struct grubConfig *readConfig(const char *inName, ++ struct configFileInfo *cfi) ++{ ++ int in; ++ char *incoming = NULL, *head; ++ int rc; ++ int sawEntry = 0; ++ int movedLine = 0; ++ struct grubConfig *cfg; ++ struct singleLine *last = NULL, *line, *defaultLine = NULL; ++ char *end; ++ struct singleEntry *entry = NULL; ++ int len; ++ char *buf; ++ ++ if (inName == NULL) { ++ printf("Could not find bootloader configuration\n"); ++ exit(1); ++ } else if (!strcmp(inName, "-")) { ++ in = 0; ++ } else { ++ if ((in = open(inName, O_RDONLY)) < 0) { ++ fprintf(stderr, _("error opening %s for read: %s\n"), ++ inName, strerror(errno)); ++ return NULL; ++ } + } + +- if (isEntryStart(line, cfi) || (cfg->entries && !sawEntry)) { +- sawEntry = 1; +- if (!entry) { +- cfg->entries = malloc(sizeof(*entry)); +- entry = cfg->entries; +- } else { +- entry->next = malloc(sizeof(*entry)); +- entry = entry->next; +- } +- +- entry->skip = 0; +- entry->multiboot = 0; +- entry->lines = NULL; +- entry->next = NULL; +- } +- +- if (line->type == LT_SET_VARIABLE) { +- dbgPrintf("found 'set' command (%d elements): ", line->numElements); +- dbgPrintf("%s", line->indent); +- for (int i = 0; i < line->numElements; i++) +- dbgPrintf("\"%s\"%s", line->elements[i].item, line->elements[i].indent); +- dbgPrintf("\n"); +- struct keywordTypes *kwType = getKeywordByType(LT_DEFAULT, cfi); +- if (kwType && line->numElements == 3 && +- !strcmp(line->elements[1].item, kwType->key) && +- !is_special_grub2_variable(line->elements[2].item)) { +- dbgPrintf("Line sets default config\n"); +- cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT; +- defaultLine = line; +- } +- +- } else if (iskernel(line->type)) { +- /* if by some freak chance this is multiboot and the "module" +- * lines came earlier in the template, make sure to use LT_HYPER +- * instead of LT_KERNEL now +- */ +- if (entry && entry->multiboot) +- line->type = LT_HYPER; +- +- } else if (line->type == LT_MBMODULE) { +- /* go back and fix the LT_KERNEL line to indicate LT_HYPER +- * instead, now that we know this is a multiboot entry. +- * This only applies to grub, but that's the only place we +- * should find LT_MBMODULE lines anyway. +- */ +- for (struct singleLine *l = entry->lines; l; l = l->next) { +- if (l->type == LT_HYPER) +- break; +- else if (iskernel(l->type)) { +- l->type = LT_HYPER; +- break; ++ rc = readFile(in, &incoming); ++ close(in); ++ if (rc) ++ return NULL; ++ ++ head = incoming; ++ cfg = malloc(sizeof(*cfg)); ++ cfg->primaryIndent = strdup(""); ++ cfg->secondaryIndent = strdup("\t"); ++ cfg->flags = GRUB_CONFIG_NO_DEFAULT; ++ cfg->cfi = cfi; ++ cfg->theLines = NULL; ++ cfg->entries = NULL; ++ cfg->fallbackImage = 0; ++ ++ /* copy everything we have */ ++ while (*head) { ++ line = malloc(sizeof(*line)); ++ lineInit(line); ++ ++ if (getNextLine(&head, line, cfi)) { ++ free(line); ++ /* XXX memory leak of everything in cfg */ ++ return NULL; + } +- } +- entry->multiboot = 1; +- +- } else if (line->type == LT_HYPER) { +- entry->multiboot = 1; +- +- } else if (line->type == LT_FALLBACK && line->numElements == 2) { +- cfg->fallbackImage = strtol(line->elements[1].item, &end, 10); +- if (*end) cfg->fallbackImage = -1; +- +- } else if ((line->type == LT_DEFAULT && cfi->defaultIsUnquoted) || +- (line->type == LT_TITLE && line->numElements > 1)) { +- /* make the title/default a single argument (undoing our parsing) */ +- len = 0; +- for (int i = 1; i < line->numElements; i++) { +- len += strlen(line->elements[i].item); +- len += strlen(line->elements[i].indent); +- } +- buf = malloc(len + 1); +- *buf = '\0'; +- +- for (int i = 1; i < line->numElements; i++) { +- strcat(buf, line->elements[i].item); +- free(line->elements[i].item); + +- if ((i + 1) != line->numElements) { +- strcat(buf, line->elements[i].indent); +- free(line->elements[i].indent); +- } +- } +- +- line->elements[1].indent = +- line->elements[line->numElements - 1].indent; +- line->elements[1].item = buf; +- line->numElements = 2; +- } else if (line->type == LT_MENUENTRY && line->numElements > 3) { +- /* let --remove-kernel="TITLE=what" work */ +- len = 0; +- char *extras; +- char *title; +- /* initially unseen value */ +- char quote_char = '\0'; +- +- for (int i = 1; i < line->numElements; i++) { +- len += strlen(line->elements[i].item); +- len += strlen(line->elements[i].indent); +- } +- buf = malloc(len + 1); +- *buf = '\0'; +- +- /* allocate mem for extra flags. */ +- extras = malloc(len + 1); +- *extras = '\0'; +- +- /* get title. */ +- for (int i = 0; i < line->numElements; i++) { +- if (!strcmp(line->elements[i].item, "menuentry")) +- continue; +- if (isquote(*line->elements[i].item) && quote_char == '\0') { +- /* ensure we properly pair off quotes */ +- quote_char = *line->elements[i].item; +- title = line->elements[i].item + 1; +- } else { +- title = line->elements[i].item; ++ if (!sawEntry && line->numElements) { ++ free(cfg->primaryIndent); ++ cfg->primaryIndent = strdup(line->indent); ++ } else if (line->numElements) { ++ free(cfg->secondaryIndent); ++ cfg->secondaryIndent = strdup(line->indent); + } + +- len = strlen(title); +- if (title[len-1] == quote_char) { +- strncat(buf, title,len-1); +- break; +- } else { +- strcat(buf, title); +- strcat(buf, line->elements[i].indent); +- } +- } +- +- /* get extras */ +- int count = 0; +- quote_char = '\0'; +- for (int i = 0; i < line->numElements; i++) { +- if (count >= 2) { +- strcat(extras, line->elements[i].item); +- strcat(extras, line->elements[i].indent); ++ if (isEntryStart(line, cfi) || (cfg->entries && !sawEntry)) { ++ sawEntry = 1; ++ if (!entry) { ++ cfg->entries = malloc(sizeof(*entry)); ++ entry = cfg->entries; ++ } else { ++ entry->next = malloc(sizeof(*entry)); ++ entry = entry->next; ++ } ++ ++ entry->skip = 0; ++ entry->multiboot = 0; ++ entry->lines = NULL; ++ entry->next = NULL; + } + +- if (!strcmp(line->elements[i].item, "menuentry")) +- continue; ++ if (line->type == LT_SET_VARIABLE) { ++ dbgPrintf("found 'set' command (%d elements): ", ++ line->numElements); ++ dbgPrintf("%s", line->indent); ++ for (int i = 0; i < line->numElements; i++) ++ dbgPrintf("\"%s\"%s", line->elements[i].item, ++ line->elements[i].indent); ++ dbgPrintf("\n"); ++ struct keywordTypes *kwType = ++ getKeywordByType(LT_DEFAULT, cfi); ++ if (kwType && line->numElements == 3 ++ && !strcmp(line->elements[1].item, kwType->key) ++ && !is_special_grub2_variable(line->elements[2]. ++ item)) { ++ dbgPrintf("Line sets default config\n"); ++ cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT; ++ defaultLine = line; ++ } ++ ++ } else if (iskernel(line->type)) { ++ /* if by some freak chance this is multiboot and the "module" ++ * lines came earlier in the template, make sure to use LT_HYPER ++ * instead of LT_KERNEL now ++ */ ++ if (entry && entry->multiboot) ++ line->type = LT_HYPER; ++ ++ } else if (line->type == LT_MBMODULE) { ++ /* go back and fix the LT_KERNEL line to indicate LT_HYPER ++ * instead, now that we know this is a multiboot entry. ++ * This only applies to grub, but that's the only place we ++ * should find LT_MBMODULE lines anyway. ++ */ ++ for (struct singleLine * l = entry->lines; l; ++ l = l->next) { ++ if (l->type == LT_HYPER) ++ break; ++ else if (iskernel(l->type)) { ++ l->type = LT_HYPER; ++ break; ++ } ++ } ++ entry->multiboot = 1; ++ ++ } else if (line->type == LT_HYPER) { ++ entry->multiboot = 1; ++ ++ } else if (line->type == LT_FALLBACK && line->numElements == 2) { ++ cfg->fallbackImage = ++ strtol(line->elements[1].item, &end, 10); ++ if (*end) ++ cfg->fallbackImage = -1; ++ ++ } else if ((line->type == LT_DEFAULT && cfi->defaultIsUnquoted) ++ || (line->type == LT_TITLE ++ && line->numElements > 1)) { ++ /* make the title/default a single argument (undoing our parsing) */ ++ len = 0; ++ for (int i = 1; i < line->numElements; i++) { ++ len += strlen(line->elements[i].item); ++ len += strlen(line->elements[i].indent); ++ } ++ buf = malloc(len + 1); ++ *buf = '\0'; ++ ++ for (int i = 1; i < line->numElements; i++) { ++ strcat(buf, line->elements[i].item); ++ free(line->elements[i].item); ++ ++ if ((i + 1) != line->numElements) { ++ strcat(buf, line->elements[i].indent); ++ free(line->elements[i].indent); ++ } ++ } ++ ++ line->elements[1].indent = ++ line->elements[line->numElements - 1].indent; ++ line->elements[1].item = buf; ++ line->numElements = 2; ++ } else if (line->type == LT_MENUENTRY && line->numElements > 3) { ++ /* let --remove-kernel="TITLE=what" work */ ++ len = 0; ++ char *extras; ++ char *title; ++ /* initially unseen value */ ++ char quote_char = '\0'; ++ ++ for (int i = 1; i < line->numElements; i++) { ++ len += strlen(line->elements[i].item); ++ len += strlen(line->elements[i].indent); ++ } ++ buf = malloc(len + 1); ++ *buf = '\0'; ++ ++ /* allocate mem for extra flags. */ ++ extras = malloc(len + 1); ++ *extras = '\0'; ++ ++ /* get title. */ ++ for (int i = 0; i < line->numElements; i++) { ++ if (!strcmp ++ (line->elements[i].item, "menuentry")) ++ continue; ++ if (isquote(*line->elements[i].item) ++ && quote_char == '\0') { ++ /* ensure we properly pair off quotes */ ++ quote_char = *line->elements[i].item; ++ title = line->elements[i].item + 1; ++ } else { ++ title = line->elements[i].item; ++ } ++ ++ len = strlen(title); ++ if (title[len - 1] == quote_char) { ++ strncat(buf, title, len - 1); ++ break; ++ } else { ++ strcat(buf, title); ++ strcat(buf, line->elements[i].indent); ++ } ++ } ++ ++ /* get extras */ ++ int count = 0; ++ quote_char = '\0'; ++ for (int i = 0; i < line->numElements; i++) { ++ if (count >= 2) { ++ strcat(extras, line->elements[i].item); ++ strcat(extras, ++ line->elements[i].indent); ++ } ++ ++ if (!strcmp ++ (line->elements[i].item, "menuentry")) ++ continue; + +- /* count ' or ", there should be two in menuentry line. */ +- if (isquote(*line->elements[i].item) && quote_char == '\0') { +- /* ensure we properly pair off quotes */ +- quote_char = *line->elements[i].item; +- count++; ++ /* count ' or ", there should be two in menuentry line. */ ++ if (isquote(*line->elements[i].item) ++ && quote_char == '\0') { ++ /* ensure we properly pair off quotes */ ++ quote_char = *line->elements[i].item; ++ count++; ++ } ++ ++ len = strlen(line->elements[i].item); ++ ++ if (line->elements[i].item[len - 1] == ++ quote_char) ++ count++; ++ ++ /* ok, we get the final ' or ", others are extras. */ ++ } ++ line->elements[1].indent = ++ line->elements[line->numElements - 2].indent; ++ line->elements[1].item = buf; ++ line->elements[2].indent = ++ line->elements[line->numElements - 2].indent; ++ line->elements[2].item = extras; ++ line->numElements = 3; ++ } else if (line->type == LT_KERNELARGS && cfi->argsInQuotes) { ++ /* Strip off any " which may be present; they'll be put back ++ on write. This is one of the few (the only?) places that grubby ++ canonicalizes the output */ ++ ++ if (line->numElements >= 2) { ++ int last, len; ++ ++ if (isquote(*line->elements[1].item)) ++ memmove(line->elements[1].item, ++ line->elements[1].item + 1, ++ strlen(line->elements[1].item + ++ 1) + 1); ++ ++ last = line->numElements - 1; ++ len = strlen(line->elements[last].item) - 1; ++ if (isquote(line->elements[last].item[len])) ++ line->elements[last].item[len] = '\0'; ++ } + } + +- len = strlen(line->elements[i].item); +- +- if (line->elements[i].item[len -1] == quote_char) +- count++; +- +- /* ok, we get the final ' or ", others are extras. */ +- } +- line->elements[1].indent = +- line->elements[line->numElements - 2].indent; +- line->elements[1].item = buf; +- line->elements[2].indent = +- line->elements[line->numElements - 2].indent; +- line->elements[2].item = extras; +- line->numElements = 3; +- } else if (line->type == LT_KERNELARGS && cfi->argsInQuotes) { +- /* Strip off any " which may be present; they'll be put back +- on write. This is one of the few (the only?) places that grubby +- canonicalizes the output */ +- +- if (line->numElements >= 2) { +- int last, len; +- +- if (isquote(*line->elements[1].item)) +- memmove(line->elements[1].item, line->elements[1].item + 1, +- strlen(line->elements[1].item + 1) + 1); +- +- last = line->numElements - 1; +- len = strlen(line->elements[last].item) - 1; +- if (isquote(line->elements[last].item[len])) +- line->elements[last].item[len] = '\0'; +- } +- } +- +- if (line->type == LT_DEFAULT && line->numElements == 2) { +- cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT; +- defaultLine = line; +- } +- +- /* If we find a generic config option which should live at the +- top of the file, move it there. Old versions of grubby were +- probably responsible for putting new images in the wrong +- place in front of it anyway. */ +- if (sawEntry && line->type == LT_GENERIC) { +- struct singleLine **l = &cfg->theLines; +- struct singleLine **last_nonws = &cfg->theLines; +- while (*l) { +- if ((*l)->type != LT_WHITESPACE) +- last_nonws = &((*l)->next); +- l = &((*l)->next); ++ if (line->type == LT_DEFAULT && line->numElements == 2) { ++ cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT; ++ defaultLine = line; + } +- line->next = *last_nonws; +- *last_nonws = line; +- movedLine = 1; +- continue; /* without setting 'last' */ +- } + +- /* If a second line of whitespace happens after a generic option +- which was moved, drop it. */ +- if (movedLine && line->type == LT_WHITESPACE && last->type == LT_WHITESPACE) { +- lineFree(line); +- free(line); ++ /* If we find a generic config option which should live at the ++ top of the file, move it there. Old versions of grubby were ++ probably responsible for putting new images in the wrong ++ place in front of it anyway. */ ++ if (sawEntry && line->type == LT_GENERIC) { ++ struct singleLine **l = &cfg->theLines; ++ struct singleLine **last_nonws = &cfg->theLines; ++ while (*l) { ++ if ((*l)->type != LT_WHITESPACE) ++ last_nonws = &((*l)->next); ++ l = &((*l)->next); ++ } ++ line->next = *last_nonws; ++ *last_nonws = line; ++ movedLine = 1; ++ continue; /* without setting 'last' */ ++ } ++ ++ /* If a second line of whitespace happens after a generic option ++ which was moved, drop it. */ ++ if (movedLine && line->type == LT_WHITESPACE ++ && last->type == LT_WHITESPACE) { ++ lineFree(line); ++ free(line); ++ movedLine = 0; ++ continue; ++ } + movedLine = 0; +- continue; +- } +- movedLine = 0; + +- if (sawEntry) { +- if (!entry->lines) +- entry->lines = line; +- else +- last->next = line; +- dbgPrintf("readConfig added %s to %p\n", getKeyByType(line->type, cfi), entry); ++ if (sawEntry) { ++ if (!entry->lines) ++ entry->lines = line; ++ else ++ last->next = line; ++ dbgPrintf("readConfig added %s to %p\n", ++ getKeyByType(line->type, cfi), entry); ++ ++ /* we could have seen this outside of an entry... if so, we ++ * ignore it like any other line we don't grok */ ++ if (line->type == LT_ENTRY_END && sawEntry) ++ sawEntry = 0; ++ } else { ++ if (!cfg->theLines) ++ cfg->theLines = line; ++ else ++ last->next = line; ++ dbgPrintf("readConfig added %s to cfg\n", ++ getKeyByType(line->type, cfi)); ++ } + +- /* we could have seen this outside of an entry... if so, we +- * ignore it like any other line we don't grok */ +- if (line->type == LT_ENTRY_END && sawEntry) +- sawEntry = 0; +- } else { +- if (!cfg->theLines) +- cfg->theLines = line; +- else +- last->next = line; +- dbgPrintf("readConfig added %s to cfg\n", getKeyByType(line->type, cfi)); ++ last = line; + } + +- last = line; +- } +- +- free(incoming); ++ free(incoming); ++ ++ dbgPrintf("defaultLine is %s\n", defaultLine ? "set" : "unset"); ++ if (defaultLine) { ++ if (defaultLine->numElements > 2 && ++ cfi->defaultSupportSaved && ++ !strncmp(defaultLine->elements[2].item, ++ "\"${saved_entry}\"", 16)) { ++ cfg->cfi->defaultIsSaved = 1; ++ cfg->defaultImage = DEFAULT_SAVED_GRUB2; ++ if (cfg->cfi->getEnv) { ++ char *defTitle = ++ cfi->getEnv(cfg->cfi, "saved_entry"); ++ if (defTitle) { ++ int index = 0; ++ if (isnumber(defTitle)) { ++ index = atoi(defTitle); ++ entry = ++ findEntryByIndex(cfg, ++ index); ++ } else { ++ entry = ++ findEntryByTitle(cfg, ++ defTitle, ++ &index); ++ } ++ if (entry) ++ cfg->defaultImage = index; ++ } ++ } ++ } else if (cfi->defaultIsVariable) { ++ char *value = defaultLine->elements[2].item; ++ while (*value && (*value == '"' || *value == '\'' || ++ *value == ' ' || *value == '\t')) ++ value++; ++ cfg->defaultImage = strtol(value, &end, 10); ++ while (*end && (*end == '"' || *end == '\'' || ++ *end == ' ' || *end == '\t')) ++ end++; ++ if (*end) ++ cfg->defaultImage = -1; ++ } else if (cfi->defaultSupportSaved && ++ !strncmp(defaultLine->elements[1].item, "saved", ++ 5)) { ++ cfg->defaultImage = DEFAULT_SAVED; ++ } else if (cfi->defaultIsIndex) { ++ cfg->defaultImage = ++ strtol(defaultLine->elements[1].item, &end, 10); ++ if (*end) ++ cfg->defaultImage = -1; ++ } else if (defaultLine->numElements >= 2) { ++ int i = 0; ++ while ((entry = findEntryByIndex(cfg, i))) { ++ for (line = entry->lines; line; ++ line = line->next) ++ if (line->type == LT_TITLE) ++ break; ++ ++ if (!cfi->titleBracketed) { ++ if (line && (line->numElements >= 2) && ++ !strcmp(defaultLine->elements[1]. ++ item, ++ line->elements[1].item)) ++ break; ++ } else if (line) { ++ if (!strcmp ++ (defaultLine->elements[1].item, ++ extractTitle(cfg, line))) ++ break; ++ } ++ i++; ++ entry = NULL; ++ } + +- dbgPrintf("defaultLine is %s\n", defaultLine ? "set" : "unset"); +- if (defaultLine) { +- if (defaultLine->numElements > 2 && +- cfi->defaultSupportSaved && +- !strncmp(defaultLine->elements[2].item,"\"${saved_entry}\"", 16)) { +- cfg->cfi->defaultIsSaved = 1; +- cfg->defaultImage = DEFAULT_SAVED_GRUB2; +- if (cfg->cfi->getEnv) { +- char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry"); +- if (defTitle) { ++ if (entry) { ++ cfg->defaultImage = i; ++ } else { ++ cfg->defaultImage = -1; ++ } ++ } ++ } else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) { ++ char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry"); ++ if (defTitle) { + int index = 0; + if (isnumber(defTitle)) { +- index = atoi(defTitle); +- entry = findEntryByIndex(cfg, index); ++ index = atoi(defTitle); ++ entry = findEntryByIndex(cfg, index); + } else { +- entry = findEntryByTitle(cfg, defTitle, &index); ++ entry = findEntryByTitle(cfg, defTitle, &index); + } + if (entry) +- cfg->defaultImage = index; +- } ++ cfg->defaultImage = index; + } +- } else if (cfi->defaultIsVariable) { +- char *value = defaultLine->elements[2].item; +- while (*value && (*value == '"' || *value == '\'' || +- *value == ' ' || *value == '\t')) +- value++; +- cfg->defaultImage = strtol(value, &end, 10); +- while (*end && (*end == '"' || *end == '\'' || +- *end == ' ' || *end == '\t')) +- end++; +- if (*end) cfg->defaultImage = -1; +- } else if (cfi->defaultSupportSaved && +- !strncmp(defaultLine->elements[1].item, "saved", 5)) { +- cfg->defaultImage = DEFAULT_SAVED; +- } else if (cfi->defaultIsIndex) { +- cfg->defaultImage = strtol(defaultLine->elements[1].item, &end, 10); +- if (*end) cfg->defaultImage = -1; +- } else if (defaultLine->numElements >= 2) { +- int i = 0; +- while ((entry = findEntryByIndex(cfg, i))) { +- for (line = entry->lines; line; line = line->next) +- if (line->type == LT_TITLE) break; +- +- if (!cfi->titleBracketed) { +- if (line && (line->numElements >= 2) && +- !strcmp(defaultLine->elements[1].item, +- line->elements[1].item)) break; +- } else if (line) { +- if (!strcmp(defaultLine->elements[1].item, +- extractTitle(cfg, line))) break; +- } +- i++; +- entry = NULL; +- } +- +- if (entry){ +- cfg->defaultImage = i; +- }else{ +- cfg->defaultImage = -1; +- } +- } +- } else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) { +- char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry"); +- if (defTitle) { +- int index = 0; +- if (isnumber(defTitle)) { +- index = atoi(defTitle); +- entry = findEntryByIndex(cfg, index); +- } else { +- entry = findEntryByTitle(cfg, defTitle, &index); +- } +- if (entry) +- cfg->defaultImage = index; +- } +- } else { +- cfg->defaultImage = 0; +- } +- +- return cfg; ++ } else { ++ cfg->defaultImage = 0; ++ } ++ ++ return cfg; + } + +-static void writeDefault(FILE * out, char * indent, +- char * separator, struct grubConfig * cfg) { +- struct singleEntry * entry; +- struct singleLine * line; +- int i; +- +- if (!cfg->defaultImage && cfg->flags == GRUB_CONFIG_NO_DEFAULT) +- return; +- +- if (cfg->defaultImage == DEFAULT_SAVED) +- fprintf(out, "%sdefault%ssaved\n", indent, separator); +- else if (cfg->cfi->defaultIsSaved) { +- fprintf(out, "%sset default=\"${saved_entry}\"\n", indent); +- if (cfg->defaultImage >= 0 && cfg->cfi->setEnv) { +- char *title; +- entry = findEntryByIndex(cfg, cfg->defaultImage); +- line = getLineByType(LT_MENUENTRY, entry->lines); +- if (!line) +- line = getLineByType(LT_TITLE, entry->lines); +- if (line) { +- title = extractTitle(cfg, line); +- if (title) +- cfg->cfi->setEnv(cfg->cfi, "saved_entry", title); +- } +- } +- } else if (cfg->defaultImage > -1) { +- if (cfg->cfi->defaultIsIndex) { +- if (cfg->cfi->defaultIsVariable) { +- fprintf(out, "%sset default=\"%d\"\n", indent, +- cfg->defaultImage); +- } else { +- fprintf(out, "%sdefault%s%d\n", indent, separator, +- cfg->defaultImage); +- } +- } else { +- int image = cfg->defaultImage; ++static void writeDefault(FILE * out, char *indent, ++ char *separator, struct grubConfig *cfg) ++{ ++ struct singleEntry *entry; ++ struct singleLine *line; ++ int i; + +- entry = cfg->entries; +- while (entry && entry->skip) +- entry = entry->next; ++ if (!cfg->defaultImage && cfg->flags == GRUB_CONFIG_NO_DEFAULT) ++ return; + +- i = 0; +- while (entry && i < image) { +- entry = entry->next; ++ if (cfg->defaultImage == DEFAULT_SAVED) ++ fprintf(out, "%sdefault%ssaved\n", indent, separator); ++ else if (cfg->cfi->defaultIsSaved) { ++ fprintf(out, "%sset default=\"${saved_entry}\"\n", indent); ++ if (cfg->defaultImage >= 0 && cfg->cfi->setEnv) { ++ char *title; ++ entry = findEntryByIndex(cfg, cfg->defaultImage); ++ line = getLineByType(LT_MENUENTRY, entry->lines); ++ if (!line) ++ line = getLineByType(LT_TITLE, entry->lines); ++ if (line) { ++ title = extractTitle(cfg, line); ++ if (title) ++ cfg->cfi->setEnv(cfg->cfi, ++ "saved_entry", title); ++ } ++ } ++ } else if (cfg->defaultImage > -1) { ++ if (cfg->cfi->defaultIsIndex) { ++ if (cfg->cfi->defaultIsVariable) { ++ fprintf(out, "%sset default=\"%d\"\n", indent, ++ cfg->defaultImage); ++ } else { ++ fprintf(out, "%sdefault%s%d\n", indent, ++ separator, cfg->defaultImage); ++ } ++ } else { ++ int image = cfg->defaultImage; + +- while (entry && entry->skip) +- entry = entry->next; +- i++; +- } ++ entry = cfg->entries; ++ while (entry && entry->skip) ++ entry = entry->next; + +- if (!entry) +- return; ++ i = 0; ++ while (entry && i < image) { ++ entry = entry->next; + +- line = getLineByType(LT_TITLE, entry->lines); ++ while (entry && entry->skip) ++ entry = entry->next; ++ i++; ++ } + +- if (line && line->numElements >= 2) +- fprintf(out, "%sdefault%s%s\n", indent, separator, +- line->elements[1].item); +- else if (line && (line->numElements == 1) && +- cfg->cfi->titleBracketed) { +- char *title = extractTitle(cfg, line); +- if (title) { +- fprintf(out, "%sdefault%s%s\n", indent, separator, title); +- free(title); ++ if (!entry) ++ return; ++ ++ line = getLineByType(LT_TITLE, entry->lines); ++ ++ if (line && line->numElements >= 2) ++ fprintf(out, "%sdefault%s%s\n", indent, ++ separator, line->elements[1].item); ++ else if (line && (line->numElements == 1) ++ && cfg->cfi->titleBracketed) { ++ char *title = extractTitle(cfg, line); ++ if (title) { ++ fprintf(out, "%sdefault%s%s\n", indent, ++ separator, title); ++ free(title); ++ } ++ } + } +- } + } +- } + } + +-static int writeConfig(struct grubConfig * cfg, char * outName, +- const char * prefix) { +- FILE * out; +- struct singleLine * line; +- struct singleEntry * entry; +- char * tmpOutName; +- int needs = MAIN_DEFAULT; +- struct stat sb; +- int i; +- +- if (!strcmp(outName, "-")) { +- out = stdout; +- tmpOutName = NULL; +- } else { +- if (!lstat(outName, &sb) && S_ISLNK(sb.st_mode)) { +- char * buf; +- int len = 256; +- int rc; +- +- /* most likely the symlink is relative, so change our +- directory to the dir of the symlink */ +- char *dir = strdupa(outName); +- rc = chdir(dirname(dir)); +- do { +- buf = alloca(len + 1); +- rc = readlink(basename(outName), buf, len); +- if (rc == len) len += 256; +- } while (rc == len); +- +- if (rc < 0) { +- fprintf(stderr, _("grubby: error readlink link %s: %s\n"), +- outName, strerror(errno)); +- return 1; +- } +- +- outName = buf; +- outName[rc] = '\0'; +- } +- +- tmpOutName = alloca(strlen(outName) + 2); +- sprintf(tmpOutName, "%s-", outName); +- out = fopen(tmpOutName, "w"); +- if (!out) { +- fprintf(stderr, _("grubby: error creating %s: %s\n"), tmpOutName, +- strerror(errno)); +- return 1; +- } +- +- if (!stat(outName, &sb)) { +- if (chmod(tmpOutName, sb.st_mode & ~(S_IFMT))) { +- fprintf(stderr, _("grubby: error setting perms on %s: %s\n"), +- tmpOutName, strerror(errno)); +- fclose(out); +- unlink(tmpOutName); +- return 1; +- } +- } +- } +- +- line = cfg->theLines; +- struct keywordTypes *defaultKw = getKeywordByType(LT_DEFAULT, cfg->cfi); +- while (line) { +- if (line->type == LT_SET_VARIABLE && defaultKw && +- line->numElements == 3 && +- !strcmp(line->elements[1].item, defaultKw->key) && +- !is_special_grub2_variable(line->elements[2].item)) { +- writeDefault(out, line->indent, line->elements[0].indent, cfg); +- needs &= ~MAIN_DEFAULT; +- } else if (line->type == LT_DEFAULT) { +- writeDefault(out, line->indent, line->elements[0].indent, cfg); +- needs &= ~MAIN_DEFAULT; +- } else if (line->type == LT_FALLBACK) { +- if (cfg->fallbackImage > -1) +- fprintf(out, "%s%s%s%d\n", line->indent, +- line->elements[0].item, line->elements[0].indent, +- cfg->fallbackImage); ++static int writeConfig(struct grubConfig *cfg, char *outName, ++ const char *prefix) ++{ ++ FILE *out; ++ struct singleLine *line; ++ struct singleEntry *entry; ++ char *tmpOutName; ++ int needs = MAIN_DEFAULT; ++ struct stat sb; ++ int i; ++ ++ if (!strcmp(outName, "-")) { ++ out = stdout; ++ tmpOutName = NULL; + } else { +- if (lineWrite(out, line, cfg->cfi) == -1) { +- fprintf(stderr, _("grubby: error writing %s: %s\n"), +- tmpOutName, strerror(errno)); +- fclose(out); +- unlink(tmpOutName); +- return 1; +- } +- } ++ if (!lstat(outName, &sb) && S_ISLNK(sb.st_mode)) { ++ char *buf; ++ int len = 256; ++ int rc; ++ ++ /* most likely the symlink is relative, so change our ++ directory to the dir of the symlink */ ++ char *dir = strdupa(outName); ++ rc = chdir(dirname(dir)); ++ do { ++ buf = alloca(len + 1); ++ rc = readlink(basename(outName), buf, len); ++ if (rc == len) ++ len += 256; ++ } while (rc == len); ++ ++ if (rc < 0) { ++ fprintf(stderr, ++ _ ++ ("grubby: error readlink link %s: %s\n"), ++ outName, strerror(errno)); ++ return 1; ++ } + +- line = line->next; +- } ++ outName = buf; ++ outName[rc] = '\0'; ++ } + +- if (needs & MAIN_DEFAULT) { +- writeDefault(out, cfg->primaryIndent, "=", cfg); +- needs &= ~MAIN_DEFAULT; +- } ++ tmpOutName = alloca(strlen(outName) + 2); ++ sprintf(tmpOutName, "%s-", outName); ++ out = fopen(tmpOutName, "w"); ++ if (!out) { ++ fprintf(stderr, _("grubby: error creating %s: %s\n"), ++ tmpOutName, strerror(errno)); ++ return 1; ++ } + +- i = 0; +- while ((entry = findEntryByIndex(cfg, i++))) { +- if (entry->skip) continue; ++ if (!stat(outName, &sb)) { ++ if (chmod(tmpOutName, sb.st_mode & ~(S_IFMT))) { ++ fprintf(stderr, ++ _ ++ ("grubby: error setting perms on %s: %s\n"), ++ tmpOutName, strerror(errno)); ++ fclose(out); ++ unlink(tmpOutName); ++ return 1; ++ } ++ } ++ } + +- line = entry->lines; ++ line = cfg->theLines; ++ struct keywordTypes *defaultKw = getKeywordByType(LT_DEFAULT, cfg->cfi); + while (line) { +- if (lineWrite(out, line, cfg->cfi) == -1) { +- fprintf(stderr, _("grubby: error writing %s: %s\n"), +- tmpOutName, strerror(errno)); +- fclose(out); +- unlink(tmpOutName); +- return 1; +- } +- line = line->next; +- } +- } +- +- if (tmpOutName) { +- if (rename(tmpOutName, outName)) { +- fprintf(stderr, _("grubby: error moving %s to %s: %s\n"), +- tmpOutName, outName, strerror(errno)); +- unlink(outName); +- return 1; +- } +- } +- +- return 0; +-} +- +-static int numEntries(struct grubConfig *cfg) { +- int i = 0; +- struct singleEntry * entry; +- +- entry = cfg->entries; +- while (entry) { +- if (!entry->skip) +- i++; +- entry = entry->next; +- } +- return i; +-} ++ if (line->type == LT_SET_VARIABLE && defaultKw && ++ line->numElements == 3 && ++ !strcmp(line->elements[1].item, defaultKw->key) && ++ !is_special_grub2_variable(line->elements[2].item)) { ++ writeDefault(out, line->indent, ++ line->elements[0].indent, cfg); ++ needs &= ~MAIN_DEFAULT; ++ } else if (line->type == LT_DEFAULT) { ++ writeDefault(out, line->indent, ++ line->elements[0].indent, cfg); ++ needs &= ~MAIN_DEFAULT; ++ } else if (line->type == LT_FALLBACK) { ++ if (cfg->fallbackImage > -1) ++ fprintf(out, "%s%s%s%d\n", line->indent, ++ line->elements[0].item, ++ line->elements[0].indent, ++ cfg->fallbackImage); ++ } else { ++ if (lineWrite(out, line, cfg->cfi) == -1) { ++ fprintf(stderr, ++ _("grubby: error writing %s: %s\n"), ++ tmpOutName, strerror(errno)); ++ fclose(out); ++ unlink(tmpOutName); ++ return 1; ++ } ++ } + +-static char *findDiskForRoot() +-{ +- int fd; +- char buf[65536]; +- char *devname; +- char *chptr; +- int rc; +- +- if ((fd = open(_PATH_MOUNTED, O_RDONLY)) < 0) { +- fprintf(stderr, "grubby: failed to open %s: %s\n", +- _PATH_MOUNTED, strerror(errno)); +- return NULL; +- } +- +- rc = read(fd, buf, sizeof(buf) - 1); +- if (rc <= 0) { +- fprintf(stderr, "grubby: failed to read %s: %s\n", +- _PATH_MOUNTED, strerror(errno)); +- close(fd); +- return NULL; +- } +- close(fd); +- buf[rc] = '\0'; +- chptr = buf; +- +- char *foundanswer = NULL; +- +- while (chptr && chptr != buf+rc) { +- devname = chptr; +- +- /* +- * The first column of a mtab entry is the device, but if the entry is a +- * special device it won't start with /, so move on to the next line. +- */ +- if (*devname != '/') { +- chptr = strchr(chptr, '\n'); +- if (chptr) +- chptr++; +- continue; +- } +- +- /* Seek to the next space */ +- chptr = strchr(chptr, ' '); +- if (!chptr) { +- fprintf(stderr, "grubby: error parsing %s: %s\n", +- _PATH_MOUNTED, strerror(errno)); +- return NULL; +- } +- +- /* +- * The second column of a mtab entry is the mount point, we are looking +- * for '/' obviously. +- */ +- if (*(++chptr) == '/' && *(++chptr) == ' ') { +- /* remember the last / entry in mtab */ +- foundanswer = devname; +- } +- +- /* Next line */ +- chptr = strchr(chptr, '\n'); +- if (chptr) +- chptr++; +- } +- +- /* Return the last / entry found */ +- if (foundanswer) { +- chptr = strchr(foundanswer, ' '); +- *chptr = '\0'; +- return strdup(foundanswer); +- } +- +- return NULL; +-} ++ line = line->next; ++ } + +-void printEntry(struct singleEntry * entry, FILE *f) { +- int i; +- struct singleLine * line; ++ if (needs & MAIN_DEFAULT) { ++ writeDefault(out, cfg->primaryIndent, "=", cfg); ++ needs &= ~MAIN_DEFAULT; ++ } + +- for (line = entry->lines; line; line = line->next) { +- log_message(f, "DBG: %s", line->indent); +- for (i = 0; i < line->numElements; i++) { +- /* Need to handle this, because we strip the quotes from +- * menuentry when read it. */ +- if (line->type == LT_MENUENTRY && i == 1) { +- if(!isquote(*line->elements[i].item)) +- log_message(f, "\'%s\'", line->elements[i].item); +- else +- log_message(f, "%s", line->elements[i].item); +- log_message(f, "%s", line->elements[i].indent); +- +- continue; +- } +- +- log_message(f, "%s%s", +- line->elements[i].item, line->elements[i].indent); +- } +- log_message(f, "\n"); +- } ++ i = 0; ++ while ((entry = findEntryByIndex(cfg, i++))) { ++ if (entry->skip) ++ continue; ++ ++ line = entry->lines; ++ while (line) { ++ if (lineWrite(out, line, cfg->cfi) == -1) { ++ fprintf(stderr, ++ _("grubby: error writing %s: %s\n"), ++ tmpOutName, strerror(errno)); ++ fclose(out); ++ unlink(tmpOutName); ++ return 1; ++ } ++ line = line->next; ++ } ++ } ++ ++ if (tmpOutName) { ++ if (rename(tmpOutName, outName)) { ++ fprintf(stderr, ++ _("grubby: error moving %s to %s: %s\n"), ++ tmpOutName, outName, strerror(errno)); ++ unlink(outName); ++ return 1; ++ } ++ } ++ ++ return 0; + } + +-void notSuitablePrintf(struct singleEntry * entry, int okay, const char *fmt, ...) ++static int numEntries(struct grubConfig *cfg) + { +- static int once; +- va_list argp, argq; +- +- va_start(argp, fmt); +- +- va_copy(argq, argp); +- if (!once) { +- log_time(NULL); +- log_message(NULL, "command line: %s\n", saved_command_line); +- } +- log_message(NULL, "DBG: Image entry %s: ", okay ? "succeeded" : "failed"); +- log_vmessage(NULL, fmt, argq); +- +- printEntry(entry, NULL); +- va_end(argq); +- +- if (!debug) { +- once = 1; +- va_end(argp); +- return; +- } ++ int i = 0; ++ struct singleEntry *entry; ++ ++ entry = cfg->entries; ++ while (entry) { ++ if (!entry->skip) ++ i++; ++ entry = entry->next; ++ } ++ return i; ++} ++ ++static char *findDiskForRoot() ++{ ++ int fd; ++ char buf[65536]; ++ char *devname; ++ char *chptr; ++ int rc; ++ ++ if ((fd = open(_PATH_MOUNTED, O_RDONLY)) < 0) { ++ fprintf(stderr, "grubby: failed to open %s: %s\n", ++ _PATH_MOUNTED, strerror(errno)); ++ return NULL; ++ } ++ ++ rc = read(fd, buf, sizeof(buf) - 1); ++ if (rc <= 0) { ++ fprintf(stderr, "grubby: failed to read %s: %s\n", ++ _PATH_MOUNTED, strerror(errno)); ++ close(fd); ++ return NULL; ++ } ++ close(fd); ++ buf[rc] = '\0'; ++ chptr = buf; ++ ++ char *foundanswer = NULL; ++ ++ while (chptr && chptr != buf + rc) { ++ devname = chptr; ++ ++ /* ++ * The first column of a mtab entry is the device, but if the entry is a ++ * special device it won't start with /, so move on to the next line. ++ */ ++ if (*devname != '/') { ++ chptr = strchr(chptr, '\n'); ++ if (chptr) ++ chptr++; ++ continue; ++ } ++ ++ /* Seek to the next space */ ++ chptr = strchr(chptr, ' '); ++ if (!chptr) { ++ fprintf(stderr, "grubby: error parsing %s: %s\n", ++ _PATH_MOUNTED, strerror(errno)); ++ return NULL; ++ } ++ ++ /* ++ * The second column of a mtab entry is the mount point, we are looking ++ * for '/' obviously. ++ */ ++ if (*(++chptr) == '/' && *(++chptr) == ' ') { ++ /* remember the last / entry in mtab */ ++ foundanswer = devname; ++ } ++ ++ /* Next line */ ++ chptr = strchr(chptr, '\n'); ++ if (chptr) ++ chptr++; ++ } ++ ++ /* Return the last / entry found */ ++ if (foundanswer) { ++ chptr = strchr(foundanswer, ' '); ++ *chptr = '\0'; ++ return strdup(foundanswer); ++ } ++ ++ return NULL; ++} ++ ++void printEntry(struct singleEntry *entry, FILE * f) ++{ ++ int i; ++ struct singleLine *line; ++ ++ for (line = entry->lines; line; line = line->next) { ++ log_message(f, "DBG: %s", line->indent); ++ for (i = 0; i < line->numElements; i++) { ++ /* Need to handle this, because we strip the quotes from ++ * menuentry when read it. */ ++ if (line->type == LT_MENUENTRY && i == 1) { ++ if (!isquote(*line->elements[i].item)) ++ log_message(f, "\'%s\'", ++ line->elements[i].item); ++ else ++ log_message(f, "%s", ++ line->elements[i].item); ++ log_message(f, "%s", line->elements[i].indent); ++ ++ continue; ++ } ++ ++ log_message(f, "%s%s", ++ line->elements[i].item, ++ line->elements[i].indent); ++ } ++ log_message(f, "\n"); ++ } ++} + +- if (okay) { ++void notSuitablePrintf(struct singleEntry *entry, int okay, const char *fmt, ++ ...) ++{ ++ static int once; ++ va_list argp, argq; ++ ++ va_start(argp, fmt); ++ ++ va_copy(argq, argp); ++ if (!once) { ++ log_time(NULL); ++ log_message(NULL, "command line: %s\n", saved_command_line); ++ } ++ log_message(NULL, "DBG: Image entry %s: ", ++ okay ? "succeeded" : "failed"); ++ log_vmessage(NULL, fmt, argq); ++ ++ printEntry(entry, NULL); ++ va_end(argq); ++ ++ if (!debug) { ++ once = 1; ++ va_end(argp); ++ return; ++ } ++ ++ if (okay) { ++ va_end(argp); ++ return; ++ } ++ ++ if (!once) ++ log_message(stderr, "DBG: command line: %s\n", ++ saved_command_line); ++ once = 1; ++ fprintf(stderr, "DBG: Image entry failed: "); ++ vfprintf(stderr, fmt, argp); ++ printEntry(entry, stderr); + va_end(argp); +- return; +- } +- +- if (!once) +- log_message(stderr, "DBG: command line: %s\n", saved_command_line); +- once = 1; +- fprintf(stderr, "DBG: Image entry failed: "); +- vfprintf(stderr, fmt, argp); +- printEntry(entry, stderr); +- va_end(argp); + } + + #define beginswith(s, c) ((s) && (s)[0] == (c)) +@@ -1860,281 +1979,317 @@ static int endswith(const char *s, char c) + return s[slen] == c; + } + +-int suitableImage(struct singleEntry * entry, const char * bootPrefix, +- int skipRemoved, int flags) { +- struct singleLine * line; +- char * fullName; +- int i; +- char * dev; +- char * rootspec; +- char * rootdev; +- +- if (skipRemoved && entry->skip) { +- notSuitablePrintf(entry, 0, "marked to skip\n"); +- return 0; +- } ++int suitableImage(struct singleEntry *entry, const char *bootPrefix, ++ int skipRemoved, int flags) ++{ ++ struct singleLine *line; ++ char *fullName; ++ int i; ++ char *dev; ++ char *rootspec; ++ char *rootdev; ++ ++ if (skipRemoved && entry->skip) { ++ notSuitablePrintf(entry, 0, "marked to skip\n"); ++ return 0; ++ } + +- line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); +- if (!line) { +- notSuitablePrintf(entry, 0, "no line found\n"); +- return 0; +- } +- if (line->numElements < 2) { +- notSuitablePrintf(entry, 0, "line has only %d elements\n", +- line->numElements); +- return 0; +- } +- +- if (flags & GRUBBY_BADIMAGE_OKAY) { +- notSuitablePrintf(entry, 1, "\n"); +- return 1; +- } +- +- fullName = alloca(strlen(bootPrefix) + +- strlen(line->elements[1].item) + 1); +- rootspec = getRootSpecifier(line->elements[1].item); +- int rootspec_offset = rootspec ? strlen(rootspec) : 0; +- int hasslash = endswith(bootPrefix, '/') || +- beginswith(line->elements[1].item + rootspec_offset, '/'); +- sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/", +- line->elements[1].item + rootspec_offset); +- if (access(fullName, R_OK)) { +- notSuitablePrintf(entry, 0, "access to %s failed\n", fullName); +- return 0; +- } +- for (i = 2; i < line->numElements; i++) +- if (!strncasecmp(line->elements[i].item, "root=", 5)) break; +- if (i < line->numElements) { +- dev = line->elements[i].item + 5; +- } else { +- /* look for a lilo style LT_ROOT line */ +- line = getLineByType(LT_ROOT, entry->lines); ++ line = ++ getLineByType(LT_KERNEL | LT_HYPER | LT_KERNEL_EFI | LT_KERNEL_16, ++ entry->lines); ++ if (!line) { ++ notSuitablePrintf(entry, 0, "no line found\n"); ++ return 0; ++ } ++ if (line->numElements < 2) { ++ notSuitablePrintf(entry, 0, "line has only %d elements\n", ++ line->numElements); ++ return 0; ++ } + +- if (line && line->numElements >= 2) { +- dev = line->elements[1].item; +- } else { +- /* didn't succeed in finding a LT_ROOT, let's try LT_KERNELARGS. +- * grub+multiboot uses LT_MBMODULE for the args, so check that too. +- */ +- line = getLineByType(LT_KERNELARGS|LT_MBMODULE, entry->lines); ++ if (flags & GRUBBY_BADIMAGE_OKAY) { ++ notSuitablePrintf(entry, 1, "\n"); ++ return 1; ++ } + +- /* failed to find one */ +- if (!line) { +- notSuitablePrintf(entry, 0, "no line found\n"); ++ fullName = alloca(strlen(bootPrefix) + ++ strlen(line->elements[1].item) + 1); ++ rootspec = getRootSpecifier(line->elements[1].item); ++ int rootspec_offset = rootspec ? strlen(rootspec) : 0; ++ int hasslash = endswith(bootPrefix, '/') || ++ beginswith(line->elements[1].item + rootspec_offset, '/'); ++ sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/", ++ line->elements[1].item + rootspec_offset); ++ if (access(fullName, R_OK)) { ++ notSuitablePrintf(entry, 0, "access to %s failed\n", fullName); + return 0; +- } +- +- for (i = 1; i < line->numElements; i++) +- if (!strncasecmp(line->elements[i].item, "root=", 5)) break; +- if (i < line->numElements) +- dev = line->elements[i].item + 5; +- else { +- notSuitablePrintf(entry, 0, "no root= entry found\n"); +- /* it failed too... can't find root= */ +- return 0; +- } +- } +- } +- +- dev = getpathbyspec(dev); +- if (!getpathbyspec(dev)) { +- notSuitablePrintf(entry, 0, "can't find blkid entry for %s\n", dev); +- return 0; +- } else ++ } ++ for (i = 2; i < line->numElements; i++) ++ if (!strncasecmp(line->elements[i].item, "root=", 5)) ++ break; ++ if (i < line->numElements) { ++ dev = line->elements[i].item + 5; ++ } else { ++ /* look for a lilo style LT_ROOT line */ ++ line = getLineByType(LT_ROOT, entry->lines); ++ ++ if (line && line->numElements >= 2) { ++ dev = line->elements[1].item; ++ } else { ++ /* didn't succeed in finding a LT_ROOT, let's try LT_KERNELARGS. ++ * grub+multiboot uses LT_MBMODULE for the args, so check that too. ++ */ ++ line = ++ getLineByType(LT_KERNELARGS | LT_MBMODULE, ++ entry->lines); ++ ++ /* failed to find one */ ++ if (!line) { ++ notSuitablePrintf(entry, 0, "no line found\n"); ++ return 0; ++ } ++ ++ for (i = 1; i < line->numElements; i++) ++ if (!strncasecmp ++ (line->elements[i].item, "root=", 5)) ++ break; ++ if (i < line->numElements) ++ dev = line->elements[i].item + 5; ++ else { ++ notSuitablePrintf(entry, 0, ++ "no root= entry found\n"); ++ /* it failed too... can't find root= */ ++ return 0; ++ } ++ } ++ } ++ + dev = getpathbyspec(dev); ++ if (!getpathbyspec(dev)) { ++ notSuitablePrintf(entry, 0, "can't find blkid entry for %s\n", ++ dev); ++ return 0; ++ } else ++ dev = getpathbyspec(dev); + +- rootdev = findDiskForRoot(); +- if (!rootdev) { +- notSuitablePrintf(entry, 0, "can't find root device\n"); +- return 0; +- } +- +- if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) { +- notSuitablePrintf(entry, 0, "uuid missing: rootdev %s, dev %s\n", +- getuuidbydev(rootdev), getuuidbydev(dev)); +- free(rootdev); +- return 0; +- } +- +- if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) { +- notSuitablePrintf(entry, 0, "uuid mismatch: rootdev %s, dev %s\n", +- getuuidbydev(rootdev), getuuidbydev(dev)); +- free(rootdev); +- return 0; +- } ++ rootdev = findDiskForRoot(); ++ if (!rootdev) { ++ notSuitablePrintf(entry, 0, "can't find root device\n"); ++ return 0; ++ } + +- free(rootdev); +- notSuitablePrintf(entry, 1, "\n"); ++ if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) { ++ notSuitablePrintf(entry, 0, ++ "uuid missing: rootdev %s, dev %s\n", ++ getuuidbydev(rootdev), getuuidbydev(dev)); ++ free(rootdev); ++ return 0; ++ } ++ ++ if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) { ++ notSuitablePrintf(entry, 0, ++ "uuid mismatch: rootdev %s, dev %s\n", ++ getuuidbydev(rootdev), getuuidbydev(dev)); ++ free(rootdev); ++ return 0; ++ } ++ ++ free(rootdev); ++ notSuitablePrintf(entry, 1, "\n"); + +- return 1; ++ return 1; + } + + /* returns the first match on or after the one pointed to by index (if index + is not NULL) which is not marked as skip */ +-struct singleEntry * findEntryByPath(struct grubConfig * config, +- const char * kernel, const char * prefix, +- int * index) { +- struct singleEntry * entry = NULL; +- struct singleLine * line; +- int i; +- char * chptr; +- char * rootspec = NULL; +- enum lineType_e checkType = LT_KERNEL; +- +- if (isdigit(*kernel)) { +- int * indexVars = alloca(sizeof(*indexVars) * strlen(kernel)); +- +- i = 0; +- indexVars[i] = strtol(kernel, &chptr, 10); +- while (*chptr == ',') { +- i++; +- kernel = chptr + 1; +- indexVars[i] = strtol(kernel, &chptr, 10); +- } ++struct singleEntry *findEntryByPath(struct grubConfig *config, ++ const char *kernel, const char *prefix, ++ int *index) ++{ ++ struct singleEntry *entry = NULL; ++ struct singleLine *line; ++ int i; ++ char *chptr; ++ char *rootspec = NULL; ++ enum lineType_e checkType = LT_KERNEL; ++ ++ if (isdigit(*kernel)) { ++ int *indexVars = alloca(sizeof(*indexVars) * strlen(kernel)); ++ ++ i = 0; ++ indexVars[i] = strtol(kernel, &chptr, 10); ++ while (*chptr == ',') { ++ i++; ++ kernel = chptr + 1; ++ indexVars[i] = strtol(kernel, &chptr, 10); ++ } + +- if (*chptr) { +- /* can't parse it, bail */ +- return NULL; +- } ++ if (*chptr) { ++ /* can't parse it, bail */ ++ return NULL; ++ } + +- indexVars[i + 1] = -1; ++ indexVars[i + 1] = -1; + +- i = 0; +- if (index) { +- while (i < *index) { +- i++; +- if (indexVars[i] == -1) return NULL; +- } +- } ++ i = 0; ++ if (index) { ++ while (i < *index) { ++ i++; ++ if (indexVars[i] == -1) ++ return NULL; ++ } ++ } + +- entry = findEntryByIndex(config, indexVars[i]); +- if (!entry) return NULL; ++ entry = findEntryByIndex(config, indexVars[i]); ++ if (!entry) ++ return NULL; + +- line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); +- if (!line) return NULL; ++ line = ++ getLineByType(LT_KERNEL | LT_HYPER | LT_KERNEL_EFI | ++ LT_KERNEL_16, entry->lines); ++ if (!line) ++ return NULL; + +- if (index) *index = indexVars[i]; +- return entry; +- } +- +- if (!strcmp(kernel, "DEFAULT")) { +- if (index && *index > config->defaultImage) { +- entry = NULL; +- } else { +- entry = findEntryByIndex(config, config->defaultImage); +- if (entry && entry->skip) +- entry = NULL; +- else if (index) +- *index = config->defaultImage; ++ if (index) ++ *index = indexVars[i]; ++ return entry; + } +- } else if (!strcmp(kernel, "ALL")) { +- if (index) +- i = *index; +- else +- i = 0; + +- while ((entry = findEntryByIndex(config, i))) { +- if (!entry->skip) break; +- i++; +- } ++ if (!strcmp(kernel, "DEFAULT")) { ++ if (index && *index > config->defaultImage) { ++ entry = NULL; ++ } else { ++ entry = findEntryByIndex(config, config->defaultImage); ++ if (entry && entry->skip) ++ entry = NULL; ++ else if (index) ++ *index = config->defaultImage; ++ } ++ } else if (!strcmp(kernel, "ALL")) { ++ if (index) ++ i = *index; ++ else ++ i = 0; + +- if (entry && index) +- *index = i; +- } else { +- if (index) +- i = *index; +- else +- i = 0; ++ while ((entry = findEntryByIndex(config, i))) { ++ if (!entry->skip) ++ break; ++ i++; ++ } + +- if (!strncmp(kernel, "TITLE=", 6)) { +- prefix = ""; +- checkType = LT_TITLE|LT_MENUENTRY; +- kernel += 6; +- } ++ if (entry && index) ++ *index = i; ++ } else { ++ if (index) ++ i = *index; ++ else ++ i = 0; + +- for (entry = findEntryByIndex(config, i); entry; entry = entry->next, i++) { +- if (entry->skip) continue; ++ if (!strncmp(kernel, "TITLE=", 6)) { ++ prefix = ""; ++ checkType = LT_TITLE | LT_MENUENTRY; ++ kernel += 6; ++ } + +- dbgPrintf("findEntryByPath looking for %d %s in %p\n", checkType, kernel, entry); ++ for (entry = findEntryByIndex(config, i); entry; ++ entry = entry->next, i++) { ++ if (entry->skip) ++ continue; ++ ++ dbgPrintf("findEntryByPath looking for %d %s in %p\n", ++ checkType, kernel, entry); ++ ++ /* check all the lines matching checkType */ ++ for (line = entry->lines; line; line = line->next) { ++ enum lineType_e ct = checkType; ++ if (entry->multiboot && checkType == LT_KERNEL) ++ ct = LT_KERNEL | LT_KERNEL_EFI | ++ LT_MBMODULE | LT_HYPER | ++ LT_KERNEL_16; ++ else if (checkType & LT_KERNEL) ++ ct = checkType | LT_KERNEL_EFI | ++ LT_KERNEL_16; ++ line = getLineByType(ct, line); ++ if (!line) ++ break; /* not found in this entry */ ++ ++ if (line && line->type != LT_MENUENTRY && ++ line->numElements >= 2) { ++ rootspec = ++ getRootSpecifier(line->elements[1]. ++ item); ++ if (!strcmp ++ (line->elements[1].item + ++ ((rootspec != ++ NULL) ? strlen(rootspec) : 0), ++ kernel + strlen(prefix))) ++ break; ++ } ++ if (line->type == LT_MENUENTRY && ++ !strcmp(line->elements[1].item, kernel)) ++ break; ++ } + +- /* check all the lines matching checkType */ +- for (line = entry->lines; line; line = line->next) { +- enum lineType_e ct = checkType; +- if (entry->multiboot && checkType == LT_KERNEL) +- ct = LT_KERNEL|LT_KERNEL_EFI|LT_MBMODULE|LT_HYPER|LT_KERNEL_16; +- else if (checkType & LT_KERNEL) +- ct = checkType | LT_KERNEL_EFI | LT_KERNEL_16; +- line = getLineByType(ct, line); +- if (!line) +- break; /* not found in this entry */ +- +- if (line && line->type != LT_MENUENTRY && +- line->numElements >= 2) { +- rootspec = getRootSpecifier(line->elements[1].item); +- if (!strcmp(line->elements[1].item + +- ((rootspec != NULL) ? strlen(rootspec) : 0), +- kernel + strlen(prefix))) +- break; ++ /* make sure this entry has a kernel identifier; this skips ++ * non-Linux boot entries (could find netbsd etc, though, which is ++ * unfortunate) ++ */ ++ if (line ++ && getLineByType(LT_KERNEL | LT_HYPER | ++ LT_KERNEL_EFI | LT_KERNEL_16, ++ entry->lines)) ++ break; /* found 'im! */ + } +- if(line->type == LT_MENUENTRY && +- !strcmp(line->elements[1].item, kernel)) +- break; +- } + +- /* make sure this entry has a kernel identifier; this skips +- * non-Linux boot entries (could find netbsd etc, though, which is +- * unfortunate) +- */ +- if (line && getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines)) +- break; /* found 'im! */ ++ if (index) ++ *index = i; + } + +- if (index) *index = i; +- } +- +- return entry; ++ return entry; + } + +-struct singleEntry * findEntryByTitle(struct grubConfig * cfg, char *title, +- int * index) { +- struct singleEntry * entry; +- struct singleLine * line; +- int i; +- char * newtitle; ++struct singleEntry *findEntryByTitle(struct grubConfig *cfg, char *title, ++ int *index) ++{ ++ struct singleEntry *entry; ++ struct singleLine *line; ++ int i; ++ char *newtitle; ++ ++ for (i = 0, entry = cfg->entries; entry; entry = entry->next, i++) { ++ if (index && i < *index) ++ continue; ++ line = getLineByType(LT_TITLE, entry->lines); ++ if (!line) ++ line = getLineByType(LT_MENUENTRY, entry->lines); ++ if (!line) ++ continue; ++ newtitle = grub2ExtractTitle(line); ++ if (!newtitle) ++ continue; ++ if (!strcmp(title, newtitle)) ++ break; ++ } + +- for (i = 0, entry = cfg->entries; entry; entry = entry->next, i++) { +- if (index && i < *index) +- continue; +- line = getLineByType(LT_TITLE, entry->lines); +- if (!line) +- line = getLineByType(LT_MENUENTRY, entry->lines); +- if (!line) +- continue; +- newtitle = grub2ExtractTitle(line); +- if (!newtitle) +- continue; +- if (!strcmp(title, newtitle)) +- break; +- } +- +- if (!entry) +- return NULL; ++ if (!entry) ++ return NULL; + +- if (index) +- *index = i; +- return entry; ++ if (index) ++ *index = i; ++ return entry; + } + +-struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index) { +- struct singleEntry * entry; ++struct singleEntry *findEntryByIndex(struct grubConfig *cfg, int index) ++{ ++ struct singleEntry *entry; + +- entry = cfg->entries; +- while (index && entry) { +- entry = entry->next; +- index--; +- } ++ entry = cfg->entries; ++ while (index && entry) { ++ entry = entry->next; ++ index--; ++ } + +- return entry; ++ return entry; + } + + /* Find a good template to use for the new kernel. An entry is +@@ -2142,2550 +2297,2822 @@ struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index) { + * is going to be removed). Try and use the default entry, but + * if that doesn't work just take the first. If we can't find one, + * bail. */ +-struct singleEntry * findTemplate(struct grubConfig * cfg, const char * prefix, +- int * indexPtr, int skipRemoved, int flags) { +- struct singleEntry * entry, * entry2; +- int index; +- +- if (cfg->cfi->defaultIsSaved) { +- if (cfg->cfi->getEnv) { +- char *defTitle = cfg->cfi->getEnv(cfg->cfi, "saved_entry"); +- if (defTitle) { +- int index = 0; +- if (isnumber(defTitle)) { +- index = atoi(defTitle); +- entry = findEntryByIndex(cfg, index); +- } else { +- entry = findEntryByTitle(cfg, defTitle, &index); ++struct singleEntry *findTemplate(struct grubConfig *cfg, const char *prefix, ++ int *indexPtr, int skipRemoved, int flags) ++{ ++ struct singleEntry *entry, *entry2; ++ int index; ++ ++ if (cfg->cfi->defaultIsSaved) { ++ if (cfg->cfi->getEnv) { ++ char *defTitle = ++ cfg->cfi->getEnv(cfg->cfi, "saved_entry"); ++ if (defTitle) { ++ int index = 0; ++ if (isnumber(defTitle)) { ++ index = atoi(defTitle); ++ entry = findEntryByIndex(cfg, index); ++ } else { ++ entry = ++ findEntryByTitle(cfg, defTitle, ++ &index); ++ } ++ if (entry ++ && suitableImage(entry, prefix, skipRemoved, ++ flags)) { ++ cfg->defaultImage = index; ++ if (indexPtr) ++ *indexPtr = index; ++ return entry; ++ } ++ } + } ++ } else if (cfg->defaultImage > -1) { ++ entry = findEntryByIndex(cfg, cfg->defaultImage); + if (entry && suitableImage(entry, prefix, skipRemoved, flags)) { +- cfg->defaultImage = index; +- if (indexPtr) +- *indexPtr = index; +- return entry; ++ if (indexPtr) ++ *indexPtr = cfg->defaultImage; ++ return entry; + } +- } + } +- } else if (cfg->defaultImage > -1) { +- entry = findEntryByIndex(cfg, cfg->defaultImage); +- if (entry && suitableImage(entry, prefix, skipRemoved, flags)) { +- if (indexPtr) *indexPtr = cfg->defaultImage; +- return entry; +- } +- } + +- index = 0; +- while ((entry = findEntryByIndex(cfg, index))) { +- if (suitableImage(entry, prefix, skipRemoved, flags)) { +- int j; +- for (j = 0; j < index; j++) { +- entry2 = findEntryByIndex(cfg, j); +- if (entry2->skip) index--; +- } +- if (indexPtr) *indexPtr = index; ++ index = 0; ++ while ((entry = findEntryByIndex(cfg, index))) { ++ if (suitableImage(entry, prefix, skipRemoved, flags)) { ++ int j; ++ for (j = 0; j < index; j++) { ++ entry2 = findEntryByIndex(cfg, j); ++ if (entry2->skip) ++ index--; ++ } ++ if (indexPtr) ++ *indexPtr = index; + +- return entry; +- } ++ return entry; ++ } + +- index++; +- } ++ index++; ++ } + +- fprintf(stderr, _("grubby fatal error: unable to find a suitable template\n")); ++ fprintf(stderr, ++ _("grubby fatal error: unable to find a suitable template\n")); + +- return NULL; ++ return NULL; + } + +-char * findBootPrefix(void) { +- struct stat sb, sb2; ++char *findBootPrefix(void) ++{ ++ struct stat sb, sb2; + +- stat("/", &sb); ++ stat("/", &sb); + #ifdef __ia64__ +- stat("/boot/efi/EFI/redhat/", &sb2); ++ stat("/boot/efi/EFI/redhat/", &sb2); + #else +- stat("/boot", &sb2); ++ stat("/boot", &sb2); + #endif + +- if (sb.st_dev == sb2.st_dev) +- return strdup(""); ++ if (sb.st_dev == sb2.st_dev) ++ return strdup(""); + + #ifdef __ia64__ +- return strdup("/boot/efi/EFI/redhat/"); ++ return strdup("/boot/efi/EFI/redhat/"); + #else +- return strdup("/boot"); ++ return strdup("/boot"); + #endif + } + +-void markRemovedImage(struct grubConfig * cfg, const char * image, +- const char * prefix) { +- struct singleEntry * entry; ++void markRemovedImage(struct grubConfig *cfg, const char *image, ++ const char *prefix) ++{ ++ struct singleEntry *entry; + +- if (!image) +- return; ++ if (!image) ++ return; + +- /* check and see if we're removing the default image */ +- if (isdigit(*image)) { +- entry = findEntryByPath(cfg, image, prefix, NULL); +- if(entry) +- entry->skip = 1; +- return; +- } ++ /* check and see if we're removing the default image */ ++ if (isdigit(*image)) { ++ entry = findEntryByPath(cfg, image, prefix, NULL); ++ if (entry) ++ entry->skip = 1; ++ return; ++ } + +- while ((entry = findEntryByPath(cfg, image, prefix, NULL))) +- entry->skip = 1; ++ while ((entry = findEntryByPath(cfg, image, prefix, NULL))) ++ entry->skip = 1; + } + +-void setDefaultImage(struct grubConfig * config, int hasNew, +- const char * defaultKernelPath, int newIsDefault, +- const char * prefix, int flags, int index) { +- struct singleEntry * entry, * entry2, * newDefault; +- int i, j; +- +- if (newIsDefault) { +- config->defaultImage = 0; +- return; +- } else if ((index >= 0) && config->cfi->defaultIsIndex) { +- if (findEntryByIndex(config, index)) +- config->defaultImage = index; +- else +- config->defaultImage = -1; +- return; +- } else if (defaultKernelPath) { +- i = 0; +- if (findEntryByPath(config, defaultKernelPath, prefix, &i)) { +- config->defaultImage = i; +- } else { +- config->defaultImage = -1; +- return; ++void setDefaultImage(struct grubConfig *config, int hasNew, ++ const char *defaultKernelPath, int newIsDefault, ++ const char *prefix, int flags, int index) ++{ ++ struct singleEntry *entry, *entry2, *newDefault; ++ int i, j; ++ ++ if (newIsDefault) { ++ config->defaultImage = 0; ++ return; ++ } else if ((index >= 0) && config->cfi->defaultIsIndex) { ++ if (findEntryByIndex(config, index)) ++ config->defaultImage = index; ++ else ++ config->defaultImage = -1; ++ return; ++ } else if (defaultKernelPath) { ++ i = 0; ++ if (findEntryByPath(config, defaultKernelPath, prefix, &i)) { ++ config->defaultImage = i; ++ } else { ++ config->defaultImage = -1; ++ return; ++ } + } +- } + +- /* defaultImage now points to what we'd like to use, but before any order +- changes */ +- if ((config->defaultImage == DEFAULT_SAVED) || +- (config->defaultImage == DEFAULT_SAVED_GRUB2)) +- /* default is set to saved, we don't want to change it */ +- return; ++ /* defaultImage now points to what we'd like to use, but before any order ++ changes */ ++ if ((config->defaultImage == DEFAULT_SAVED) || ++ (config->defaultImage == DEFAULT_SAVED_GRUB2)) ++ /* default is set to saved, we don't want to change it */ ++ return; + +- if (config->defaultImage > -1) +- entry = findEntryByIndex(config, config->defaultImage); +- else +- entry = NULL; ++ if (config->defaultImage > -1) ++ entry = findEntryByIndex(config, config->defaultImage); ++ else ++ entry = NULL; + +- if (entry && !entry->skip) { +- /* we can preserve the default */ +- if (hasNew) +- config->defaultImage++; +- +- /* count the number of entries erased before this one */ +- for (j = 0; j < config->defaultImage; j++) { +- entry2 = findEntryByIndex(config, j); +- if (entry2->skip) config->defaultImage--; +- } +- } else if (hasNew) { +- config->defaultImage = 0; +- } else { +- /* Either we just erased the default (or the default line was bad +- * to begin with) and didn't put a new one in. We'll use the first +- * valid image. */ +- newDefault = findTemplate(config, prefix, &config->defaultImage, 1, +- flags); +- if (!newDefault) +- config->defaultImage = -1; +- } +-} ++ if (entry && !entry->skip) { ++ /* we can preserve the default */ ++ if (hasNew) ++ config->defaultImage++; + +-void setFallbackImage(struct grubConfig * config, int hasNew) { +- struct singleEntry * entry, * entry2; +- int j; +- +- if (config->fallbackImage == -1) return; +- +- entry = findEntryByIndex(config, config->fallbackImage); +- if (!entry || entry->skip) { +- config->fallbackImage = -1; +- return; +- } +- +- if (hasNew) +- config->fallbackImage++; +- +- /* count the number of entries erased before this one */ +- for (j = 0; j < config->fallbackImage; j++) { +- entry2 = findEntryByIndex(config, j); +- if (entry2->skip) config->fallbackImage--; +- } ++ /* count the number of entries erased before this one */ ++ for (j = 0; j < config->defaultImage; j++) { ++ entry2 = findEntryByIndex(config, j); ++ if (entry2->skip) ++ config->defaultImage--; ++ } ++ } else if (hasNew) { ++ config->defaultImage = 0; ++ } else { ++ /* Either we just erased the default (or the default line was bad ++ * to begin with) and didn't put a new one in. We'll use the first ++ * valid image. */ ++ newDefault = ++ findTemplate(config, prefix, &config->defaultImage, 1, ++ flags); ++ if (!newDefault) ++ config->defaultImage = -1; ++ } + } + +-void displayEntry(struct singleEntry * entry, const char * prefix, int index) { +- struct singleLine * line; +- char * root = NULL; +- int i; +- +- printf("index=%d\n", index); +- +- line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); +- if (!line) { +- printf("non linux entry\n"); +- return; +- } +- +- if (!strncmp(prefix, line->elements[1].item, strlen(prefix))) +- printf("kernel=%s\n", line->elements[1].item); +- else +- printf("kernel=%s%s\n", prefix, line->elements[1].item); +- +- if (line->numElements >= 3) { +- printf("args=\""); +- i = 2; +- while (i < line->numElements) { +- if (!strncmp(line->elements[i].item, "root=", 5)) { +- root = line->elements[i].item + 5; +- } else { +- printf("%s%s", line->elements[i].item, +- line->elements[i].indent); +- } +- +- i++; +- } +- printf("\"\n"); +- } else { +- line = getLineByType(LT_KERNELARGS, entry->lines); +- if (line) { +- char * s; ++void setFallbackImage(struct grubConfig *config, int hasNew) ++{ ++ struct singleEntry *entry, *entry2; ++ int j; + +- printf("args=\""); +- i = 1; +- while (i < line->numElements) { +- if (!strncmp(line->elements[i].item, "root=", 5)) { +- root = line->elements[i].item + 5; +- } else { +- s = line->elements[i].item; ++ if (config->fallbackImage == -1) ++ return; + +- printf("%s%s", s, line->elements[i].indent); +- } ++ entry = findEntryByIndex(config, config->fallbackImage); ++ if (!entry || entry->skip) { ++ config->fallbackImage = -1; ++ return; ++ } + +- i++; +- } ++ if (hasNew) ++ config->fallbackImage++; + +- s = line->elements[i - 1].indent; +- printf("\"\n"); ++ /* count the number of entries erased before this one */ ++ for (j = 0; j < config->fallbackImage; j++) { ++ entry2 = findEntryByIndex(config, j); ++ if (entry2->skip) ++ config->fallbackImage--; + } +- } ++} + +- if (!root) { +- line = getLineByType(LT_ROOT, entry->lines); +- if (line && line->numElements >= 2) +- root=line->elements[1].item; +- } ++void displayEntry(struct singleEntry *entry, const char *prefix, int index) ++{ ++ struct singleLine *line; ++ char *root = NULL; ++ int i; + +- if (root) { +- char * s = alloca(strlen(root) + 1); +- +- strcpy(s, root); +- if (s[strlen(s) - 1] == '"') +- s[strlen(s) - 1] = '\0'; +- /* make sure the root doesn't have a trailing " */ +- printf("root=%s\n", s); +- } ++ printf("index=%d\n", index); + +- line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines); ++ line = ++ getLineByType(LT_KERNEL | LT_HYPER | LT_KERNEL_EFI | LT_KERNEL_16, ++ entry->lines); ++ if (!line) { ++ printf("non linux entry\n"); ++ return; ++ } + +- if (line && line->numElements >= 2) { + if (!strncmp(prefix, line->elements[1].item, strlen(prefix))) +- printf("initrd="); ++ printf("kernel=%s\n", line->elements[1].item); + else +- printf("initrd=%s", prefix); +- +- for (i = 1; i < line->numElements; i++) +- printf("%s%s", line->elements[i].item, line->elements[i].indent); +- printf("\n"); +- } +- +- line = getLineByType(LT_TITLE, entry->lines); +- if (line) { +- printf("title=%s\n", line->elements[1].item); +- } else { +- char * title; +- line = getLineByType(LT_MENUENTRY, entry->lines); +- if (line) { +- title = grub2ExtractTitle(line); +- if (title) +- printf("title=%s\n", title); +- } +- } +-} +- +-int isSuseSystem(void) { +- const char * path; +- const static char default_path[] = "/etc/SuSE-release"; +- +- if ((path = getenv("GRUBBY_SUSE_RELEASE")) == NULL) +- path = default_path; +- +- if (!access(path, R_OK)) +- return 1; +- return 0; +-} ++ printf("kernel=%s%s\n", prefix, line->elements[1].item); ++ ++ if (line->numElements >= 3) { ++ printf("args=\""); ++ i = 2; ++ while (i < line->numElements) { ++ if (!strncmp(line->elements[i].item, "root=", 5)) { ++ root = line->elements[i].item + 5; ++ } else { ++ printf("%s%s", line->elements[i].item, ++ line->elements[i].indent); ++ } + +-int isSuseGrubConf(const char * path) { +- FILE * grubConf; +- char * line = NULL; +- size_t len = 0, res = 0; ++ i++; ++ } ++ printf("\"\n"); ++ } else { ++ line = getLineByType(LT_KERNELARGS, entry->lines); ++ if (line) { ++ char *s; ++ ++ printf("args=\""); ++ i = 1; ++ while (i < line->numElements) { ++ if (!strncmp ++ (line->elements[i].item, "root=", 5)) { ++ root = line->elements[i].item + 5; ++ } else { ++ s = line->elements[i].item; ++ ++ printf("%s%s", s, ++ line->elements[i].indent); ++ } + +- grubConf = fopen(path, "r"); +- if (!grubConf) { +- dbgPrintf("Could not open SuSE configuration file '%s'\n", path); +- return 0; +- } ++ i++; ++ } + +- while ((res = getline(&line, &len, grubConf)) != -1) { +- if (!strncmp(line, "setup", 5)) { +- fclose(grubConf); +- free(line); +- return 1; ++ s = line->elements[i - 1].indent; ++ printf("\"\n"); ++ } + } +- } + +- dbgPrintf("SuSE configuration file '%s' does not appear to be valid\n", +- path); ++ if (!root) { ++ line = getLineByType(LT_ROOT, entry->lines); ++ if (line && line->numElements >= 2) ++ root = line->elements[1].item; ++ } + +- fclose(grubConf); +- free(line); +- return 0; +-} ++ if (root) { ++ char *s = alloca(strlen(root) + 1); + +-int suseGrubConfGetLba(const char * path, int * lbaPtr) { +- FILE * grubConf; +- char * line = NULL; +- size_t res = 0, len = 0; ++ strcpy(s, root); ++ if (s[strlen(s) - 1] == '"') ++ s[strlen(s) - 1] = '\0'; ++ /* make sure the root doesn't have a trailing " */ ++ printf("root=%s\n", s); ++ } + +- if (!path) return 1; +- if (!lbaPtr) return 1; ++ line = ++ getLineByType(LT_INITRD | LT_INITRD_EFI | LT_INITRD_16, ++ entry->lines); + +- grubConf = fopen(path, "r"); +- if (!grubConf) return 1; ++ if (line && line->numElements >= 2) { ++ if (!strncmp(prefix, line->elements[1].item, strlen(prefix))) ++ printf("initrd="); ++ else ++ printf("initrd=%s", prefix); + +- while ((res = getline(&line, &len, grubConf)) != -1) { +- if (line[res - 1] == '\n') +- line[res - 1] = '\0'; +- else if (len > res) +- line[res] = '\0'; +- else { +- line = realloc(line, res + 1); +- line[res] = '\0'; ++ for (i = 1; i < line->numElements; i++) ++ printf("%s%s", line->elements[i].item, ++ line->elements[i].indent); ++ printf("\n"); + } + +- if (!strncmp(line, "setup", 5)) { +- if (strstr(line, "--force-lba")) { +- *lbaPtr = 1; +- } else { +- *lbaPtr = 0; +- } +- dbgPrintf("lba: %i\n", *lbaPtr); +- break; ++ line = getLineByType(LT_TITLE, entry->lines); ++ if (line) { ++ printf("title=%s\n", line->elements[1].item); ++ } else { ++ char *title; ++ line = getLineByType(LT_MENUENTRY, entry->lines); ++ if (line) { ++ title = grub2ExtractTitle(line); ++ if (title) ++ printf("title=%s\n", title); ++ } + } +- } +- +- free(line); +- fclose(grubConf); +- return 0; + } + +-int suseGrubConfGetInstallDevice(const char * path, char ** devicePtr) { +- FILE * grubConf; +- char * line = NULL; +- size_t res = 0, len = 0; +- char * lastParamPtr = NULL; +- char * secLastParamPtr = NULL; +- char installDeviceNumber = '\0'; +- char * bounds = NULL; +- +- if (!path) return 1; +- if (!devicePtr) return 1; +- +- grubConf = fopen(path, "r"); +- if (!grubConf) return 1; +- +- while ((res = getline(&line, &len, grubConf)) != -1) { +- if (strncmp(line, "setup", 5)) +- continue; +- +- if (line[res - 1] == '\n') +- line[res - 1] = '\0'; +- else if (len > res) +- line[res] = '\0'; +- else { +- line = realloc(line, res + 1); +- line[res] = '\0'; +- } +- +- lastParamPtr = bounds = line + res; ++int isSuseSystem(void) ++{ ++ const char *path; ++ const static char default_path[] = "/etc/SuSE-release"; + +- /* Last parameter in grub may be an optional IMAGE_DEVICE */ +- while (!isspace(*lastParamPtr)) +- lastParamPtr--; +- lastParamPtr++; ++ if ((path = getenv("GRUBBY_SUSE_RELEASE")) == NULL) ++ path = default_path; + +- secLastParamPtr = lastParamPtr - 2; +- dbgPrintf("lastParamPtr: %s\n", lastParamPtr); ++ if (!access(path, R_OK)) ++ return 1; ++ return 0; ++} + +- if (lastParamPtr + 3 > bounds) { +- dbgPrintf("lastParamPtr going over boundary"); +- fclose(grubConf); +- free(line); +- return 1; ++int isSuseGrubConf(const char *path) ++{ ++ FILE *grubConf; ++ char *line = NULL; ++ size_t len = 0, res = 0; ++ ++ grubConf = fopen(path, "r"); ++ if (!grubConf) { ++ dbgPrintf("Could not open SuSE configuration file '%s'\n", ++ path); ++ return 0; + } +- if (!strncmp(lastParamPtr, "(hd", 3)) +- lastParamPtr += 3; +- dbgPrintf("lastParamPtr: %c\n", *lastParamPtr); + +- /* +- * Second last parameter will decide wether last parameter is +- * an IMAGE_DEVICE or INSTALL_DEVICE +- */ +- while (!isspace(*secLastParamPtr)) +- secLastParamPtr--; +- secLastParamPtr++; +- +- if (secLastParamPtr + 3 > bounds) { +- dbgPrintf("secLastParamPtr going over boundary"); +- fclose(grubConf); +- free(line); +- return 1; +- } +- dbgPrintf("secLastParamPtr: %s\n", secLastParamPtr); +- if (!strncmp(secLastParamPtr, "(hd", 3)) { +- secLastParamPtr += 3; +- dbgPrintf("secLastParamPtr: %c\n", *secLastParamPtr); +- installDeviceNumber = *secLastParamPtr; +- } else { +- installDeviceNumber = *lastParamPtr; ++ while ((res = getline(&line, &len, grubConf)) != -1) { ++ if (!strncmp(line, "setup", 5)) { ++ fclose(grubConf); ++ free(line); ++ return 1; ++ } + } + +- *devicePtr = malloc(6); +- snprintf(*devicePtr, 6, "(hd%c)", installDeviceNumber); +- dbgPrintf("installDeviceNumber: %c\n", installDeviceNumber); ++ dbgPrintf("SuSE configuration file '%s' does not appear to be valid\n", ++ path); ++ + fclose(grubConf); + free(line); + return 0; +- } +- +- free(line); +- fclose(grubConf); +- return 1; + } + +-int grubGetBootFromDeviceMap(const char * device, +- char ** bootPtr) { +- FILE * deviceMap; +- char * line = NULL; +- size_t res = 0, len = 0; +- char * devicePtr; +- char * bounds = NULL; +- const char * path; +- const static char default_path[] = "/boot/grub/device.map"; +- +- if (!device) return 1; +- if (!bootPtr) return 1; +- +- if ((path = getenv("GRUBBY_GRUB_DEVICE_MAP")) == NULL) +- path = default_path; +- +- dbgPrintf("opening grub device.map file from: %s\n", path); +- deviceMap = fopen(path, "r"); +- if (!deviceMap) +- return 1; +- +- while ((res = getline(&line, &len, deviceMap)) != -1) { +- if (!strncmp(line, "#", 1)) +- continue; +- +- if (line[res - 1] == '\n') +- line[res - 1] = '\0'; +- else if (len > res) +- line[res] = '\0'; +- else { +- line = realloc(line, res + 1); +- line[res] = '\0'; +- } ++int suseGrubConfGetLba(const char *path, int *lbaPtr) ++{ ++ FILE *grubConf; ++ char *line = NULL; ++ size_t res = 0, len = 0; + +- devicePtr = line; +- bounds = line + res; ++ if (!path) ++ return 1; ++ if (!lbaPtr) ++ return 1; + +- while ((isspace(*line) && ((devicePtr + 1) <= bounds))) +- devicePtr++; +- dbgPrintf("device: %s\n", devicePtr); ++ grubConf = fopen(path, "r"); ++ if (!grubConf) ++ return 1; + +- if (!strncmp(devicePtr, device, strlen(device))) { +- devicePtr += strlen(device); +- while (isspace(*devicePtr) && ((devicePtr + 1) <= bounds)) +- devicePtr++; ++ while ((res = getline(&line, &len, grubConf)) != -1) { ++ if (line[res - 1] == '\n') ++ line[res - 1] = '\0'; ++ else if (len > res) ++ line[res] = '\0'; ++ else { ++ line = realloc(line, res + 1); ++ line[res] = '\0'; ++ } + +- *bootPtr = strdup(devicePtr); +- break; ++ if (!strncmp(line, "setup", 5)) { ++ if (strstr(line, "--force-lba")) { ++ *lbaPtr = 1; ++ } else { ++ *lbaPtr = 0; ++ } ++ dbgPrintf("lba: %i\n", *lbaPtr); ++ break; ++ } + } +- } + +- free(line); +- fclose(deviceMap); +- return 0; ++ free(line); ++ fclose(grubConf); ++ return 0; + } + +-int suseGrubConfGetBoot(const char * path, char ** bootPtr) { +- char * grubDevice; ++int suseGrubConfGetInstallDevice(const char *path, char **devicePtr) ++{ ++ FILE *grubConf; ++ char *line = NULL; ++ size_t res = 0, len = 0; ++ char *lastParamPtr = NULL; ++ char *secLastParamPtr = NULL; ++ char installDeviceNumber = '\0'; ++ char *bounds = NULL; ++ ++ if (!path) ++ return 1; ++ if (!devicePtr) ++ return 1; + +- if (suseGrubConfGetInstallDevice(path, &grubDevice)) +- dbgPrintf("error looking for grub installation device\n"); +- else +- dbgPrintf("grubby installation device: %s\n", grubDevice); ++ grubConf = fopen(path, "r"); ++ if (!grubConf) ++ return 1; + +- if (grubGetBootFromDeviceMap(grubDevice, bootPtr)) +- dbgPrintf("error looking for grub boot device\n"); +- else +- dbgPrintf("grubby boot device: %s\n", *bootPtr); ++ while ((res = getline(&line, &len, grubConf)) != -1) { ++ if (strncmp(line, "setup", 5)) ++ continue; ++ ++ if (line[res - 1] == '\n') ++ line[res - 1] = '\0'; ++ else if (len > res) ++ line[res] = '\0'; ++ else { ++ line = realloc(line, res + 1); ++ line[res] = '\0'; ++ } + +- free(grubDevice); +- return 0; +-} ++ lastParamPtr = bounds = line + res; + +-int parseSuseGrubConf(int * lbaPtr, char ** bootPtr) { +- /* +- * This SuSE grub configuration file at this location is not your average +- * grub configuration file, but instead the grub commands used to setup +- * grub on that system. +- */ +- const char * path; +- const static char default_path[] = "/etc/grub.conf"; ++ /* Last parameter in grub may be an optional IMAGE_DEVICE */ ++ while (!isspace(*lastParamPtr)) ++ lastParamPtr--; ++ lastParamPtr++; + +- if ((path = getenv("GRUBBY_SUSE_GRUB_CONF")) == NULL) +- path = default_path; ++ secLastParamPtr = lastParamPtr - 2; ++ dbgPrintf("lastParamPtr: %s\n", lastParamPtr); + +- if (!isSuseGrubConf(path)) return 1; ++ if (lastParamPtr + 3 > bounds) { ++ dbgPrintf("lastParamPtr going over boundary"); ++ fclose(grubConf); ++ free(line); ++ return 1; ++ } ++ if (!strncmp(lastParamPtr, "(hd", 3)) ++ lastParamPtr += 3; ++ dbgPrintf("lastParamPtr: %c\n", *lastParamPtr); + +- if (lbaPtr) { +- *lbaPtr = 0; +- if (suseGrubConfGetLba(path, lbaPtr)) +- return 1; +- } ++ /* ++ * Second last parameter will decide wether last parameter is ++ * an IMAGE_DEVICE or INSTALL_DEVICE ++ */ ++ while (!isspace(*secLastParamPtr)) ++ secLastParamPtr--; ++ secLastParamPtr++; ++ ++ if (secLastParamPtr + 3 > bounds) { ++ dbgPrintf("secLastParamPtr going over boundary"); ++ fclose(grubConf); ++ free(line); ++ return 1; ++ } ++ dbgPrintf("secLastParamPtr: %s\n", secLastParamPtr); ++ if (!strncmp(secLastParamPtr, "(hd", 3)) { ++ secLastParamPtr += 3; ++ dbgPrintf("secLastParamPtr: %c\n", *secLastParamPtr); ++ installDeviceNumber = *secLastParamPtr; ++ } else { ++ installDeviceNumber = *lastParamPtr; ++ } + +- if (bootPtr) { +- *bootPtr = NULL; +- suseGrubConfGetBoot(path, bootPtr); +- } ++ *devicePtr = malloc(6); ++ snprintf(*devicePtr, 6, "(hd%c)", installDeviceNumber); ++ dbgPrintf("installDeviceNumber: %c\n", installDeviceNumber); ++ fclose(grubConf); ++ free(line); ++ return 0; ++ } + +- return 0; ++ free(line); ++ fclose(grubConf); ++ return 1; + } + +-int parseSysconfigGrub(int * lbaPtr, char ** bootPtr) { +- FILE * in; +- char buf[1024]; +- char * chptr; +- char * start; +- char * param; +- +- in = fopen("/etc/sysconfig/grub", "r"); +- if (!in) return 1; ++int grubGetBootFromDeviceMap(const char *device, char **bootPtr) ++{ ++ FILE *deviceMap; ++ char *line = NULL; ++ size_t res = 0, len = 0; ++ char *devicePtr; ++ char *bounds = NULL; ++ const char *path; ++ const static char default_path[] = "/boot/grub/device.map"; ++ ++ if (!device) ++ return 1; ++ if (!bootPtr) ++ return 1; + +- if (lbaPtr) *lbaPtr = 0; +- if (bootPtr) *bootPtr = NULL; ++ if ((path = getenv("GRUBBY_GRUB_DEVICE_MAP")) == NULL) ++ path = default_path; + +- while (fgets(buf, sizeof(buf), in)) { +- start = buf; +- while (isspace(*start)) start++; +- if (*start == '#') continue; ++ dbgPrintf("opening grub device.map file from: %s\n", path); ++ deviceMap = fopen(path, "r"); ++ if (!deviceMap) ++ return 1; + +- chptr = strchr(start, '='); +- if (!chptr) continue; +- chptr--; +- while (*chptr && isspace(*chptr)) chptr--; +- chptr++; +- *chptr = '\0'; ++ while ((res = getline(&line, &len, deviceMap)) != -1) { ++ if (!strncmp(line, "#", 1)) ++ continue; ++ ++ if (line[res - 1] == '\n') ++ line[res - 1] = '\0'; ++ else if (len > res) ++ line[res] = '\0'; ++ else { ++ line = realloc(line, res + 1); ++ line[res] = '\0'; ++ } + +- param = chptr + 1; +- while (*param && isspace(*param)) param++; +- if (*param == '=') { +- param++; +- while (*param && isspace(*param)) param++; +- } ++ devicePtr = line; ++ bounds = line + res; + +- chptr = param; +- while (*chptr && !isspace(*chptr)) chptr++; +- *chptr = '\0'; ++ while ((isspace(*line) && ((devicePtr + 1) <= bounds))) ++ devicePtr++; ++ dbgPrintf("device: %s\n", devicePtr); + +- if (!strcmp(start, "forcelba") && !strcmp(param, "1") && lbaPtr) +- *lbaPtr = 1; +- else if (!strcmp(start, "boot") && bootPtr) +- *bootPtr = strdup(param); +- } ++ if (!strncmp(devicePtr, device, strlen(device))) { ++ devicePtr += strlen(device); ++ while (isspace(*devicePtr) ++ && ((devicePtr + 1) <= bounds)) ++ devicePtr++; + +- fclose(in); ++ *bootPtr = strdup(devicePtr); ++ break; ++ } ++ } + +- return 0; ++ free(line); ++ fclose(deviceMap); ++ return 0; + } + +-void dumpSysconfigGrub(void) { +- char * boot = NULL; +- int lba; ++int suseGrubConfGetBoot(const char *path, char **bootPtr) ++{ ++ char *grubDevice; + +- if (isSuseSystem()) { +- if (parseSuseGrubConf(&lba, &boot)) { +- free(boot); +- return; +- } +- } else { +- if (parseSysconfigGrub(&lba, &boot)) { +- free(boot); +- return; +- } +- } ++ if (suseGrubConfGetInstallDevice(path, &grubDevice)) ++ dbgPrintf("error looking for grub installation device\n"); ++ else ++ dbgPrintf("grubby installation device: %s\n", grubDevice); + +- if (lba) printf("lba\n"); +- if (boot) { +- printf("boot=%s\n", boot); +- free(boot); +- } +-} ++ if (grubGetBootFromDeviceMap(grubDevice, bootPtr)) ++ dbgPrintf("error looking for grub boot device\n"); ++ else ++ dbgPrintf("grubby boot device: %s\n", *bootPtr); + +-int displayInfo(struct grubConfig * config, char * kernel, +- const char * prefix) { +- int i = 0; +- struct singleEntry * entry; +- struct singleLine * line; ++ free(grubDevice); ++ return 0; ++} + +- entry = findEntryByPath(config, kernel, prefix, &i); +- if (!entry) { +- fprintf(stderr, _("grubby: kernel not found\n")); +- return 1; +- } ++int parseSuseGrubConf(int *lbaPtr, char **bootPtr) ++{ ++ /* ++ * This SuSE grub configuration file at this location is not your average ++ * grub configuration file, but instead the grub commands used to setup ++ * grub on that system. ++ */ ++ const char *path; ++ const static char default_path[] = "/etc/grub.conf"; + +- /* this is a horrible hack to support /etc/sysconfig/grub; there must +- be a better way */ +- if (config->cfi == &grubConfigType) { +- dumpSysconfigGrub(); +- } else { +- line = getLineByType(LT_BOOT, config->theLines); +- if (line && line->numElements >= 1) { +- printf("boot=%s\n", line->elements[1].item); +- } ++ if ((path = getenv("GRUBBY_SUSE_GRUB_CONF")) == NULL) ++ path = default_path; + +- line = getLineByType(LT_LBA, config->theLines); +- if (line) printf("lba\n"); +- } ++ if (!isSuseGrubConf(path)) ++ return 1; + +- displayEntry(entry, prefix, i); ++ if (lbaPtr) { ++ *lbaPtr = 0; ++ if (suseGrubConfGetLba(path, lbaPtr)) ++ return 1; ++ } + +- i++; +- while ((entry = findEntryByPath(config, kernel, prefix, &i))) { +- displayEntry(entry, prefix, i); +- i++; +- } ++ if (bootPtr) { ++ *bootPtr = NULL; ++ suseGrubConfGetBoot(path, bootPtr); ++ } + +- return 0; ++ return 0; + } + +-struct singleLine * addLineTmpl(struct singleEntry * entry, +- struct singleLine * tmplLine, +- struct singleLine * prevLine, +- const char * val, +- struct configFileInfo * cfi) ++int parseSysconfigGrub(int *lbaPtr, char **bootPtr) + { +- struct singleLine * newLine = lineDup(tmplLine); +- +- if (isEfi && cfi == &grub2ConfigType) { +- enum lineType_e old = newLine->type; +- newLine->type = preferredLineType(newLine->type, cfi); +- if (old != newLine->type) +- newLine->elements[0].item = getKeyByType(newLine->type, cfi); +- } +- +- if (val) { +- /* override the inherited value with our own. +- * This is a little weak because it only applies to elements[1] +- */ +- if (newLine->numElements > 1) +- removeElement(newLine, 1); +- insertElement(newLine, val, 1, cfi); +- +- /* but try to keep the rootspec from the template... sigh */ +- if (tmplLine->type & (LT_HYPER|LT_KERNEL|LT_MBMODULE|LT_INITRD|LT_KERNEL_EFI|LT_INITRD_EFI|LT_KERNEL_16|LT_INITRD_16)) { +- char * rootspec = getRootSpecifier(tmplLine->elements[1].item); +- if (rootspec != NULL) { +- free(newLine->elements[1].item); +- newLine->elements[1].item = +- sdupprintf("%s%s", rootspec, val); +- } +- } +- } +- +- dbgPrintf("addLineTmpl(%s)\n", newLine->numElements ? +- newLine->elements[0].item : ""); +- +- if (!entry->lines) { +- /* first one on the list */ +- entry->lines = newLine; +- } else if (prevLine) { +- /* add after prevLine */ +- newLine->next = prevLine->next; +- prevLine->next = newLine; +- } +- +- return newLine; +-} ++ FILE *in; ++ char buf[1024]; ++ char *chptr; ++ char *start; ++ char *param; ++ ++ in = fopen("/etc/sysconfig/grub", "r"); ++ if (!in) ++ return 1; + +-/* val may be NULL */ +-struct singleLine * addLine(struct singleEntry * entry, +- struct configFileInfo * cfi, +- enum lineType_e type, char * defaultIndent, +- const char * val) { +- struct singleLine * line, * prev; +- struct keywordTypes * kw; +- struct singleLine tmpl; +- +- /* NB: This function shouldn't allocate items on the heap, rather on the +- * stack since it calls addLineTmpl which will make copies. +- */ +- if (type == LT_TITLE && cfi->titleBracketed) { +- /* we're doing a bracketed title (zipl) */ +- tmpl.type = type; +- tmpl.numElements = 1; +- tmpl.elements = alloca(sizeof(*tmpl.elements)); +- tmpl.elements[0].item = alloca(strlen(val)+3); +- sprintf(tmpl.elements[0].item, "[%s]", val); +- tmpl.elements[0].indent = ""; +- val = NULL; +- } else if (type == LT_MENUENTRY) { +- char *lineend = "--class gnu-linux --class gnu --class os {"; +- if (!val) { +- fprintf(stderr, "Line type LT_MENUENTRY requires a value\n"); +- abort(); +- } +- kw = getKeywordByType(type, cfi); +- if (!kw) { +- fprintf(stderr, "Looking up keyword for unknown type %d\n", type); +- abort(); +- } +- tmpl.indent = ""; +- tmpl.type = type; +- tmpl.numElements = 3; +- tmpl.elements = alloca(sizeof(*tmpl.elements) * tmpl.numElements); +- tmpl.elements[0].item = kw->key; +- tmpl.elements[0].indent = alloca(2); +- sprintf(tmpl.elements[0].indent, "%c", kw->nextChar); +- tmpl.elements[1].item = (char *)val; +- tmpl.elements[1].indent = alloca(2); +- sprintf(tmpl.elements[1].indent, "%c", kw->nextChar); +- tmpl.elements[2].item = alloca(strlen(lineend)+1); +- strcpy(tmpl.elements[2].item, lineend); +- tmpl.elements[2].indent = ""; +- } else { +- kw = getKeywordByType(type, cfi); +- if (!kw) { +- fprintf(stderr, "Looking up keyword for unknown type %d\n", type); +- abort(); +- } +- tmpl.type = type; +- tmpl.numElements = val ? 2 : 1; +- tmpl.elements = alloca(sizeof(*tmpl.elements) * tmpl.numElements); +- tmpl.elements[0].item = kw->key; +- tmpl.elements[0].indent = alloca(2); +- sprintf(tmpl.elements[0].indent, "%c", kw->nextChar); +- if (val) { +- tmpl.elements[1].item = (char *)val; +- tmpl.elements[1].indent = ""; +- } +- } +- +- /* The last non-empty line gives us the indention to us and the line +- to insert after. Note that comments are considered empty lines, which +- may not be ideal? If there are no lines or we are looking at the +- first line, we use defaultIndent (the first line is normally indented +- differently from the rest) */ +- for (line = entry->lines, prev = NULL; line; line = line->next) { +- if (line->numElements) prev = line; +- /* fall back on the last line if prev isn't otherwise set */ +- if (!line->next && !prev) prev = line; +- } +- +- struct singleLine *menuEntry; +- menuEntry = getLineByType(LT_MENUENTRY, entry->lines); +- if (tmpl.type == LT_ENTRY_END) { +- if (menuEntry) +- tmpl.indent = menuEntry->indent; +- else +- tmpl.indent = defaultIndent ?: ""; +- } else if (tmpl.type != LT_MENUENTRY) { +- if (menuEntry) +- tmpl.indent = "\t"; +- else if (prev == entry->lines) +- tmpl.indent = defaultIndent ?: ""; +- else +- tmpl.indent = prev->indent; +- } ++ if (lbaPtr) ++ *lbaPtr = 0; ++ if (bootPtr) ++ *bootPtr = NULL; ++ ++ while (fgets(buf, sizeof(buf), in)) { ++ start = buf; ++ while (isspace(*start)) ++ start++; ++ if (*start == '#') ++ continue; ++ ++ chptr = strchr(start, '='); ++ if (!chptr) ++ continue; ++ chptr--; ++ while (*chptr && isspace(*chptr)) ++ chptr--; ++ chptr++; ++ *chptr = '\0'; ++ ++ param = chptr + 1; ++ while (*param && isspace(*param)) ++ param++; ++ if (*param == '=') { ++ param++; ++ while (*param && isspace(*param)) ++ param++; ++ } + +- return addLineTmpl(entry, &tmpl, prev, val, cfi); +-} ++ chptr = param; ++ while (*chptr && !isspace(*chptr)) ++ chptr++; ++ *chptr = '\0'; ++ ++ if (!strcmp(start, "forcelba") && !strcmp(param, "1") && lbaPtr) ++ *lbaPtr = 1; ++ else if (!strcmp(start, "boot") && bootPtr) ++ *bootPtr = strdup(param); ++ } + +-void removeLine(struct singleEntry * entry, struct singleLine * line) { +- struct singleLine * prev; +- int i; +- +- for (i = 0; i < line->numElements; i++) { +- free(line->elements[i].item); +- free(line->elements[i].indent); +- } +- free(line->elements); +- free(line->indent); +- +- if (line == entry->lines) { +- entry->lines = line->next; +- } else { +- prev = entry->lines; +- while (prev->next != line) prev = prev->next; +- prev->next = line->next; +- } +- +- free(line); ++ fclose(in); ++ ++ return 0; + } + +-static void requote(struct singleLine *tmplLine, struct configFileInfo * cfi) ++void dumpSysconfigGrub(void) + { +- struct singleLine newLine = { +- .indent = tmplLine->indent, +- .type = tmplLine->type, +- .next = tmplLine->next, +- }; +- int firstQuotedItem = -1; +- int quoteLen = 0; +- int j; +- int element = 0; +- char *c; +- +- c = malloc(strlen(tmplLine->elements[0].item) + 1); +- strcpy(c, tmplLine->elements[0].item); +- insertElement(&newLine, c, element++, cfi); +- free(c); +- c = NULL; +- +- for (j = 1; j < tmplLine->numElements; j++) { +- if (firstQuotedItem == -1) { +- quoteLen += strlen(tmplLine->elements[j].item); +- +- if (isquote(tmplLine->elements[j].item[0])) { +- firstQuotedItem = j; +- quoteLen += strlen(tmplLine->elements[j].indent); +- } else { +- c = malloc(quoteLen + 1); +- strcpy(c, tmplLine->elements[j].item); +- insertElement(&newLine, c, element++, cfi); +- free(c); +- quoteLen = 0; +- } ++ char *boot = NULL; ++ int lba; ++ ++ if (isSuseSystem()) { ++ if (parseSuseGrubConf(&lba, &boot)) { ++ free(boot); ++ return; ++ } + } else { +- int itemlen = strlen(tmplLine->elements[j].item); +- quoteLen += itemlen; +- quoteLen += strlen(tmplLine->elements[j].indent); +- +- if (isquote(tmplLine->elements[j].item[itemlen - 1])) { +- c = malloc(quoteLen + 1); +- c[0] = '\0'; +- for (int i = firstQuotedItem; i < j+1; i++) { +- strcat(c, tmplLine->elements[i].item); +- strcat(c, tmplLine->elements[i].indent); ++ if (parseSysconfigGrub(&lba, &boot)) { ++ free(boot); ++ return; + } +- insertElement(&newLine, c, element++, cfi); +- free(c); +- +- firstQuotedItem = -1; +- quoteLen = 0; +- } +- } +- } +- while (tmplLine->numElements) +- removeElement(tmplLine, 0); +- if (tmplLine->elements) +- free(tmplLine->elements); +- +- tmplLine->numElements = newLine.numElements; +- tmplLine->elements = newLine.elements; +-} ++ } + +-static void insertElement(struct singleLine * line, +- const char * item, int insertHere, +- struct configFileInfo * cfi) +-{ +- struct keywordTypes * kw; +- char indent[2] = ""; +- +- /* sanity check */ +- if (insertHere > line->numElements) { +- dbgPrintf("insertElement() adjusting insertHere from %d to %d\n", +- insertHere, line->numElements); +- insertHere = line->numElements; +- } +- +- line->elements = realloc(line->elements, (line->numElements + 1) * +- sizeof(*line->elements)); +- memmove(&line->elements[insertHere+1], +- &line->elements[insertHere], +- (line->numElements - insertHere) * +- sizeof(*line->elements)); +- line->elements[insertHere].item = strdup(item); +- +- kw = getKeywordByType(line->type, cfi); +- +- if (line->numElements == 0) { +- indent[0] = '\0'; +- } else if (insertHere == 0) { +- indent[0] = kw->nextChar; +- } else if (kw->separatorChar != '\0') { +- indent[0] = kw->separatorChar; +- } else { +- indent[0] = ' '; +- } +- +- if (insertHere > 0 && line->elements[insertHere-1].indent[0] == '\0') { +- /* move the end-of-line forward */ +- line->elements[insertHere].indent = +- line->elements[insertHere-1].indent; +- line->elements[insertHere-1].indent = strdup(indent); +- } else { +- line->elements[insertHere].indent = strdup(indent); +- } +- +- line->numElements++; +- +- dbgPrintf("insertElement(%s, '%s%s', %d)\n", +- line->elements[0].item, +- line->elements[insertHere].item, +- line->elements[insertHere].indent, +- insertHere); ++ if (lba) ++ printf("lba\n"); ++ if (boot) { ++ printf("boot=%s\n", boot); ++ free(boot); ++ } + } + +-static void removeElement(struct singleLine * line, int removeHere) { +- int i; ++int displayInfo(struct grubConfig *config, char *kernel, const char *prefix) ++{ ++ int i = 0; ++ struct singleEntry *entry; ++ struct singleLine *line; + +- /* sanity check */ +- if (removeHere >= line->numElements) return; ++ entry = findEntryByPath(config, kernel, prefix, &i); ++ if (!entry) { ++ fprintf(stderr, _("grubby: kernel not found\n")); ++ return 1; ++ } + +- dbgPrintf("removeElement(%s, %d:%s)\n", line->elements[0].item, +- removeHere, line->elements[removeHere].item); ++ /* this is a horrible hack to support /etc/sysconfig/grub; there must ++ be a better way */ ++ if (config->cfi == &grubConfigType) { ++ dumpSysconfigGrub(); ++ } else { ++ line = getLineByType(LT_BOOT, config->theLines); ++ if (line && line->numElements >= 1) { ++ printf("boot=%s\n", line->elements[1].item); ++ } + +- free(line->elements[removeHere].item); ++ line = getLineByType(LT_LBA, config->theLines); ++ if (line) ++ printf("lba\n"); ++ } + +- if (removeHere > 1) { +- /* previous argument gets this argument's post-indentation */ +- free(line->elements[removeHere-1].indent); +- line->elements[removeHere-1].indent = +- line->elements[removeHere].indent; +- } else { +- free(line->elements[removeHere].indent); +- } ++ displayEntry(entry, prefix, i); + +- /* now collapse the array, but don't bother to realloc smaller */ +- for (i = removeHere; i < line->numElements - 1; i++) +- line->elements[i] = line->elements[i + 1]; ++ i++; ++ while ((entry = findEntryByPath(config, kernel, prefix, &i))) { ++ displayEntry(entry, prefix, i); ++ i++; ++ } + +- line->numElements--; ++ return 0; + } + +-int argMatch(const char * one, const char * two) { +- char * first, * second; +- char * chptr; ++struct singleLine *addLineTmpl(struct singleEntry *entry, ++ struct singleLine *tmplLine, ++ struct singleLine *prevLine, ++ const char *val, struct configFileInfo *cfi) ++{ ++ struct singleLine *newLine = lineDup(tmplLine); ++ ++ if (isEfi && cfi == &grub2ConfigType) { ++ enum lineType_e old = newLine->type; ++ newLine->type = preferredLineType(newLine->type, cfi); ++ if (old != newLine->type) ++ newLine->elements[0].item = ++ getKeyByType(newLine->type, cfi); ++ } + +- first = strcpy(alloca(strlen(one) + 1), one); +- second = strcpy(alloca(strlen(two) + 1), two); ++ if (val) { ++ /* override the inherited value with our own. ++ * This is a little weak because it only applies to elements[1] ++ */ ++ if (newLine->numElements > 1) ++ removeElement(newLine, 1); ++ insertElement(newLine, val, 1, cfi); ++ ++ /* but try to keep the rootspec from the template... sigh */ ++ if (tmplLine-> ++ type & (LT_HYPER | LT_KERNEL | LT_MBMODULE | LT_INITRD | ++ LT_KERNEL_EFI | LT_INITRD_EFI | LT_KERNEL_16 | ++ LT_INITRD_16)) { ++ char *rootspec = ++ getRootSpecifier(tmplLine->elements[1].item); ++ if (rootspec != NULL) { ++ free(newLine->elements[1].item); ++ newLine->elements[1].item = ++ sdupprintf("%s%s", rootspec, val); ++ } ++ } ++ } + +- chptr = strchr(first, '='); +- if (chptr) *chptr = '\0'; ++ dbgPrintf("addLineTmpl(%s)\n", newLine->numElements ? ++ newLine->elements[0].item : ""); + +- chptr = strchr(second, '='); +- if (chptr) *chptr = '\0'; ++ if (!entry->lines) { ++ /* first one on the list */ ++ entry->lines = newLine; ++ } else if (prevLine) { ++ /* add after prevLine */ ++ newLine->next = prevLine->next; ++ prevLine->next = newLine; ++ } + +- return strcmp(first, second); ++ return newLine; + } + +-int updateActualImage(struct grubConfig * cfg, const char * image, +- const char * prefix, const char * addArgs, +- const char * removeArgs, int multibootArgs) { +- struct singleEntry * entry; +- struct singleLine * line, * rootLine; +- int index = 0; +- int i, k; +- const char ** newArgs, ** oldArgs; +- const char ** arg; +- int useKernelArgs, useRoot; +- int firstElement; +- int *usedElements; +- int doreplace; +- +- if (!image) return 0; +- +- if (!addArgs) { +- newArgs = malloc(sizeof(*newArgs)); +- *newArgs = NULL; +- } else { +- if (poptParseArgvString(addArgs, NULL, &newArgs)) { +- fprintf(stderr, +- _("grubby: error separating arguments '%s'\n"), addArgs); +- return 1; +- } +- } +- +- if (!removeArgs) { +- oldArgs = malloc(sizeof(*oldArgs)); +- *oldArgs = NULL; +- } else { +- if (poptParseArgvString(removeArgs, NULL, &oldArgs)) { +- fprintf(stderr, +- _("grubby: error separating arguments '%s'\n"), removeArgs); +- free(newArgs); +- return 1; +- } +- } +- +- +- useKernelArgs = (getKeywordByType(LT_KERNELARGS, cfg->cfi) +- && (!multibootArgs || cfg->cfi->mbConcatArgs)); +- +- useRoot = (getKeywordByType(LT_ROOT, cfg->cfi) +- && !multibootArgs); +- +- for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) { +- +- if (multibootArgs && !entry->multiboot) +- continue; +- +- /* Determine where to put the args. If this config supports +- * LT_KERNELARGS, use that. Otherwise use +- * LT_HYPER/LT_KERNEL/LT_MBMODULE lines. +- */ +- if (useKernelArgs) { +- line = getLineByType(LT_KERNELARGS, entry->lines); +- if (!line) { +- /* no LT_KERNELARGS, need to add it */ +- line = addLine(entry, cfg->cfi, LT_KERNELARGS, +- cfg->secondaryIndent, NULL); +- } +- firstElement = 1; +- +- } else if (multibootArgs) { +- line = getLineByType(LT_HYPER, entry->lines); +- if (!line) { +- /* a multiboot entry without LT_HYPER? */ +- continue; +- } +- firstElement = 2; +- +- } else { +- line = getLineByType(LT_KERNEL|LT_MBMODULE|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); +- if (!line) { +- /* no LT_KERNEL or LT_MBMODULE in this entry? */ +- continue; +- } +- firstElement = 2; +- } ++/* val may be NULL */ ++struct singleLine *addLine(struct singleEntry *entry, ++ struct configFileInfo *cfi, ++ enum lineType_e type, char *defaultIndent, ++ const char *val) ++{ ++ struct singleLine *line, *prev; ++ struct keywordTypes *kw; ++ struct singleLine tmpl; + +- /* handle the elilo case which does: +- * append="hypervisor args -- kernel args" ++ /* NB: This function shouldn't allocate items on the heap, rather on the ++ * stack since it calls addLineTmpl which will make copies. + */ +- if (entry->multiboot && cfg->cfi->mbConcatArgs) { +- /* this is a multiboot entry, make sure there's +- * -- on the args line +- */ +- for (i = firstElement; i < line->numElements; i++) { +- if (!strcmp(line->elements[i].item, "--")) +- break; +- } +- if (i == line->numElements) { +- /* assume all existing args are kernel args, +- * prepend -- to make it official +- */ +- insertElement(line, "--", firstElement, cfg->cfi); +- i = firstElement; +- } +- if (!multibootArgs) { +- /* kernel args start after the -- */ +- firstElement = i + 1; +- } +- } else if (cfg->cfi->mbConcatArgs) { +- /* this is a non-multiboot entry, remove hyper args */ +- for (i = firstElement; i < line->numElements; i++) { +- if (!strcmp(line->elements[i].item, "--")) +- break; +- } +- if (i < line->numElements) { +- /* remove args up to -- */ +- while (strcmp(line->elements[firstElement].item, "--")) +- removeElement(line, firstElement); +- /* remove -- */ +- removeElement(line, firstElement); +- } +- } +- +- usedElements = calloc(line->numElements, sizeof(*usedElements)); +- +- for (k = 0, arg = newArgs; *arg; arg++, k++) { +- +- doreplace = 1; +- for (i = firstElement; i < line->numElements; i++) { +- if (multibootArgs && cfg->cfi->mbConcatArgs && +- !strcmp(line->elements[i].item, "--")) +- { +- /* reached the end of hyper args, insert here */ +- doreplace = 0; +- break; ++ if (type == LT_TITLE && cfi->titleBracketed) { ++ /* we're doing a bracketed title (zipl) */ ++ tmpl.type = type; ++ tmpl.numElements = 1; ++ tmpl.elements = alloca(sizeof(*tmpl.elements)); ++ tmpl.elements[0].item = alloca(strlen(val) + 3); ++ sprintf(tmpl.elements[0].item, "[%s]", val); ++ tmpl.elements[0].indent = ""; ++ val = NULL; ++ } else if (type == LT_MENUENTRY) { ++ char *lineend = "--class gnu-linux --class gnu --class os {"; ++ if (!val) { ++ fprintf(stderr, ++ "Line type LT_MENUENTRY requires a value\n"); ++ abort(); + } +- if (usedElements[i]) +- continue; +- if (!argMatch(line->elements[i].item, *arg)) { +- usedElements[i]=1; +- break; +- } +- } +- +- if (i < line->numElements && doreplace) { +- /* direct replacement */ +- free(line->elements[i].item); +- line->elements[i].item = strdup(*arg); +- +- } else if (useRoot && !strncmp(*arg, "root=/dev/", 10)) { +- /* root= replacement */ +- rootLine = getLineByType(LT_ROOT, entry->lines); +- if (rootLine) { +- free(rootLine->elements[1].item); +- rootLine->elements[1].item = strdup(*arg + 5); +- } else { +- rootLine = addLine(entry, cfg->cfi, LT_ROOT, +- cfg->secondaryIndent, *arg + 5); ++ kw = getKeywordByType(type, cfi); ++ if (!kw) { ++ fprintf(stderr, ++ "Looking up keyword for unknown type %d\n", ++ type); ++ abort(); + } +- } +- +- else { +- /* insert/append */ +- insertElement(line, *arg, i, cfg->cfi); +- usedElements = realloc(usedElements, line->numElements * +- sizeof(*usedElements)); +- memmove(&usedElements[i + 1], &usedElements[i], +- line->numElements - i - 1); +- usedElements[i] = 1; +- +- /* if we updated a root= here even though there is a +- LT_ROOT available we need to remove the LT_ROOT entry +- (this will happen if we switch from a device to a label) */ +- if (useRoot && !strncmp(*arg, "root=", 5)) { +- rootLine = getLineByType(LT_ROOT, entry->lines); +- if (rootLine) +- removeLine(entry, rootLine); ++ tmpl.indent = ""; ++ tmpl.type = type; ++ tmpl.numElements = 3; ++ tmpl.elements = ++ alloca(sizeof(*tmpl.elements) * tmpl.numElements); ++ tmpl.elements[0].item = kw->key; ++ tmpl.elements[0].indent = alloca(2); ++ sprintf(tmpl.elements[0].indent, "%c", kw->nextChar); ++ tmpl.elements[1].item = (char *)val; ++ tmpl.elements[1].indent = alloca(2); ++ sprintf(tmpl.elements[1].indent, "%c", kw->nextChar); ++ tmpl.elements[2].item = alloca(strlen(lineend) + 1); ++ strcpy(tmpl.elements[2].item, lineend); ++ tmpl.elements[2].indent = ""; ++ } else { ++ kw = getKeywordByType(type, cfi); ++ if (!kw) { ++ fprintf(stderr, ++ "Looking up keyword for unknown type %d\n", ++ type); ++ abort(); + } +- } +- } +- +- free(usedElements); +- +- for (arg = oldArgs; *arg; arg++) { +- for (i = firstElement; i < line->numElements; i++) { +- if (multibootArgs && cfg->cfi->mbConcatArgs && +- !strcmp(line->elements[i].item, "--")) +- /* reached the end of hyper args, stop here */ +- break; +- if (!argMatch(line->elements[i].item, *arg)) { +- removeElement(line, i); +- break; ++ tmpl.type = type; ++ tmpl.numElements = val ? 2 : 1; ++ tmpl.elements = ++ alloca(sizeof(*tmpl.elements) * tmpl.numElements); ++ tmpl.elements[0].item = kw->key; ++ tmpl.elements[0].indent = alloca(2); ++ sprintf(tmpl.elements[0].indent, "%c", kw->nextChar); ++ if (val) { ++ tmpl.elements[1].item = (char *)val; ++ tmpl.elements[1].indent = ""; + } +- } +- /* handle removing LT_ROOT line too */ +- if (useRoot && !strncmp(*arg, "root=", 5)) { +- rootLine = getLineByType(LT_ROOT, entry->lines); +- if (rootLine) +- removeLine(entry, rootLine); +- } + } + +- if (line->numElements == 1) { +- /* don't need the line at all (note it has to be a +- LT_KERNELARGS for this to happen */ +- removeLine(entry, line); ++ /* The last non-empty line gives us the indention to us and the line ++ to insert after. Note that comments are considered empty lines, which ++ may not be ideal? If there are no lines or we are looking at the ++ first line, we use defaultIndent (the first line is normally indented ++ differently from the rest) */ ++ for (line = entry->lines, prev = NULL; line; line = line->next) { ++ if (line->numElements) ++ prev = line; ++ /* fall back on the last line if prev isn't otherwise set */ ++ if (!line->next && !prev) ++ prev = line; + } +- } + +- free(newArgs); +- free(oldArgs); ++ struct singleLine *menuEntry; ++ menuEntry = getLineByType(LT_MENUENTRY, entry->lines); ++ if (tmpl.type == LT_ENTRY_END) { ++ if (menuEntry) ++ tmpl.indent = menuEntry->indent; ++ else ++ tmpl.indent = defaultIndent ? : ""; ++ } else if (tmpl.type != LT_MENUENTRY) { ++ if (menuEntry) ++ tmpl.indent = "\t"; ++ else if (prev == entry->lines) ++ tmpl.indent = defaultIndent ? : ""; ++ else ++ tmpl.indent = prev->indent; ++ } + +- return 0; ++ return addLineTmpl(entry, &tmpl, prev, val, cfi); + } + +-int updateImage(struct grubConfig * cfg, const char * image, +- const char * prefix, const char * addArgs, +- const char * removeArgs, +- const char * addMBArgs, const char * removeMBArgs) { +- int rc = 0; ++void removeLine(struct singleEntry *entry, struct singleLine *line) ++{ ++ struct singleLine *prev; ++ int i; + +- if (!image) return rc; ++ for (i = 0; i < line->numElements; i++) { ++ free(line->elements[i].item); ++ free(line->elements[i].indent); ++ } ++ free(line->elements); ++ free(line->indent); + +- /* update the main args first... */ +- if (addArgs || removeArgs) +- rc = updateActualImage(cfg, image, prefix, addArgs, removeArgs, 0); +- if (rc) return rc; ++ if (line == entry->lines) { ++ entry->lines = line->next; ++ } else { ++ prev = entry->lines; ++ while (prev->next != line) ++ prev = prev->next; ++ prev->next = line->next; ++ } + +- /* and now any multiboot args */ +- if (addMBArgs || removeMBArgs) +- rc = updateActualImage(cfg, image, prefix, addMBArgs, removeMBArgs, 1); +- return rc; ++ free(line); + } + +-int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel, +- const char * image, const char * prefix, const char * initrd, +- const char * title) { +- struct singleEntry * entry; +- struct singleLine * line, * kernelLine, *endLine = NULL; +- int index = 0; +- +- if (!image) return 0; +- +- for (; (entry = findEntryByPath(cfg, newMBKernel, prefix, &index)); index++) { +- kernelLine = getLineByType(LT_MBMODULE, entry->lines); +- if (!kernelLine) continue; +- +- /* if title is supplied, the entry's title must match it. */ +- if (title) { +- char *linetitle; +- +- line = getLineByType(LT_TITLE|LT_MENUENTRY, entry->lines); +- if (!line) +- continue; +- +- linetitle = extractTitle(cfg, line); +- if (!linetitle) +- continue; +- if (strcmp(title, linetitle)) { +- free(linetitle); +- continue; +- } +- free(linetitle); +- } +- +- if (prefix) { +- int prefixLen = strlen(prefix); +- if (!strncmp(initrd, prefix, prefixLen)) +- initrd += prefixLen; +- } +- endLine = getLineByType(LT_ENTRY_END, entry->lines); +- if (endLine) +- removeLine(entry, endLine); +- line = addLine(entry, cfg->cfi, preferredLineType(LT_MBMODULE,cfg->cfi), +- kernelLine->indent, initrd); +- if (!line) +- return 1; +- if (endLine) { +- line = addLine(entry, cfg->cfi, LT_ENTRY_END, "", NULL); +- if (!line) +- return 1; +- } ++static void requote(struct singleLine *tmplLine, struct configFileInfo *cfi) ++{ ++ struct singleLine newLine = { ++ .indent = tmplLine->indent, ++ .type = tmplLine->type, ++ .next = tmplLine->next, ++ }; ++ int firstQuotedItem = -1; ++ int quoteLen = 0; ++ int j; ++ int element = 0; ++ char *c; ++ ++ c = malloc(strlen(tmplLine->elements[0].item) + 1); ++ strcpy(c, tmplLine->elements[0].item); ++ insertElement(&newLine, c, element++, cfi); ++ free(c); ++ c = NULL; ++ ++ for (j = 1; j < tmplLine->numElements; j++) { ++ if (firstQuotedItem == -1) { ++ quoteLen += strlen(tmplLine->elements[j].item); ++ ++ if (isquote(tmplLine->elements[j].item[0])) { ++ firstQuotedItem = j; ++ quoteLen += ++ strlen(tmplLine->elements[j].indent); ++ } else { ++ c = malloc(quoteLen + 1); ++ strcpy(c, tmplLine->elements[j].item); ++ insertElement(&newLine, c, element++, cfi); ++ free(c); ++ quoteLen = 0; ++ } ++ } else { ++ int itemlen = strlen(tmplLine->elements[j].item); ++ quoteLen += itemlen; ++ quoteLen += strlen(tmplLine->elements[j].indent); ++ ++ if (isquote(tmplLine->elements[j].item[itemlen - 1])) { ++ c = malloc(quoteLen + 1); ++ c[0] = '\0'; ++ for (int i = firstQuotedItem; i < j + 1; i++) { ++ strcat(c, tmplLine->elements[i].item); ++ strcat(c, tmplLine->elements[i].indent); ++ } ++ insertElement(&newLine, c, element++, cfi); ++ free(c); + +- break; +- } ++ firstQuotedItem = -1; ++ quoteLen = 0; ++ } ++ } ++ } ++ while (tmplLine->numElements) ++ removeElement(tmplLine, 0); ++ if (tmplLine->elements) ++ free(tmplLine->elements); + +- return 0; ++ tmplLine->numElements = newLine.numElements; ++ tmplLine->elements = newLine.elements; + } + +-int updateInitrd(struct grubConfig * cfg, const char * image, +- const char * prefix, const char * initrd, const char * title) { +- struct singleEntry * entry; +- struct singleLine * line, * kernelLine, *endLine = NULL; +- int index = 0; +- +- if (!image) return 0; +- +- for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) { +- kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); +- if (!kernelLine) continue; +- +- /* if title is supplied, the entry's title must match it. */ +- if (title) { +- char *linetitle; +- +- line = getLineByType(LT_TITLE|LT_MENUENTRY, entry->lines); +- if (!line) +- continue; +- +- linetitle = extractTitle(cfg, line); +- if (!linetitle) +- continue; +- if (strcmp(title, linetitle)) { +- free(linetitle); +- continue; +- } +- free(linetitle); +- } +- +- line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines); +- if (line) +- removeLine(entry, line); +- if (prefix) { +- int prefixLen = strlen(prefix); +- if (!strncmp(initrd, prefix, prefixLen)) +- initrd += prefixLen; +- } +- endLine = getLineByType(LT_ENTRY_END, entry->lines); +- if (endLine) +- removeLine(entry, endLine); +- enum lineType_e lt; +- switch(kernelLine->type) { +- case LT_KERNEL: +- lt = LT_INITRD; +- break; +- case LT_KERNEL_EFI: +- lt = LT_INITRD_EFI; +- break; +- case LT_KERNEL_16: +- lt = LT_INITRD_16; +- break; +- default: +- lt = preferredLineType(LT_INITRD, cfg->cfi); ++static void insertElement(struct singleLine *line, ++ const char *item, int insertHere, ++ struct configFileInfo *cfi) ++{ ++ struct keywordTypes *kw; ++ char indent[2] = ""; ++ ++ /* sanity check */ ++ if (insertHere > line->numElements) { ++ dbgPrintf ++ ("insertElement() adjusting insertHere from %d to %d\n", ++ insertHere, line->numElements); ++ insertHere = line->numElements; + } +- line = addLine(entry, cfg->cfi, lt, kernelLine->indent, initrd); +- if (!line) +- return 1; +- if (endLine) { +- line = addLine(entry, cfg->cfi, LT_ENTRY_END, "", NULL); +- if (!line) +- return 1; ++ ++ line->elements = realloc(line->elements, (line->numElements + 1) * ++ sizeof(*line->elements)); ++ memmove(&line->elements[insertHere + 1], ++ &line->elements[insertHere], ++ (line->numElements - insertHere) * sizeof(*line->elements)); ++ line->elements[insertHere].item = strdup(item); ++ ++ kw = getKeywordByType(line->type, cfi); ++ ++ if (line->numElements == 0) { ++ indent[0] = '\0'; ++ } else if (insertHere == 0) { ++ indent[0] = kw->nextChar; ++ } else if (kw->separatorChar != '\0') { ++ indent[0] = kw->separatorChar; ++ } else { ++ indent[0] = ' '; ++ } ++ ++ if (insertHere > 0 && line->elements[insertHere - 1].indent[0] == '\0') { ++ /* move the end-of-line forward */ ++ line->elements[insertHere].indent = ++ line->elements[insertHere - 1].indent; ++ line->elements[insertHere - 1].indent = strdup(indent); ++ } else { ++ line->elements[insertHere].indent = strdup(indent); + } + +- break; +- } ++ line->numElements++; + +- return 0; ++ dbgPrintf("insertElement(%s, '%s%s', %d)\n", ++ line->elements[0].item, ++ line->elements[insertHere].item, ++ line->elements[insertHere].indent, insertHere); + } + +-int checkDeviceBootloader(const char * device, const unsigned char * boot) { +- int fd; +- unsigned char bootSect[512]; +- int offset; ++static void removeElement(struct singleLine *line, int removeHere) ++{ ++ int i; + +- fd = open(device, O_RDONLY); +- if (fd < 0) { +- fprintf(stderr, _("grubby: unable to open %s: %s\n"), +- device, strerror(errno)); +- return 1; +- } ++ /* sanity check */ ++ if (removeHere >= line->numElements) ++ return; + +- if (read(fd, bootSect, 512) != 512) { +- fprintf(stderr, _("grubby: unable to read %s: %s\n"), +- device, strerror(errno)); +- return 1; +- } +- close(fd); ++ dbgPrintf("removeElement(%s, %d:%s)\n", line->elements[0].item, ++ removeHere, line->elements[removeHere].item); + +- /* first three bytes should match, a jmp short should be in there */ +- if (memcmp(boot, bootSect, 3)) +- return 0; ++ free(line->elements[removeHere].item); + +- 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] == 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 { +- return 0; +- } ++ if (removeHere > 1) { ++ /* previous argument gets this argument's post-indentation */ ++ free(line->elements[removeHere - 1].indent); ++ line->elements[removeHere - 1].indent = ++ line->elements[removeHere].indent; ++ } else { ++ free(line->elements[removeHere].indent); ++ } + +- if (memcmp(boot + offset, bootSect + offset, CODE_SEG_SIZE)) +- return 0; ++ /* now collapse the array, but don't bother to realloc smaller */ ++ for (i = removeHere; i < line->numElements - 1; i++) ++ line->elements[i] = line->elements[i + 1]; + +- return 2; ++ line->numElements--; + } + +-int checkLiloOnRaid(char * mdDev, const unsigned char * boot) { +- int fd; +- char buf[65536]; +- char * end; +- char * chptr; +- char * chptr2; +- int rc; +- +- /* it's on raid; we need to parse /proc/mdstat and check all of the +- *raw* devices listed in there */ ++int argMatch(const char *one, const char *two) ++{ ++ char *first, *second; ++ char *chptr; + +- if (!strncmp(mdDev, "/dev/", 5)) +- mdDev += 5; ++ first = strcpy(alloca(strlen(one) + 1), one); ++ second = strcpy(alloca(strlen(two) + 1), two); + +- if ((fd = open("/proc/mdstat", O_RDONLY)) < 0) { +- fprintf(stderr, _("grubby: failed to open /proc/mdstat: %s\n"), +- strerror(errno)); +- return 2; +- } ++ chptr = strchr(first, '='); ++ if (chptr) ++ *chptr = '\0'; + +- rc = read(fd, buf, sizeof(buf) - 1); +- if (rc < 0 || rc == (sizeof(buf) - 1)) { +- fprintf(stderr, _("grubby: failed to read /proc/mdstat: %s\n"), +- strerror(errno)); +- close(fd); +- return 2; +- } +- close(fd); +- buf[rc] = '\0'; +- +- chptr = buf; +- while (*chptr) { +- end = strchr(chptr, '\n'); +- if (!end) break; +- *end = '\0'; ++ chptr = strchr(second, '='); ++ if (chptr) ++ *chptr = '\0'; + +- if (!strncmp(chptr, mdDev, strlen(mdDev)) && +- chptr[strlen(mdDev)] == ' ') { +- +- /* found the device */ +- while (*chptr && *chptr != ':') chptr++; +- chptr++; +- while (*chptr && isspace(*chptr)) chptr++; +- +- /* skip the "active" bit */ +- while (*chptr && !isspace(*chptr)) chptr++; +- while (*chptr && isspace(*chptr)) chptr++; +- +- /* skip the raid level */ +- while (*chptr && !isspace(*chptr)) chptr++; +- while (*chptr && isspace(*chptr)) chptr++; +- +- /* everything else is partition stuff */ +- while (*chptr) { +- chptr2 = chptr; +- while (*chptr2 && *chptr2 != '[') chptr2++; +- if (!*chptr2) break; +- +- /* yank off the numbers at the end */ +- chptr2--; +- while (isdigit(*chptr2) && chptr2 > chptr) chptr2--; +- chptr2++; +- *chptr2 = '\0'; +- +- /* Better, now we need the /dev/ back. We're done with +- * everything before this point, so we can just put +- * the /dev/ part there. There will always be room. */ +- memcpy(chptr - 5, "/dev/", 5); +- rc = checkDeviceBootloader(chptr - 5, boot); +- if (rc != 2) { +- return rc; +- } ++ return strcmp(first, second); ++} + +- chptr = chptr2 + 1; +- /* skip the [11] bit */ +- while (*chptr && !isspace(*chptr)) chptr++; +- /* and move to the next one */ +- while (*chptr && isspace(*chptr)) chptr++; +- } ++int updateActualImage(struct grubConfig *cfg, const char *image, ++ const char *prefix, const char *addArgs, ++ const char *removeArgs, int multibootArgs) ++{ ++ struct singleEntry *entry; ++ struct singleLine *line, *rootLine; ++ int index = 0; ++ int i, k; ++ const char **newArgs, **oldArgs; ++ const char **arg; ++ int useKernelArgs, useRoot; ++ int firstElement; ++ int *usedElements; ++ int doreplace; ++ ++ if (!image) ++ return 0; + +- /* we're good to go */ +- return 2; ++ if (!addArgs) { ++ newArgs = malloc(sizeof(*newArgs)); ++ *newArgs = NULL; ++ } else { ++ if (poptParseArgvString(addArgs, NULL, &newArgs)) { ++ fprintf(stderr, ++ _("grubby: error separating arguments '%s'\n"), ++ addArgs); ++ return 1; ++ } + } + +- chptr = end + 1; +- } ++ if (!removeArgs) { ++ oldArgs = malloc(sizeof(*oldArgs)); ++ *oldArgs = NULL; ++ } else { ++ if (poptParseArgvString(removeArgs, NULL, &oldArgs)) { ++ fprintf(stderr, ++ _("grubby: error separating arguments '%s'\n"), ++ removeArgs); ++ free(newArgs); ++ return 1; ++ } ++ } + +- fprintf(stderr, +- _("grubby: raid device /dev/%s not found in /proc/mdstat\n"), +- mdDev); +- return 0; +-} ++ useKernelArgs = (getKeywordByType(LT_KERNELARGS, cfg->cfi) ++ && (!multibootArgs || cfg->cfi->mbConcatArgs)); + +-int checkForLilo(struct grubConfig * config) { +- int fd; +- unsigned char boot[512]; +- struct singleLine * line; ++ useRoot = (getKeywordByType(LT_ROOT, cfg->cfi) ++ && !multibootArgs); + +- for (line = config->theLines; line; line = line->next) +- if (line->type == LT_BOOT) break; ++ for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) { + +- if (!line) { +- fprintf(stderr, +- _("grubby: no boot line found in lilo configuration\n")); +- return 1; +- } ++ if (multibootArgs && !entry->multiboot) ++ continue; + +- if (line->numElements != 2) return 1; ++ /* Determine where to put the args. If this config supports ++ * LT_KERNELARGS, use that. Otherwise use ++ * LT_HYPER/LT_KERNEL/LT_MBMODULE lines. ++ */ ++ if (useKernelArgs) { ++ line = getLineByType(LT_KERNELARGS, entry->lines); ++ if (!line) { ++ /* no LT_KERNELARGS, need to add it */ ++ line = addLine(entry, cfg->cfi, LT_KERNELARGS, ++ cfg->secondaryIndent, NULL); ++ } ++ firstElement = 1; + +- fd = open("/boot/boot.b", O_RDONLY); +- if (fd < 0) { +- fprintf(stderr, _("grubby: unable to open %s: %s\n"), +- "/boot/boot.b", strerror(errno)); +- return 1; +- } ++ } else if (multibootArgs) { ++ line = getLineByType(LT_HYPER, entry->lines); ++ if (!line) { ++ /* a multiboot entry without LT_HYPER? */ ++ continue; ++ } ++ firstElement = 2; + +- if (read(fd, boot, 512) != 512) { +- fprintf(stderr, _("grubby: unable to read %s: %s\n"), +- "/boot/boot.b", strerror(errno)); +- return 1; +- } +- close(fd); ++ } else { ++ line = ++ getLineByType(LT_KERNEL | LT_MBMODULE | ++ LT_KERNEL_EFI | LT_KERNEL_16, ++ entry->lines); ++ if (!line) { ++ /* no LT_KERNEL or LT_MBMODULE in this entry? */ ++ continue; ++ } ++ firstElement = 2; ++ } + +- if (!strncmp("/dev/md", line->elements[1].item, 7)) +- return checkLiloOnRaid(line->elements[1].item, boot); ++ /* handle the elilo case which does: ++ * append="hypervisor args -- kernel args" ++ */ ++ if (entry->multiboot && cfg->cfi->mbConcatArgs) { ++ /* this is a multiboot entry, make sure there's ++ * -- on the args line ++ */ ++ for (i = firstElement; i < line->numElements; i++) { ++ if (!strcmp(line->elements[i].item, "--")) ++ break; ++ } ++ if (i == line->numElements) { ++ /* assume all existing args are kernel args, ++ * prepend -- to make it official ++ */ ++ insertElement(line, "--", firstElement, ++ cfg->cfi); ++ i = firstElement; ++ } ++ if (!multibootArgs) { ++ /* kernel args start after the -- */ ++ firstElement = i + 1; ++ } ++ } else if (cfg->cfi->mbConcatArgs) { ++ /* this is a non-multiboot entry, remove hyper args */ ++ for (i = firstElement; i < line->numElements; i++) { ++ if (!strcmp(line->elements[i].item, "--")) ++ break; ++ } ++ if (i < line->numElements) { ++ /* remove args up to -- */ ++ while (strcmp ++ (line->elements[firstElement].item, ++ "--")) ++ removeElement(line, firstElement); ++ /* remove -- */ ++ removeElement(line, firstElement); ++ } ++ } + +- return checkDeviceBootloader(line->elements[1].item, boot); +-} ++ usedElements = calloc(line->numElements, sizeof(*usedElements)); + +-int checkForGrub2(struct grubConfig * config) { +- if (!access("/etc/grub.d/", R_OK)) +- return 2; ++ for (k = 0, arg = newArgs; *arg; arg++, k++) { + +- return 1; +-} ++ doreplace = 1; ++ for (i = firstElement; i < line->numElements; i++) { ++ if (multibootArgs && cfg->cfi->mbConcatArgs && ++ !strcmp(line->elements[i].item, "--")) { ++ /* reached the end of hyper args, insert here */ ++ doreplace = 0; ++ break; ++ } ++ if (usedElements[i]) ++ continue; ++ if (!argMatch(line->elements[i].item, *arg)) { ++ usedElements[i] = 1; ++ break; ++ } ++ } + +-int checkForGrub(struct grubConfig * config) { +- int fd; +- unsigned char bootSect[512]; +- char * boot; +- int onSuse = isSuseSystem(); ++ if (i < line->numElements && doreplace) { ++ /* direct replacement */ ++ free(line->elements[i].item); ++ line->elements[i].item = strdup(*arg); ++ ++ } else if (useRoot && !strncmp(*arg, "root=/dev/", 10)) { ++ /* root= replacement */ ++ rootLine = getLineByType(LT_ROOT, entry->lines); ++ if (rootLine) { ++ free(rootLine->elements[1].item); ++ rootLine->elements[1].item = ++ strdup(*arg + 5); ++ } else { ++ rootLine = ++ addLine(entry, cfg->cfi, LT_ROOT, ++ cfg->secondaryIndent, ++ *arg + 5); ++ } ++ } + ++ else { ++ /* insert/append */ ++ insertElement(line, *arg, i, cfg->cfi); ++ usedElements = ++ realloc(usedElements, ++ line->numElements * ++ sizeof(*usedElements)); ++ memmove(&usedElements[i + 1], &usedElements[i], ++ line->numElements - i - 1); ++ usedElements[i] = 1; ++ ++ /* if we updated a root= here even though there is a ++ LT_ROOT available we need to remove the LT_ROOT entry ++ (this will happen if we switch from a device to a label) */ ++ if (useRoot && !strncmp(*arg, "root=", 5)) { ++ rootLine = ++ getLineByType(LT_ROOT, ++ entry->lines); ++ if (rootLine) ++ removeLine(entry, rootLine); ++ } ++ } ++ } + +- if (onSuse) { +- if (parseSuseGrubConf(NULL, &boot)) +- return 0; +- } else { +- if (parseSysconfigGrub(NULL, &boot)) +- return 0; +- } ++ free(usedElements); + +- /* assume grub is not installed -- not an error condition */ +- if (!boot) +- return 0; ++ for (arg = oldArgs; *arg; arg++) { ++ for (i = firstElement; i < line->numElements; i++) { ++ if (multibootArgs && cfg->cfi->mbConcatArgs && ++ !strcmp(line->elements[i].item, "--")) ++ /* reached the end of hyper args, stop here */ ++ break; ++ if (!argMatch(line->elements[i].item, *arg)) { ++ removeElement(line, i); ++ break; ++ } ++ } ++ /* handle removing LT_ROOT line too */ ++ if (useRoot && !strncmp(*arg, "root=", 5)) { ++ rootLine = getLineByType(LT_ROOT, entry->lines); ++ if (rootLine) ++ removeLine(entry, rootLine); ++ } ++ } + +- fd = open("/boot/grub/stage1", O_RDONLY); +- if (fd < 0) +- /* this doesn't exist if grub hasn't been installed */ +- return 0; ++ if (line->numElements == 1) { ++ /* don't need the line at all (note it has to be a ++ LT_KERNELARGS for this to happen */ ++ removeLine(entry, line); ++ } ++ } + +- if (read(fd, bootSect, 512) != 512) { +- fprintf(stderr, _("grubby: unable to read %s: %s\n"), +- "/boot/grub/stage1", strerror(errno)); +- close(fd); +- return 1; +- } +- close(fd); ++ free(newArgs); ++ free(oldArgs); + +- /* The more elaborate checks do not work on SuSE. The checks done +- * seem to be reasonble (at least for now), so just return success +- */ +- if (onSuse) +- return 2; ++ return 0; ++} + +- return checkDeviceBootloader(boot, bootSect); ++int updateImage(struct grubConfig *cfg, const char *image, ++ const char *prefix, const char *addArgs, ++ const char *removeArgs, ++ const char *addMBArgs, const char *removeMBArgs) ++{ ++ int rc = 0; ++ ++ if (!image) ++ return rc; ++ ++ /* update the main args first... */ ++ if (addArgs || removeArgs) ++ rc = updateActualImage(cfg, image, prefix, addArgs, removeArgs, ++ 0); ++ if (rc) ++ return rc; ++ ++ /* and now any multiboot args */ ++ if (addMBArgs || removeMBArgs) ++ rc = updateActualImage(cfg, image, prefix, addMBArgs, ++ removeMBArgs, 1); ++ return rc; + } + +-int checkForExtLinux(struct grubConfig * config) { +- int fd; +- unsigned char bootSect[512]; +- char * boot; +- char executable[] = "/boot/extlinux/extlinux"; ++int addMBInitrd(struct grubConfig *cfg, const char *newMBKernel, ++ const char *image, const char *prefix, const char *initrd, ++ const char *title) ++{ ++ struct singleEntry *entry; ++ struct singleLine *line, *kernelLine, *endLine = NULL; ++ int index = 0; + +- printf("entered: checkForExtLinux()\n"); ++ if (!image) ++ return 0; + +- if (parseSysconfigGrub(NULL, &boot)) +- return 0; ++ for (; (entry = findEntryByPath(cfg, newMBKernel, prefix, &index)); ++ index++) { ++ kernelLine = getLineByType(LT_MBMODULE, entry->lines); ++ if (!kernelLine) ++ continue; + +- /* assume grub is not installed -- not an error condition */ +- if (!boot) +- return 0; ++ /* if title is supplied, the entry's title must match it. */ ++ if (title) { ++ char *linetitle; ++ ++ line = ++ getLineByType(LT_TITLE | LT_MENUENTRY, ++ entry->lines); ++ if (!line) ++ continue; ++ ++ linetitle = extractTitle(cfg, line); ++ if (!linetitle) ++ continue; ++ if (strcmp(title, linetitle)) { ++ free(linetitle); ++ continue; ++ } ++ free(linetitle); ++ } + +- fd = open(executable, O_RDONLY); +- if (fd < 0) +- /* this doesn't exist if grub hasn't been installed */ +- return 0; ++ if (prefix) { ++ int prefixLen = strlen(prefix); ++ if (!strncmp(initrd, prefix, prefixLen)) ++ initrd += prefixLen; ++ } ++ endLine = getLineByType(LT_ENTRY_END, entry->lines); ++ if (endLine) ++ removeLine(entry, endLine); ++ line = ++ addLine(entry, cfg->cfi, ++ preferredLineType(LT_MBMODULE, cfg->cfi), ++ kernelLine->indent, initrd); ++ if (!line) ++ return 1; ++ if (endLine) { ++ line = addLine(entry, cfg->cfi, LT_ENTRY_END, "", NULL); ++ if (!line) ++ return 1; ++ } + +- if (read(fd, bootSect, 512) != 512) { +- fprintf(stderr, _("grubby: unable to read %s: %s\n"), +- executable, strerror(errno)); +- return 1; +- } +- close(fd); ++ break; ++ } + +- return checkDeviceBootloader(boot, bootSect); ++ return 0; + } + +-int checkForYaboot(struct grubConfig * config) { +- /* +- * This is a simplistic check that we consider good enough for own puporses +- * +- * If we were to properly check if yaboot is *installed* we'd need to: +- * 1) get the system boot device (LT_BOOT) +- * 2) considering it's a raw filesystem, check if the yaboot binary matches +- * the content on the boot device +- * 3) if not, copy the binary to a temporary file and run "addnote" on it +- * 4) check again if binary and boot device contents match +- */ +- if (!access("/etc/yaboot.conf", R_OK)) +- return 2; +- +- return 1; +-} ++int updateInitrd(struct grubConfig *cfg, const char *image, ++ const char *prefix, const char *initrd, const char *title) ++{ ++ struct singleEntry *entry; ++ struct singleLine *line, *kernelLine, *endLine = NULL; ++ int index = 0; + +-int checkForElilo(struct grubConfig * config) { +- if (!access("/etc/elilo.conf", R_OK)) +- return 2; ++ if (!image) ++ return 0; + +- return 1; +-} ++ for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) { ++ kernelLine = ++ getLineByType(LT_KERNEL | LT_KERNEL_EFI | LT_KERNEL_16, ++ entry->lines); ++ if (!kernelLine) ++ continue; + +-static char * getRootSpecifier(char * str) { +- char * idx, * rootspec = NULL; ++ /* if title is supplied, the entry's title must match it. */ ++ if (title) { ++ char *linetitle; ++ ++ line = ++ getLineByType(LT_TITLE | LT_MENUENTRY, ++ entry->lines); ++ if (!line) ++ continue; ++ ++ linetitle = extractTitle(cfg, line); ++ if (!linetitle) ++ continue; ++ if (strcmp(title, linetitle)) { ++ free(linetitle); ++ continue; ++ } ++ free(linetitle); ++ } + +- if (*str == '(') { +- idx = rootspec = strdup(str); +- while(*idx && (*idx != ')') && (!isspace(*idx))) idx++; +- *(++idx) = '\0'; +- } +- return rootspec; ++ line = ++ getLineByType(LT_INITRD | LT_INITRD_EFI | LT_INITRD_16, ++ entry->lines); ++ if (line) ++ removeLine(entry, line); ++ if (prefix) { ++ int prefixLen = strlen(prefix); ++ if (!strncmp(initrd, prefix, prefixLen)) ++ initrd += prefixLen; ++ } ++ endLine = getLineByType(LT_ENTRY_END, entry->lines); ++ if (endLine) ++ removeLine(entry, endLine); ++ enum lineType_e lt; ++ switch (kernelLine->type) { ++ case LT_KERNEL: ++ lt = LT_INITRD; ++ break; ++ case LT_KERNEL_EFI: ++ lt = LT_INITRD_EFI; ++ break; ++ case LT_KERNEL_16: ++ lt = LT_INITRD_16; ++ break; ++ default: ++ lt = preferredLineType(LT_INITRD, cfg->cfi); ++ } ++ line = addLine(entry, cfg->cfi, lt, kernelLine->indent, initrd); ++ if (!line) ++ return 1; ++ if (endLine) { ++ line = addLine(entry, cfg->cfi, LT_ENTRY_END, "", NULL); ++ if (!line) ++ return 1; ++ } ++ ++ break; ++ } ++ ++ return 0; + } + +-static char * getInitrdVal(struct grubConfig * config, +- const char * prefix, struct singleLine *tmplLine, +- const char * newKernelInitrd, +- const char ** extraInitrds, int extraInitrdCount) ++int checkDeviceBootloader(const char *device, const unsigned char *boot) + { +- char *initrdVal, *end; +- int i; +- size_t totalSize; +- size_t prefixLen; +- char separatorChar; ++ int fd; ++ unsigned char bootSect[512]; ++ int offset; ++ ++ fd = open(device, O_RDONLY); ++ if (fd < 0) { ++ fprintf(stderr, _("grubby: unable to open %s: %s\n"), ++ device, strerror(errno)); ++ return 1; ++ } + +- prefixLen = strlen(prefix); +- totalSize = strlen(newKernelInitrd) - prefixLen + 1 /* \0 */; ++ if (read(fd, bootSect, 512) != 512) { ++ fprintf(stderr, _("grubby: unable to read %s: %s\n"), ++ device, strerror(errno)); ++ return 1; ++ } ++ close(fd); + +- for (i = 0; i < extraInitrdCount; i++) { +- totalSize += sizeof(separatorChar); +- totalSize += strlen(extraInitrds[i]) - prefixLen; +- } ++ /* first three bytes should match, a jmp short should be in there */ ++ if (memcmp(boot, bootSect, 3)) ++ return 0; + +- initrdVal = end = malloc(totalSize); ++ 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] == 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 { ++ return 0; ++ } + +- end = stpcpy (end, newKernelInitrd + prefixLen); ++ if (memcmp(boot + offset, bootSect + offset, CODE_SEG_SIZE)) ++ return 0; + +- separatorChar = getKeywordByType(LT_INITRD, config->cfi)->separatorChar; +- for (i = 0; i < extraInitrdCount; i++) { +- const char *extraInitrd; +- int j; ++ return 2; ++} + +- extraInitrd = extraInitrds[i] + prefixLen; +- /* Don't add entries that are already there */ +- if (tmplLine != NULL) { +- for (j = 2; j < tmplLine->numElements; j++) +- if (strcmp(extraInitrd, tmplLine->elements[j].item) == 0) +- break; ++int checkLiloOnRaid(char *mdDev, const unsigned char *boot) ++{ ++ int fd; ++ char buf[65536]; ++ char *end; ++ char *chptr; ++ char *chptr2; ++ int rc; ++ ++ /* it's on raid; we need to parse /proc/mdstat and check all of the ++ *raw* devices listed in there */ ++ ++ if (!strncmp(mdDev, "/dev/", 5)) ++ mdDev += 5; ++ ++ if ((fd = open("/proc/mdstat", O_RDONLY)) < 0) { ++ fprintf(stderr, _("grubby: failed to open /proc/mdstat: %s\n"), ++ strerror(errno)); ++ return 2; ++ } + +- if (j != tmplLine->numElements) +- continue; ++ rc = read(fd, buf, sizeof(buf) - 1); ++ if (rc < 0 || rc == (sizeof(buf) - 1)) { ++ fprintf(stderr, _("grubby: failed to read /proc/mdstat: %s\n"), ++ strerror(errno)); ++ close(fd); ++ return 2; + } ++ close(fd); ++ buf[rc] = '\0'; + +- *end++ = separatorChar; +- end = stpcpy(end, extraInitrd); +- } ++ chptr = buf; ++ while (*chptr) { ++ end = strchr(chptr, '\n'); ++ if (!end) ++ break; ++ *end = '\0'; ++ ++ if (!strncmp(chptr, mdDev, strlen(mdDev)) && ++ chptr[strlen(mdDev)] == ' ') { ++ ++ /* found the device */ ++ while (*chptr && *chptr != ':') ++ chptr++; ++ chptr++; ++ while (*chptr && isspace(*chptr)) ++ chptr++; ++ ++ /* skip the "active" bit */ ++ while (*chptr && !isspace(*chptr)) ++ chptr++; ++ while (*chptr && isspace(*chptr)) ++ chptr++; ++ ++ /* skip the raid level */ ++ while (*chptr && !isspace(*chptr)) ++ chptr++; ++ while (*chptr && isspace(*chptr)) ++ chptr++; ++ ++ /* everything else is partition stuff */ ++ while (*chptr) { ++ chptr2 = chptr; ++ while (*chptr2 && *chptr2 != '[') ++ chptr2++; ++ if (!*chptr2) ++ break; + +- return initrdVal; +-} ++ /* yank off the numbers at the end */ ++ chptr2--; ++ while (isdigit(*chptr2) && chptr2 > chptr) ++ chptr2--; ++ chptr2++; ++ *chptr2 = '\0'; ++ ++ /* Better, now we need the /dev/ back. We're done with ++ * everything before this point, so we can just put ++ * the /dev/ part there. There will always be room. */ ++ memcpy(chptr - 5, "/dev/", 5); ++ rc = checkDeviceBootloader(chptr - 5, boot); ++ if (rc != 2) { ++ return rc; ++ } + +-int addNewKernel(struct grubConfig * config, struct singleEntry * template, +- const char * prefix, +- const char * newKernelPath, const char * newKernelTitle, +- const char * newKernelArgs, const char * newKernelInitrd, +- const char ** extraInitrds, int extraInitrdCount, +- const char * newMBKernel, const char * newMBKernelArgs) { +- struct singleEntry * new; +- struct singleLine * newLine = NULL, * tmplLine = NULL, * masterLine = NULL; +- int needs; +- char * chptr; +- +- if (!newKernelPath) return 0; +- +- /* if the newKernelTitle is too long silently munge it into something +- * we can live with. truncating is first check, then we'll just mess with +- * it until it looks better */ +- if (config->cfi->maxTitleLength && +- (strlen(newKernelTitle) > config->cfi->maxTitleLength)) { +- char * buf = alloca(config->cfi->maxTitleLength + 7); +- char * numBuf = alloca(config->cfi->maxTitleLength + 1); +- int i = 1; +- +- sprintf(buf, "TITLE=%.*s", config->cfi->maxTitleLength, newKernelTitle); +- while (findEntryByPath(config, buf, NULL, NULL)) { +- sprintf(numBuf, "%d", i++); +- strcpy(buf + strlen(buf) - strlen(numBuf), numBuf); +- } +- +- newKernelTitle = buf + 6; +- } +- +- new = malloc(sizeof(*new)); +- new->skip = 0; +- new->multiboot = 0; +- new->next = config->entries; +- new->lines = NULL; +- config->entries = new; +- +- /* copy/update from the template */ +- needs = NEED_KERNEL | NEED_TITLE; +- if (newKernelInitrd) +- needs |= NEED_INITRD; +- if (newMBKernel) { +- needs |= NEED_MB; +- new->multiboot = 1; +- } +- +- if (template) { +- for (masterLine = template->lines; +- masterLine && (tmplLine = lineDup(masterLine)); +- lineFree(tmplLine), masterLine = masterLine->next) +- { +- dbgPrintf("addNewKernel processing %d\n", tmplLine->type); +- +- /* skip comments */ +- chptr = tmplLine->indent; +- while (*chptr && isspace(*chptr)) chptr++; +- if (*chptr == '#') continue; +- +- if (iskernel(tmplLine->type) && tmplLine->numElements >= 2) { +- if (!template->multiboot && (needs & NEED_MB)) { +- /* it's not a multiboot template and this is the kernel +- * line. Try to be intelligent about inserting the +- * hypervisor at the same time. +- */ +- if (config->cfi->mbHyperFirst) { +- /* insert the hypervisor first */ +- newLine = addLine(new, config->cfi, LT_HYPER, +- tmplLine->indent, +- newMBKernel + strlen(prefix)); +- /* set up for adding the kernel line */ +- free(tmplLine->indent); +- tmplLine->indent = strdup(config->secondaryIndent); +- needs &= ~NEED_MB; +- } +- if (needs & NEED_KERNEL) { +- /* use addLineTmpl to preserve line elements, +- * otherwise we could just call addLine. Unfortunately +- * this means making some changes to the template +- * such as the indent change above and the type +- * change below. +- */ +- struct keywordTypes * mbm_kw = +- getKeywordByType(LT_MBMODULE, config->cfi); +- if (mbm_kw) { +- tmplLine->type = LT_MBMODULE; +- free(tmplLine->elements[0].item); +- tmplLine->elements[0].item = strdup(mbm_kw->key); ++ chptr = chptr2 + 1; ++ /* skip the [11] bit */ ++ while (*chptr && !isspace(*chptr)) ++ chptr++; ++ /* and move to the next one */ ++ while (*chptr && isspace(*chptr)) ++ chptr++; + } +- newLine = addLineTmpl(new, tmplLine, newLine, +- newKernelPath + strlen(prefix), config->cfi); +- needs &= ~NEED_KERNEL; +- } +- if (needs & NEED_MB) { /* !mbHyperFirst */ +- newLine = addLine(new, config->cfi, LT_HYPER, +- config->secondaryIndent, +- newMBKernel + strlen(prefix)); +- needs &= ~NEED_MB; +- } +- } else if (needs & NEED_KERNEL) { +- newLine = addLineTmpl(new, tmplLine, newLine, +- newKernelPath + strlen(prefix), config->cfi); +- needs &= ~NEED_KERNEL; +- } + +- } else if (tmplLine->type == LT_HYPER && +- tmplLine->numElements >= 2) { +- if (needs & NEED_MB) { +- newLine = addLineTmpl(new, tmplLine, newLine, +- newMBKernel + strlen(prefix), config->cfi); +- needs &= ~NEED_MB; ++ /* we're good to go */ ++ return 2; + } + +- } else if (tmplLine->type == LT_MBMODULE && +- tmplLine->numElements >= 2) { +- if (new->multiboot) { +- if (needs & NEED_KERNEL) { +- newLine = addLineTmpl(new, tmplLine, newLine, +- newKernelPath + +- strlen(prefix), config->cfi); +- needs &= ~NEED_KERNEL; +- } else if (config->cfi->mbInitRdIsModule && +- (needs & NEED_INITRD)) { +- char *initrdVal; +- initrdVal = getInitrdVal(config, prefix, tmplLine, +- newKernelInitrd, extraInitrds, +- extraInitrdCount); +- newLine = addLineTmpl(new, tmplLine, newLine, +- initrdVal, config->cfi); +- free(initrdVal); +- needs &= ~NEED_INITRD; +- } +- } else if (needs & NEED_KERNEL) { +- /* template is multi but new is not, +- * insert the kernel in the first module slot +- */ +- tmplLine->type = preferredLineType(LT_KERNEL, config->cfi); +- free(tmplLine->elements[0].item); +- tmplLine->elements[0].item = +- strdup(getKeywordByType(tmplLine->type, +- config->cfi)->key); +- newLine = addLineTmpl(new, tmplLine, newLine, +- newKernelPath + strlen(prefix), +- config->cfi); +- needs &= ~NEED_KERNEL; +- } else if (needs & NEED_INITRD) { +- char *initrdVal; +- /* template is multi but new is not, +- * insert the initrd in the second module slot +- */ +- tmplLine->type = preferredLineType(LT_INITRD, config->cfi); +- free(tmplLine->elements[0].item); +- tmplLine->elements[0].item = +- strdup(getKeywordByType(tmplLine->type, +- config->cfi)->key); +- initrdVal = getInitrdVal(config, prefix, tmplLine, newKernelInitrd, extraInitrds, extraInitrdCount); +- newLine = addLineTmpl(new, tmplLine, newLine, initrdVal, config->cfi); +- free(initrdVal); +- needs &= ~NEED_INITRD; +- } ++ chptr = end + 1; ++ } ++ ++ fprintf(stderr, ++ _("grubby: raid device /dev/%s not found in /proc/mdstat\n"), ++ mdDev); ++ return 0; ++} ++ ++int checkForLilo(struct grubConfig *config) ++{ ++ int fd; ++ unsigned char boot[512]; ++ struct singleLine *line; ++ ++ for (line = config->theLines; line; line = line->next) ++ if (line->type == LT_BOOT) ++ break; ++ ++ if (!line) { ++ fprintf(stderr, ++ _ ++ ("grubby: no boot line found in lilo configuration\n")); ++ return 1; ++ } ++ ++ if (line->numElements != 2) ++ return 1; ++ ++ fd = open("/boot/boot.b", O_RDONLY); ++ if (fd < 0) { ++ fprintf(stderr, _("grubby: unable to open %s: %s\n"), ++ "/boot/boot.b", strerror(errno)); ++ return 1; ++ } ++ ++ if (read(fd, boot, 512) != 512) { ++ fprintf(stderr, _("grubby: unable to read %s: %s\n"), ++ "/boot/boot.b", strerror(errno)); ++ return 1; ++ } ++ close(fd); ++ ++ if (!strncmp("/dev/md", line->elements[1].item, 7)) ++ return checkLiloOnRaid(line->elements[1].item, boot); ++ ++ return checkDeviceBootloader(line->elements[1].item, boot); ++} ++ ++int checkForGrub2(struct grubConfig *config) ++{ ++ if (!access("/etc/grub.d/", R_OK)) ++ return 2; ++ ++ return 1; ++} ++ ++int checkForGrub(struct grubConfig *config) ++{ ++ int fd; ++ unsigned char bootSect[512]; ++ char *boot; ++ int onSuse = isSuseSystem(); ++ ++ if (onSuse) { ++ if (parseSuseGrubConf(NULL, &boot)) ++ return 0; ++ } else { ++ if (parseSysconfigGrub(NULL, &boot)) ++ return 0; ++ } ++ ++ /* assume grub is not installed -- not an error condition */ ++ if (!boot) ++ return 0; + +- } else if (isinitrd(tmplLine->type) && tmplLine->numElements >= 2) { +- if (needs & NEED_INITRD && +- new->multiboot && !template->multiboot && +- config->cfi->mbInitRdIsModule) { +- /* make sure we don't insert the module initrd +- * before the module kernel... if we don't do it here, +- * it will be inserted following the template. +- */ +- if (!needs & NEED_KERNEL) { +- char *initrdVal; +- +- initrdVal = getInitrdVal(config, prefix, tmplLine, newKernelInitrd, extraInitrds, extraInitrdCount); +- newLine = addLine(new, config->cfi, LT_MBMODULE, +- config->secondaryIndent, +- initrdVal); +- free(initrdVal); +- needs &= ~NEED_INITRD; +- } +- } else if (needs & NEED_INITRD) { +- char *initrdVal; +- initrdVal = getInitrdVal(config, prefix, tmplLine, newKernelInitrd, extraInitrds, extraInitrdCount); +- newLine = addLineTmpl(new, tmplLine, newLine, initrdVal, config->cfi); +- free(initrdVal); +- needs &= ~NEED_INITRD; ++ fd = open("/boot/grub/stage1", O_RDONLY); ++ if (fd < 0) ++ /* this doesn't exist if grub hasn't been installed */ ++ return 0; ++ ++ if (read(fd, bootSect, 512) != 512) { ++ fprintf(stderr, _("grubby: unable to read %s: %s\n"), ++ "/boot/grub/stage1", strerror(errno)); ++ close(fd); ++ return 1; ++ } ++ close(fd); ++ ++ /* The more elaborate checks do not work on SuSE. The checks done ++ * seem to be reasonble (at least for now), so just return success ++ */ ++ if (onSuse) ++ return 2; ++ ++ return checkDeviceBootloader(boot, bootSect); ++} ++ ++int checkForExtLinux(struct grubConfig *config) ++{ ++ int fd; ++ unsigned char bootSect[512]; ++ char *boot; ++ char executable[] = "/boot/extlinux/extlinux"; ++ ++ printf("entered: checkForExtLinux()\n"); ++ ++ if (parseSysconfigGrub(NULL, &boot)) ++ return 0; ++ ++ /* assume grub is not installed -- not an error condition */ ++ if (!boot) ++ return 0; ++ ++ fd = open(executable, O_RDONLY); ++ if (fd < 0) ++ /* this doesn't exist if grub hasn't been installed */ ++ return 0; ++ ++ if (read(fd, bootSect, 512) != 512) { ++ fprintf(stderr, _("grubby: unable to read %s: %s\n"), ++ executable, strerror(errno)); ++ return 1; ++ } ++ close(fd); ++ ++ return checkDeviceBootloader(boot, bootSect); ++} ++ ++int checkForYaboot(struct grubConfig *config) ++{ ++ /* ++ * This is a simplistic check that we consider good enough for own puporses ++ * ++ * If we were to properly check if yaboot is *installed* we'd need to: ++ * 1) get the system boot device (LT_BOOT) ++ * 2) considering it's a raw filesystem, check if the yaboot binary matches ++ * the content on the boot device ++ * 3) if not, copy the binary to a temporary file and run "addnote" on it ++ * 4) check again if binary and boot device contents match ++ */ ++ if (!access("/etc/yaboot.conf", R_OK)) ++ return 2; ++ ++ return 1; ++} ++ ++int checkForElilo(struct grubConfig *config) ++{ ++ if (!access("/etc/elilo.conf", R_OK)) ++ return 2; ++ ++ return 1; ++} ++ ++static char *getRootSpecifier(char *str) ++{ ++ char *idx, *rootspec = NULL; ++ ++ if (*str == '(') { ++ idx = rootspec = strdup(str); ++ while (*idx && (*idx != ')') && (!isspace(*idx))) ++ idx++; ++ *(++idx) = '\0'; ++ } ++ return rootspec; ++} ++ ++static char *getInitrdVal(struct grubConfig *config, ++ const char *prefix, struct singleLine *tmplLine, ++ const char *newKernelInitrd, ++ const char **extraInitrds, int extraInitrdCount) ++{ ++ char *initrdVal, *end; ++ int i; ++ size_t totalSize; ++ size_t prefixLen; ++ char separatorChar; ++ ++ prefixLen = strlen(prefix); ++ totalSize = strlen(newKernelInitrd) - prefixLen + 1 /* \0 */ ; ++ ++ for (i = 0; i < extraInitrdCount; i++) { ++ totalSize += sizeof(separatorChar); ++ totalSize += strlen(extraInitrds[i]) - prefixLen; ++ } ++ ++ initrdVal = end = malloc(totalSize); ++ ++ end = stpcpy(end, newKernelInitrd + prefixLen); ++ ++ separatorChar = getKeywordByType(LT_INITRD, config->cfi)->separatorChar; ++ for (i = 0; i < extraInitrdCount; i++) { ++ const char *extraInitrd; ++ int j; ++ ++ extraInitrd = extraInitrds[i] + prefixLen; ++ /* Don't add entries that are already there */ ++ if (tmplLine != NULL) { ++ for (j = 2; j < tmplLine->numElements; j++) ++ if (strcmp ++ (extraInitrd, ++ tmplLine->elements[j].item) == 0) ++ break; ++ ++ if (j != tmplLine->numElements) ++ continue; + } + +- } else if (tmplLine->type == LT_MENUENTRY && +- (needs & NEED_TITLE)) { +- requote(tmplLine, config->cfi); +- char *nkt = malloc(strlen(newKernelTitle)+3); +- strcpy(nkt, "'"); +- strcat(nkt, newKernelTitle); +- strcat(nkt, "'"); +- newLine = addLineTmpl(new, tmplLine, newLine, nkt, config->cfi); +- free(nkt); +- needs &= ~NEED_TITLE; +- } else if (tmplLine->type == LT_TITLE && +- (needs & NEED_TITLE)) { +- if (tmplLine->numElements >= 2) { +- newLine = addLineTmpl(new, tmplLine, newLine, +- newKernelTitle, config->cfi); +- needs &= ~NEED_TITLE; +- } else if (tmplLine->numElements == 1 && +- config->cfi->titleBracketed) { +- /* addLineTmpl doesn't handle titleBracketed */ +- newLine = addLine(new, config->cfi, LT_TITLE, +- tmplLine->indent, newKernelTitle); +- needs &= ~NEED_TITLE; ++ *end++ = separatorChar; ++ end = stpcpy(end, extraInitrd); ++ } ++ ++ return initrdVal; ++} ++ ++int addNewKernel(struct grubConfig *config, struct singleEntry *template, ++ const char *prefix, ++ const char *newKernelPath, const char *newKernelTitle, ++ const char *newKernelArgs, const char *newKernelInitrd, ++ const char **extraInitrds, int extraInitrdCount, ++ const char *newMBKernel, const char *newMBKernelArgs) ++{ ++ struct singleEntry *new; ++ struct singleLine *newLine = NULL, *tmplLine = NULL, *masterLine = NULL; ++ int needs; ++ char *chptr; ++ ++ if (!newKernelPath) ++ return 0; ++ ++ /* if the newKernelTitle is too long silently munge it into something ++ * we can live with. truncating is first check, then we'll just mess with ++ * it until it looks better */ ++ if (config->cfi->maxTitleLength && ++ (strlen(newKernelTitle) > config->cfi->maxTitleLength)) { ++ char *buf = alloca(config->cfi->maxTitleLength + 7); ++ char *numBuf = alloca(config->cfi->maxTitleLength + 1); ++ int i = 1; ++ ++ sprintf(buf, "TITLE=%.*s", config->cfi->maxTitleLength, ++ newKernelTitle); ++ while (findEntryByPath(config, buf, NULL, NULL)) { ++ sprintf(numBuf, "%d", i++); ++ strcpy(buf + strlen(buf) - strlen(numBuf), numBuf); + } +- } else if (tmplLine->type == LT_ECHO) { +- requote(tmplLine, config->cfi); +- static const char *prefix = "'Loading "; +- if (tmplLine->numElements > 1 && +- strstr(tmplLine->elements[1].item, prefix) && +- masterLine->next && +- iskernel(masterLine->next->type)) { +- char *newTitle = malloc(strlen(prefix) + +- strlen(newKernelTitle) + 2); +- +- strcpy(newTitle, prefix); +- strcat(newTitle, newKernelTitle); +- strcat(newTitle, "'"); +- newLine = addLine(new, config->cfi, LT_ECHO, +- tmplLine->indent, newTitle); +- free(newTitle); +- } else { +- /* pass through other lines from the template */ +- newLine = addLineTmpl(new, tmplLine, newLine, NULL, +- config->cfi); +- } +- } else { +- /* pass through other lines from the template */ +- newLine = addLineTmpl(new, tmplLine, newLine, NULL, config->cfi); +- } ++ ++ newKernelTitle = buf + 6; + } + +- } else { +- /* don't have a template, so start the entry with the +- * appropriate starting line +- */ +- switch (config->cfi->entryStart) { +- case LT_KERNEL: +- case LT_KERNEL_EFI: +- case LT_KERNEL_16: +- if (new->multiboot && config->cfi->mbHyperFirst) { +- /* fall through to LT_HYPER */ +- } else { +- newLine = addLine(new, config->cfi, +- preferredLineType(LT_KERNEL, config->cfi), +- config->primaryIndent, +- newKernelPath + strlen(prefix)); +- needs &= ~NEED_KERNEL; +- break; ++ new = malloc(sizeof(*new)); ++ new->skip = 0; ++ new->multiboot = 0; ++ new->next = config->entries; ++ new->lines = NULL; ++ config->entries = new; ++ ++ /* copy/update from the template */ ++ needs = NEED_KERNEL | NEED_TITLE; ++ if (newKernelInitrd) ++ needs |= NEED_INITRD; ++ if (newMBKernel) { ++ needs |= NEED_MB; ++ new->multiboot = 1; ++ } ++ ++ if (template) { ++ for (masterLine = template->lines; ++ masterLine && (tmplLine = lineDup(masterLine)); ++ lineFree(tmplLine), masterLine = masterLine->next) { ++ dbgPrintf("addNewKernel processing %d\n", ++ tmplLine->type); ++ ++ /* skip comments */ ++ chptr = tmplLine->indent; ++ while (*chptr && isspace(*chptr)) ++ chptr++; ++ if (*chptr == '#') ++ continue; ++ ++ if (iskernel(tmplLine->type) ++ && tmplLine->numElements >= 2) { ++ if (!template->multiboot && (needs & NEED_MB)) { ++ /* it's not a multiboot template and this is the kernel ++ * line. Try to be intelligent about inserting the ++ * hypervisor at the same time. ++ */ ++ if (config->cfi->mbHyperFirst) { ++ /* insert the hypervisor first */ ++ newLine = ++ addLine(new, config->cfi, ++ LT_HYPER, ++ tmplLine->indent, ++ newMBKernel + ++ strlen(prefix)); ++ /* set up for adding the kernel line */ ++ free(tmplLine->indent); ++ tmplLine->indent = ++ strdup(config-> ++ secondaryIndent); ++ needs &= ~NEED_MB; ++ } ++ if (needs & NEED_KERNEL) { ++ /* use addLineTmpl to preserve line elements, ++ * otherwise we could just call addLine. Unfortunately ++ * this means making some changes to the template ++ * such as the indent change above and the type ++ * change below. ++ */ ++ struct keywordTypes *mbm_kw = ++ getKeywordByType ++ (LT_MBMODULE, config->cfi); ++ if (mbm_kw) { ++ tmplLine->type = ++ LT_MBMODULE; ++ free(tmplLine-> ++ elements[0].item); ++ tmplLine->elements[0]. ++ item = ++ strdup(mbm_kw->key); ++ } ++ newLine = ++ addLineTmpl(new, tmplLine, ++ newLine, ++ newKernelPath + ++ strlen(prefix), ++ config->cfi); ++ needs &= ~NEED_KERNEL; ++ } ++ if (needs & NEED_MB) { /* !mbHyperFirst */ ++ newLine = ++ addLine(new, config->cfi, ++ LT_HYPER, ++ config-> ++ secondaryIndent, ++ newMBKernel + ++ strlen(prefix)); ++ needs &= ~NEED_MB; ++ } ++ } else if (needs & NEED_KERNEL) { ++ newLine = ++ addLineTmpl(new, tmplLine, newLine, ++ newKernelPath + ++ strlen(prefix), ++ config->cfi); ++ needs &= ~NEED_KERNEL; ++ } ++ ++ } else if (tmplLine->type == LT_HYPER && ++ tmplLine->numElements >= 2) { ++ if (needs & NEED_MB) { ++ newLine = ++ addLineTmpl(new, tmplLine, newLine, ++ newMBKernel + ++ strlen(prefix), ++ config->cfi); ++ needs &= ~NEED_MB; ++ } ++ ++ } else if (tmplLine->type == LT_MBMODULE && ++ tmplLine->numElements >= 2) { ++ if (new->multiboot) { ++ if (needs & NEED_KERNEL) { ++ newLine = ++ addLineTmpl(new, tmplLine, ++ newLine, ++ newKernelPath + ++ strlen(prefix), ++ config->cfi); ++ needs &= ~NEED_KERNEL; ++ } else if (config->cfi->mbInitRdIsModule ++ && (needs & NEED_INITRD)) { ++ char *initrdVal; ++ initrdVal = ++ getInitrdVal(config, prefix, ++ tmplLine, ++ newKernelInitrd, ++ extraInitrds, ++ extraInitrdCount); ++ newLine = ++ addLineTmpl(new, tmplLine, ++ newLine, ++ initrdVal, ++ config->cfi); ++ free(initrdVal); ++ needs &= ~NEED_INITRD; ++ } ++ } else if (needs & NEED_KERNEL) { ++ /* template is multi but new is not, ++ * insert the kernel in the first module slot ++ */ ++ tmplLine->type = ++ preferredLineType(LT_KERNEL, ++ config->cfi); ++ free(tmplLine->elements[0].item); ++ tmplLine->elements[0].item = ++ strdup(getKeywordByType ++ (tmplLine->type, ++ config->cfi)->key); ++ newLine = ++ addLineTmpl(new, tmplLine, newLine, ++ newKernelPath + ++ strlen(prefix), ++ config->cfi); ++ needs &= ~NEED_KERNEL; ++ } else if (needs & NEED_INITRD) { ++ char *initrdVal; ++ /* template is multi but new is not, ++ * insert the initrd in the second module slot ++ */ ++ tmplLine->type = ++ preferredLineType(LT_INITRD, ++ config->cfi); ++ free(tmplLine->elements[0].item); ++ tmplLine->elements[0].item = ++ strdup(getKeywordByType ++ (tmplLine->type, ++ config->cfi)->key); ++ initrdVal = ++ getInitrdVal(config, prefix, ++ tmplLine, ++ newKernelInitrd, ++ extraInitrds, ++ extraInitrdCount); ++ newLine = ++ addLineTmpl(new, tmplLine, newLine, ++ initrdVal, config->cfi); ++ free(initrdVal); ++ needs &= ~NEED_INITRD; ++ } ++ ++ } else if (isinitrd(tmplLine->type) ++ && tmplLine->numElements >= 2) { ++ if (needs & NEED_INITRD && new->multiboot ++ && !template->multiboot ++ && config->cfi->mbInitRdIsModule) { ++ /* make sure we don't insert the module initrd ++ * before the module kernel... if we don't do it here, ++ * it will be inserted following the template. ++ */ ++ if (!needs & NEED_KERNEL) { ++ char *initrdVal; ++ ++ initrdVal = ++ getInitrdVal(config, prefix, ++ tmplLine, ++ newKernelInitrd, ++ extraInitrds, ++ extraInitrdCount); ++ newLine = ++ addLine(new, config->cfi, ++ LT_MBMODULE, ++ config-> ++ secondaryIndent, ++ initrdVal); ++ free(initrdVal); ++ needs &= ~NEED_INITRD; ++ } ++ } else if (needs & NEED_INITRD) { ++ char *initrdVal; ++ initrdVal = ++ getInitrdVal(config, prefix, ++ tmplLine, ++ newKernelInitrd, ++ extraInitrds, ++ extraInitrdCount); ++ newLine = ++ addLineTmpl(new, tmplLine, newLine, ++ initrdVal, config->cfi); ++ free(initrdVal); ++ needs &= ~NEED_INITRD; ++ } ++ ++ } else if (tmplLine->type == LT_MENUENTRY && ++ (needs & NEED_TITLE)) { ++ requote(tmplLine, config->cfi); ++ char *nkt = malloc(strlen(newKernelTitle) + 3); ++ strcpy(nkt, "'"); ++ strcat(nkt, newKernelTitle); ++ strcat(nkt, "'"); ++ newLine = ++ addLineTmpl(new, tmplLine, newLine, nkt, ++ config->cfi); ++ free(nkt); ++ needs &= ~NEED_TITLE; ++ } else if (tmplLine->type == LT_TITLE && ++ (needs & NEED_TITLE)) { ++ if (tmplLine->numElements >= 2) { ++ newLine = ++ addLineTmpl(new, tmplLine, newLine, ++ newKernelTitle, ++ config->cfi); ++ needs &= ~NEED_TITLE; ++ } else if (tmplLine->numElements == 1 && ++ config->cfi->titleBracketed) { ++ /* addLineTmpl doesn't handle titleBracketed */ ++ newLine = ++ addLine(new, config->cfi, LT_TITLE, ++ tmplLine->indent, ++ newKernelTitle); ++ needs &= ~NEED_TITLE; ++ } ++ } else if (tmplLine->type == LT_ECHO) { ++ requote(tmplLine, config->cfi); ++ static const char *prefix = "'Loading "; ++ if (tmplLine->numElements > 1 && ++ strstr(tmplLine->elements[1].item, prefix) ++ && masterLine->next ++ && iskernel(masterLine->next->type)) { ++ char *newTitle = ++ malloc(strlen(prefix) + ++ strlen(newKernelTitle) + 2); ++ ++ strcpy(newTitle, prefix); ++ strcat(newTitle, newKernelTitle); ++ strcat(newTitle, "'"); ++ newLine = ++ addLine(new, config->cfi, LT_ECHO, ++ tmplLine->indent, newTitle); ++ free(newTitle); ++ } else { ++ /* pass through other lines from the template */ ++ newLine = ++ addLineTmpl(new, tmplLine, newLine, ++ NULL, config->cfi); ++ } ++ } else { ++ /* pass through other lines from the template */ ++ newLine = ++ addLineTmpl(new, tmplLine, newLine, NULL, ++ config->cfi); ++ } + } + +- case LT_HYPER: +- newLine = addLine(new, config->cfi, LT_HYPER, +- config->primaryIndent, +- newMBKernel + strlen(prefix)); +- needs &= ~NEED_MB; +- break; ++ } else { ++ /* don't have a template, so start the entry with the ++ * appropriate starting line ++ */ ++ switch (config->cfi->entryStart) { ++ case LT_KERNEL: ++ case LT_KERNEL_EFI: ++ case LT_KERNEL_16: ++ if (new->multiboot && config->cfi->mbHyperFirst) { ++ /* fall through to LT_HYPER */ ++ } else { ++ newLine = addLine(new, config->cfi, ++ preferredLineType(LT_KERNEL, ++ config-> ++ cfi), ++ config->primaryIndent, ++ newKernelPath + ++ strlen(prefix)); ++ needs &= ~NEED_KERNEL; ++ break; ++ } + +- case LT_MENUENTRY: { +- char *nkt = malloc(strlen(newKernelTitle)+3); +- strcpy(nkt, "'"); +- strcat(nkt, newKernelTitle); +- strcat(nkt, "'"); +- newLine = addLine(new, config->cfi, LT_MENUENTRY, +- config->primaryIndent, nkt); +- free(nkt); +- needs &= ~NEED_TITLE; +- needs |= NEED_END; +- break; +- } +- case LT_TITLE: +- if( useextlinuxmenu != 0 ){ // We just need useextlinuxmenu to not be zero (set above) +- char * templabel; +- int x = 0, y = 0; +- +- templabel = strdup(newKernelTitle); +- while( templabel[x]){ +- if( templabel[x] == ' ' ){ +- y = x; +- while( templabel[y] ){ +- templabel[y] = templabel[y+1]; +- y++; ++ case LT_HYPER: ++ newLine = addLine(new, config->cfi, LT_HYPER, ++ config->primaryIndent, ++ newMBKernel + strlen(prefix)); ++ needs &= ~NEED_MB; ++ break; ++ ++ case LT_MENUENTRY:{ ++ char *nkt = malloc(strlen(newKernelTitle) + 3); ++ strcpy(nkt, "'"); ++ strcat(nkt, newKernelTitle); ++ strcat(nkt, "'"); ++ newLine = ++ addLine(new, config->cfi, LT_MENUENTRY, ++ config->primaryIndent, nkt); ++ free(nkt); ++ needs &= ~NEED_TITLE; ++ needs |= NEED_END; ++ break; ++ } ++ case LT_TITLE: ++ if (useextlinuxmenu != 0) { // We just need useextlinuxmenu to not be zero (set above) ++ char *templabel; ++ int x = 0, y = 0; ++ ++ templabel = strdup(newKernelTitle); ++ while (templabel[x]) { ++ if (templabel[x] == ' ') { ++ y = x; ++ while (templabel[y]) { ++ templabel[y] = ++ templabel[y + 1]; ++ y++; ++ } + } ++ x++; + } +- x++; ++ newLine = addLine(new, config->cfi, LT_TITLE, ++ config->primaryIndent, ++ templabel); ++ free(templabel); ++ } else { ++ newLine = addLine(new, config->cfi, LT_TITLE, ++ config->primaryIndent, ++ newKernelTitle); + } +- newLine = addLine(new, config->cfi, LT_TITLE, +- config->primaryIndent, templabel); +- free(templabel); +- }else{ +- newLine = addLine(new, config->cfi, LT_TITLE, +- config->primaryIndent, newKernelTitle); ++ needs &= ~NEED_TITLE; ++ break; ++ ++ default: ++ abort(); + } ++ } ++ ++ struct singleLine *endLine = NULL; ++ endLine = getLineByType(LT_ENTRY_END, new->lines); ++ if (endLine) { ++ removeLine(new, endLine); ++ needs |= NEED_END; ++ } ++ ++ /* add the remainder of the lines, i.e. those that either ++ * weren't present in the template, or in the case of no template, ++ * all the lines following the entryStart. ++ */ ++ if (needs & NEED_TITLE) { ++ newLine = addLine(new, config->cfi, LT_TITLE, ++ config->secondaryIndent, newKernelTitle); + needs &= ~NEED_TITLE; +- break; ++ } ++ if ((needs & NEED_MB) && config->cfi->mbHyperFirst) { ++ newLine = addLine(new, config->cfi, LT_HYPER, ++ config->secondaryIndent, ++ newMBKernel + strlen(prefix)); ++ needs &= ~NEED_MB; ++ } ++ if (needs & NEED_KERNEL) { ++ newLine = addLine(new, config->cfi, ++ (new->multiboot ++ && getKeywordByType(LT_MBMODULE, ++ config->cfi)) ++ ? LT_MBMODULE : preferredLineType(LT_KERNEL, ++ config-> ++ cfi), ++ config->secondaryIndent, ++ newKernelPath + strlen(prefix)); ++ needs &= ~NEED_KERNEL; ++ } ++ if (needs & NEED_MB) { ++ newLine = addLine(new, config->cfi, LT_HYPER, ++ config->secondaryIndent, ++ newMBKernel + strlen(prefix)); ++ needs &= ~NEED_MB; ++ } ++ if (needs & NEED_INITRD) { ++ char *initrdVal; ++ initrdVal = ++ getInitrdVal(config, prefix, NULL, newKernelInitrd, ++ extraInitrds, extraInitrdCount); ++ newLine = ++ addLine(new, config->cfi, ++ (new->multiboot ++ && getKeywordByType(LT_MBMODULE, config->cfi)) ++ ? LT_MBMODULE : preferredLineType(LT_INITRD, ++ config->cfi), ++ config->secondaryIndent, initrdVal); ++ free(initrdVal); ++ needs &= ~NEED_INITRD; ++ } ++ if (needs & NEED_END) { ++ newLine = addLine(new, config->cfi, LT_ENTRY_END, ++ config->secondaryIndent, NULL); ++ needs &= ~NEED_END; ++ } + +- default: ++ if (needs) { ++ printf(_("grubby: needs=%d, aborting\n"), needs); + abort(); + } +- } +- +- struct singleLine *endLine = NULL; +- endLine = getLineByType(LT_ENTRY_END, new->lines); +- if (endLine) { +- removeLine(new, endLine); +- needs |= NEED_END; +- } +- +- /* add the remainder of the lines, i.e. those that either +- * weren't present in the template, or in the case of no template, +- * all the lines following the entryStart. +- */ +- if (needs & NEED_TITLE) { +- newLine = addLine(new, config->cfi, LT_TITLE, +- config->secondaryIndent, +- newKernelTitle); +- needs &= ~NEED_TITLE; +- } +- if ((needs & NEED_MB) && config->cfi->mbHyperFirst) { +- newLine = addLine(new, config->cfi, LT_HYPER, +- config->secondaryIndent, +- newMBKernel + strlen(prefix)); +- needs &= ~NEED_MB; +- } +- if (needs & NEED_KERNEL) { +- newLine = addLine(new, config->cfi, +- (new->multiboot && getKeywordByType(LT_MBMODULE, +- config->cfi)) +- ? LT_MBMODULE +- : preferredLineType(LT_KERNEL, config->cfi), +- config->secondaryIndent, +- newKernelPath + strlen(prefix)); +- needs &= ~NEED_KERNEL; +- } +- if (needs & NEED_MB) { +- newLine = addLine(new, config->cfi, LT_HYPER, +- config->secondaryIndent, +- newMBKernel + strlen(prefix)); +- needs &= ~NEED_MB; +- } +- if (needs & NEED_INITRD) { +- char *initrdVal; +- initrdVal = getInitrdVal(config, prefix, NULL, newKernelInitrd, extraInitrds, extraInitrdCount); +- newLine = addLine(new, config->cfi, +- (new->multiboot && getKeywordByType(LT_MBMODULE, +- config->cfi)) +- ? LT_MBMODULE +- : preferredLineType(LT_INITRD, config->cfi), +- config->secondaryIndent, +- initrdVal); +- free(initrdVal); +- needs &= ~NEED_INITRD; +- } +- if (needs & NEED_END) { +- newLine = addLine(new, config->cfi, LT_ENTRY_END, +- config->secondaryIndent, NULL); +- needs &= ~NEED_END; +- } +- +- if (needs) { +- printf(_("grubby: needs=%d, aborting\n"), needs); +- abort(); +- } +- +- if (updateImage(config, "0", prefix, newKernelArgs, NULL, +- newMBKernelArgs, NULL)) return 1; +- +- return 0; ++ ++ if (updateImage(config, "0", prefix, newKernelArgs, NULL, ++ newMBKernelArgs, NULL)) ++ return 1; ++ ++ return 0; + } + +-int main(int argc, const char ** argv) { +- poptContext optCon; +- const char * grubConfig = NULL; +- char * outputFile = NULL; +- int arg = 0; +- int flags = 0; +- int badImageOkay = 0; +- int configureGrub2 = 0; +- int configureLilo = 0, configureELilo = 0, configureGrub = 0; +- int configureYaboot = 0, configureSilo = 0, configureZipl = 0; +- int configureExtLinux = 0; +- int bootloaderProbe = 0; +- int extraInitrdCount = 0; +- char * updateKernelPath = NULL; +- char * newKernelPath = NULL; +- char * removeKernelPath = NULL; +- char * newKernelArgs = NULL; +- char * newKernelInitrd = NULL; +- char * newKernelTitle = NULL; +- char * newKernelVersion = NULL; +- char * newMBKernel = NULL; +- char * newMBKernelArgs = NULL; +- char * removeMBKernelArgs = NULL; +- char * removeMBKernel = NULL; +- char * bootPrefix = NULL; +- char * defaultKernel = NULL; +- char * removeArgs = NULL; +- char * kernelInfo = NULL; +- char * extraInitrds[MAX_EXTRA_INITRDS] = { NULL }; +- char * envPath = NULL; +- const char * chptr = NULL; +- struct configFileInfo * cfi = NULL; +- struct grubConfig * config; +- struct singleEntry * template = NULL; +- int copyDefault = 0, makeDefault = 0; +- int displayDefault = 0; +- int displayDefaultIndex = 0; +- int displayDefaultTitle = 0; +- int defaultIndex = -1; +- struct poptOption options[] = { +- { "add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0, +- _("add an entry for the specified kernel"), _("kernel-path") }, +- { "add-multiboot", 0, POPT_ARG_STRING, &newMBKernel, 0, +- _("add an entry for the specified multiboot kernel"), NULL }, +- { "args", 0, POPT_ARG_STRING, &newKernelArgs, 0, +- _("default arguments for the new kernel or new arguments for " +- "kernel being updated"), _("args") }, +- { "mbargs", 0, POPT_ARG_STRING, &newMBKernelArgs, 0, +- _("default arguments for the new multiboot kernel or " +- "new arguments for multiboot kernel being updated"), NULL }, +- { "bad-image-okay", 0, 0, &badImageOkay, 0, +- _("don't sanity check images in boot entries (for testing only)"), +- NULL }, +- { "boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0, +- _("filestystem which contains /boot directory (for testing only)"), +- _("bootfs") }, ++int main(int argc, const char **argv) ++{ ++ poptContext optCon; ++ const char *grubConfig = NULL; ++ char *outputFile = NULL; ++ int arg = 0; ++ int flags = 0; ++ int badImageOkay = 0; ++ int configureGrub2 = 0; ++ int configureLilo = 0, configureELilo = 0, configureGrub = 0; ++ int configureYaboot = 0, configureSilo = 0, configureZipl = 0; ++ int configureExtLinux = 0; ++ int bootloaderProbe = 0; ++ int extraInitrdCount = 0; ++ char *updateKernelPath = NULL; ++ char *newKernelPath = NULL; ++ char *removeKernelPath = NULL; ++ char *newKernelArgs = NULL; ++ char *newKernelInitrd = NULL; ++ char *newKernelTitle = NULL; ++ char *newKernelVersion = NULL; ++ char *newMBKernel = NULL; ++ char *newMBKernelArgs = NULL; ++ char *removeMBKernelArgs = NULL; ++ char *removeMBKernel = NULL; ++ char *bootPrefix = NULL; ++ char *defaultKernel = NULL; ++ char *removeArgs = NULL; ++ char *kernelInfo = NULL; ++ char *extraInitrds[MAX_EXTRA_INITRDS] = { NULL }; ++ char *envPath = NULL; ++ const char *chptr = NULL; ++ struct configFileInfo *cfi = NULL; ++ struct grubConfig *config; ++ struct singleEntry *template = NULL; ++ int copyDefault = 0, makeDefault = 0; ++ int displayDefault = 0; ++ int displayDefaultIndex = 0; ++ int displayDefaultTitle = 0; ++ int defaultIndex = -1; ++ struct poptOption options[] = { ++ {"add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0, ++ _("add an entry for the specified kernel"), _("kernel-path")}, ++ {"add-multiboot", 0, POPT_ARG_STRING, &newMBKernel, 0, ++ _("add an entry for the specified multiboot kernel"), NULL}, ++ {"args", 0, POPT_ARG_STRING, &newKernelArgs, 0, ++ _("default arguments for the new kernel or new arguments for " ++ "kernel being updated"), _("args")}, ++ {"mbargs", 0, POPT_ARG_STRING, &newMBKernelArgs, 0, ++ _("default arguments for the new multiboot kernel or " ++ "new arguments for multiboot kernel being updated"), NULL}, ++ {"bad-image-okay", 0, 0, &badImageOkay, 0, ++ _ ++ ("don't sanity check images in boot entries (for testing only)"), ++ NULL}, ++ {"boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0, ++ _ ++ ("filestystem which contains /boot directory (for testing only)"), ++ _("bootfs")}, + #if defined(__i386__) || defined(__x86_64__) || defined (__powerpc64__) || defined (__ia64__) +- { "bootloader-probe", 0, POPT_ARG_NONE, &bootloaderProbe, 0, +- _("check which bootloader is installed on boot sector") }, ++ {"bootloader-probe", 0, POPT_ARG_NONE, &bootloaderProbe, 0, ++ _("check which bootloader is installed on boot sector")}, + #endif +- { "config-file", 'c', POPT_ARG_STRING, &grubConfig, 0, +- _("path to grub config file to update (\"-\" for stdin)"), +- _("path") }, +- { "copy-default", 0, 0, ©Default, 0, +- _("use the default boot entry as a template for the new entry " +- "being added; if the default is not a linux image, or if " +- "the kernel referenced by the default image does not exist, " +- "the first linux entry whose kernel does exist is used as the " +- "template"), NULL }, +- { "debug", 0, 0, &debug, 0, +- _("print debugging information for failures") }, +- { "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") }, +- { "efi", 0, POPT_ARG_NONE, &isEfi, 0, +- _("force grub2 stanzas to use efi") }, +- { "env", 0, POPT_ARG_STRING, &envPath, 0, +- _("path for environment data"), +- _("path") }, +- { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0, +- _("configure extlinux bootloader (from syslinux)") }, +- { "grub", 0, POPT_ARG_NONE, &configureGrub, 0, +- _("configure grub bootloader") }, +- { "grub2", 0, POPT_ARG_NONE, &configureGrub2, 0, +- _("configure grub2 bootloader") }, +- { "info", 0, POPT_ARG_STRING, &kernelInfo, 0, +- _("display boot information for specified kernel"), +- _("kernel-path") }, +- { "initrd", 0, POPT_ARG_STRING, &newKernelInitrd, 0, +- _("initrd image for the new kernel"), _("initrd-path") }, +- { "extra-initrd", 'i', POPT_ARG_STRING, NULL, 'i', +- _("auxiliary initrd image for things other than the new kernel"), _("initrd-path") }, +- { "lilo", 0, POPT_ARG_NONE, &configureLilo, 0, +- _("configure lilo bootloader") }, +- { "make-default", 0, 0, &makeDefault, 0, +- _("make the newly added entry the default boot entry"), NULL }, +- { "output-file", 'o', POPT_ARG_STRING, &outputFile, 0, +- _("path to output updated config file (\"-\" for stdout)"), +- _("path") }, +- { "remove-args", 0, POPT_ARG_STRING, &removeArgs, 0, +- _("remove kernel arguments"), NULL }, +- { "remove-mbargs", 0, POPT_ARG_STRING, &removeMBKernelArgs, 0, +- _("remove multiboot kernel arguments"), NULL }, +- { "remove-kernel", 0, POPT_ARG_STRING, &removeKernelPath, 0, +- _("remove all entries for the specified kernel"), +- _("kernel-path") }, +- { "remove-multiboot", 0, POPT_ARG_STRING, &removeMBKernel, 0, +- _("remove all entries for the specified multiboot kernel"), NULL }, +- { "set-default", 0, POPT_ARG_STRING, &defaultKernel, 0, +- _("make the first entry referencing the specified kernel " +- "the default"), _("kernel-path") }, +- { "set-default-index", 0, POPT_ARG_INT, &defaultIndex, 0, +- _("make the given entry index the default entry"), +- _("entry-index") }, +- { "silo", 0, POPT_ARG_NONE, &configureSilo, 0, +- _("configure silo bootloader") }, +- { "title", 0, POPT_ARG_STRING, &newKernelTitle, 0, +- _("title to use for the new kernel entry"), _("entry-title") }, +- { "update-kernel", 0, POPT_ARG_STRING, &updateKernelPath, 0, +- _("updated information for the specified kernel"), +- _("kernel-path") }, +- { "version", 'v', 0, NULL, 'v', +- _("print the version of this program and exit"), NULL }, +- { "yaboot", 0, POPT_ARG_NONE, &configureYaboot, 0, +- _("configure yaboot bootloader") }, +- { "zipl", 0, POPT_ARG_NONE, &configureZipl, 0, +- _("configure zipl bootloader") }, +- POPT_AUTOHELP +- { 0, 0, 0, 0, 0 } +- }; +- +- useextlinuxmenu=0; +- +- int i = 0; +- for (int j = 1; j < argc; j++) +- i += strlen(argv[j]) + 1; +- saved_command_line = malloc(i); +- if (!saved_command_line) { +- fprintf(stderr, "grubby: %m\n"); +- exit(1); +- } +- saved_command_line[0] = '\0'; +- for (int j = 1; j < argc; j++) { +- strcat(saved_command_line, argv[j]); +- strncat(saved_command_line, j == argc -1 ? "" : " ", 1); +- } +- +- optCon = poptGetContext("grubby", argc, argv, options, 0); +- poptReadDefaultConfig(optCon, 1); +- +- while ((arg = poptGetNextOpt(optCon)) >= 0) { +- switch (arg) { +- case 'v': +- printf("grubby version %s\n", VERSION); +- exit(0); +- break; +- case 'i': +- if (extraInitrdCount < MAX_EXTRA_INITRDS) { +- extraInitrds[extraInitrdCount++] = strdup(poptGetOptArg(optCon)); +- } else { +- fprintf(stderr, _("grubby: extra initrd maximum is %d\n"), extraInitrdCount); ++ {"config-file", 'c', POPT_ARG_STRING, &grubConfig, 0, ++ _("path to grub config file to update (\"-\" for stdin)"), ++ _("path")}, ++ {"copy-default", 0, 0, ©Default, 0, ++ _("use the default boot entry as a template for the new entry " ++ "being added; if the default is not a linux image, or if " ++ "the kernel referenced by the default image does not exist, " ++ "the first linux entry whose kernel does exist is used as the " ++ "template"), NULL}, ++ {"debug", 0, 0, &debug, 0, ++ _("print debugging information for failures")}, ++ {"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")}, ++ {"efi", 0, POPT_ARG_NONE, &isEfi, 0, ++ _("force grub2 stanzas to use efi")}, ++ {"env", 0, POPT_ARG_STRING, &envPath, 0, ++ _("path for environment data"), ++ _("path")}, ++ {"extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0, ++ _("configure extlinux bootloader (from syslinux)")}, ++ {"grub", 0, POPT_ARG_NONE, &configureGrub, 0, ++ _("configure grub bootloader")}, ++ {"grub2", 0, POPT_ARG_NONE, &configureGrub2, 0, ++ _("configure grub2 bootloader")}, ++ {"info", 0, POPT_ARG_STRING, &kernelInfo, 0, ++ _("display boot information for specified kernel"), ++ _("kernel-path")}, ++ {"initrd", 0, POPT_ARG_STRING, &newKernelInitrd, 0, ++ _("initrd image for the new kernel"), _("initrd-path")}, ++ {"extra-initrd", 'i', POPT_ARG_STRING, NULL, 'i', ++ _ ++ ("auxiliary initrd image for things other than the new kernel"), ++ _("initrd-path")}, ++ {"lilo", 0, POPT_ARG_NONE, &configureLilo, 0, ++ _("configure lilo bootloader")}, ++ {"make-default", 0, 0, &makeDefault, 0, ++ _("make the newly added entry the default boot entry"), NULL}, ++ {"output-file", 'o', POPT_ARG_STRING, &outputFile, 0, ++ _("path to output updated config file (\"-\" for stdout)"), ++ _("path")}, ++ {"remove-args", 0, POPT_ARG_STRING, &removeArgs, 0, ++ _("remove kernel arguments"), NULL}, ++ {"remove-mbargs", 0, POPT_ARG_STRING, &removeMBKernelArgs, 0, ++ _("remove multiboot kernel arguments"), NULL}, ++ {"remove-kernel", 0, POPT_ARG_STRING, &removeKernelPath, 0, ++ _("remove all entries for the specified kernel"), ++ _("kernel-path")}, ++ {"remove-multiboot", 0, POPT_ARG_STRING, &removeMBKernel, 0, ++ _("remove all entries for the specified multiboot kernel"), ++ NULL}, ++ {"set-default", 0, POPT_ARG_STRING, &defaultKernel, 0, ++ _("make the first entry referencing the specified kernel " ++ "the default"), _("kernel-path")}, ++ {"set-default-index", 0, POPT_ARG_INT, &defaultIndex, 0, ++ _("make the given entry index the default entry"), ++ _("entry-index")}, ++ {"silo", 0, POPT_ARG_NONE, &configureSilo, 0, ++ _("configure silo bootloader")}, ++ {"title", 0, POPT_ARG_STRING, &newKernelTitle, 0, ++ _("title to use for the new kernel entry"), _("entry-title")}, ++ {"update-kernel", 0, POPT_ARG_STRING, &updateKernelPath, 0, ++ _("updated information for the specified kernel"), ++ _("kernel-path")}, ++ {"version", 'v', 0, NULL, 'v', ++ _("print the version of this program and exit"), NULL}, ++ {"yaboot", 0, POPT_ARG_NONE, &configureYaboot, 0, ++ _("configure yaboot bootloader")}, ++ {"zipl", 0, POPT_ARG_NONE, &configureZipl, 0, ++ _("configure zipl bootloader")}, ++ POPT_AUTOHELP {0, 0, 0, 0, 0} ++ }; ++ ++ useextlinuxmenu = 0; ++ ++ int i = 0; ++ for (int j = 1; j < argc; j++) ++ i += strlen(argv[j]) + 1; ++ saved_command_line = malloc(i); ++ if (!saved_command_line) { ++ fprintf(stderr, "grubby: %m\n"); ++ exit(1); ++ } ++ saved_command_line[0] = '\0'; ++ for (int j = 1; j < argc; j++) { ++ strcat(saved_command_line, argv[j]); ++ strncat(saved_command_line, j == argc - 1 ? "" : " ", 1); ++ } ++ ++ optCon = poptGetContext("grubby", argc, argv, options, 0); ++ poptReadDefaultConfig(optCon, 1); ++ ++ while ((arg = poptGetNextOpt(optCon)) >= 0) { ++ switch (arg) { ++ case 'v': ++ printf("grubby version %s\n", VERSION); ++ exit(0); ++ break; ++ case 'i': ++ if (extraInitrdCount < MAX_EXTRA_INITRDS) { ++ extraInitrds[extraInitrdCount++] = ++ strdup(poptGetOptArg(optCon)); ++ } else { ++ fprintf(stderr, ++ _ ++ ("grubby: extra initrd maximum is %d\n"), ++ extraInitrdCount); ++ return 1; ++ } ++ break; ++ } ++ } ++ ++ if (arg < -1) { ++ fprintf(stderr, _("grubby: bad argument %s: %s\n"), ++ poptBadOption(optCon, POPT_BADOPTION_NOALIAS), ++ poptStrerror(arg)); + return 1; +- } +- break; + } +- } + +- if (arg < -1) { +- fprintf(stderr, _("grubby: bad argument %s: %s\n"), +- poptBadOption(optCon, POPT_BADOPTION_NOALIAS), +- poptStrerror(arg)); +- return 1; +- } ++ if ((chptr = poptGetArg(optCon))) { ++ fprintf(stderr, _("grubby: unexpected argument %s\n"), chptr); ++ return 1; ++ } + +- if ((chptr = poptGetArg(optCon))) { +- fprintf(stderr, _("grubby: unexpected argument %s\n"), chptr); +- return 1; +- } ++ if ((configureLilo + configureGrub2 + configureGrub + configureELilo + ++ configureYaboot + configureSilo + configureZipl + ++ configureExtLinux) > 1) { ++ fprintf(stderr, ++ _("grubby: cannot specify multiple bootloaders\n")); ++ return 1; ++ } else if (bootloaderProbe && grubConfig) { ++ fprintf(stderr, ++ _ ++ ("grubby: cannot specify config file with --bootloader-probe\n")); ++ return 1; ++ } else if (configureGrub2) { ++ cfi = &grub2ConfigType; ++ if (envPath) ++ cfi->envFile = envPath; ++ } else if (configureLilo) { ++ cfi = &liloConfigType; ++ } else if (configureGrub) { ++ cfi = &grubConfigType; ++ } else if (configureELilo) { ++ cfi = &eliloConfigType; ++ } else if (configureYaboot) { ++ cfi = &yabootConfigType; ++ } else if (configureSilo) { ++ cfi = &siloConfigType; ++ } else if (configureZipl) { ++ cfi = &ziplConfigType; ++ } else if (configureExtLinux) { ++ cfi = &extlinuxConfigType; ++ useextlinuxmenu = 1; ++ } + +- if ((configureLilo + configureGrub2 + configureGrub + configureELilo + +- configureYaboot + configureSilo + configureZipl + +- configureExtLinux ) > 1) { +- fprintf(stderr, _("grubby: cannot specify multiple bootloaders\n")); +- return 1; +- } else if (bootloaderProbe && grubConfig) { +- fprintf(stderr, +- _("grubby: cannot specify config file with --bootloader-probe\n")); +- return 1; +- } else if (configureGrub2) { +- cfi = &grub2ConfigType; +- if (envPath) +- cfi->envFile = envPath; +- } else if (configureLilo) { +- cfi = &liloConfigType; +- } else if (configureGrub) { +- cfi = &grubConfigType; +- } else if (configureELilo) { +- cfi = &eliloConfigType; +- } else if (configureYaboot) { +- cfi = &yabootConfigType; +- } else if (configureSilo) { +- cfi = &siloConfigType; +- } else if (configureZipl) { +- cfi = &ziplConfigType; +- } else if (configureExtLinux) { +- cfi = &extlinuxConfigType; +- useextlinuxmenu=1; +- } +- +- if (!cfi) { +- if (grub2FindConfig(&grub2ConfigType)) { +- cfi = &grub2ConfigType; +- if (envPath) +- cfi->envFile = envPath; +- } else +- #ifdef __ia64__ +- cfi = &eliloConfigType; +- #elif __powerpc__ +- cfi = &yabootConfigType; +- #elif __sparc__ +- cfi = &siloConfigType; +- #elif __s390__ +- cfi = &ziplConfigType; +- #elif __s390x__ +- cfi = &ziplConfigtype; +- #else +- cfi = &grubConfigType; +- #endif +- } +- +- if (!grubConfig) { +- if (cfi->findConfig) +- grubConfig = cfi->findConfig(cfi); +- if (!grubConfig) +- grubConfig = cfi->defaultConfig; +- } +- +- if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion || +- newKernelPath || removeKernelPath || makeDefault || +- defaultKernel || displayDefaultIndex || displayDefaultTitle || +- (defaultIndex >= 0))) { +- fprintf(stderr, _("grubby: --bootloader-probe may not be used with " ++ if (!cfi) { ++ if (grub2FindConfig(&grub2ConfigType)) { ++ cfi = &grub2ConfigType; ++ if (envPath) ++ cfi->envFile = envPath; ++ } else ++#ifdef __ia64__ ++ cfi = &eliloConfigType; ++#elif __powerpc__ ++ cfi = &yabootConfigType; ++#elif __sparc__ ++ cfi = &siloConfigType; ++#elif __s390__ ++ cfi = &ziplConfigType; ++#elif __s390x__ ++ cfi = &ziplConfigtype; ++#else ++ cfi = &grubConfigType; ++#endif ++ } ++ ++ if (!grubConfig) { ++ if (cfi->findConfig) ++ grubConfig = cfi->findConfig(cfi); ++ if (!grubConfig) ++ grubConfig = cfi->defaultConfig; ++ } ++ ++ if (bootloaderProbe ++ && (displayDefault || kernelInfo || newKernelVersion ++ || newKernelPath || removeKernelPath || makeDefault ++ || defaultKernel || displayDefaultIndex || displayDefaultTitle ++ || (defaultIndex >= 0))) { ++ fprintf(stderr, ++ _("grubby: --bootloader-probe may not be used with " + "specified option")); +- return 1; +- } ++ return 1; ++ } + +- if ((displayDefault || kernelInfo) && (newKernelVersion || newKernelPath || +- removeKernelPath)) { +- fprintf(stderr, _("grubby: --default-kernel and --info may not " ++ if ((displayDefault || kernelInfo) ++ && (newKernelVersion || newKernelPath || removeKernelPath)) { ++ fprintf(stderr, ++ _("grubby: --default-kernel and --info may not " + "be used when adding or removing kernels\n")); +- return 1; +- } ++ return 1; ++ } + +- if (newKernelPath && !newKernelTitle) { +- fprintf(stderr, _("grubby: kernel title must be specified\n")); +- return 1; +- } else if (!newKernelPath && (copyDefault || +- (newKernelInitrd && !updateKernelPath)|| +- makeDefault || extraInitrdCount > 0)) { +- fprintf(stderr, _("grubby: kernel path expected\n")); +- return 1; +- } ++ if (newKernelPath && !newKernelTitle) { ++ fprintf(stderr, _("grubby: kernel title must be specified\n")); ++ return 1; ++ } else if (!newKernelPath && (copyDefault || ++ (newKernelInitrd && !updateKernelPath) || ++ makeDefault || extraInitrdCount > 0)) { ++ fprintf(stderr, _("grubby: kernel path expected\n")); ++ return 1; ++ } + +- if (newKernelPath && updateKernelPath) { +- fprintf(stderr, _("grubby: --add-kernel and --update-kernel may" +- "not be used together")); +- return 1; +- } ++ if (newKernelPath && updateKernelPath) { ++ fprintf(stderr, _("grubby: --add-kernel and --update-kernel may" ++ "not be used together")); ++ return 1; ++ } + +- if (makeDefault && defaultKernel) { +- fprintf(stderr, _("grubby: --make-default and --default-kernel " +- "may not be used together\n")); +- return 1; +- } else if (defaultKernel && removeKernelPath && +- !strcmp(defaultKernel, removeKernelPath)) { +- fprintf(stderr, _("grubby: cannot make removed kernel the default\n")); +- return 1; +- } else if (defaultKernel && newKernelPath && +- !strcmp(defaultKernel, newKernelPath)) { +- makeDefault = 1; +- defaultKernel = NULL; +- } +- else if (defaultKernel && (defaultIndex >= 0)) { +- fprintf(stderr, _("grubby: --set-default and --set-default-index " ++ if (makeDefault && defaultKernel) { ++ fprintf(stderr, _("grubby: --make-default and --default-kernel " ++ "may not be used together\n")); ++ return 1; ++ } else if (defaultKernel && removeKernelPath && ++ !strcmp(defaultKernel, removeKernelPath)) { ++ fprintf(stderr, ++ _("grubby: cannot make removed kernel the default\n")); ++ return 1; ++ } else if (defaultKernel && newKernelPath && ++ !strcmp(defaultKernel, newKernelPath)) { ++ makeDefault = 1; ++ defaultKernel = NULL; ++ } else if (defaultKernel && (defaultIndex >= 0)) { ++ fprintf(stderr, ++ _("grubby: --set-default and --set-default-index " + "may not be used together\n")); +- return 1; +- } ++ return 1; ++ } + +- if (grubConfig && !strcmp(grubConfig, "-") && !outputFile) { +- fprintf(stderr, _("grubby: output file must be specified if stdin " +- "is used\n")); +- return 1; +- } ++ if (grubConfig && !strcmp(grubConfig, "-") && !outputFile) { ++ fprintf(stderr, ++ _("grubby: output file must be specified if stdin " ++ "is used\n")); ++ return 1; ++ } + +- if (!removeKernelPath && !newKernelPath && !displayDefault && !defaultKernel +- && !kernelInfo && !bootloaderProbe && !updateKernelPath +- && !removeMBKernel && !displayDefaultIndex && !displayDefaultTitle +- && (defaultIndex == -1)) { +- fprintf(stderr, _("grubby: no action specified\n")); +- return 1; +- } ++ if (!removeKernelPath && !newKernelPath && !displayDefault ++ && !defaultKernel && !kernelInfo && !bootloaderProbe ++ && !updateKernelPath && !removeMBKernel && !displayDefaultIndex ++ && !displayDefaultTitle && (defaultIndex == -1)) { ++ fprintf(stderr, _("grubby: no action specified\n")); ++ return 1; ++ } + +- flags |= badImageOkay ? GRUBBY_BADIMAGE_OKAY : 0; ++ flags |= badImageOkay ? GRUBBY_BADIMAGE_OKAY : 0; + +- if (cfi->needsBootPrefix) { +- if (!bootPrefix) { +- bootPrefix = findBootPrefix(); +- if (!bootPrefix) return 1; ++ if (cfi->needsBootPrefix) { ++ if (!bootPrefix) { ++ bootPrefix = findBootPrefix(); ++ if (!bootPrefix) ++ return 1; ++ } else { ++ /* this shouldn't end with a / */ ++ if (bootPrefix[strlen(bootPrefix) - 1] == '/') ++ bootPrefix[strlen(bootPrefix) - 1] = '\0'; ++ } + } else { +- /* this shouldn't end with a / */ +- if (bootPrefix[strlen(bootPrefix) - 1] == '/') +- bootPrefix[strlen(bootPrefix) - 1] = '\0'; ++ bootPrefix = ""; + } +- } else { +- bootPrefix = ""; +- } +- +- if (!cfi->mbAllowExtraInitRds && +- extraInitrdCount > 0) { +- fprintf(stderr, _("grubby: %s doesn't allow multiple initrds\n"), cfi->defaultConfig); +- return 1; +- } +- +- if (bootloaderProbe) { +- int lrc = 0, grc = 0, gr2c = 0, extrc = 0, yrc = 0, erc = 0; +- struct grubConfig * lconfig, * gconfig, * yconfig, * econfig; +- +- const char *grub2config = grub2FindConfig(&grub2ConfigType); +- if (grub2config) { +- gconfig = readConfig(grub2config, &grub2ConfigType); +- if (!gconfig) +- gr2c = 1; +- else +- gr2c = checkForGrub2(gconfig); +- } +- +- const char *grubconfig = grubFindConfig(&grubConfigType); +- if (!access(grubconfig, F_OK)) { +- gconfig = readConfig(grubconfig, &grubConfigType); +- if (!gconfig) +- grc = 1; +- else +- grc = checkForGrub(gconfig); +- } +- +- if (!access(liloConfigType.defaultConfig, F_OK)) { +- lconfig = readConfig(liloConfigType.defaultConfig, &liloConfigType); +- if (!lconfig) +- lrc = 1; +- else +- lrc = checkForLilo(lconfig); +- } +- +- if (!access(eliloConfigType.defaultConfig, F_OK)) { +- econfig = readConfig(eliloConfigType.defaultConfig, +- &eliloConfigType); +- if (!econfig) +- erc = 1; +- else +- erc = checkForElilo(econfig); +- } +- +- if (!access(extlinuxConfigType.defaultConfig, F_OK)) { +- lconfig = readConfig(extlinuxConfigType.defaultConfig, &extlinuxConfigType); +- if (!lconfig) +- extrc = 1; +- else +- extrc = checkForExtLinux(lconfig); +- } +- +- +- if (!access(yabootConfigType.defaultConfig, F_OK)) { +- yconfig = readConfig(yabootConfigType.defaultConfig, +- &yabootConfigType); +- if (!yconfig) +- yrc = 1; +- else +- yrc = checkForYaboot(yconfig); +- } +- +- if (lrc == 1 || grc == 1 || gr2c == 1 || extrc == 1 || yrc == 1 || +- erc == 1) +- return 1; +- +- if (lrc == 2) printf("lilo\n"); +- if (gr2c == 2) printf("grub2\n"); +- if (grc == 2) printf("grub\n"); +- if (extrc == 2) printf("extlinux\n"); +- if (yrc == 2) printf("yaboot\n"); +- if (erc == 2) printf("elilo\n"); + +- return 0; +- } ++ if (!cfi->mbAllowExtraInitRds && extraInitrdCount > 0) { ++ fprintf(stderr, ++ _("grubby: %s doesn't allow multiple initrds\n"), ++ cfi->defaultConfig); ++ return 1; ++ } + +- if (grubConfig == NULL) { +- printf("Could not find bootloader configuration file.\n"); +- exit(1); +- } ++ if (bootloaderProbe) { ++ int lrc = 0, grc = 0, gr2c = 0, extrc = 0, yrc = 0, erc = 0; ++ struct grubConfig *lconfig, *gconfig, *yconfig, *econfig; ++ ++ const char *grub2config = grub2FindConfig(&grub2ConfigType); ++ if (grub2config) { ++ gconfig = readConfig(grub2config, &grub2ConfigType); ++ if (!gconfig) ++ gr2c = 1; ++ else ++ gr2c = checkForGrub2(gconfig); ++ } + +- config = readConfig(grubConfig, cfi); +- if (!config) return 1; ++ const char *grubconfig = grubFindConfig(&grubConfigType); ++ if (!access(grubconfig, F_OK)) { ++ gconfig = readConfig(grubconfig, &grubConfigType); ++ if (!gconfig) ++ grc = 1; ++ else ++ grc = checkForGrub(gconfig); ++ } + +- if (displayDefault) { +- struct singleLine * line; +- struct singleEntry * entry; +- char * rootspec; ++ if (!access(liloConfigType.defaultConfig, F_OK)) { ++ lconfig = ++ readConfig(liloConfigType.defaultConfig, ++ &liloConfigType); ++ if (!lconfig) ++ lrc = 1; ++ else ++ lrc = checkForLilo(lconfig); ++ } + +- if (config->defaultImage == -1) return 0; +- if (config->defaultImage == DEFAULT_SAVED_GRUB2 && +- cfi->defaultIsSaved) +- config->defaultImage = 0; +- entry = findEntryByIndex(config, config->defaultImage); +- if (!entry) return 0; +- if (!suitableImage(entry, bootPrefix, 0, flags)) return 0; ++ if (!access(eliloConfigType.defaultConfig, F_OK)) { ++ econfig = readConfig(eliloConfigType.defaultConfig, ++ &eliloConfigType); ++ if (!econfig) ++ erc = 1; ++ else ++ erc = checkForElilo(econfig); ++ } + +- line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); +- if (!line) return 0; ++ if (!access(extlinuxConfigType.defaultConfig, F_OK)) { ++ lconfig = ++ readConfig(extlinuxConfigType.defaultConfig, ++ &extlinuxConfigType); ++ if (!lconfig) ++ extrc = 1; ++ else ++ extrc = checkForExtLinux(lconfig); ++ } + +- rootspec = getRootSpecifier(line->elements[1].item); +- printf("%s%s\n", bootPrefix, line->elements[1].item + +- ((rootspec != NULL) ? strlen(rootspec) : 0)); ++ if (!access(yabootConfigType.defaultConfig, F_OK)) { ++ yconfig = readConfig(yabootConfigType.defaultConfig, ++ &yabootConfigType); ++ if (!yconfig) ++ yrc = 1; ++ else ++ yrc = checkForYaboot(yconfig); ++ } + +- return 0; ++ if (lrc == 1 || grc == 1 || gr2c == 1 || extrc == 1 || yrc == 1 ++ || erc == 1) ++ return 1; + +- } else if (displayDefaultTitle) { +- struct singleLine * line; +- struct singleEntry * entry; ++ if (lrc == 2) ++ printf("lilo\n"); ++ if (gr2c == 2) ++ printf("grub2\n"); ++ if (grc == 2) ++ printf("grub\n"); ++ if (extrc == 2) ++ printf("extlinux\n"); ++ if (yrc == 2) ++ printf("yaboot\n"); ++ if (erc == 2) ++ printf("elilo\n"); + +- if (config->defaultImage == -1) +- return 0; +- if (config->defaultImage == DEFAULT_SAVED_GRUB2 && +- cfi->defaultIsSaved) +- config->defaultImage = 0; +- entry = findEntryByIndex(config, config->defaultImage); +- if (!entry) + return 0; ++ } ++ ++ if (grubConfig == NULL) { ++ printf("Could not find bootloader configuration file.\n"); ++ exit(1); ++ } ++ ++ config = readConfig(grubConfig, cfi); ++ if (!config) ++ return 1; ++ ++ if (displayDefault) { ++ struct singleLine *line; ++ struct singleEntry *entry; ++ char *rootspec; ++ ++ if (config->defaultImage == -1) ++ return 0; ++ if (config->defaultImage == DEFAULT_SAVED_GRUB2 && ++ cfi->defaultIsSaved) ++ config->defaultImage = 0; ++ entry = findEntryByIndex(config, config->defaultImage); ++ if (!entry) ++ return 0; ++ if (!suitableImage(entry, bootPrefix, 0, flags)) ++ return 0; ++ ++ line = ++ getLineByType(LT_KERNEL | LT_HYPER | LT_KERNEL_EFI | ++ LT_KERNEL_16, entry->lines); ++ if (!line) ++ return 0; ++ ++ rootspec = getRootSpecifier(line->elements[1].item); ++ printf("%s%s\n", bootPrefix, line->elements[1].item + ++ ((rootspec != NULL) ? strlen(rootspec) : 0)); + +- if (!configureGrub2) { +- char *title; +- line = getLineByType(LT_TITLE, entry->lines); +- if (!line) + return 0; +- title = extractTitle(config, line); +- if (!title) ++ ++ } else if (displayDefaultTitle) { ++ struct singleLine *line; ++ struct singleEntry *entry; ++ ++ if (config->defaultImage == -1) ++ return 0; ++ if (config->defaultImage == DEFAULT_SAVED_GRUB2 && ++ cfi->defaultIsSaved) ++ config->defaultImage = 0; ++ entry = findEntryByIndex(config, config->defaultImage); ++ if (!entry) ++ return 0; ++ ++ if (!configureGrub2) { ++ char *title; ++ line = getLineByType(LT_TITLE, entry->lines); ++ if (!line) ++ return 0; ++ title = extractTitle(config, line); ++ if (!title) ++ return 0; ++ printf("%s\n", title); ++ free(title); ++ } else { ++ char *title; ++ ++ dbgPrintf ++ ("This is GRUB2, default title is embeded in menuentry\n"); ++ line = getLineByType(LT_MENUENTRY, entry->lines); ++ if (!line) ++ return 0; ++ title = grub2ExtractTitle(line); ++ if (title) ++ printf("%s\n", title); ++ } + return 0; +- printf("%s\n", title); +- free(title); +- } else { +- char * title; + +- dbgPrintf("This is GRUB2, default title is embeded in menuentry\n"); +- line = getLineByType(LT_MENUENTRY, entry->lines); +- if (!line) ++ } else if (displayDefaultIndex) { ++ if (config->defaultImage == -1) ++ return 0; ++ if (config->defaultImage == DEFAULT_SAVED_GRUB2 && ++ cfi->defaultIsSaved) ++ config->defaultImage = 0; ++ printf("%i\n", config->defaultImage); + return 0; +- title = grub2ExtractTitle(line); +- if (title) +- printf("%s\n", title); ++ ++ } else if (kernelInfo) ++ return displayInfo(config, kernelInfo, bootPrefix); ++ ++ if (copyDefault) { ++ template = findTemplate(config, bootPrefix, NULL, 0, flags); ++ if (!template) ++ return 1; + } +- return 0; + +- } else if (displayDefaultIndex) { +- if (config->defaultImage == -1) return 0; +- if (config->defaultImage == DEFAULT_SAVED_GRUB2 && +- cfi->defaultIsSaved) +- config->defaultImage = 0; +- printf("%i\n", config->defaultImage); +- return 0; +- +- } else if (kernelInfo) +- return displayInfo(config, kernelInfo, bootPrefix); +- +- if (copyDefault) { +- template = findTemplate(config, bootPrefix, NULL, 0, flags); +- if (!template) return 1; +- } +- +- markRemovedImage(config, removeKernelPath, bootPrefix); +- markRemovedImage(config, removeMBKernel, bootPrefix); +- setDefaultImage(config, newKernelPath != NULL, defaultKernel, makeDefault, +- bootPrefix, flags, defaultIndex); +- setFallbackImage(config, newKernelPath != NULL); +- if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, +- removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1; +- if (updateKernelPath && newKernelInitrd) { +- if (newMBKernel) { +- if (addMBInitrd(config, newMBKernel, updateKernelPath, ++ markRemovedImage(config, removeKernelPath, bootPrefix); ++ markRemovedImage(config, removeMBKernel, bootPrefix); ++ setDefaultImage(config, newKernelPath != NULL, defaultKernel, ++ makeDefault, bootPrefix, flags, defaultIndex); ++ setFallbackImage(config, newKernelPath != NULL); ++ if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, ++ removeArgs, newMBKernelArgs, removeMBKernelArgs)) ++ return 1; ++ if (updateKernelPath && newKernelInitrd) { ++ if (newMBKernel) { ++ if (addMBInitrd(config, newMBKernel, updateKernelPath, + bootPrefix, newKernelInitrd, + newKernelTitle)) +- return 1; +- } else { +- if (updateInitrd(config, updateKernelPath, bootPrefix, +- newKernelInitrd, newKernelTitle)) +- return 1; +- } +- } +- if (addNewKernel(config, template, bootPrefix, newKernelPath, +- newKernelTitle, newKernelArgs, newKernelInitrd, +- (const char **)extraInitrds, extraInitrdCount, +- newMBKernel, newMBKernelArgs)) return 1; +- +- +- if (numEntries(config) == 0) { +- fprintf(stderr, _("grubby: doing this would leave no kernel entries. " +- "Not writing out new config.\n")); +- return 1; +- } +- +- if (!outputFile) +- outputFile = (char *)grubConfig; +- +- return writeConfig(config, outputFile, bootPrefix); ++ return 1; ++ } else { ++ if (updateInitrd(config, updateKernelPath, bootPrefix, ++ newKernelInitrd, newKernelTitle)) ++ return 1; ++ } ++ } ++ if (addNewKernel(config, template, bootPrefix, newKernelPath, ++ newKernelTitle, newKernelArgs, newKernelInitrd, ++ (const char **)extraInitrds, extraInitrdCount, ++ newMBKernel, newMBKernelArgs)) ++ return 1; ++ ++ if (numEntries(config) == 0) { ++ fprintf(stderr, ++ _("grubby: doing this would leave no kernel entries. " ++ "Not writing out new config.\n")); ++ return 1; ++ } ++ ++ if (!outputFile) ++ outputFile = (char *)grubConfig; ++ ++ return writeConfig(config, outputFile, bootPrefix); + } +-- +2.4.3 + diff --git a/SOURCES/0002-Honor-linux16-and-initrd16.patch b/SOURCES/0002-Honor-linux16-and-initrd16.patch deleted file mode 100644 index bb4efc2..0000000 --- a/SOURCES/0002-Honor-linux16-and-initrd16.patch +++ /dev/null @@ -1,638 +0,0 @@ -From a2c98347462a78a162525496ef694190018fb66c Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 18 Nov 2013 14:44:13 -0500 -Subject: [PATCH 02/16] Honor "linux16" and "initrd16" - -Resolves: rhbz#1031192 -Resolves: rhbz#1034743 - -Signed-off-by: Peter Jones ---- - grubby.c | 63 ++++++++++++++++++++++--------- - test.sh | 16 ++++++++ - test/grub2.10 | 84 +++++++++++++++++++++++++++++++++++++++++ - test/grub2.11 | 97 +++++++++++++++++++++++++++++++++++++++++++++++ - test/results/add/g2-1.10 | 96 +++++++++++++++++++++++++++++++++++++++++++++++ - test/results/add/g2-1.11 | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ - 6 files changed, 437 insertions(+), 17 deletions(-) - create mode 100644 test/grub2.10 - create mode 100644 test/grub2.11 - create mode 100644 test/results/add/g2-1.10 - create mode 100644 test/results/add/g2-1.11 - -diff --git a/grubby.c b/grubby.c -index bbca9d0..4488636 100644 ---- a/grubby.c -+++ b/grubby.c -@@ -90,7 +90,9 @@ enum lineType_e { - LT_SET_VARIABLE = 1 << 19, - LT_KERNEL_EFI = 1 << 20, - LT_INITRD_EFI = 1 << 21, -- LT_UNKNOWN = 1 << 22, -+ LT_KERNEL_16 = 1 << 22, -+ LT_INITRD_16 = 1 << 23, -+ LT_UNKNOWN = 1 << 24, - }; - - struct singleLine { -@@ -220,8 +222,10 @@ struct keywordTypes grub2Keywords[] = { - { "fallback", LT_FALLBACK, ' ' }, - { "linux", LT_KERNEL, ' ' }, - { "linuxefi", LT_KERNEL_EFI, ' ' }, -+ { "linux16", LT_KERNEL_16, ' ' }, - { "initrd", LT_INITRD, ' ', ' ' }, - { "initrdefi", LT_INITRD_EFI, ' ', ' ' }, -+ { "initrd16", LT_INITRD_16, ' ', ' ' }, - { "module", LT_MBMODULE, ' ' }, - { "kernel", LT_HYPER, ' ' }, - { NULL, 0, 0 }, -@@ -395,11 +399,11 @@ static int isquote(char q) - } - - static int iskernel(enum lineType_e type) { -- return (type == LT_KERNEL || type == LT_KERNEL_EFI); -+ return (type == LT_KERNEL || type == LT_KERNEL_EFI || type == LT_KERNEL_16); - } - - static int isinitrd(enum lineType_e type) { -- return (type == LT_INITRD || type == LT_INITRD_EFI); -+ return (type == LT_INITRD || type == LT_INITRD_EFI || type == LT_INITRD_16); - } - - char *grub2ExtractTitle(struct singleLine * line) { -@@ -717,6 +721,17 @@ static enum lineType_e preferredLineType(enum lineType_e type, - default: - return type; - } -+#if defined(__i386__) || defined(__x86_64__) -+ } else if (cfi == &grub2ConfigType) { -+ switch (type) { -+ case LT_KERNEL: -+ return LT_KERNEL_16; -+ case LT_INITRD: -+ return LT_INITRD_16; -+ default: -+ return type; -+ } -+#endif - } - return type; - } -@@ -1804,7 +1819,7 @@ int suitableImage(struct singleEntry * entry, const char * bootPrefix, - return 0; - } - -- 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); - if (!line) { - notSuitablePrintf(entry, 0, "no line found\n"); - return 0; -@@ -1938,7 +1953,7 @@ struct singleEntry * findEntryByPath(struct grubConfig * config, - entry = findEntryByIndex(config, indexVars[i]); - if (!entry) return NULL; - -- 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); - if (!line) return NULL; - - if (index) *index = indexVars[i]; -@@ -1989,9 +2004,9 @@ struct singleEntry * findEntryByPath(struct grubConfig * config, - for (line = entry->lines; line; line = line->next) { - enum lineType_e ct = checkType; - if (entry->multiboot && checkType == LT_KERNEL) -- ct = LT_KERNEL|LT_KERNEL_EFI|LT_MBMODULE|LT_HYPER; -+ ct = LT_KERNEL|LT_KERNEL_EFI|LT_MBMODULE|LT_HYPER|LT_KERNEL_16; - else if (checkType & LT_KERNEL) -- ct = checkType | LT_KERNEL_EFI; -+ ct = checkType | LT_KERNEL_EFI | LT_KERNEL_16; - line = getLineByType(ct, line); - if (!line) - break; /* not found in this entry */ -@@ -2013,7 +2028,7 @@ struct singleEntry * findEntryByPath(struct grubConfig * config, - * non-Linux boot entries (could find netbsd etc, though, which is - * unfortunate) - */ -- 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)) - break; /* found 'im! */ - } - -@@ -2247,7 +2262,7 @@ void displayEntry(struct singleEntry * entry, const char * prefix, int index) { - - printf("index=%d\n", index); - -- 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); - if (!line) { - printf("non linux entry\n"); - return; -@@ -2312,7 +2327,7 @@ void displayEntry(struct singleEntry * entry, const char * prefix, int index) { - printf("root=%s\n", s); - } - -- line = getLineByType(LT_INITRD|LT_INITRD_EFI, entry->lines); -+ line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines); - - if (line && line->numElements >= 2) { - if (!strncmp(prefix, line->elements[1].item, strlen(prefix))) -@@ -2729,7 +2744,7 @@ struct singleLine * addLineTmpl(struct singleEntry * entry, - insertElement(newLine, val, 1, cfi); - - /* but try to keep the rootspec from the template... sigh */ -- 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)) { - char * rootspec = getRootSpecifier(tmplLine->elements[1].item); - if (rootspec != NULL) { - free(newLine->elements[1].item); -@@ -3099,7 +3114,7 @@ int updateActualImage(struct grubConfig * cfg, const char * image, - firstElement = 2; - - } else { -- 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); - if (!line) { - /* no LT_KERNEL or LT_MBMODULE in this entry? */ - continue; -@@ -3264,10 +3279,10 @@ int updateInitrd(struct grubConfig * cfg, const char * image, - if (!image) return 0; - - for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) { -- kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI, entry->lines); -+ kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); - if (!kernelLine) continue; - -- line = getLineByType(LT_INITRD|LT_INITRD_EFI, entry->lines); -+ line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines); - if (line) - removeLine(entry, line); - if (prefix) { -@@ -3278,8 +3293,21 @@ int updateInitrd(struct grubConfig * cfg, const char * image, - endLine = getLineByType(LT_ENTRY_END, entry->lines); - if (endLine) - removeLine(entry, endLine); -- line = addLine(entry, cfg->cfi, preferredLineType(LT_INITRD, cfg->cfi), -- kernelLine->indent, initrd); -+ enum lineType_e lt; -+ switch(kernelLine->type) { -+ case LT_KERNEL: -+ lt = LT_INITRD; -+ break; -+ case LT_KERNEL_EFI: -+ lt = LT_INITRD_EFI; -+ break; -+ case LT_KERNEL_16: -+ lt = LT_INITRD_16; -+ break; -+ default: -+ lt = preferredLineType(LT_INITRD, cfg->cfi); -+ } -+ line = addLine(entry, cfg->cfi, lt, kernelLine->indent, initrd); - if (!line) - return 1; - if (endLine) { -@@ -3877,6 +3905,7 @@ int addNewKernel(struct grubConfig * config, struct singleEntry * template, - switch (config->cfi->entryStart) { - case LT_KERNEL: - case LT_KERNEL_EFI: -+ case LT_KERNEL_16: - if (new->multiboot && config->cfi->mbHyperFirst) { - /* fall through to LT_HYPER */ - } else { -@@ -4435,7 +4464,7 @@ int main(int argc, const char ** argv) { - if (!entry) return 0; - if (!suitableImage(entry, bootPrefix, 0, flags)) return 0; - -- 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); - if (!line) return 0; - - rootspec = getRootSpecifier(line->elements[1].item); -diff --git a/test.sh b/test.sh -index 17b40fe..5be4006 100755 ---- a/test.sh -+++ b/test.sh -@@ -536,6 +536,22 @@ if [ "$testgrub2" == "y" ]; then - - testing="GRUB2 --default-index with default=saved_entry and empty grubenv" - grub2DisplayTest grub2.8 defaultindex/0 --env grubenv.0 --default-index -+ -+ testlinux16=n -+ case $ARCH in -+ ia32|x86_64) testlinux16=y ;; -+ esac -+ -+ if [ "$testlinux16" == "y" ]; then -+ testing="GRUB2 add kernel with linux16" -+ grub2Test grub2.10 add/g2-1.10 --add-kernel=/boot/new-kernel.img \ -+ --title='title' --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ -+ --copy-default -+ -+ testing="GRUB2 add initrd with linux16" -+ grub2Test grub2.11 add/g2-1.11 --update-kernel=/boot/new-kernel.img \ -+ --initrd=/boot/new-initrd --boot-filesystem=/boot/ -+ fi - fi - - testing="YABOOT add kernel" -diff --git a/test/grub2.10 b/test/grub2.10 -new file mode 100644 -index 0000000..d010783 ---- /dev/null -+++ b/test/grub2.10 -@@ -0,0 +1,84 @@ -+# -+# DO NOT EDIT THIS FILE -+# -+# It is automatically generated by grub2-mkconfig using templates -+# from /etc/grub.d and settings from /etc/default/grub -+# -+ -+### BEGIN /etc/grub.d/00_header ### -+if [ -s $prefix/grubenv ]; then -+ load_env -+fi -+set default="0" -+if [ "${prev_saved_entry}" ]; then -+ set saved_entry="${prev_saved_entry}" -+ save_env saved_entry -+ set prev_saved_entry= -+ save_env prev_saved_entry -+ set boot_once=true -+fi -+ -+function savedefault { -+ if [ -z "${boot_once}" ]; then -+ saved_entry="${chosen}" -+ save_env saved_entry -+ fi -+} -+ -+function load_video { -+ insmod vbe -+ insmod vga -+ insmod video_bochs -+ insmod video_cirrus -+} -+ -+set timeout=5 -+### END /etc/grub.d/00_header ### -+ -+### BEGIN /etc/grub.d/10_linux ### -+menuentry 'Linux, with Fedora 2.6.38.8-32.fc15.x86_64' --class gnu-linux --class gnu --class os { -+ load_video -+ set gfxpayload=keep -+ insmod part_msdos -+ insmod ext2 -+ set root='(hd0,msdos1)' -+ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed -+ echo 'Loading Fedora 2.6.38.8-32.fc15.x86_64 ...' -+ linux16 /vmlinuz-2.6.38.8-32.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb -+ echo 'Loading initial ramdisk ...' -+ initrd16 /initramfs-2.6.38.8-32.fc15.x86_64.img -+} -+menuentry 'Linux, with Linux 2.6.38.2-9.fc15.x86_64' --class gnu-linux --class gnu --class os { -+ load_video -+ set gfxpayload=keep -+ insmod part_msdos -+ insmod ext2 -+ set root='(hd0,msdos1)' -+ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed -+ echo 'Loading Linux 2.6.38.2-9.fc15.x86_64 ...' -+ linux16 /vmlinuz-2.6.38.2-9.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb -+ echo 'Loading initial ramdisk ...' -+ initrd16 /initramfs-2.6.38.2-9.fc15.x86_64.img -+} -+### END /etc/grub.d/10_linux ### -+ -+### BEGIN /etc/grub.d/20_linux_xen ### -+### END /etc/grub.d/20_linux_xen ### -+ -+### BEGIN /etc/grub.d/30_os-prober ### -+### END /etc/grub.d/30_os-prober ### -+ -+### BEGIN /etc/grub.d/40_custom ### -+# This file provides an easy way to add custom menu entries. Simply type the -+# menu entries you want to add after this comment. Be careful not to change -+# the 'exec tail' line above. -+### END /etc/grub.d/40_custom ### -+ -+### BEGIN /etc/grub.d/41_custom ### -+if [ -f $prefix/custom.cfg ]; then -+ source $prefix/custom.cfg; -+fi -+### END /etc/grub.d/41_custom ### -+ -+### BEGIN /etc/grub.d/90_persistent ### -+### END /etc/grub.d/90_persistent ### -diff --git a/test/grub2.11 b/test/grub2.11 -new file mode 100644 -index 0000000..820880a ---- /dev/null -+++ b/test/grub2.11 -@@ -0,0 +1,97 @@ -+# -+# DO NOT EDIT THIS FILE -+# -+# It is automatically generated by grub2-mkconfig using templates -+# from /etc/grub.d and settings from /etc/default/grub -+# -+ -+### BEGIN /etc/grub.d/00_header ### -+if [ -s $prefix/grubenv ]; then -+ load_env -+fi -+set default="0" -+if [ "${prev_saved_entry}" ]; then -+ set saved_entry="${prev_saved_entry}" -+ save_env saved_entry -+ set prev_saved_entry= -+ save_env prev_saved_entry -+ set boot_once=true -+fi -+ -+function savedefault { -+ if [ -z "${boot_once}" ]; then -+ saved_entry="${chosen}" -+ save_env saved_entry -+ fi -+} -+ -+function load_video { -+ insmod vbe -+ insmod vga -+ insmod video_bochs -+ insmod video_cirrus -+} -+ -+set timeout=5 -+### END /etc/grub.d/00_header ### -+ -+set superusers="foo bar baz" -+ -+### BEGIN /etc/grub.d/10_linux ### -+menuentry 'title' --class gnu-linux --class gnu --class os { -+ load_video -+ set gfxpayload=keep -+ insmod part_msdos -+ insmod ext2 -+ set root='(hd0,msdos1)' -+ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed -+ echo 'Loading title' -+ linux16 /new-kernel.img root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb -+ echo 'Loading initial ramdisk ...' -+} -+menuentry 'Linux, with Linux 2.6.38.8-32.fc15.x86_64' --class gnu-linux --class gnu --class os { -+ load_video -+ set gfxpayload=keep -+ insmod part_msdos -+ insmod ext2 -+ set root='(hd0,msdos1)' -+ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed -+ echo 'Loading Linux 2.6.38.8-32.fc15.x86_64 ...' -+ linux16 /vmlinuz-2.6.38.8-32.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb -+ echo 'Loading initial ramdisk ...' -+ initrd16 /initramfs-2.6.38.8-32.fc15.x86_64.img -+} -+menuentry 'Linux, with Linux 2.6.38.2-9.fc15.x86_64' --class gnu-linux --class gnu --class os { -+ load_video -+ set gfxpayload=keep -+ insmod part_msdos -+ insmod ext2 -+ set root='(hd0,msdos1)' -+ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed -+ echo 'Loading Linux 2.6.38.2-9.fc15.x86_64 ...' -+ linux16 /vmlinuz-2.6.38.2-9.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb -+ echo 'Loading initial ramdisk ...' -+ initrd16 /initramfs-2.6.38.2-9.fc15.x86_64.img -+} -+### END /etc/grub.d/10_linux ### -+ -+### BEGIN /etc/grub.d/20_linux_xen ### -+### END /etc/grub.d/20_linux_xen ### -+ -+### BEGIN /etc/grub.d/30_os-prober ### -+### END /etc/grub.d/30_os-prober ### -+ -+### BEGIN /etc/grub.d/40_custom ### -+# This file provides an easy way to add custom menu entries. Simply type the -+# menu entries you want to add after this comment. Be careful not to change -+# the 'exec tail' line above. -+### END /etc/grub.d/40_custom ### -+ -+### BEGIN /etc/grub.d/41_custom ### -+if [ -f $prefix/custom.cfg ]; then -+ source $prefix/custom.cfg; -+fi -+### END /etc/grub.d/41_custom ### -+ -+### BEGIN /etc/grub.d/90_persistent ### -+### END /etc/grub.d/90_persistent ### -diff --git a/test/results/add/g2-1.10 b/test/results/add/g2-1.10 -new file mode 100644 -index 0000000..bb2c71c ---- /dev/null -+++ b/test/results/add/g2-1.10 -@@ -0,0 +1,96 @@ -+# -+# DO NOT EDIT THIS FILE -+# -+# It is automatically generated by grub2-mkconfig using templates -+# from /etc/grub.d and settings from /etc/default/grub -+# -+ -+### BEGIN /etc/grub.d/00_header ### -+if [ -s $prefix/grubenv ]; then -+ load_env -+fi -+set default="1" -+if [ "${prev_saved_entry}" ]; then -+ set saved_entry="${prev_saved_entry}" -+ save_env saved_entry -+ set prev_saved_entry= -+ save_env prev_saved_entry -+ set boot_once=true -+fi -+ -+function savedefault { -+ if [ -z "${boot_once}" ]; then -+ saved_entry="${chosen}" -+ save_env saved_entry -+ fi -+} -+ -+function load_video { -+ insmod vbe -+ insmod vga -+ insmod video_bochs -+ insmod video_cirrus -+} -+ -+set timeout=5 -+### END /etc/grub.d/00_header ### -+ -+### BEGIN /etc/grub.d/10_linux ### -+menuentry 'title' --class gnu-linux --class gnu --class os { -+ load_video -+ set gfxpayload=keep -+ insmod part_msdos -+ insmod ext2 -+ set root='(hd0,msdos1)' -+ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed -+ echo 'Loading title' -+ linux16 /new-kernel.img root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb -+ echo 'Loading initial ramdisk ...' -+ initrd16 /new-initrd -+} -+menuentry 'Linux, with Fedora 2.6.38.8-32.fc15.x86_64' --class gnu-linux --class gnu --class os { -+ load_video -+ set gfxpayload=keep -+ insmod part_msdos -+ insmod ext2 -+ set root='(hd0,msdos1)' -+ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed -+ echo 'Loading Fedora 2.6.38.8-32.fc15.x86_64 ...' -+ linux16 /vmlinuz-2.6.38.8-32.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb -+ echo 'Loading initial ramdisk ...' -+ initrd16 /initramfs-2.6.38.8-32.fc15.x86_64.img -+} -+menuentry 'Linux, with Linux 2.6.38.2-9.fc15.x86_64' --class gnu-linux --class gnu --class os { -+ load_video -+ set gfxpayload=keep -+ insmod part_msdos -+ insmod ext2 -+ set root='(hd0,msdos1)' -+ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed -+ echo 'Loading Linux 2.6.38.2-9.fc15.x86_64 ...' -+ linux16 /vmlinuz-2.6.38.2-9.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb -+ echo 'Loading initial ramdisk ...' -+ initrd16 /initramfs-2.6.38.2-9.fc15.x86_64.img -+} -+### END /etc/grub.d/10_linux ### -+ -+### BEGIN /etc/grub.d/20_linux_xen ### -+### END /etc/grub.d/20_linux_xen ### -+ -+### BEGIN /etc/grub.d/30_os-prober ### -+### END /etc/grub.d/30_os-prober ### -+ -+### BEGIN /etc/grub.d/40_custom ### -+# This file provides an easy way to add custom menu entries. Simply type the -+# menu entries you want to add after this comment. Be careful not to change -+# the 'exec tail' line above. -+### END /etc/grub.d/40_custom ### -+ -+### BEGIN /etc/grub.d/41_custom ### -+if [ -f $prefix/custom.cfg ]; then -+ source $prefix/custom.cfg; -+fi -+### END /etc/grub.d/41_custom ### -+ -+### BEGIN /etc/grub.d/90_persistent ### -+### END /etc/grub.d/90_persistent ### -diff --git a/test/results/add/g2-1.11 b/test/results/add/g2-1.11 -new file mode 100644 -index 0000000..a11cb41 ---- /dev/null -+++ b/test/results/add/g2-1.11 -@@ -0,0 +1,98 @@ -+# -+# DO NOT EDIT THIS FILE -+# -+# It is automatically generated by grub2-mkconfig using templates -+# from /etc/grub.d and settings from /etc/default/grub -+# -+ -+### BEGIN /etc/grub.d/00_header ### -+if [ -s $prefix/grubenv ]; then -+ load_env -+fi -+set default="0" -+if [ "${prev_saved_entry}" ]; then -+ set saved_entry="${prev_saved_entry}" -+ save_env saved_entry -+ set prev_saved_entry= -+ save_env prev_saved_entry -+ set boot_once=true -+fi -+ -+function savedefault { -+ if [ -z "${boot_once}" ]; then -+ saved_entry="${chosen}" -+ save_env saved_entry -+ fi -+} -+ -+function load_video { -+ insmod vbe -+ insmod vga -+ insmod video_bochs -+ insmod video_cirrus -+} -+ -+set timeout=5 -+### END /etc/grub.d/00_header ### -+ -+set superusers="foo bar baz" -+ -+### BEGIN /etc/grub.d/10_linux ### -+menuentry 'title' --class gnu-linux --class gnu --class os { -+ load_video -+ set gfxpayload=keep -+ insmod part_msdos -+ insmod ext2 -+ set root='(hd0,msdos1)' -+ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed -+ echo 'Loading title' -+ linux16 /new-kernel.img root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb -+ echo 'Loading initial ramdisk ...' -+ initrd16 /new-initrd -+} -+menuentry 'Linux, with Linux 2.6.38.8-32.fc15.x86_64' --class gnu-linux --class gnu --class os { -+ load_video -+ set gfxpayload=keep -+ insmod part_msdos -+ insmod ext2 -+ set root='(hd0,msdos1)' -+ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed -+ echo 'Loading Linux 2.6.38.8-32.fc15.x86_64 ...' -+ linux16 /vmlinuz-2.6.38.8-32.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb -+ echo 'Loading initial ramdisk ...' -+ initrd16 /initramfs-2.6.38.8-32.fc15.x86_64.img -+} -+menuentry 'Linux, with Linux 2.6.38.2-9.fc15.x86_64' --class gnu-linux --class gnu --class os { -+ load_video -+ set gfxpayload=keep -+ insmod part_msdos -+ insmod ext2 -+ set root='(hd0,msdos1)' -+ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed -+ echo 'Loading Linux 2.6.38.2-9.fc15.x86_64 ...' -+ linux16 /vmlinuz-2.6.38.2-9.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb -+ echo 'Loading initial ramdisk ...' -+ initrd16 /initramfs-2.6.38.2-9.fc15.x86_64.img -+} -+### END /etc/grub.d/10_linux ### -+ -+### BEGIN /etc/grub.d/20_linux_xen ### -+### END /etc/grub.d/20_linux_xen ### -+ -+### BEGIN /etc/grub.d/30_os-prober ### -+### END /etc/grub.d/30_os-prober ### -+ -+### BEGIN /etc/grub.d/40_custom ### -+# This file provides an easy way to add custom menu entries. Simply type the -+# menu entries you want to add after this comment. Be careful not to change -+# the 'exec tail' line above. -+### END /etc/grub.d/40_custom ### -+ -+### BEGIN /etc/grub.d/41_custom ### -+if [ -f $prefix/custom.cfg ]; then -+ source $prefix/custom.cfg; -+fi -+### END /etc/grub.d/41_custom ### -+ -+### BEGIN /etc/grub.d/90_persistent ### -+### END /etc/grub.d/90_persistent ### --- -1.9.3 - diff --git a/SOURCES/0002-If-we-re-using-multiboot-add-a-new-mbmodule-not-an-i.patch b/SOURCES/0002-If-we-re-using-multiboot-add-a-new-mbmodule-not-an-i.patch new file mode 100644 index 0000000..b63a94f --- /dev/null +++ b/SOURCES/0002-If-we-re-using-multiboot-add-a-new-mbmodule-not-an-i.patch @@ -0,0 +1,97 @@ +From e19e664d4fcb1637f8ba4a4a088454acf2f94334 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 12 Sep 2013 20:41:33 +0200 +Subject: [PATCH 02/41] If we're using multiboot, add a new mbmodule not an + initramfs + +I really don't know how this ever worked. +Related: rhbz#957681 + +Signed-off-by: Peter Jones +--- + grubby.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- + new-kernel-pkg | 3 ++- + 2 files changed, 47 insertions(+), 3 deletions(-) + +diff --git a/grubby.c b/grubby.c +index bbca9d0..d91a847 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -3255,6 +3255,42 @@ int updateImage(struct grubConfig * cfg, const char * image, + return rc; + } + ++int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel, ++ const char * image, const char * prefix, const char * initrd) { ++ struct singleEntry * entry; ++ struct singleLine * line, * kernelLine, *endLine = NULL; ++ int index = 0; ++ ++ if (!image) return 0; ++ ++ for (; (entry = findEntryByPath(cfg, newMBKernel, prefix, &index)); index++) { ++ kernelLine = getLineByType(LT_MBMODULE, entry->lines); ++ if (!kernelLine) continue; ++ ++ if (prefix) { ++ int prefixLen = strlen(prefix); ++ if (!strncmp(initrd, prefix, prefixLen)) ++ initrd += prefixLen; ++ } ++ endLine = getLineByType(LT_ENTRY_END, entry->lines); ++ if (endLine) ++ removeLine(entry, endLine); ++ line = addLine(entry, cfg->cfi, preferredLineType(LT_MBMODULE,cfg->cfi), ++ kernelLine->indent, initrd); ++ if (!line) ++ return 1; ++ if (endLine) { ++ line = addLine(entry, cfg->cfi, LT_ENTRY_END, "", NULL); ++ if (!line) ++ return 1; ++ } ++ ++ break; ++ } ++ ++ return 0; ++} ++ + int updateInitrd(struct grubConfig * cfg, const char * image, + const char * prefix, const char * initrd) { + struct singleEntry * entry; +@@ -4496,8 +4532,15 @@ int main(int argc, const char ** argv) { + if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, + removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1; + if (updateKernelPath && newKernelInitrd) { +- if (updateInitrd(config, updateKernelPath, bootPrefix, +- newKernelInitrd)) return 1; ++ if (newMBKernel) { ++ if (addMBInitrd(config, newMBKernel, updateKernelPath, ++ bootPrefix, newKernelInitrd)) ++ return 1; ++ } else { ++ if (updateInitrd(config, updateKernelPath, bootPrefix, ++ newKernelInitrd)) ++ return 1; ++ } + } + if (addNewKernel(config, template, bootPrefix, newKernelPath, + newKernelTitle, newKernelArgs, newKernelInitrd, +diff --git a/new-kernel-pkg b/new-kernel-pkg +index 7fec1fe..6373385 100755 +--- a/new-kernel-pkg ++++ b/new-kernel-pkg +@@ -404,7 +404,8 @@ update() { + --update-kernel=$kernelImage \ + $INITRD \ + ${kernargs:+--args="$kernargs"} \ +- ${removeargs:+--remove-args="$removeargs"} ++ ${removeargs:+--remove-args="$removeargs"} \ ++ ${mbkernel:+--add-multiboot="$mbkernel"} + else + [ -n "$verbose" ] && echo "$grubConfig does not exist, not running grubby" + fi +-- +2.4.3 + diff --git a/SOURCES/0002-Strdup-the-right-place-in-title-extraction.patch b/SOURCES/0002-Strdup-the-right-place-in-title-extraction.patch deleted file mode 100644 index d55014c..0000000 --- a/SOURCES/0002-Strdup-the-right-place-in-title-extraction.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 320159cd9da53448793b39d044eec7c10fe17ffe Mon Sep 17 00:00:00 2001 -From: Jan Stancek -Date: Tue, 11 Nov 2014 10:44:09 -0500 -Subject: [PATCH 2/2] Strdup the right place in title extraction. - -Instead of strduping and then incrementing, which means we free the -wrong location, strdup the incremented pointer. - -Resolves: rhbz#1152152 - -Signed-off-by: Peter Jones ---- - grubby.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/grubby.c b/grubby.c -index 3ee6c98..4586310 100644 ---- a/grubby.c -+++ b/grubby.c -@@ -826,11 +826,10 @@ static int isEntryStart(struct singleLine * line, - - /* extract the title from within brackets (for zipl) */ - static char * extractTitle(struct singleLine * line) { -- /* bracketed title... let's extract it (leaks a byte) */ -+ /* bracketed title... let's extract it */ - char * title = NULL; - if (line->type == LT_TITLE) { -- title = strdup(line->elements[0].item); -- title++; -+ title = strdup(line->elements[0].item + 1); - *(title + strlen(title) - 1) = '\0'; - } else if (line->type == LT_MENUENTRY) - title = strdup(line->elements[1].item); --- -1.9.3 - diff --git a/SOURCES/0003-Make-SET_VARIABLE-get-handled-individually-in-GetNex.patch b/SOURCES/0003-Make-SET_VARIABLE-get-handled-individually-in-GetNex.patch new file mode 100644 index 0000000..08a32e5 --- /dev/null +++ b/SOURCES/0003-Make-SET_VARIABLE-get-handled-individually-in-GetNex.patch @@ -0,0 +1,581 @@ +From 8a3357d1257e5e36648c944ff1e461f0f77c88f4 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 6 Aug 2015 10:07:11 -0400 +Subject: [PATCH 3/3] Make SET_VARIABLE get handled individually in + GetNextLine() + +Resolves: rhbz#1152550 + +Signed-off-by: Peter Jones +--- + .gitignore | 2 + + grubby.c | 118 ++++++++++++++++++++++++++------ + test.sh | 8 +++ + test/grub2.16 | 156 +++++++++++++++++++++++++++++++++++++++++++ + test/results/add/g2-1.16 | 170 +++++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 433 insertions(+), 21 deletions(-) + create mode 100644 test/grub2.16 + create mode 100644 test/results/add/g2-1.16 + +diff --git a/.gitignore b/.gitignore +index e64d3bc..e78a392 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -1,3 +1,5 @@ + grubby + version.h + *.o ++core.* ++vgcore.* +diff --git a/grubby.c b/grubby.c +index 53c11a8..04c5bcb 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -75,6 +75,7 @@ struct lineElement { + }; + + enum lineType_e { ++ LT_UNIDENTIFIED = 0, + LT_WHITESPACE = 1 << 0, + LT_TITLE = 1 << 1, + LT_KERNEL = 1 << 2, +@@ -740,6 +741,33 @@ static char *sdupprintf(const char *format, ...) + return buf; + } + ++static inline int ++kwcmp(struct keywordTypes *kw, const char * label, int case_insensitive) ++{ ++ int kwl = strlen(kw->key); ++ int ll = strlen(label); ++ int rc; ++ int (*snc)(const char *s1, const char *s2, size_t n) = ++ case_insensitive ? strncasecmp : strncmp; ++ int (*sc)(const char *s1, const char *s2) = ++ case_insensitive ? strcasecmp : strcmp; ++ ++ rc = snc(kw->key, label, kwl); ++ if (rc) ++ return rc; ++ ++ for (int i = kwl; i < ll; i++) { ++ if (isspace(label[i])) ++ return 0; ++ if (kw->separatorChar && label[i] == kw->separatorChar) ++ return 0; ++ else if (kw->nextChar && label[i] == kw->nextChar) ++ return 0; ++ return sc(kw->key+kwl, label+kwl); ++ } ++ return 0; ++} ++ + static enum lineType_e preferredLineType(enum lineType_e type, + struct configFileInfo *cfi) + { +@@ -805,13 +833,8 @@ static enum lineType_e getTypeByKeyword(char *keyword, + struct configFileInfo *cfi) + { + for (struct keywordTypes * kw = cfi->keywords; kw->key; kw++) { +- if (cfi->caseInsensitive) { +- if (!strcasecmp(keyword, kw->key)) +- return kw->type; +- } else { +- if (!strcmp(keyword, kw->key)) +- return kw->type; +- } ++ if (!kwcmp(kw, keyword, cfi->caseInsensitive)) ++ return kw->type; + } + return LT_UNKNOWN; + } +@@ -906,6 +929,7 @@ static int readFile(int fd, char **bufPtr) + + static void lineInit(struct singleLine *line) + { ++ line->type = LT_UNIDENTIFIED; + line->indent = NULL; + line->elements = NULL; + line->numElements = 0; +@@ -987,7 +1011,7 @@ static int lineWrite(FILE * out, struct singleLine *line, + + if (fprintf(out, "%s", line->elements[i].item) == -1) + return -1; +- if (i < line->numElements - 1) ++ if (i < line->numElements - 1 || line->type == LT_SET_VARIABLE) + if (fprintf(out, "%s", line->elements[i].indent) == -1) + return -1; + } +@@ -1042,6 +1066,8 @@ static int getNextLine(char **bufPtr, struct singleLine *line, + break; + chptr++; + } ++ if (line->type == LT_UNIDENTIFIED) ++ line->type = getTypeByKeyword(start, cfi); + element->item = strndup(start, chptr - start); + start = chptr; + +@@ -1105,7 +1131,7 @@ static int getNextLine(char **bufPtr, struct singleLine *line, + line->type = LT_WHITESPACE; + line->numElements = 0; + } +- } else { ++ } else if (line->type == LT_INITRD) { + struct keywordTypes *kw; + + kw = getKeywordByType(line->type, cfi); +@@ -1167,6 +1193,39 @@ static int getNextLine(char **bufPtr, struct singleLine *line, + } + } + } ++ } else if (line->type == LT_SET_VARIABLE) { ++ /* and if it's a "set blah=" we need to split it ++ * yet a third way to avoid rhbz# XXX FIXME :/ ++ */ ++ char *eq; ++ int l; ++ int numElements = line->numElements; ++ struct lineElement *newElements; ++ eq = strchr(line->elements[1].item, '='); ++ if (!eq) ++ return 0; ++ l = eq - line->elements[1].item; ++ if (eq[1] != 0) ++ numElements++; ++ newElements = calloc(numElements,sizeof (*newElements)); ++ memcpy(&newElements[0], &line->elements[0], ++ sizeof (newElements[0])); ++ newElements[1].item = ++ strndup(line->elements[1].item, l); ++ newElements[1].indent = "="; ++ *(eq++) = '\0'; ++ newElements[2].item = strdup(eq); ++ free(line->elements[1].item); ++ if (line->elements[1].indent) ++ newElements[2].indent = line->elements[1].indent; ++ for (int i = 2; i < line->numElements; i++) { ++ newElements[i+1].item = line->elements[i].item; ++ newElements[i+1].indent = ++ line->elements[i].indent; ++ } ++ free(line->elements); ++ line->elements = newElements; ++ line->numElements = numElements; + } + } + +@@ -1272,8 +1331,8 @@ static struct grubConfig *readConfig(const char *inName, + getKeywordByType(LT_DEFAULT, cfi); + if (kwType && line->numElements == 3 + && !strcmp(line->elements[1].item, kwType->key) +- && !is_special_grub2_variable(line->elements[2]. +- item)) { ++ && !is_special_grub2_variable( ++ line->elements[2].item)) { + dbgPrintf("Line sets default config\n"); + cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT; + defaultLine = line; +@@ -1529,16 +1588,33 @@ static struct grubConfig *readConfig(const char *inName, + } + } + } else if (cfi->defaultIsVariable) { +- char *value = defaultLine->elements[2].item; +- while (*value && (*value == '"' || *value == '\'' || +- *value == ' ' || *value == '\t')) +- value++; +- cfg->defaultImage = strtol(value, &end, 10); +- while (*end && (*end == '"' || *end == '\'' || +- *end == ' ' || *end == '\t')) +- end++; +- if (*end) +- cfg->defaultImage = -1; ++ if (defaultLine->numElements == 2) { ++ char *value = defaultLine->elements[1].item + 8; ++ while (*value && (*value == '"' || ++ *value == '\'' || ++ *value == ' ' || ++ *value == '\t')) ++ value++; ++ cfg->defaultImage = strtol(value, &end, 10); ++ while (*end && (*end == '"' || *end == '\'' || ++ *end == ' ' || *end == '\t')) ++ end++; ++ if (*end) ++ cfg->defaultImage = -1; ++ } else if (defaultLine->numElements == 3) { ++ char *value = defaultLine->elements[2].item; ++ while (*value && (*value == '"' || ++ *value == '\'' || ++ *value == ' ' || ++ *value == '\t')) ++ value++; ++ cfg->defaultImage = strtol(value, &end, 10); ++ while (*end && (*end == '"' || *end == '\'' || ++ *end == ' ' || *end == '\t')) ++ end++; ++ if (*end) ++ cfg->defaultImage = -1; ++ } + } else if (cfi->defaultSupportSaved && + !strncmp(defaultLine->elements[1].item, "saved", + 5)) { +diff --git a/test.sh b/test.sh +index c2a66e2..9e9be23 100755 +--- a/test.sh ++++ b/test.sh +@@ -542,6 +542,14 @@ if [ "$testgrub2" == "y" ]; then + ;; + esac + ++ # a grub2 add with a "set" of the form: set foo="bar=1,2". bz#1152550 ++ # has this being emitted as: set foo="bar=1,2"=1,2" ++ # which is wrong. ++ grub2Test grub2.16 add/g2-1.16 \ ++ --add-kernel=/boot/vmlinuz-foo \ ++ --copy-default --title 'Red Hat Enterprise Linux Server' \ ++ --args=root=/dev/mapper/foo-- ++ + testing="GRUB2 add initrd" + grub2Test grub2.2 add/g2-1.4 --update-kernel=/boot/new-kernel.img \ + --initrd=/boot/new-initrd --boot-filesystem=/boot/ +diff --git a/test/grub2.16 b/test/grub2.16 +new file mode 100644 +index 0000000..136880a +--- /dev/null ++++ b/test/grub2.16 +@@ -0,0 +1,156 @@ ++# ++# DO NOT EDIT THIS FILE ++# ++# It is automatically generated by grub2-mkconfig using templates ++# from /etc/grub.d and settings from /etc/default/grub ++# ++ ++### BEGIN /etc/grub.d/00_header ### ++set pager=1 ++ ++if [ -s $prefix/grubenv ]; then ++ load_env ++fi ++if [ "${next_entry}" ] ; then ++ set default="${next_entry}" ++ set next_entry= ++ save_env next_entry ++ set boot_once=true ++else ++ set default="${saved_entry}" ++fi ++ ++if [ x"${feature_menuentry_id}" = xy ]; then ++ menuentry_id_option="--id" ++else ++ menuentry_id_option="" ++fi ++ ++export menuentry_id_option ++ ++if [ "${prev_saved_entry}" ]; then ++ set saved_entry="${prev_saved_entry}" ++ save_env saved_entry ++ set prev_saved_entry= ++ save_env prev_saved_entry ++ set boot_once=true ++fi ++ ++function savedefault { ++ if [ -z "${boot_once}" ]; then ++ saved_entry="${chosen}" ++ save_env saved_entry ++ fi ++} ++ ++function load_video { ++ if [ x$feature_all_video_module = xy ]; then ++ insmod all_video ++ else ++ insmod efi_gop ++ insmod efi_uga ++ insmod ieee1275_fb ++ insmod vbe ++ insmod vga ++ insmod video_bochs ++ insmod video_cirrus ++ fi ++} ++ ++serial --speed=115200 ++terminal_input serial console ++terminal_output serial console ++if [ x$feature_timeout_style = xy ] ; then ++ set timeout_style=menu ++ set timeout=5 ++# Fallback normal timeout code in case the timeout_style feature is ++# unavailable. ++else ++ set timeout=5 ++fi ++### END /etc/grub.d/00_header ### ++ ++### BEGIN /etc/grub.d/00_tuned ### ++set tuned_params="isolcpus=1,3" ++### END /etc/grub.d/00_tuned ### ++ ++### BEGIN /etc/grub.d/01_users ### ++if [ -f ${prefix}/user.cfg ]; then ++ source ${prefix}/user.cfg ++ if [ -n ${GRUB2_PASSWORD} ]; then ++ set superusers="root" ++ export superusers ++ password_pbkdf2 root ${GRUB2_PASSWORD} ++ fi ++fi ++### END /etc/grub.d/01_users ### ++ ++### BEGIN /etc/grub.d/10_linux ### ++menuentry 'Red Hat Enterprise Linux Server (3.10.0-297.el7.x86_64) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-296.el7.x86_64-advanced-ae7b3742-9092-4432-9f7f-8abdbf0dc3db' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod xfs ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' cae02b39-f239-4d26-9032-674d261c93d8 ++ else ++ search --no-floppy --fs-uuid --set=root cae02b39-f239-4d26-9032-674d261c93d8 ++ fi ++ linux16 /vmlinuz-3.10.0-297.el7.x86_64 root=/dev/mapper/rhel_hp--dl380pgen8--02--vm--10-root ro crashkernel=auto rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/root rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/swap console=ttyS0,115200n81 $tuned_params LANG=en_US.UTF-8 ++} ++menuentry 'Red Hat Enterprise Linux Server (3.10.0-296.el7.x86_64) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-296.el7.x86_64-advanced-ae7b3742-9092-4432-9f7f-8abdbf0dc3db' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod xfs ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' cae02b39-f239-4d26-9032-674d261c93d8 ++ else ++ search --no-floppy --fs-uuid --set=root cae02b39-f239-4d26-9032-674d261c93d8 ++ fi ++ linux16 /vmlinuz-3.10.0-296.el7.x86_64 root=/dev/mapper/rhel_hp--dl380pgen8--02--vm--10-root ro crashkernel=auto rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/root rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/swap console=ttyS0,115200n81 $tuned_params ++ initrd16 /initramfs-3.10.0-296.el7.x86_64.img ++} ++menuentry 'Red Hat Enterprise Linux Server (0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7-advanced-ae7b3742-9092-4432-9f7f-8abdbf0dc3db' { ++ load_video ++ insmod gzio ++ insmod part_msdos ++ insmod xfs ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' cae02b39-f239-4d26-9032-674d261c93d8 ++ else ++ search --no-floppy --fs-uuid --set=root cae02b39-f239-4d26-9032-674d261c93d8 ++ fi ++ linux16 /vmlinuz-0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7 root=/dev/mapper/rhel_hp--dl380pgen8--02--vm--10-root ro crashkernel=auto rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/root rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/swap console=ttyS0,115200n81 $tuned_params ++ initrd16 /initramfs-0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7.img ++} ++if [ "x$default" = 'Red Hat Enterprise Linux Server (3.10.0-296.el7.x86_64) 7.2 (Maipo)' ]; then default='Advanced options for Red Hat Enterprise Linux Server>Red Hat Enterprise Linux Server (3.10.0-296.el7.x86_64) 7.2 (Maipo)'; fi; ++### END /etc/grub.d/10_linux ### ++ ++### BEGIN /etc/grub.d/20_linux_xen ### ++### END /etc/grub.d/20_linux_xen ### ++ ++### BEGIN /etc/grub.d/20_ppc_terminfo ### ++### END /etc/grub.d/20_ppc_terminfo ### ++ ++### BEGIN /etc/grub.d/30_os-prober ### ++### END /etc/grub.d/30_os-prober ### ++ ++### BEGIN /etc/grub.d/40_custom ### ++# This file provides an easy way to add custom menu entries. Simply type the ++# menu entries you want to add after this comment. Be careful not to change ++# the 'exec tail' line above. ++### END /etc/grub.d/40_custom ### ++ ++### BEGIN /etc/grub.d/41_custom ### ++if [ -f ${config_directory}/custom.cfg ]; then ++ source ${config_directory}/custom.cfg ++elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then ++ source $prefix/custom.cfg; ++fi ++### END /etc/grub.d/41_custom ### +diff --git a/test/results/add/g2-1.16 b/test/results/add/g2-1.16 +new file mode 100644 +index 0000000..fc98757 +--- /dev/null ++++ b/test/results/add/g2-1.16 +@@ -0,0 +1,170 @@ ++# ++# DO NOT EDIT THIS FILE ++# ++# It is automatically generated by grub2-mkconfig using templates ++# from /etc/grub.d and settings from /etc/default/grub ++# ++ ++### BEGIN /etc/grub.d/00_header ### ++set pager=1 ++ ++if [ -s $prefix/grubenv ]; then ++ load_env ++fi ++if [ "${next_entry}" ] ; then ++ set default="${next_entry}" ++ set next_entry= ++ save_env next_entry ++ set boot_once=true ++else ++ set default="${saved_entry}" ++fi ++ ++if [ x"${feature_menuentry_id}" = xy ]; then ++ menuentry_id_option="--id" ++else ++ menuentry_id_option="" ++fi ++ ++export menuentry_id_option ++ ++if [ "${prev_saved_entry}" ]; then ++ set saved_entry="${prev_saved_entry}" ++ save_env saved_entry ++ set prev_saved_entry= ++ save_env prev_saved_entry ++ set boot_once=true ++fi ++ ++function savedefault { ++ if [ -z "${boot_once}" ]; then ++ saved_entry="${chosen}" ++ save_env saved_entry ++ fi ++} ++ ++function load_video { ++ if [ x$feature_all_video_module = xy ]; then ++ insmod all_video ++ else ++ insmod efi_gop ++ insmod efi_uga ++ insmod ieee1275_fb ++ insmod vbe ++ insmod vga ++ insmod video_bochs ++ insmod video_cirrus ++ fi ++} ++ ++serial --speed=115200 ++terminal_input serial console ++terminal_output serial console ++if [ x$feature_timeout_style = xy ] ; then ++ set timeout_style=menu ++ set timeout=5 ++# Fallback normal timeout code in case the timeout_style feature is ++# unavailable. ++else ++ set timeout=5 ++fi ++### END /etc/grub.d/00_header ### ++ ++### BEGIN /etc/grub.d/00_tuned ### ++set tuned_params="isolcpus=1,3" ++### END /etc/grub.d/00_tuned ### ++ ++### BEGIN /etc/grub.d/01_users ### ++if [ -f ${prefix}/user.cfg ]; then ++ source ${prefix}/user.cfg ++ if [ -n ${GRUB2_PASSWORD} ]; then ++ set superusers="root" ++ export superusers ++ password_pbkdf2 root ${GRUB2_PASSWORD} ++ fi ++fi ++### END /etc/grub.d/01_users ### ++ ++### BEGIN /etc/grub.d/10_linux ### ++menuentry 'Red Hat Enterprise Linux Server' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-296.el7.x86_64-advanced-ae7b3742-9092-4432-9f7f-8abdbf0dc3db' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod xfs ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' cae02b39-f239-4d26-9032-674d261c93d8 ++ else ++ search --no-floppy --fs-uuid --set=root cae02b39-f239-4d26-9032-674d261c93d8 ++ fi ++ linux16 /vmlinuz-foo root=/dev/mapper/foo-- ro crashkernel=auto rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/root rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/swap console=ttyS0,115200n81 $tuned_params LANG=en_US.UTF-8 ++} ++menuentry 'Red Hat Enterprise Linux Server (3.10.0-297.el7.x86_64) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-296.el7.x86_64-advanced-ae7b3742-9092-4432-9f7f-8abdbf0dc3db' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod xfs ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' cae02b39-f239-4d26-9032-674d261c93d8 ++ else ++ search --no-floppy --fs-uuid --set=root cae02b39-f239-4d26-9032-674d261c93d8 ++ fi ++ linux16 /vmlinuz-3.10.0-297.el7.x86_64 root=/dev/mapper/rhel_hp--dl380pgen8--02--vm--10-root ro crashkernel=auto rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/root rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/swap console=ttyS0,115200n81 $tuned_params LANG=en_US.UTF-8 ++} ++menuentry 'Red Hat Enterprise Linux Server (3.10.0-296.el7.x86_64) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-296.el7.x86_64-advanced-ae7b3742-9092-4432-9f7f-8abdbf0dc3db' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod xfs ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' cae02b39-f239-4d26-9032-674d261c93d8 ++ else ++ search --no-floppy --fs-uuid --set=root cae02b39-f239-4d26-9032-674d261c93d8 ++ fi ++ linux16 /vmlinuz-3.10.0-296.el7.x86_64 root=/dev/mapper/rhel_hp--dl380pgen8--02--vm--10-root ro crashkernel=auto rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/root rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/swap console=ttyS0,115200n81 $tuned_params ++ initrd16 /initramfs-3.10.0-296.el7.x86_64.img ++} ++menuentry 'Red Hat Enterprise Linux Server (0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7-advanced-ae7b3742-9092-4432-9f7f-8abdbf0dc3db' { ++ load_video ++ insmod gzio ++ insmod part_msdos ++ insmod xfs ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' cae02b39-f239-4d26-9032-674d261c93d8 ++ else ++ search --no-floppy --fs-uuid --set=root cae02b39-f239-4d26-9032-674d261c93d8 ++ fi ++ linux16 /vmlinuz-0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7 root=/dev/mapper/rhel_hp--dl380pgen8--02--vm--10-root ro crashkernel=auto rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/root rd.lvm.lv=rhel_hp-dl380pgen8-02-vm-10/swap console=ttyS0,115200n81 $tuned_params ++ initrd16 /initramfs-0-rescue-cc21b92886f9ebbd3ed5a494639b7fd7.img ++} ++if [ "x$default" = 'Red Hat Enterprise Linux Server (3.10.0-296.el7.x86_64) 7.2 (Maipo)' ]; then default='Advanced options for Red Hat Enterprise Linux Server>Red Hat Enterprise Linux Server (3.10.0-296.el7.x86_64) 7.2 (Maipo)'; fi; ++### END /etc/grub.d/10_linux ### ++ ++### BEGIN /etc/grub.d/20_linux_xen ### ++### END /etc/grub.d/20_linux_xen ### ++ ++### BEGIN /etc/grub.d/20_ppc_terminfo ### ++### END /etc/grub.d/20_ppc_terminfo ### ++ ++### BEGIN /etc/grub.d/30_os-prober ### ++### END /etc/grub.d/30_os-prober ### ++ ++### BEGIN /etc/grub.d/40_custom ### ++# This file provides an easy way to add custom menu entries. Simply type the ++# menu entries you want to add after this comment. Be careful not to change ++# the 'exec tail' line above. ++### END /etc/grub.d/40_custom ### ++ ++### BEGIN /etc/grub.d/41_custom ### ++if [ -f ${config_directory}/custom.cfg ]; then ++ source ${config_directory}/custom.cfg ++elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then ++ source $prefix/custom.cfg; ++fi ++### END /etc/grub.d/41_custom ### +-- +2.4.3 + diff --git a/SOURCES/0003-Only-set-RPM_OPT_FLAGS-if-undefined.patch b/SOURCES/0003-Only-set-RPM_OPT_FLAGS-if-undefined.patch deleted file mode 100644 index 6604a6e..0000000 --- a/SOURCES/0003-Only-set-RPM_OPT_FLAGS-if-undefined.patch +++ /dev/null @@ -1,32 +0,0 @@ -From c0980dceebc0c67eeb25315b860f6d843e1baed6 Mon Sep 17 00:00:00 2001 -From: "d.marlin" -Date: Mon, 24 Jun 2013 14:57:40 -0500 -Subject: [PATCH 03/16] Only set RPM_OPT_FLAGS if undefined. - -Currently RPM_OPT_FLAGS are set even if they were already defined. -This overrides any defaults set by RPM, including architecture-specific -values that may be needed to compile on some architectures. - -To avoid this issue, only set RPM_OPT_FLAGS if previously undefined. - -Signed-off-by: David A. Marlin ---- - Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/Makefile b/Makefile -index 5a151ce..94cef27 100644 ---- a/Makefile -+++ b/Makefile -@@ -23,7 +23,7 @@ TARGETS = grubby - OBJECTS = grubby.o log.o - - CC = gcc --RPM_OPT_FLAGS := -O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector -+RPM_OPT_FLAGS ?= -O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector - CFLAGS += $(RPM_OPT_FLAGS) -std=gnu99 -Wall -Werror -Wno-error=unused-function -Wno-unused-function -ggdb - LDFLAGS := - --- -1.9.3 - diff --git a/SOURCES/0003-Use-PREFIX-during-make-install.patch b/SOURCES/0003-Use-PREFIX-during-make-install.patch new file mode 100644 index 0000000..09c81e3 --- /dev/null +++ b/SOURCES/0003-Use-PREFIX-during-make-install.patch @@ -0,0 +1,36 @@ +From 61223ca7c6ac36c81ff06df502f8c9a02a133708 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 13 Sep 2013 10:37:10 -0400 +Subject: [PATCH 03/41] Use $(PREFIX) during make install. + +Signed-off-by: Peter Jones +--- + Makefile | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/Makefile b/Makefile +index 5dbf0f7..94cef27 100644 +--- a/Makefile ++++ b/Makefile +@@ -42,14 +42,14 @@ test: all + @./test.sh + + install: all +- mkdir -p $(DESTDIR)/sbin ++ mkdir -p $(DESTDIR)$(PREFIX)/sbin + mkdir -p $(DESTDIR)/$(mandir)/man8 +- install -m 755 new-kernel-pkg $(DESTDIR)/sbin ++ install -m 755 new-kernel-pkg $(DESTDIR)$(PREFIX)/sbin + install -m 644 new-kernel-pkg.8 $(DESTDIR)/$(mandir)/man8 +- install -m 755 installkernel $(DESTDIR)/sbin ++ install -m 755 installkernel $(DESTDIR)$(PREFIX)/sbin + install -m 644 installkernel.8 $(DESTDIR)/$(mandir)/man8 + if [ -f grubby ]; then \ +- install -m 755 grubby $(DESTDIR)/sbin ; \ ++ install -m 755 grubby $(DESTDIR)$(PREFIX)/sbin ; \ + install -m 644 grubby.8 $(DESTDIR)/$(mandir)/man8 ; \ + fi + +-- +2.4.3 + diff --git a/SOURCES/0004-Drop-SEGV-handler.patch b/SOURCES/0004-Drop-SEGV-handler.patch deleted file mode 100644 index eb34d6a..0000000 --- a/SOURCES/0004-Drop-SEGV-handler.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 149a5e63ff5fc58d4cea9024d2ecfdd7f755fbc4 Mon Sep 17 00:00:00 2001 -From: Lubomir Rintel -Date: Thu, 27 Feb 2014 10:35:59 +0100 -Subject: [PATCH 04/16] Drop SEGV handler - -The generated tracebacks are mostly useless without debuginfo (which is likely -not present if the crash is not anticipated) and prevent ABRT from doing a -better job. - -Signed-off-by: Lubomir Rintel ---- - grubby.c | 17 ----------------- - 1 file changed, 17 deletions(-) - -diff --git a/grubby.c b/grubby.c -index 4488636..d33ce6e 100644 ---- a/grubby.c -+++ b/grubby.c -@@ -4029,21 +4029,6 @@ int addNewKernel(struct grubConfig * config, struct singleEntry * template, - return 0; - } - --static void traceback(int signum) --{ -- void *array[40]; -- size_t size; -- -- signal(SIGSEGV, SIG_DFL); -- memset(array, '\0', sizeof (array)); -- size = backtrace(array, 40); -- -- fprintf(stderr, "grubby received SIGSEGV! Backtrace (%ld):\n", -- (unsigned long)size); -- backtrace_symbols_fd(array, size, STDERR_FILENO); -- exit(1); --} -- - int main(int argc, const char ** argv) { - poptContext optCon; - const char * grubConfig = NULL; -@@ -4182,8 +4167,6 @@ int main(int argc, const char ** argv) { - - useextlinuxmenu=0; - -- signal(SIGSEGV, traceback); -- - int i = 0; - for (int j = 1; j < argc; j++) - i += strlen(argv[j]) + 1; --- -1.9.3 - diff --git a/SOURCES/0004-Honor-linux16-and-initrd16.patch b/SOURCES/0004-Honor-linux16-and-initrd16.patch new file mode 100644 index 0000000..932e82e --- /dev/null +++ b/SOURCES/0004-Honor-linux16-and-initrd16.patch @@ -0,0 +1,638 @@ +From 5a5b33da8239428245f3595848f10c0f184041b3 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 18 Nov 2013 14:44:13 -0500 +Subject: [PATCH 04/41] Honor "linux16" and "initrd16" + +Resolves: rhbz#1031192 +Resolves: rhbz#1034743 + +Signed-off-by: Peter Jones +--- + grubby.c | 63 ++++++++++++++++++++++--------- + test.sh | 16 ++++++++ + test/grub2.10 | 84 +++++++++++++++++++++++++++++++++++++++++ + test/grub2.11 | 97 +++++++++++++++++++++++++++++++++++++++++++++++ + test/results/add/g2-1.10 | 96 +++++++++++++++++++++++++++++++++++++++++++++++ + test/results/add/g2-1.11 | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ + 6 files changed, 437 insertions(+), 17 deletions(-) + create mode 100644 test/grub2.10 + create mode 100644 test/grub2.11 + create mode 100644 test/results/add/g2-1.10 + create mode 100644 test/results/add/g2-1.11 + +diff --git a/grubby.c b/grubby.c +index d91a847..aa228c3 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -90,7 +90,9 @@ enum lineType_e { + LT_SET_VARIABLE = 1 << 19, + LT_KERNEL_EFI = 1 << 20, + LT_INITRD_EFI = 1 << 21, +- LT_UNKNOWN = 1 << 22, ++ LT_KERNEL_16 = 1 << 22, ++ LT_INITRD_16 = 1 << 23, ++ LT_UNKNOWN = 1 << 24, + }; + + struct singleLine { +@@ -220,8 +222,10 @@ struct keywordTypes grub2Keywords[] = { + { "fallback", LT_FALLBACK, ' ' }, + { "linux", LT_KERNEL, ' ' }, + { "linuxefi", LT_KERNEL_EFI, ' ' }, ++ { "linux16", LT_KERNEL_16, ' ' }, + { "initrd", LT_INITRD, ' ', ' ' }, + { "initrdefi", LT_INITRD_EFI, ' ', ' ' }, ++ { "initrd16", LT_INITRD_16, ' ', ' ' }, + { "module", LT_MBMODULE, ' ' }, + { "kernel", LT_HYPER, ' ' }, + { NULL, 0, 0 }, +@@ -395,11 +399,11 @@ static int isquote(char q) + } + + static int iskernel(enum lineType_e type) { +- return (type == LT_KERNEL || type == LT_KERNEL_EFI); ++ return (type == LT_KERNEL || type == LT_KERNEL_EFI || type == LT_KERNEL_16); + } + + static int isinitrd(enum lineType_e type) { +- return (type == LT_INITRD || type == LT_INITRD_EFI); ++ return (type == LT_INITRD || type == LT_INITRD_EFI || type == LT_INITRD_16); + } + + char *grub2ExtractTitle(struct singleLine * line) { +@@ -717,6 +721,17 @@ static enum lineType_e preferredLineType(enum lineType_e type, + default: + return type; + } ++#if defined(__i386__) || defined(__x86_64__) ++ } else if (cfi == &grub2ConfigType) { ++ switch (type) { ++ case LT_KERNEL: ++ return LT_KERNEL_16; ++ case LT_INITRD: ++ return LT_INITRD_16; ++ default: ++ return type; ++ } ++#endif + } + return type; + } +@@ -1804,7 +1819,7 @@ int suitableImage(struct singleEntry * entry, const char * bootPrefix, + return 0; + } + +- 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); + if (!line) { + notSuitablePrintf(entry, 0, "no line found\n"); + return 0; +@@ -1938,7 +1953,7 @@ struct singleEntry * findEntryByPath(struct grubConfig * config, + entry = findEntryByIndex(config, indexVars[i]); + if (!entry) return NULL; + +- 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); + if (!line) return NULL; + + if (index) *index = indexVars[i]; +@@ -1989,9 +2004,9 @@ struct singleEntry * findEntryByPath(struct grubConfig * config, + for (line = entry->lines; line; line = line->next) { + enum lineType_e ct = checkType; + if (entry->multiboot && checkType == LT_KERNEL) +- ct = LT_KERNEL|LT_KERNEL_EFI|LT_MBMODULE|LT_HYPER; ++ ct = LT_KERNEL|LT_KERNEL_EFI|LT_MBMODULE|LT_HYPER|LT_KERNEL_16; + else if (checkType & LT_KERNEL) +- ct = checkType | LT_KERNEL_EFI; ++ ct = checkType | LT_KERNEL_EFI | LT_KERNEL_16; + line = getLineByType(ct, line); + if (!line) + break; /* not found in this entry */ +@@ -2013,7 +2028,7 @@ struct singleEntry * findEntryByPath(struct grubConfig * config, + * non-Linux boot entries (could find netbsd etc, though, which is + * unfortunate) + */ +- 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)) + break; /* found 'im! */ + } + +@@ -2247,7 +2262,7 @@ void displayEntry(struct singleEntry * entry, const char * prefix, int index) { + + printf("index=%d\n", index); + +- 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); + if (!line) { + printf("non linux entry\n"); + return; +@@ -2312,7 +2327,7 @@ void displayEntry(struct singleEntry * entry, const char * prefix, int index) { + printf("root=%s\n", s); + } + +- line = getLineByType(LT_INITRD|LT_INITRD_EFI, entry->lines); ++ line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines); + + if (line && line->numElements >= 2) { + if (!strncmp(prefix, line->elements[1].item, strlen(prefix))) +@@ -2729,7 +2744,7 @@ struct singleLine * addLineTmpl(struct singleEntry * entry, + insertElement(newLine, val, 1, cfi); + + /* but try to keep the rootspec from the template... sigh */ +- 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)) { + char * rootspec = getRootSpecifier(tmplLine->elements[1].item); + if (rootspec != NULL) { + free(newLine->elements[1].item); +@@ -3099,7 +3114,7 @@ int updateActualImage(struct grubConfig * cfg, const char * image, + firstElement = 2; + + } else { +- 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); + if (!line) { + /* no LT_KERNEL or LT_MBMODULE in this entry? */ + continue; +@@ -3300,10 +3315,10 @@ int updateInitrd(struct grubConfig * cfg, const char * image, + if (!image) return 0; + + for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) { +- kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI, entry->lines); ++ kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); + if (!kernelLine) continue; + +- line = getLineByType(LT_INITRD|LT_INITRD_EFI, entry->lines); ++ line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines); + if (line) + removeLine(entry, line); + if (prefix) { +@@ -3314,8 +3329,21 @@ int updateInitrd(struct grubConfig * cfg, const char * image, + endLine = getLineByType(LT_ENTRY_END, entry->lines); + if (endLine) + removeLine(entry, endLine); +- line = addLine(entry, cfg->cfi, preferredLineType(LT_INITRD, cfg->cfi), +- kernelLine->indent, initrd); ++ enum lineType_e lt; ++ switch(kernelLine->type) { ++ case LT_KERNEL: ++ lt = LT_INITRD; ++ break; ++ case LT_KERNEL_EFI: ++ lt = LT_INITRD_EFI; ++ break; ++ case LT_KERNEL_16: ++ lt = LT_INITRD_16; ++ break; ++ default: ++ lt = preferredLineType(LT_INITRD, cfg->cfi); ++ } ++ line = addLine(entry, cfg->cfi, lt, kernelLine->indent, initrd); + if (!line) + return 1; + if (endLine) { +@@ -3913,6 +3941,7 @@ int addNewKernel(struct grubConfig * config, struct singleEntry * template, + switch (config->cfi->entryStart) { + case LT_KERNEL: + case LT_KERNEL_EFI: ++ case LT_KERNEL_16: + if (new->multiboot && config->cfi->mbHyperFirst) { + /* fall through to LT_HYPER */ + } else { +@@ -4471,7 +4500,7 @@ int main(int argc, const char ** argv) { + if (!entry) return 0; + if (!suitableImage(entry, bootPrefix, 0, flags)) return 0; + +- 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); + if (!line) return 0; + + rootspec = getRootSpecifier(line->elements[1].item); +diff --git a/test.sh b/test.sh +index 17b40fe..5be4006 100755 +--- a/test.sh ++++ b/test.sh +@@ -536,6 +536,22 @@ if [ "$testgrub2" == "y" ]; then + + testing="GRUB2 --default-index with default=saved_entry and empty grubenv" + grub2DisplayTest grub2.8 defaultindex/0 --env grubenv.0 --default-index ++ ++ testlinux16=n ++ case $ARCH in ++ ia32|x86_64) testlinux16=y ;; ++ esac ++ ++ if [ "$testlinux16" == "y" ]; then ++ testing="GRUB2 add kernel with linux16" ++ grub2Test grub2.10 add/g2-1.10 --add-kernel=/boot/new-kernel.img \ ++ --title='title' --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ ++ --copy-default ++ ++ testing="GRUB2 add initrd with linux16" ++ grub2Test grub2.11 add/g2-1.11 --update-kernel=/boot/new-kernel.img \ ++ --initrd=/boot/new-initrd --boot-filesystem=/boot/ ++ fi + fi + + testing="YABOOT add kernel" +diff --git a/test/grub2.10 b/test/grub2.10 +new file mode 100644 +index 0000000..d010783 +--- /dev/null ++++ b/test/grub2.10 +@@ -0,0 +1,84 @@ ++# ++# DO NOT EDIT THIS FILE ++# ++# It is automatically generated by grub2-mkconfig using templates ++# from /etc/grub.d and settings from /etc/default/grub ++# ++ ++### BEGIN /etc/grub.d/00_header ### ++if [ -s $prefix/grubenv ]; then ++ load_env ++fi ++set default="0" ++if [ "${prev_saved_entry}" ]; then ++ set saved_entry="${prev_saved_entry}" ++ save_env saved_entry ++ set prev_saved_entry= ++ save_env prev_saved_entry ++ set boot_once=true ++fi ++ ++function savedefault { ++ if [ -z "${boot_once}" ]; then ++ saved_entry="${chosen}" ++ save_env saved_entry ++ fi ++} ++ ++function load_video { ++ insmod vbe ++ insmod vga ++ insmod video_bochs ++ insmod video_cirrus ++} ++ ++set timeout=5 ++### END /etc/grub.d/00_header ### ++ ++### BEGIN /etc/grub.d/10_linux ### ++menuentry 'Linux, with Fedora 2.6.38.8-32.fc15.x86_64' --class gnu-linux --class gnu --class os { ++ load_video ++ set gfxpayload=keep ++ insmod part_msdos ++ insmod ext2 ++ set root='(hd0,msdos1)' ++ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed ++ echo 'Loading Fedora 2.6.38.8-32.fc15.x86_64 ...' ++ linux16 /vmlinuz-2.6.38.8-32.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb ++ echo 'Loading initial ramdisk ...' ++ initrd16 /initramfs-2.6.38.8-32.fc15.x86_64.img ++} ++menuentry 'Linux, with Linux 2.6.38.2-9.fc15.x86_64' --class gnu-linux --class gnu --class os { ++ load_video ++ set gfxpayload=keep ++ insmod part_msdos ++ insmod ext2 ++ set root='(hd0,msdos1)' ++ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed ++ echo 'Loading Linux 2.6.38.2-9.fc15.x86_64 ...' ++ linux16 /vmlinuz-2.6.38.2-9.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb ++ echo 'Loading initial ramdisk ...' ++ initrd16 /initramfs-2.6.38.2-9.fc15.x86_64.img ++} ++### END /etc/grub.d/10_linux ### ++ ++### BEGIN /etc/grub.d/20_linux_xen ### ++### END /etc/grub.d/20_linux_xen ### ++ ++### BEGIN /etc/grub.d/30_os-prober ### ++### END /etc/grub.d/30_os-prober ### ++ ++### BEGIN /etc/grub.d/40_custom ### ++# This file provides an easy way to add custom menu entries. Simply type the ++# menu entries you want to add after this comment. Be careful not to change ++# the 'exec tail' line above. ++### END /etc/grub.d/40_custom ### ++ ++### BEGIN /etc/grub.d/41_custom ### ++if [ -f $prefix/custom.cfg ]; then ++ source $prefix/custom.cfg; ++fi ++### END /etc/grub.d/41_custom ### ++ ++### BEGIN /etc/grub.d/90_persistent ### ++### END /etc/grub.d/90_persistent ### +diff --git a/test/grub2.11 b/test/grub2.11 +new file mode 100644 +index 0000000..820880a +--- /dev/null ++++ b/test/grub2.11 +@@ -0,0 +1,97 @@ ++# ++# DO NOT EDIT THIS FILE ++# ++# It is automatically generated by grub2-mkconfig using templates ++# from /etc/grub.d and settings from /etc/default/grub ++# ++ ++### BEGIN /etc/grub.d/00_header ### ++if [ -s $prefix/grubenv ]; then ++ load_env ++fi ++set default="0" ++if [ "${prev_saved_entry}" ]; then ++ set saved_entry="${prev_saved_entry}" ++ save_env saved_entry ++ set prev_saved_entry= ++ save_env prev_saved_entry ++ set boot_once=true ++fi ++ ++function savedefault { ++ if [ -z "${boot_once}" ]; then ++ saved_entry="${chosen}" ++ save_env saved_entry ++ fi ++} ++ ++function load_video { ++ insmod vbe ++ insmod vga ++ insmod video_bochs ++ insmod video_cirrus ++} ++ ++set timeout=5 ++### END /etc/grub.d/00_header ### ++ ++set superusers="foo bar baz" ++ ++### BEGIN /etc/grub.d/10_linux ### ++menuentry 'title' --class gnu-linux --class gnu --class os { ++ load_video ++ set gfxpayload=keep ++ insmod part_msdos ++ insmod ext2 ++ set root='(hd0,msdos1)' ++ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed ++ echo 'Loading title' ++ linux16 /new-kernel.img root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb ++ echo 'Loading initial ramdisk ...' ++} ++menuentry 'Linux, with Linux 2.6.38.8-32.fc15.x86_64' --class gnu-linux --class gnu --class os { ++ load_video ++ set gfxpayload=keep ++ insmod part_msdos ++ insmod ext2 ++ set root='(hd0,msdos1)' ++ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed ++ echo 'Loading Linux 2.6.38.8-32.fc15.x86_64 ...' ++ linux16 /vmlinuz-2.6.38.8-32.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb ++ echo 'Loading initial ramdisk ...' ++ initrd16 /initramfs-2.6.38.8-32.fc15.x86_64.img ++} ++menuentry 'Linux, with Linux 2.6.38.2-9.fc15.x86_64' --class gnu-linux --class gnu --class os { ++ load_video ++ set gfxpayload=keep ++ insmod part_msdos ++ insmod ext2 ++ set root='(hd0,msdos1)' ++ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed ++ echo 'Loading Linux 2.6.38.2-9.fc15.x86_64 ...' ++ linux16 /vmlinuz-2.6.38.2-9.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb ++ echo 'Loading initial ramdisk ...' ++ initrd16 /initramfs-2.6.38.2-9.fc15.x86_64.img ++} ++### END /etc/grub.d/10_linux ### ++ ++### BEGIN /etc/grub.d/20_linux_xen ### ++### END /etc/grub.d/20_linux_xen ### ++ ++### BEGIN /etc/grub.d/30_os-prober ### ++### END /etc/grub.d/30_os-prober ### ++ ++### BEGIN /etc/grub.d/40_custom ### ++# This file provides an easy way to add custom menu entries. Simply type the ++# menu entries you want to add after this comment. Be careful not to change ++# the 'exec tail' line above. ++### END /etc/grub.d/40_custom ### ++ ++### BEGIN /etc/grub.d/41_custom ### ++if [ -f $prefix/custom.cfg ]; then ++ source $prefix/custom.cfg; ++fi ++### END /etc/grub.d/41_custom ### ++ ++### BEGIN /etc/grub.d/90_persistent ### ++### END /etc/grub.d/90_persistent ### +diff --git a/test/results/add/g2-1.10 b/test/results/add/g2-1.10 +new file mode 100644 +index 0000000..bb2c71c +--- /dev/null ++++ b/test/results/add/g2-1.10 +@@ -0,0 +1,96 @@ ++# ++# DO NOT EDIT THIS FILE ++# ++# It is automatically generated by grub2-mkconfig using templates ++# from /etc/grub.d and settings from /etc/default/grub ++# ++ ++### BEGIN /etc/grub.d/00_header ### ++if [ -s $prefix/grubenv ]; then ++ load_env ++fi ++set default="1" ++if [ "${prev_saved_entry}" ]; then ++ set saved_entry="${prev_saved_entry}" ++ save_env saved_entry ++ set prev_saved_entry= ++ save_env prev_saved_entry ++ set boot_once=true ++fi ++ ++function savedefault { ++ if [ -z "${boot_once}" ]; then ++ saved_entry="${chosen}" ++ save_env saved_entry ++ fi ++} ++ ++function load_video { ++ insmod vbe ++ insmod vga ++ insmod video_bochs ++ insmod video_cirrus ++} ++ ++set timeout=5 ++### END /etc/grub.d/00_header ### ++ ++### BEGIN /etc/grub.d/10_linux ### ++menuentry 'title' --class gnu-linux --class gnu --class os { ++ load_video ++ set gfxpayload=keep ++ insmod part_msdos ++ insmod ext2 ++ set root='(hd0,msdos1)' ++ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed ++ echo 'Loading title' ++ linux16 /new-kernel.img root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb ++ echo 'Loading initial ramdisk ...' ++ initrd16 /new-initrd ++} ++menuentry 'Linux, with Fedora 2.6.38.8-32.fc15.x86_64' --class gnu-linux --class gnu --class os { ++ load_video ++ set gfxpayload=keep ++ insmod part_msdos ++ insmod ext2 ++ set root='(hd0,msdos1)' ++ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed ++ echo 'Loading Fedora 2.6.38.8-32.fc15.x86_64 ...' ++ linux16 /vmlinuz-2.6.38.8-32.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb ++ echo 'Loading initial ramdisk ...' ++ initrd16 /initramfs-2.6.38.8-32.fc15.x86_64.img ++} ++menuentry 'Linux, with Linux 2.6.38.2-9.fc15.x86_64' --class gnu-linux --class gnu --class os { ++ load_video ++ set gfxpayload=keep ++ insmod part_msdos ++ insmod ext2 ++ set root='(hd0,msdos1)' ++ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed ++ echo 'Loading Linux 2.6.38.2-9.fc15.x86_64 ...' ++ linux16 /vmlinuz-2.6.38.2-9.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb ++ echo 'Loading initial ramdisk ...' ++ initrd16 /initramfs-2.6.38.2-9.fc15.x86_64.img ++} ++### END /etc/grub.d/10_linux ### ++ ++### BEGIN /etc/grub.d/20_linux_xen ### ++### END /etc/grub.d/20_linux_xen ### ++ ++### BEGIN /etc/grub.d/30_os-prober ### ++### END /etc/grub.d/30_os-prober ### ++ ++### BEGIN /etc/grub.d/40_custom ### ++# This file provides an easy way to add custom menu entries. Simply type the ++# menu entries you want to add after this comment. Be careful not to change ++# the 'exec tail' line above. ++### END /etc/grub.d/40_custom ### ++ ++### BEGIN /etc/grub.d/41_custom ### ++if [ -f $prefix/custom.cfg ]; then ++ source $prefix/custom.cfg; ++fi ++### END /etc/grub.d/41_custom ### ++ ++### BEGIN /etc/grub.d/90_persistent ### ++### END /etc/grub.d/90_persistent ### +diff --git a/test/results/add/g2-1.11 b/test/results/add/g2-1.11 +new file mode 100644 +index 0000000..a11cb41 +--- /dev/null ++++ b/test/results/add/g2-1.11 +@@ -0,0 +1,98 @@ ++# ++# DO NOT EDIT THIS FILE ++# ++# It is automatically generated by grub2-mkconfig using templates ++# from /etc/grub.d and settings from /etc/default/grub ++# ++ ++### BEGIN /etc/grub.d/00_header ### ++if [ -s $prefix/grubenv ]; then ++ load_env ++fi ++set default="0" ++if [ "${prev_saved_entry}" ]; then ++ set saved_entry="${prev_saved_entry}" ++ save_env saved_entry ++ set prev_saved_entry= ++ save_env prev_saved_entry ++ set boot_once=true ++fi ++ ++function savedefault { ++ if [ -z "${boot_once}" ]; then ++ saved_entry="${chosen}" ++ save_env saved_entry ++ fi ++} ++ ++function load_video { ++ insmod vbe ++ insmod vga ++ insmod video_bochs ++ insmod video_cirrus ++} ++ ++set timeout=5 ++### END /etc/grub.d/00_header ### ++ ++set superusers="foo bar baz" ++ ++### BEGIN /etc/grub.d/10_linux ### ++menuentry 'title' --class gnu-linux --class gnu --class os { ++ load_video ++ set gfxpayload=keep ++ insmod part_msdos ++ insmod ext2 ++ set root='(hd0,msdos1)' ++ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed ++ echo 'Loading title' ++ linux16 /new-kernel.img root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb ++ echo 'Loading initial ramdisk ...' ++ initrd16 /new-initrd ++} ++menuentry 'Linux, with Linux 2.6.38.8-32.fc15.x86_64' --class gnu-linux --class gnu --class os { ++ load_video ++ set gfxpayload=keep ++ insmod part_msdos ++ insmod ext2 ++ set root='(hd0,msdos1)' ++ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed ++ echo 'Loading Linux 2.6.38.8-32.fc15.x86_64 ...' ++ linux16 /vmlinuz-2.6.38.8-32.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb ++ echo 'Loading initial ramdisk ...' ++ initrd16 /initramfs-2.6.38.8-32.fc15.x86_64.img ++} ++menuentry 'Linux, with Linux 2.6.38.2-9.fc15.x86_64' --class gnu-linux --class gnu --class os { ++ load_video ++ set gfxpayload=keep ++ insmod part_msdos ++ insmod ext2 ++ set root='(hd0,msdos1)' ++ search --no-floppy --fs-uuid --set=root df0170c9-7d05-415c-bbd1-d4d503ba0eed ++ echo 'Loading Linux 2.6.38.2-9.fc15.x86_64 ...' ++ linux16 /vmlinuz-2.6.38.2-9.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb ++ echo 'Loading initial ramdisk ...' ++ initrd16 /initramfs-2.6.38.2-9.fc15.x86_64.img ++} ++### END /etc/grub.d/10_linux ### ++ ++### BEGIN /etc/grub.d/20_linux_xen ### ++### END /etc/grub.d/20_linux_xen ### ++ ++### BEGIN /etc/grub.d/30_os-prober ### ++### END /etc/grub.d/30_os-prober ### ++ ++### BEGIN /etc/grub.d/40_custom ### ++# This file provides an easy way to add custom menu entries. Simply type the ++# menu entries you want to add after this comment. Be careful not to change ++# the 'exec tail' line above. ++### END /etc/grub.d/40_custom ### ++ ++### BEGIN /etc/grub.d/41_custom ### ++if [ -f $prefix/custom.cfg ]; then ++ source $prefix/custom.cfg; ++fi ++### END /etc/grub.d/41_custom ### ++ ++### BEGIN /etc/grub.d/90_persistent ### ++### END /etc/grub.d/90_persistent ### +-- +2.4.3 + diff --git a/SOURCES/0005-If-we-re-on-a-zipl-based-platform-use-banner-passed-.patch b/SOURCES/0005-If-we-re-on-a-zipl-based-platform-use-banner-passed-.patch new file mode 100644 index 0000000..766773e --- /dev/null +++ b/SOURCES/0005-If-we-re-on-a-zipl-based-platform-use-banner-passed-.patch @@ -0,0 +1,55 @@ +From ce1c4cd2bbb326729ffaf186e96548bcf225dd11 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 22 Jan 2014 17:16:06 -0500 +Subject: [PATCH 05/41] If we're on a zipl-based platform, use --banner passed + to us (sanitized.) + +"lilo" type bootloaders have gotten $version as their title since +forever, but on zipl that'll cause collisions when creating extra boot +images with the same version. So on that platform, choose to honor +--banner even though it has a lot of limitations, and attempt to get rid +of spaces in the result to avoid some of those problems. + +Related: rhbz#1032048 + +Signed-off-by: Peter Jones +--- + new-kernel-pkg | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/new-kernel-pkg b/new-kernel-pkg +index 6373385..4fa94b7 100755 +--- a/new-kernel-pkg ++++ b/new-kernel-pkg +@@ -179,10 +179,16 @@ install() { + + + if [ -n "$banner" ]; then +- title="$banner ($version)" ++ if [ $ARCH = 's390' -o $ARCH = 's390x' ]; then ++ title=$(echo $banner | sed 's/ /_/g') ++ else ++ title="$banner ($version)" ++ fi ++ elif [ $ARCH = 's390' -o $ARCH = 's390x' ]; then ++ title=$(echo $version | sed 's/ /_/g') + elif [ -f /etc/os-release ]; then +- . /etc/os-release +- title="$NAME ($version) $VERSION" ++ . /etc/os-release ++ title="$NAME ($version) $VERSION" + elif [ -f /etc/redhat-release ]; then + title="$(sed 's/ release.*$//' < /etc/redhat-release) ($version)" + else +@@ -230,7 +236,7 @@ install() { + [ -n "$verbose" ] && echo "adding $version to $liloConfig" + + $grubby --add-kernel=$kernelImage $INITRD \ +- --copy-default $makedefault --title $version \ ++ --copy-default $makedefault --title "$title" \ + ${mbkernel:+--add-multiboot="$mbkernel"} ${mbargs:+--mbargs="$mbargs"} \ + --args="root=$rootdevice $kernargs" --remove-kernel="TITLE=$version" \ + --$liloFlag +-- +2.4.3 + diff --git a/SOURCES/0005-grub-Fix-a-crash-with-kernel-line-without-being-prec.patch b/SOURCES/0005-grub-Fix-a-crash-with-kernel-line-without-being-prec.patch deleted file mode 100644 index df104ce..0000000 --- a/SOURCES/0005-grub-Fix-a-crash-with-kernel-line-without-being-prec.patch +++ /dev/null @@ -1,36 +0,0 @@ -From b2ca7caef3da7bc3ca7a90c1d39f2dc42770a682 Mon Sep 17 00:00:00 2001 -From: Lubomir Rintel -Date: Wed, 27 Nov 2013 16:59:48 +0100 -Subject: [PATCH 05/16] grub: Fix a crash with kernel line without being - preceded by title - -Quite obviously this implies a broken configuration file where a lone kernel -line is found without ever seeing an entry start, resulting in a NULL -dereference attempt. Reproducible by running GRUB code against extlinux -configuration: - -./grubby --grub -c test/extlinux.1 --default-kernel -grubby received SIGSEGV! Backtrace (6): -... - -Signed-off-by: Lubomir Rintel ---- - grubby.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/grubby.c b/grubby.c -index d33ce6e..4773852 100644 ---- a/grubby.c -+++ b/grubby.c -@@ -1188,7 +1188,7 @@ static struct grubConfig * readConfig(const char * inName, - * lines came earlier in the template, make sure to use LT_HYPER - * instead of LT_KERNEL now - */ -- if (entry->multiboot) -+ if (entry && entry->multiboot) - line->type = LT_HYPER; - - } else if (line->type == LT_MBMODULE) { --- -1.9.3 - diff --git a/SOURCES/0006-Support-devicetree-directive-in-grub2.patch b/SOURCES/0006-Support-devicetree-directive-in-grub2.patch index e1de8a1..e77261b 100644 --- a/SOURCES/0006-Support-devicetree-directive-in-grub2.patch +++ b/SOURCES/0006-Support-devicetree-directive-in-grub2.patch @@ -1,7 +1,7 @@ -From 058afd893cef267ee5d88f331da5c64708378b8b Mon Sep 17 00:00:00 2001 +From 87408a542b2626078e69ba019d2c581ebabc104e Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Tue, 11 Feb 2014 10:24:48 -0500 -Subject: [PATCH 06/16] Support "devicetree" directive in grub2. +Subject: [PATCH 06/41] Support "devicetree" directive in grub2. Resolves: rhbz#1063534 @@ -11,7 +11,7 @@ Signed-off-by: Peter Jones 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/new-kernel-pkg b/new-kernel-pkg -index 7fec1fe..30477cc 100755 +index 4fa94b7..7479557 100755 --- a/new-kernel-pkg +++ b/new-kernel-pkg @@ -111,6 +111,7 @@ initrd="" @@ -44,7 +44,7 @@ index 7fec1fe..30477cc 100755 # FIXME: is this a good heuristic to find out if we're on iSeries? if [ -d /proc/iSeries ]; then [ -n "$verbose" ] && echo "On an iSeries, just making img file" -@@ -537,6 +544,15 @@ while [ $# -gt 0 ]; do +@@ -544,6 +551,15 @@ while [ $# -gt 0 ]; do initrd="remove" ;; @@ -61,5 +61,5 @@ index 7fec1fe..30477cc 100755 dracut=--dracut ;; -- -1.9.3 +2.4.3 diff --git a/SOURCES/0007-Actually-USE-DEVTREE-in-new-kernel-pkg.patch b/SOURCES/0007-Actually-USE-DEVTREE-in-new-kernel-pkg.patch index 0f503b1..d8b008d 100644 --- a/SOURCES/0007-Actually-USE-DEVTREE-in-new-kernel-pkg.patch +++ b/SOURCES/0007-Actually-USE-DEVTREE-in-new-kernel-pkg.patch @@ -1,7 +1,7 @@ -From e3290d26354228a6d1ffa0e24377c35a53ef780f Mon Sep 17 00:00:00 2001 +From b8ad9832948f86bf051c15d212fe2c978313c7f8 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Wed, 12 Feb 2014 10:58:48 -0500 -Subject: [PATCH 07/16] Actually /USE/ $DEVTREE in new-kernel-pkg. +Subject: [PATCH 07/41] Actually /USE/ $DEVTREE in new-kernel-pkg. Resolves: rhbz#1063534 @@ -11,10 +11,10 @@ Signed-off-by: Peter Jones 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/new-kernel-pkg b/new-kernel-pkg -index 30477cc..f4fd275 100755 +index 7479557..97e1839 100755 --- a/new-kernel-pkg +++ b/new-kernel-pkg -@@ -224,7 +224,7 @@ install() { +@@ -230,7 +230,7 @@ install() { [ -n "$verbose" ] && echo "adding $version to $grub2EfiConfig" $grubby --grub2 -c $grub2EfiConfig --efi \ @@ -24,5 +24,5 @@ index 30477cc..f4fd275 100755 ${mbkernel:+--add-multiboot="$mbkernel"} \ ${mbargs:+--mbargs="$mbargs"} \ -- -1.9.3 +2.4.3 diff --git a/SOURCES/0008-Fix-bad-check-for-new-kernel-pkg-s-command-line-argu.patch b/SOURCES/0008-Fix-bad-check-for-new-kernel-pkg-s-command-line-argu.patch deleted file mode 100644 index 1d36bdd..0000000 --- a/SOURCES/0008-Fix-bad-check-for-new-kernel-pkg-s-command-line-argu.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 3ed06bf8ca9681a009f4ee0355829f05ed5ceade Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 31 Mar 2014 13:59:34 -0400 -Subject: [PATCH 08/16] Fix bad check for new-kernel-pkg's command line - arguments. - ---devtree's argument needs to be nonempty, not just pass -f. -Resolves: rhbz#1082318 - -Signed-off-by: Peter Jones ---- - new-kernel-pkg | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/new-kernel-pkg b/new-kernel-pkg -index f4fd275..5fb0949 100755 ---- a/new-kernel-pkg -+++ b/new-kernel-pkg -@@ -153,7 +153,7 @@ install() { - fi - - DEVTREE="" -- if [ -f $devtreefile ]; then -+ if [ "x$devtreefile" != "x" -a -f $devtreefile ]; then - [ -n "$verbose" ] && echo "found $devtreefile and using it with grubby" - DEVTREE="--devtree $devtreefile" - fi --- -1.9.3 - diff --git a/SOURCES/0008-Use-the-correct-load-commands-for-aarch64-efi.patch b/SOURCES/0008-Use-the-correct-load-commands-for-aarch64-efi.patch new file mode 100644 index 0000000..ece17c7 --- /dev/null +++ b/SOURCES/0008-Use-the-correct-load-commands-for-aarch64-efi.patch @@ -0,0 +1,64 @@ +From 939f2d3dc981fe6a3258ac943673c43d7a4964a1 Mon Sep 17 00:00:00 2001 +From: no one +Date: Thu, 13 Feb 2014 10:30:11 -0500 +Subject: [PATCH 08/41] Use the correct load commands for aarch64 efi. + +Resolves: rhbz#1081269 +--- + grubby.c | 7 +++++++ + test.sh | 17 ++++++++++++++--- + 2 files changed, 21 insertions(+), 3 deletions(-) + +diff --git a/grubby.c b/grubby.c +index aa228c3..0205882 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -714,10 +714,17 @@ static enum lineType_e preferredLineType(enum lineType_e type, + struct configFileInfo *cfi) { + if (isEfi && cfi == &grub2ConfigType) { + switch (type) { ++#if defined(__aarch64__) ++ case LT_KERNEL: ++ return LT_KERNEL; ++ case LT_INITRD: ++ return LT_INITRD; ++#else + case LT_KERNEL: + return LT_KERNEL_EFI; + case LT_INITRD: + return LT_INITRD_EFI; ++#endif + default: + return type; + } +diff --git a/test.sh b/test.sh +index 5be4006..1d28fb1 100755 +--- a/test.sh ++++ b/test.sh +@@ -443,9 +443,20 @@ if [ "$testgrub2" == "y" ]; then + grub2Test grub2.1 add/g2-1.1 --add-kernel=/boot/new-kernel.img \ + --title='title' --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ + --copy-default +- grub2Test grub2.1 add/g2-1.6 --add-kernel=/boot/new-kernel.img \ +- --title='title' --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ +- --copy-default --efi ++ case $ARCH in ++ aarch64) ++ grub2Test grub2.1 add/g2-1.1 --add-kernel=/boot/new-kernel.img \ ++ --title='title' \ ++ --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ ++ --copy-default --efi ++ ;; ++ *) ++ grub2Test grub2.1 add/g2-1.6 --add-kernel=/boot/new-kernel.img \ ++ --title='title' \ ++ --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ ++ --copy-default --efi ++ ;; ++ esac + grub2Test grub2.6 add/g2-1.7 --add-kernel=/boot/new-kernel.img \ + --title='title' --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ + --copy-default --efi +-- +2.4.3 + diff --git a/SOURCES/0009-Actually-do-a-fix-for-rhbz-1082318-that-fixes-the-is.patch b/SOURCES/0009-Actually-do-a-fix-for-rhbz-1082318-that-fixes-the-is.patch deleted file mode 100644 index 61cbf69..0000000 --- a/SOURCES/0009-Actually-do-a-fix-for-rhbz-1082318-that-fixes-the-is.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 6125b964c666c57fc10746d9b1a4d02167cf3689 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 1 Apr 2014 08:48:09 -0400 -Subject: [PATCH 09/16] Actually do a fix for rhbz#1082318 that fixes the issue - there. - -News: after all these years I'm still terrible at shell scripts, just -like everybody else. - -Related: rhbz#1063534 - -Signed-off-by: Peter Jones ---- - new-kernel-pkg | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/new-kernel-pkg b/new-kernel-pkg -index 5fb0949..e6096ca 100755 ---- a/new-kernel-pkg -+++ b/new-kernel-pkg -@@ -153,7 +153,7 @@ install() { - fi - - DEVTREE="" -- if [ "x$devtreefile" != "x" -a -f $devtreefile ]; then -+ if [ "x$devtreefile" != "x" -a -f "$devtreefile" ]; then - [ -n "$verbose" ] && echo "found $devtreefile and using it with grubby" - DEVTREE="--devtree $devtreefile" - fi --- -1.9.3 - diff --git a/SOURCES/0009-Always-choose-linux-initrd-on-efi-only-platforms.patch b/SOURCES/0009-Always-choose-linux-initrd-on-efi-only-platforms.patch new file mode 100644 index 0000000..3b484a9 --- /dev/null +++ b/SOURCES/0009-Always-choose-linux-initrd-on-efi-only-platforms.patch @@ -0,0 +1,52 @@ +From fd966254fc3e6ad1ee3187862b2e86575ebb55b4 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 28 Mar 2014 15:36:53 -0400 +Subject: [PATCH 09/41] Always choose "linux"/"initrd" on efi-only platforms. + +Which basically just means Aarch64. + +Signed-off-by: Peter Jones +--- + grubby.c | 17 ++++++++--------- + 1 file changed, 8 insertions(+), 9 deletions(-) + +diff --git a/grubby.c b/grubby.c +index 0205882..895ed06 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -60,6 +60,12 @@ int debug = 0; /* Currently just for template debugging */ + + int isEfi = 0; + ++#if defined(__arch64__) ++#define isEfiOnly 1 ++#else ++#define isEfiOnly 0 ++#endif ++ + char *saved_command_line = NULL; + + /* comments get lumped in with indention */ +@@ -714,17 +720,10 @@ static enum lineType_e preferredLineType(enum lineType_e type, + struct configFileInfo *cfi) { + if (isEfi && cfi == &grub2ConfigType) { + switch (type) { +-#if defined(__aarch64__) + case LT_KERNEL: +- return LT_KERNEL; ++ return isEfiOnly ? LT_KERNEL : LT_KERNEL_EFI; + case LT_INITRD: +- return LT_INITRD; +-#else +- case LT_KERNEL: +- return LT_KERNEL_EFI; +- case LT_INITRD: +- return LT_INITRD_EFI; +-#endif ++ return isEfiOnly ? LT_INITRD : LT_INITRD_EFI; + default: + return type; + } +-- +2.4.3 + diff --git a/SOURCES/0010-Use-the-correct-load-commands-for-aarch64-efi.patch b/SOURCES/0010-Use-the-correct-load-commands-for-aarch64-efi.patch deleted file mode 100644 index 4b11c51..0000000 --- a/SOURCES/0010-Use-the-correct-load-commands-for-aarch64-efi.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 1d7f20b6b0f803f960cc9375816d94cc3270d711 Mon Sep 17 00:00:00 2001 -From: no one -Date: Thu, 13 Feb 2014 10:30:11 -0500 -Subject: [PATCH 10/16] Use the correct load commands for aarch64 efi. - -Resolves: rhbz#1081269 ---- - grubby.c | 7 +++++++ - test.sh | 17 ++++++++++++++--- - 2 files changed, 21 insertions(+), 3 deletions(-) - -diff --git a/grubby.c b/grubby.c -index 4773852..74818a2 100644 ---- a/grubby.c -+++ b/grubby.c -@@ -714,10 +714,17 @@ static enum lineType_e preferredLineType(enum lineType_e type, - struct configFileInfo *cfi) { - if (isEfi && cfi == &grub2ConfigType) { - switch (type) { -+#if defined(__aarch64__) -+ case LT_KERNEL: -+ return LT_KERNEL; -+ case LT_INITRD: -+ return LT_INITRD; -+#else - case LT_KERNEL: - return LT_KERNEL_EFI; - case LT_INITRD: - return LT_INITRD_EFI; -+#endif - default: - return type; - } -diff --git a/test.sh b/test.sh -index 5be4006..1d28fb1 100755 ---- a/test.sh -+++ b/test.sh -@@ -443,9 +443,20 @@ if [ "$testgrub2" == "y" ]; then - grub2Test grub2.1 add/g2-1.1 --add-kernel=/boot/new-kernel.img \ - --title='title' --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ - --copy-default -- grub2Test grub2.1 add/g2-1.6 --add-kernel=/boot/new-kernel.img \ -- --title='title' --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ -- --copy-default --efi -+ case $ARCH in -+ aarch64) -+ grub2Test grub2.1 add/g2-1.1 --add-kernel=/boot/new-kernel.img \ -+ --title='title' \ -+ --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ -+ --copy-default --efi -+ ;; -+ *) -+ grub2Test grub2.1 add/g2-1.6 --add-kernel=/boot/new-kernel.img \ -+ --title='title' \ -+ --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ -+ --copy-default --efi -+ ;; -+ esac - grub2Test grub2.6 add/g2-1.7 --add-kernel=/boot/new-kernel.img \ - --title='title' --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ - --copy-default --efi --- -1.9.3 - diff --git a/SOURCES/0010-extlinux-Understand-default-properly.patch b/SOURCES/0010-extlinux-Understand-default-properly.patch new file mode 100644 index 0000000..a20668c --- /dev/null +++ b/SOURCES/0010-extlinux-Understand-default-properly.patch @@ -0,0 +1,81 @@ +From b0b7669740fd8cb9ee465d0f978ed30d5e28af6e Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Wed, 27 Nov 2013 16:59:50 +0100 +Subject: [PATCH 10/41] extlinux: Understand "default" properly + +The configuration looks like the following: + + default Fedora (3.11.6-301.fc20.i686+PAE) 20 (Heisenbug) + + title Fedora (3.11.6-301.fc20.i686+PAE) 20 (Heisenbug) + ... + +Grubby skips over the default clause as it has more than one element. And even +if it did not, it would not match it against the title, since it handles titles +specially, concatenating the title, but not the default clause. + +This commit adds special handling for extlinux, which causes it to parse +default and title in the same way. + +Signed-off-by: Lubomir Rintel +--- + grubby.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/grubby.c b/grubby.c +index 895ed06..21c5044 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -159,6 +159,7 @@ struct configFileInfo { + int defaultIsVariable; + int defaultSupportSaved; + int defaultIsSaved; ++ int defaultIsUnquoted; + enum lineType_e entryStart; + enum lineType_e entryEnd; + int needsBootPrefix; +@@ -630,6 +631,7 @@ struct configFileInfo extlinuxConfigType = { + .needsBootPrefix = 1, + .maxTitleLength = 255, + .mbAllowExtraInitRds = 1, ++ .defaultIsUnquoted = 1, + }; + + struct grubConfig { +@@ -1185,9 +1187,6 @@ static struct grubConfig * readConfig(const char * inName, + cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT; + defaultLine = line; + } +- } else if (line->type == LT_DEFAULT && line->numElements == 2) { +- cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT; +- defaultLine = line; + + } else if (iskernel(line->type)) { + /* if by some freak chance this is multiboot and the "module" +@@ -1220,8 +1219,9 @@ static struct grubConfig * readConfig(const char * inName, + cfg->fallbackImage = strtol(line->elements[1].item, &end, 10); + if (*end) cfg->fallbackImage = -1; + +- } else if (line->type == LT_TITLE && line->numElements > 1) { +- /* make the title a single argument (undoing our parsing) */ ++ } else if ((line->type == LT_DEFAULT && cfi->defaultIsUnquoted) || ++ (line->type == LT_TITLE && line->numElements > 1)) { ++ /* make the title/default a single argument (undoing our parsing) */ + len = 0; + for (int i = 1; i < line->numElements; i++) { + len += strlen(line->elements[i].item); +@@ -1328,6 +1328,11 @@ static struct grubConfig * readConfig(const char * inName, + } + } + ++ if (line->type == LT_DEFAULT && line->numElements == 2) { ++ cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT; ++ defaultLine = line; ++ } ++ + /* If we find a generic config option which should live at the + top of the file, move it there. Old versions of grubby were + probably responsible for putting new images in the wrong +-- +2.4.3 + diff --git a/SOURCES/0011-Tell-a-slightly-better-fib-about-default-bootloader-.patch b/SOURCES/0011-Tell-a-slightly-better-fib-about-default-bootloader-.patch deleted file mode 100644 index 1762852..0000000 --- a/SOURCES/0011-Tell-a-slightly-better-fib-about-default-bootloader-.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 6798634625ff6525632bf1fa26a54b85bd3cba5b Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 12 Sep 2014 15:50:05 -0400 -Subject: [PATCH 11/16] Tell a slightly better fib about default bootloader - config paths. - -It's not going to be right everywhere, but... whatever. - -Resolves: rhbz#1001664 -Signed-off-by: Peter Jones ---- - grubby.8 | 14 ++++++++------ - 1 file changed, 8 insertions(+), 6 deletions(-) - -diff --git a/grubby.8 b/grubby.8 -index d79e60e..9d7a1fd 100644 ---- a/grubby.8 -+++ b/grubby.8 -@@ -18,16 +18,18 @@ grubby \- command line tool for configuring grub, lilo, elilo, yaboot and zipl - - .SH DESCRIPTION - \fBgrubby\fR is a command line tool for updating and displaying information --about the configuration files for the \fBgrub\fR, \fBlilo\fR, \fBelilo\fR -+about the configuration files for the \fBgrub\fR, \fBlilo\fR, \fBelilo\fR - (ia64), \fByaboot\fR (powerpc) and \fBzipl\fR (s390) boot loaders. It - is primarily designed to be used from scripts which install new - kernels and need to find information about the current boot environment. - --On Intel x86 platforms, \fBgrub\fR is the default bootloader and the --configuration file is in \fB/boot/grub/grub.conf\fR. On Intel ia64 platforms, --\fBelilo\fR mode is used and the default location for the configuration file --is \fB/boot/grub/grub.conf\fR. On PowerPC platforms, \fByaboot\fR parsing --is used and the configuration file should be in \fB/etc/yaboot.conf\fR. -+On BIOS-based Intel x86 platforms, \fBgrub2\fR is the default bootloader and -+the configuration file is in \fB/boot/grub2/grub.cfg\fR. On UEFI-based Intel -+x86 platforms, \fBgrub2\fR is the default bootloader, and the configuration -+file is in \fB/boot/efi/EFI/redhat/grub.cfg\fR. On Intel ia64 platforms, -+\fBelilo\fR mode is used and the default location for the configuration file -+is \fB/boot/efi/EFI/redhat/elilo.conf\fR. On PowerPC platforms, \fByaboot\fR -+parsing is used and the configuration file should be in \fB/etc/yaboot.conf\fR. - - There are a number of ways to specify the kernel used for \fB-\-info\fR, - \fB-\-remove-kernel\fR, and \fB-\-update-kernel\fR. Specificying \fBDEFAULT\fR --- -1.9.3 - diff --git a/SOURCES/0011-extlinux-Add-test-suite.patch b/SOURCES/0011-extlinux-Add-test-suite.patch new file mode 100644 index 0000000..bb189be --- /dev/null +++ b/SOURCES/0011-extlinux-Add-test-suite.patch @@ -0,0 +1,891 @@ +From afd2fe90807de46476f1a50e84cdea5245b0e902 Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Wed, 27 Nov 2013 16:59:49 +0100 +Subject: [PATCH 11/41] extlinux: Add test suite + +Strongly inspired aby GRUB test suite. Note that this does not pass currently, +since the extlinux default line gets eaten (rhbz#964178). A fix will follow. + +Signed-off-by: Lubomir Rintel +--- + test.sh | 58 +++++++++++++++++++++++++++++++++++++++- + test/extlinux.1 | 17 ++++++++++++ + test/extlinux.2 | 21 +++++++++++++++ + test/extlinux.3 | 15 +++++++++++ + test/extlinux.4 | 32 ++++++++++++++++++++++ + test/results/add/extlinux1.1 | 20 ++++++++++++++ + test/results/add/extlinux1.2 | 20 ++++++++++++++ + test/results/add/extlinux1.3 | 21 +++++++++++++++ + test/results/add/extlinux1.4 | 21 +++++++++++++++ + test/results/add/extlinux2.1 | 21 +++++++++++++++ + test/results/args/extlinux1.1 | 20 ++++++++++++++ + test/results/args/extlinux1.2 | 20 ++++++++++++++ + test/results/default/extlinux1.1 | 19 +++++++++++++ + test/results/default/extlinux1.2 | 19 +++++++++++++ + test/results/default/extlinux3.1 | 16 +++++++++++ + test/results/default/extlinux3.2 | 15 +++++++++++ + test/results/remove/extlinux3.1 | 10 +++++++ + test/results/remove/extlinux4.1 | 27 +++++++++++++++++++ + test/results/updargs/extlinux1.1 | 17 ++++++++++++ + test/results/updargs/extlinux1.2 | 18 +++++++++++++ + test/results/updargs/extlinux3.1 | 15 +++++++++++ + test/results/updargs/extlinux3.2 | 15 +++++++++++ + test/results/updargs/extlinux3.4 | 15 +++++++++++ + test/results/updargs/extlinux3.7 | 13 +++++++++ + test/results/updargs/extlinux4.2 | 32 ++++++++++++++++++++++ + test/results/updargs/extlinux4.3 | 32 ++++++++++++++++++++++ + test/results/updargs/extlinux4.4 | 32 ++++++++++++++++++++++ + test/results/updargs/extlinux4.5 | 33 +++++++++++++++++++++++ + 28 files changed, 613 insertions(+), 1 deletion(-) + create mode 100644 test/extlinux.1 + create mode 100644 test/extlinux.2 + create mode 100644 test/extlinux.3 + create mode 100644 test/extlinux.4 + create mode 100644 test/results/add/extlinux1.1 + create mode 100644 test/results/add/extlinux1.2 + create mode 100644 test/results/add/extlinux1.3 + create mode 100644 test/results/add/extlinux1.4 + create mode 100644 test/results/add/extlinux2.1 + create mode 100644 test/results/args/extlinux1.1 + create mode 100644 test/results/args/extlinux1.2 + create mode 100644 test/results/default/extlinux1.1 + create mode 100644 test/results/default/extlinux1.2 + create mode 100644 test/results/default/extlinux3.1 + create mode 100644 test/results/default/extlinux3.2 + create mode 100644 test/results/remove/extlinux3.1 + create mode 100644 test/results/remove/extlinux4.1 + create mode 100644 test/results/updargs/extlinux1.1 + create mode 100644 test/results/updargs/extlinux1.2 + create mode 100644 test/results/updargs/extlinux3.1 + create mode 100644 test/results/updargs/extlinux3.2 + create mode 100644 test/results/updargs/extlinux3.4 + create mode 100644 test/results/updargs/extlinux3.7 + create mode 100644 test/results/updargs/extlinux4.2 + create mode 100644 test/results/updargs/extlinux4.3 + create mode 100644 test/results/updargs/extlinux4.4 + create mode 100644 test/results/updargs/extlinux4.5 + +diff --git a/test.sh b/test.sh +index 1d28fb1..734b755 100755 +--- a/test.sh ++++ b/test.sh +@@ -158,7 +158,7 @@ commandTest() { + + # generate convenience functions + for b in $(./grubby --help | \ +- sed -n 's/^.*--\([^ ]*\) *configure \1 bootloader$/\1/p'); do ++ sed -n 's/^.*--\([^ ]*\) *configure \1 bootloader.*/\1/p'); do + eval "${b}Test() { [[ \"$b\" == \$opt_bootloader ]] && oneTest --$b \"\$@\"; }" + eval "${b}DisplayTest() { [[ \"$b\" == \$opt_bootloader ]] && oneDisplayTest --$b \"\$@\"; }" + done +@@ -316,12 +316,24 @@ grubTest grub.5 fallback/g5.3 --remove-kernel=/boot/vmlinuz-2.4.7-2.5 \ + --boot-filesystem=/ --copy-default --add-kernel=/boot/new-kernel \ + --title="Some_Title" + ++testing="Extlinux default directive" ++extlinuxTest extlinux.1 default/extlinux1.1 --boot-filesystem=/boot --add-kernel /boot/new-kernel --title Some_Title ++extlinuxTest extlinux.1 default/extlinux1.2 --boot-filesystem=/boot --add-kernel /boot/new-kernel --title Some_Title --make-default ++extlinuxTest extlinux.3 default/extlinux3.1 --boot-filesystem=/boot --set-default=/boot/vmlinuz-3.12.0-2.fc21.i686 ++extlinuxTest extlinux.3 default/extlinux3.2 --boot-filesystem=/boot --set-default=/boot/vmlinuz-3.12.0-2.fc21.i686+PAE ++ + testing="GRUB new kernel argument handling" + grubTest grub.1 args/g1.1 --boot-filesystem=/boot \ + --add-kernel=/boot/foo --title=some_title --args="1234" --copy-default + grubTest grub.1 args/g1.2 --boot-filesystem=/boot \ + --add-kernel=/boot/foo --title=some_title --args="1234" + ++testing="Extlinux new kernel argument handling" ++extlinuxTest extlinux.1 args/extlinux1.1 --boot-filesystem=/boot \ ++ --add-kernel=/boot/foo --title=some_title --args="1234" --copy-default ++extlinuxTest extlinux.1 args/extlinux1.2 --boot-filesystem=/boot \ ++ --add-kernel=/boot/foo --title=some_title --args="1234" ++ + testing="GRUB remove kernel" + grubTest grub.7 remove/g7.1 --boot-filesystem=/ \ + --remove-kernel=/boot/vmlinuz-2.4.7-2.5 +@@ -339,6 +351,12 @@ testing="Z/IPL remove kernel" + ziplTest zipl.1 remove/z1.1 --remove-kernel=/boot/vmlinuz-2.4.9-38 + ziplTest zipl.1 remove/z1.2 --remove-kernel=DEFAULT + ++testing="Extlinux remove kernel" ++extlinuxTest extlinux.4 remove/extlinux4.1 --boot-filesystem=/ \ ++ --remove-kernel=/boot/vmlinuz-3.11.7-301.fc20.i686 ++extlinuxTest extlinux.3 remove/extlinux3.1 --boot-filesystem=/ \ ++ --remove-kernel=DEFAULT ++ + testing="GRUB update kernel argument handling" + grubTest grub.1 updargs/g1.1 --update-kernel=DEFAULT --args="root=/dev/hda1" + grubTest grub.1 updargs/g1.2 --update-kernel=DEFAULT \ +@@ -391,6 +409,30 @@ liloTest lilo.3 updargs/l3.1 --update-kernel=/boot/vmlinuz-2.4.18-4 \ + liloTest lilo.3 updargs/l3.2 --update-kernel=ALL \ + --remove-args="single" --args "root=/dev/hda2" + ++testing="Extlinux update kernel argument handling" ++extlinuxTest extlinux.1 updargs/extlinux1.1 --update-kernel=DEFAULT --args="root=/dev/hda1" ++extlinuxTest extlinux.1 updargs/extlinux1.2 --update-kernel=DEFAULT \ ++ --args="root=/dev/hda1 hda=ide-scsi root=/dev/hda2" ++extlinuxTest extlinux.3 updargs/extlinux3.1 --update-kernel=DEFAULT --args "hdd=notide-scsi" ++extlinuxTest extlinux.3 updargs/extlinux3.2 --update-kernel=DEFAULT \ ++ --args "hdd=notide-scsi root=/dev/hdd1" ++extlinuxTest extlinux.3 updargs/extlinux3.2 --update-kernel=DEFAULT \ ++ --args "root=/dev/hdd1 hdd=notide-scsi" ++extlinuxTest extlinux.3 updargs/extlinux3.4 --update-kernel=ALL --remove-args="hdd" ++extlinuxTest extlinux.3 updargs/extlinux3.4 --update-kernel=ALL --remove-args="hdd=ide-scsi" ++extlinuxTest extlinux.3 updargs/extlinux3.4 --update-kernel=ALL --remove-args="hdd=foobar" ++extlinuxTest extlinux.3 updargs/extlinux3.7 --update-kernel=ALL \ ++ --remove-args="hdd root ro" ++extlinuxTest extlinux.4 updargs/extlinux4.2 --boot-filesystem=/ \ ++ --update-kernel=ALL --args "hde=ide-scsi" ++extlinuxTest extlinux.4 updargs/extlinux4.3 --boot-filesystem=/ \ ++ --update-kernel=DEFAULT --args "hde=ide-scsi" ++extlinuxTest extlinux.4 updargs/extlinux4.4 --boot-filesystem=/ \ ++ --update-kernel=/vmlinuz-3.12.0-2.fc21.i686 \ ++ --args "ro root=LABEL=/ console=tty0 console=ttyS1,9600n81 single" ++extlinuxTest extlinux.4 updargs/extlinux4.5 --boot-filesystem=/ \ ++ --update-kernel=ALL --args "root=/dev/hda2" ++ + testing="LILO add kernel" + liloTest lilo.4 add/l4.1 --add-kernel=/boot/new-kernel.img --title="title" \ + --copy-default --boot-filesystem=/boot +@@ -577,6 +619,20 @@ testing="Z/IPL add kernel" + ziplTest zipl.1 add/z1.1 --add-kernel=/boot/new-kernel.img --title test + ziplTest zipl.1 add/z1.2 --add-kernel=/boot/new-kernel.img --title test --copy-default + ++testing="Extlinux add kernel" ++extlinuxTest extlinux.1 add/extlinux1.1 --add-kernel=/boot/new-kernel.img --title='title' \ ++ --initrd=/boot/new-initrd --boot-filesystem=/ ++extlinuxTest extlinux.1 add/extlinux1.2 --add-kernel=/boot/new-kernel.img --title='title' \ ++ --initrd=/boot/new-initrd --boot-filesystem=/boot ++extlinuxTest extlinux.1 add/extlinux1.3 --add-kernel=/boot/new-kernel.img --title='title' \ ++ --initrd=/boot/new-initrd --boot-filesystem=/ --copy-default ++extlinuxTest extlinux.1 add/extlinux1.4 --add-kernel=/boot/new-kernel.img --title='title' \ ++ --initrd=/boot/new-initrd --boot-filesystem=/boot --copy-default ++extlinuxTest extlinux.2 add/extlinux2.1 --add-kernel=/boot/vmlinuz-3.12.0-2.fc21.i686 \ ++ --initrd=/boot/initrd-3.12.0-2.fc21.i686-new.img --boot-filesystem=/boot --copy-default \ ++ --title="Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug)" \ ++ --remove-kernel="TITLE=Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug)" ++ + testing="LILO long titles" + liloTest lilo.1 longtitle/l1.1 --add-kernel=/boot/new-kernel.img \ + --title="linux-longtitle" --copy-default --boot-filesystem=/boot +diff --git a/test/extlinux.1 b/test/extlinux.1 +new file mode 100644 +index 0000000..85c9272 +--- /dev/null ++++ b/test/extlinux.1 +@@ -0,0 +1,17 @@ ++# extlinux.conf generated by anaconda ++ ++ui menu.c32 ++ ++menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options. ++menu title Fedora Boot Options. ++menu hidden ++ ++timeout 50 ++totaltimeout 9000 ++ ++default Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img +diff --git a/test/extlinux.2 b/test/extlinux.2 +new file mode 100644 +index 0000000..eae4aa7 +--- /dev/null ++++ b/test/extlinux.2 +@@ -0,0 +1,21 @@ ++# extlinux.conf generated by anaconda ++ ++ui menu.c32 ++ ++menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options. ++menu title Fedora Boot Options. ++menu hidden ++ ++timeout 50 ++totaltimeout 9000 ++ ++default Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/hda5 hdd=ide-scsi ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 +diff --git a/test/extlinux.3 b/test/extlinux.3 +new file mode 100644 +index 0000000..63f97bf +--- /dev/null ++++ b/test/extlinux.3 +@@ -0,0 +1,15 @@ ++prompt 0 ++ ++label Fedora (3.12.0-2.fc21.i686+PAE) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686+PAE ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686+PAE.img ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 +diff --git a/test/extlinux.4 b/test/extlinux.4 +new file mode 100644 +index 0000000..14b795c +--- /dev/null ++++ b/test/extlinux.4 +@@ -0,0 +1,32 @@ ++ui menu.c32 ++ ++menu hidden ++timeout 50 ++totaltimeout 9000 ++ ++prompt 10 ++default Fedora (3.13.0-0.rc0.git5.1.fc21.i686) 20 (Heisenbug) ++ ++label Fedora (3.11.7-300.fc20.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.11.7-300.fc20.i686 ++append ro root=/dev/hda6 ++initrd /boot/initrd-3.11.7-300.fc20.i686.img ++ ++label Fedora (3.11.7-301.fc20.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.11.7-301.fc20.i686 ++append ro root=/dev/hda6 ++initrd /boot/initrd-3.11.7-301.fc20.i686.img ++ ++label Fedora (3.13.0-0.rc0.git5.1.fc21.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.13.0-0.rc0.git5.1.fc21.i686 ++append ro root=/dev/hda6 ++initrd /boot/initrd-3.13.0-0.rc0.git5.1.fc21.i686.img ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 console=tty0 console=ttyS1,9600n81 ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 +diff --git a/test/results/add/extlinux1.1 b/test/results/add/extlinux1.1 +new file mode 100644 +index 0000000..f81a7ed +--- /dev/null ++++ b/test/results/add/extlinux1.1 +@@ -0,0 +1,20 @@ ++# extlinux.conf generated by anaconda ++ ++ui menu.c32 ++ ++menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options. ++menu title Fedora Boot Options. ++menu hidden ++ ++timeout 50 ++totaltimeout 9000 ++ ++default Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++ ++label title ++kernel /boot/new-kernel.img ++initrd /boot/new-initrd ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img +diff --git a/test/results/add/extlinux1.2 b/test/results/add/extlinux1.2 +new file mode 100644 +index 0000000..71e0437 +--- /dev/null ++++ b/test/results/add/extlinux1.2 +@@ -0,0 +1,20 @@ ++# extlinux.conf generated by anaconda ++ ++ui menu.c32 ++ ++menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options. ++menu title Fedora Boot Options. ++menu hidden ++ ++timeout 50 ++totaltimeout 9000 ++ ++default Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++ ++label title ++kernel /new-kernel.img ++initrd /new-initrd ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img +diff --git a/test/results/add/extlinux1.3 b/test/results/add/extlinux1.3 +new file mode 100644 +index 0000000..9634025 +--- /dev/null ++++ b/test/results/add/extlinux1.3 +@@ -0,0 +1,21 @@ ++# extlinux.conf generated by anaconda ++ ++ui menu.c32 ++ ++menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options. ++menu title Fedora Boot Options. ++menu hidden ++ ++timeout 50 ++totaltimeout 9000 ++ ++default Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++ ++label title ++kernel /boot/new-kernel.img ++append ro root=/dev/sda1 ++initrd /boot/new-initrd ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img +diff --git a/test/results/add/extlinux1.4 b/test/results/add/extlinux1.4 +new file mode 100644 +index 0000000..aa1ce63 +--- /dev/null ++++ b/test/results/add/extlinux1.4 +@@ -0,0 +1,21 @@ ++# extlinux.conf generated by anaconda ++ ++ui menu.c32 ++ ++menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options. ++menu title Fedora Boot Options. ++menu hidden ++ ++timeout 50 ++totaltimeout 9000 ++ ++default Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++ ++label title ++kernel /new-kernel.img ++append ro root=/dev/sda1 ++initrd /new-initrd ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img +diff --git a/test/results/add/extlinux2.1 b/test/results/add/extlinux2.1 +new file mode 100644 +index 0000000..13a4179 +--- /dev/null ++++ b/test/results/add/extlinux2.1 +@@ -0,0 +1,21 @@ ++# extlinux.conf generated by anaconda ++ ++ui menu.c32 ++ ++menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options. ++menu title Fedora Boot Options. ++menu hidden ++ ++timeout 50 ++totaltimeout 9000 ++ ++default Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/hda5 hdd=ide-scsi ++initrd /initrd-3.12.0-2.fc21.i686-new.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 +diff --git a/test/results/args/extlinux1.1 b/test/results/args/extlinux1.1 +new file mode 100644 +index 0000000..2d8c800 +--- /dev/null ++++ b/test/results/args/extlinux1.1 +@@ -0,0 +1,20 @@ ++# extlinux.conf generated by anaconda ++ ++ui menu.c32 ++ ++menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options. ++menu title Fedora Boot Options. ++menu hidden ++ ++timeout 50 ++totaltimeout 9000 ++ ++default Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++ ++label some_title ++kernel /foo ++append ro root=/dev/sda1 1234 ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img +diff --git a/test/results/args/extlinux1.2 b/test/results/args/extlinux1.2 +new file mode 100644 +index 0000000..41cc324 +--- /dev/null ++++ b/test/results/args/extlinux1.2 +@@ -0,0 +1,20 @@ ++# extlinux.conf generated by anaconda ++ ++ui menu.c32 ++ ++menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options. ++menu title Fedora Boot Options. ++menu hidden ++ ++timeout 50 ++totaltimeout 9000 ++ ++default Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++ ++label some_title ++kernel /foo ++append 1234 ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img +diff --git a/test/results/default/extlinux1.1 b/test/results/default/extlinux1.1 +new file mode 100644 +index 0000000..5d7f73d +--- /dev/null ++++ b/test/results/default/extlinux1.1 +@@ -0,0 +1,19 @@ ++# extlinux.conf generated by anaconda ++ ++ui menu.c32 ++ ++menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options. ++menu title Fedora Boot Options. ++menu hidden ++ ++timeout 50 ++totaltimeout 9000 ++ ++default Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++ ++label Some_Title ++kernel /new-kernel ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img +diff --git a/test/results/default/extlinux1.2 b/test/results/default/extlinux1.2 +new file mode 100644 +index 0000000..e98ff12 +--- /dev/null ++++ b/test/results/default/extlinux1.2 +@@ -0,0 +1,19 @@ ++# extlinux.conf generated by anaconda ++ ++ui menu.c32 ++ ++menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options. ++menu title Fedora Boot Options. ++menu hidden ++ ++timeout 50 ++totaltimeout 9000 ++ ++default Some_Title ++ ++label Some_Title ++kernel /new-kernel ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img +diff --git a/test/results/default/extlinux3.1 b/test/results/default/extlinux3.1 +new file mode 100644 +index 0000000..5a5495d +--- /dev/null ++++ b/test/results/default/extlinux3.1 +@@ -0,0 +1,16 @@ ++prompt 0 ++ ++default=Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++label Fedora (3.12.0-2.fc21.i686+PAE) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686+PAE ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686+PAE.img ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 +diff --git a/test/results/default/extlinux3.2 b/test/results/default/extlinux3.2 +new file mode 100644 +index 0000000..63f97bf +--- /dev/null ++++ b/test/results/default/extlinux3.2 +@@ -0,0 +1,15 @@ ++prompt 0 ++ ++label Fedora (3.12.0-2.fc21.i686+PAE) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686+PAE ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686+PAE.img ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 +diff --git a/test/results/remove/extlinux3.1 b/test/results/remove/extlinux3.1 +new file mode 100644 +index 0000000..12b4ef5 +--- /dev/null ++++ b/test/results/remove/extlinux3.1 +@@ -0,0 +1,10 @@ ++prompt 0 ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 +diff --git a/test/results/remove/extlinux4.1 b/test/results/remove/extlinux4.1 +new file mode 100644 +index 0000000..5e1824e +--- /dev/null ++++ b/test/results/remove/extlinux4.1 +@@ -0,0 +1,27 @@ ++ui menu.c32 ++ ++menu hidden ++timeout 50 ++totaltimeout 9000 ++ ++prompt 10 ++default Fedora (3.13.0-0.rc0.git5.1.fc21.i686) 20 (Heisenbug) ++ ++label Fedora (3.11.7-300.fc20.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.11.7-300.fc20.i686 ++append ro root=/dev/hda6 ++initrd /boot/initrd-3.11.7-300.fc20.i686.img ++ ++label Fedora (3.13.0-0.rc0.git5.1.fc21.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.13.0-0.rc0.git5.1.fc21.i686 ++append ro root=/dev/hda6 ++initrd /boot/initrd-3.13.0-0.rc0.git5.1.fc21.i686.img ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 console=tty0 console=ttyS1,9600n81 ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 +diff --git a/test/results/updargs/extlinux1.1 b/test/results/updargs/extlinux1.1 +new file mode 100644 +index 0000000..1e2a709 +--- /dev/null ++++ b/test/results/updargs/extlinux1.1 +@@ -0,0 +1,17 @@ ++# extlinux.conf generated by anaconda ++ ++ui menu.c32 ++ ++menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options. ++menu title Fedora Boot Options. ++menu hidden ++ ++timeout 50 ++totaltimeout 9000 ++ ++default Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/hda1 ++initrd /initrd-3.12.0-2.fc21.i686.img +diff --git a/test/results/updargs/extlinux1.2 b/test/results/updargs/extlinux1.2 +new file mode 100644 +index 0000000..764655a +--- /dev/null ++++ b/test/results/updargs/extlinux1.2 +@@ -0,0 +1,18 @@ ++# extlinux.conf generated by anaconda ++ ++ui menu.c32 ++ ++menu autoboot Welcome to Fedora. Automatic boot in # second{,s}. Press a key for options. ++menu title Fedora Boot Options. ++menu hidden ++ ++timeout 50 ++totaltimeout 9000 ++ ++default Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/hda1 hda=ide-scsi ++initrd /initrd-3.12.0-2.fc21.i686.img ++root /dev/hda2 +diff --git a/test/results/updargs/extlinux3.1 b/test/results/updargs/extlinux3.1 +new file mode 100644 +index 0000000..ef9fa86 +--- /dev/null ++++ b/test/results/updargs/extlinux3.1 +@@ -0,0 +1,15 @@ ++prompt 0 ++ ++label Fedora (3.12.0-2.fc21.i686+PAE) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686+PAE ++append ro root=/dev/sda1 hdd=notide-scsi ++initrd /initrd-3.12.0-2.fc21.i686+PAE.img ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 +diff --git a/test/results/updargs/extlinux3.2 b/test/results/updargs/extlinux3.2 +new file mode 100644 +index 0000000..c85b6bf +--- /dev/null ++++ b/test/results/updargs/extlinux3.2 +@@ -0,0 +1,15 @@ ++prompt 0 ++ ++label Fedora (3.12.0-2.fc21.i686+PAE) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686+PAE ++append ro root=/dev/hdd1 hdd=notide-scsi ++initrd /initrd-3.12.0-2.fc21.i686+PAE.img ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 +diff --git a/test/results/updargs/extlinux3.4 b/test/results/updargs/extlinux3.4 +new file mode 100644 +index 0000000..63f97bf +--- /dev/null ++++ b/test/results/updargs/extlinux3.4 +@@ -0,0 +1,15 @@ ++prompt 0 ++ ++label Fedora (3.12.0-2.fc21.i686+PAE) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686+PAE ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686+PAE.img ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 +diff --git a/test/results/updargs/extlinux3.7 b/test/results/updargs/extlinux3.7 +new file mode 100644 +index 0000000..b542ad3 +--- /dev/null ++++ b/test/results/updargs/extlinux3.7 +@@ -0,0 +1,13 @@ ++prompt 0 ++ ++label Fedora (3.12.0-2.fc21.i686+PAE) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686+PAE ++initrd /initrd-3.12.0-2.fc21.i686+PAE.img ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 +diff --git a/test/results/updargs/extlinux4.2 b/test/results/updargs/extlinux4.2 +new file mode 100644 +index 0000000..9bf16b7 +--- /dev/null ++++ b/test/results/updargs/extlinux4.2 +@@ -0,0 +1,32 @@ ++ui menu.c32 ++ ++menu hidden ++timeout 50 ++totaltimeout 9000 ++ ++prompt 10 ++default Fedora (3.13.0-0.rc0.git5.1.fc21.i686) 20 (Heisenbug) ++ ++label Fedora (3.11.7-300.fc20.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.11.7-300.fc20.i686 ++append ro root=/dev/hda6 hde=ide-scsi ++initrd /boot/initrd-3.11.7-300.fc20.i686.img ++ ++label Fedora (3.11.7-301.fc20.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.11.7-301.fc20.i686 ++append ro root=/dev/hda6 hde=ide-scsi ++initrd /boot/initrd-3.11.7-301.fc20.i686.img ++ ++label Fedora (3.13.0-0.rc0.git5.1.fc21.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.13.0-0.rc0.git5.1.fc21.i686 ++append ro root=/dev/hda6 hde=ide-scsi ++initrd /boot/initrd-3.13.0-0.rc0.git5.1.fc21.i686.img ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 console=tty0 console=ttyS1,9600n81 hde=ide-scsi ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 hde=ide-scsi +diff --git a/test/results/updargs/extlinux4.3 b/test/results/updargs/extlinux4.3 +new file mode 100644 +index 0000000..218711d +--- /dev/null ++++ b/test/results/updargs/extlinux4.3 +@@ -0,0 +1,32 @@ ++ui menu.c32 ++ ++menu hidden ++timeout 50 ++totaltimeout 9000 ++ ++prompt 10 ++default Fedora (3.13.0-0.rc0.git5.1.fc21.i686) 20 (Heisenbug) ++ ++label Fedora (3.11.7-300.fc20.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.11.7-300.fc20.i686 ++append ro root=/dev/hda6 ++initrd /boot/initrd-3.11.7-300.fc20.i686.img ++ ++label Fedora (3.11.7-301.fc20.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.11.7-301.fc20.i686 ++append ro root=/dev/hda6 ++initrd /boot/initrd-3.11.7-301.fc20.i686.img ++ ++label Fedora (3.13.0-0.rc0.git5.1.fc21.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.13.0-0.rc0.git5.1.fc21.i686 ++append ro root=/dev/hda6 hde=ide-scsi ++initrd /boot/initrd-3.13.0-0.rc0.git5.1.fc21.i686.img ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/sda1 console=tty0 console=ttyS1,9600n81 ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 +diff --git a/test/results/updargs/extlinux4.4 b/test/results/updargs/extlinux4.4 +new file mode 100644 +index 0000000..dc298fb +--- /dev/null ++++ b/test/results/updargs/extlinux4.4 +@@ -0,0 +1,32 @@ ++ui menu.c32 ++ ++menu hidden ++timeout 50 ++totaltimeout 9000 ++ ++prompt 10 ++default Fedora (3.13.0-0.rc0.git5.1.fc21.i686) 20 (Heisenbug) ++ ++label Fedora (3.11.7-300.fc20.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.11.7-300.fc20.i686 ++append ro root=/dev/hda6 ++initrd /boot/initrd-3.11.7-300.fc20.i686.img ++ ++label Fedora (3.11.7-301.fc20.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.11.7-301.fc20.i686 ++append ro root=/dev/hda6 ++initrd /boot/initrd-3.11.7-301.fc20.i686.img ++ ++label Fedora (3.13.0-0.rc0.git5.1.fc21.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.13.0-0.rc0.git5.1.fc21.i686 ++append ro root=/dev/hda6 ++initrd /boot/initrd-3.13.0-0.rc0.git5.1.fc21.i686.img ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=LABEL=/ console=tty0 console=ttyS1,9600n81 single ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 +diff --git a/test/results/updargs/extlinux4.5 b/test/results/updargs/extlinux4.5 +new file mode 100644 +index 0000000..6418a48 +--- /dev/null ++++ b/test/results/updargs/extlinux4.5 +@@ -0,0 +1,33 @@ ++ui menu.c32 ++ ++menu hidden ++timeout 50 ++totaltimeout 9000 ++ ++prompt 10 ++default Fedora (3.13.0-0.rc0.git5.1.fc21.i686) 20 (Heisenbug) ++ ++label Fedora (3.11.7-300.fc20.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.11.7-300.fc20.i686 ++append ro root=/dev/hda2 ++initrd /boot/initrd-3.11.7-300.fc20.i686.img ++ ++label Fedora (3.11.7-301.fc20.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.11.7-301.fc20.i686 ++append ro root=/dev/hda2 ++initrd /boot/initrd-3.11.7-301.fc20.i686.img ++ ++label Fedora (3.13.0-0.rc0.git5.1.fc21.i686) 20 (Heisenbug) ++kernel /boot/vmlinuz-3.13.0-0.rc0.git5.1.fc21.i686 ++append ro root=/dev/hda2 ++initrd /boot/initrd-3.13.0-0.rc0.git5.1.fc21.i686.img ++ ++label Fedora (3.12.0-2.fc21.i686) 20 (Heisenbug) ++kernel /vmlinuz-3.12.0-2.fc21.i686 ++append ro root=/dev/hda2 console=tty0 console=ttyS1,9600n81 ++initrd /initrd-3.12.0-2.fc21.i686.img ++ ++label DOS ++com32 chain.c32 ++append hd0 1 ++root /dev/hda2 +-- +2.4.3 + diff --git a/SOURCES/0012-Make-findTemplate-actually-return-the-saved-default.patch b/SOURCES/0012-Make-findTemplate-actually-return-the-saved-default.patch deleted file mode 100644 index 326c0ea..0000000 --- a/SOURCES/0012-Make-findTemplate-actually-return-the-saved-default.patch +++ /dev/null @@ -1,35 +0,0 @@ -From a045b730c7d5296097aab3b4194847165eed26dc Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 15 Sep 2014 14:31:01 -0400 -Subject: [PATCH 12/16] Make findTemplate actually return the saved default. - -Really not sure why this wasn't returning here before; going into the -loop below is just going to clobber all that it's done. - -Related: rhbz#957681 -Signed-off-by: Peter Jones ---- - grubby.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/grubby.c b/grubby.c -index 74818a2..6cfc5b7 100644 ---- a/grubby.c -+++ b/grubby.c -@@ -2108,8 +2108,12 @@ struct singleEntry * findTemplate(struct grubConfig * cfg, const char * prefix, - } else { - entry = findEntryByTitle(cfg, defTitle, &index); - } -- if (entry) -+ if (entry && suitableImage(entry, prefix, skipRemoved, flags)) { - cfg->defaultImage = index; -+ if (indexPtr) -+ *indexPtr = index; -+ return entry; -+ } - } - } - } else if (cfg->defaultImage > -1) { --- -1.9.3 - diff --git a/SOURCES/0012-grub-Fix-a-crash-with-kernel-line-without-being-prec.patch b/SOURCES/0012-grub-Fix-a-crash-with-kernel-line-without-being-prec.patch new file mode 100644 index 0000000..0bce24d --- /dev/null +++ b/SOURCES/0012-grub-Fix-a-crash-with-kernel-line-without-being-prec.patch @@ -0,0 +1,36 @@ +From ae451cb921126aa965abfe79c8716b7367c690de Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Wed, 27 Nov 2013 16:59:48 +0100 +Subject: [PATCH 12/41] grub: Fix a crash with kernel line without being + preceded by title + +Quite obviously this implies a broken configuration file where a lone kernel +line is found without ever seeing an entry start, resulting in a NULL +dereference attempt. Reproducible by running GRUB code against extlinux +configuration: + +./grubby --grub -c test/extlinux.1 --default-kernel +grubby received SIGSEGV! Backtrace (6): +... + +Signed-off-by: Lubomir Rintel +--- + grubby.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grubby.c b/grubby.c +index 21c5044..3cded58 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -1193,7 +1193,7 @@ static struct grubConfig * readConfig(const char * inName, + * lines came earlier in the template, make sure to use LT_HYPER + * instead of LT_KERNEL now + */ +- if (entry->multiboot) ++ if (entry && entry->multiboot) + line->type = LT_HYPER; + + } else if (line->type == LT_MBMODULE) { +-- +2.4.3 + diff --git a/SOURCES/0013-If-we-re-using-multiboot-add-a-new-mbmodule-not-an-i.patch b/SOURCES/0013-If-we-re-using-multiboot-add-a-new-mbmodule-not-an-i.patch deleted file mode 100644 index 371d59e..0000000 --- a/SOURCES/0013-If-we-re-using-multiboot-add-a-new-mbmodule-not-an-i.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 45561f504ef2329d0461b8d2c38447f54610f12e Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 12 Sep 2013 20:41:33 +0200 -Subject: [PATCH 13/16] If we're using multiboot, add a new mbmodule not an - initramfs - -I really don't know how this ever worked. -Related: rhbz#957681 - -Signed-off-by: Peter Jones ---- - grubby.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- - new-kernel-pkg | 3 ++- - 2 files changed, 47 insertions(+), 3 deletions(-) - -diff --git a/grubby.c b/grubby.c -index 6cfc5b7..c82ab00 100644 ---- a/grubby.c -+++ b/grubby.c -@@ -3281,6 +3281,42 @@ int updateImage(struct grubConfig * cfg, const char * image, - return rc; - } - -+int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel, -+ const char * image, const char * prefix, const char * initrd) { -+ struct singleEntry * entry; -+ struct singleLine * line, * kernelLine, *endLine = NULL; -+ int index = 0; -+ -+ if (!image) return 0; -+ -+ for (; (entry = findEntryByPath(cfg, newMBKernel, prefix, &index)); index++) { -+ kernelLine = getLineByType(LT_MBMODULE, entry->lines); -+ if (!kernelLine) continue; -+ -+ if (prefix) { -+ int prefixLen = strlen(prefix); -+ if (!strncmp(initrd, prefix, prefixLen)) -+ initrd += prefixLen; -+ } -+ endLine = getLineByType(LT_ENTRY_END, entry->lines); -+ if (endLine) -+ removeLine(entry, endLine); -+ line = addLine(entry, cfg->cfi, preferredLineType(LT_MBMODULE,cfg->cfi), -+ kernelLine->indent, initrd); -+ if (!line) -+ return 1; -+ if (endLine) { -+ line = addLine(entry, cfg->cfi, LT_ENTRY_END, "", NULL); -+ if (!line) -+ return 1; -+ } -+ -+ break; -+ } -+ -+ return 0; -+} -+ - int updateInitrd(struct grubConfig * cfg, const char * image, - const char * prefix, const char * initrd) { - struct singleEntry * entry; -@@ -4519,8 +4555,15 @@ int main(int argc, const char ** argv) { - if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, - removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1; - if (updateKernelPath && newKernelInitrd) { -- if (updateInitrd(config, updateKernelPath, bootPrefix, -- newKernelInitrd)) return 1; -+ if (newMBKernel) { -+ if (addMBInitrd(config, newMBKernel, updateKernelPath, -+ bootPrefix, newKernelInitrd)) -+ return 1; -+ } else { -+ if (updateInitrd(config, updateKernelPath, bootPrefix, -+ newKernelInitrd)) -+ return 1; -+ } - } - if (addNewKernel(config, template, bootPrefix, newKernelPath, - newKernelTitle, newKernelArgs, newKernelInitrd, -diff --git a/new-kernel-pkg b/new-kernel-pkg -index e6096ca..fe0d55a 100755 ---- a/new-kernel-pkg -+++ b/new-kernel-pkg -@@ -411,7 +411,8 @@ update() { - --update-kernel=$kernelImage \ - $INITRD \ - ${kernargs:+--args="$kernargs"} \ -- ${removeargs:+--remove-args="$removeargs"} -+ ${removeargs:+--remove-args="$removeargs"} \ -+ ${mbkernel:+--add-multiboot="$mbkernel"} - else - [ -n "$verbose" ] && echo "$grubConfig does not exist, not running grubby" - fi --- -1.9.3 - diff --git a/SOURCES/0013-grub-Remove-a-redundant-test.patch b/SOURCES/0013-grub-Remove-a-redundant-test.patch new file mode 100644 index 0000000..f57b7de --- /dev/null +++ b/SOURCES/0013-grub-Remove-a-redundant-test.patch @@ -0,0 +1,26 @@ +From 0a24262f5c59998ef75d72a1e0a698c33cd8dd28 Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Wed, 27 Nov 2013 16:59:47 +0100 +Subject: [PATCH 13/41] grub: Remove a redundant test + +Signed-off-by: Lubomir Rintel +--- + test.sh | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/test.sh b/test.sh +index 734b755..50a2d25 100755 +--- a/test.sh ++++ b/test.sh +@@ -373,8 +373,6 @@ grubTest grub.3 updargs/g3.7 --update-kernel=ALL \ + --remove-args="hdd root ro" + grubTest grub.7 updargs/g7.2 --boot-filesystem=/ \ + --update-kernel=ALL --args "hde=ide-scsi" +-grubTest grub.7 updargs/g7.2 --boot-filesystem=/ \ +- --update-kernel=ALL --args "hde=ide-scsi" + grubTest grub.7 updargs/g7.3 --boot-filesystem=/ \ + --update-kernel=DEFAULT --args "hde=ide-scsi" + grubTest grub.7 updargs/g7.4 --boot-filesystem=/ \ +-- +2.4.3 + diff --git a/SOURCES/0014-Fix-bad-check-for-new-kernel-pkg-s-command-line-argu.patch b/SOURCES/0014-Fix-bad-check-for-new-kernel-pkg-s-command-line-argu.patch new file mode 100644 index 0000000..550ff97 --- /dev/null +++ b/SOURCES/0014-Fix-bad-check-for-new-kernel-pkg-s-command-line-argu.patch @@ -0,0 +1,30 @@ +From be859414ba41001747b03b1066e2a198886041db Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 31 Mar 2014 13:59:34 -0400 +Subject: [PATCH 14/41] Fix bad check for new-kernel-pkg's command line + arguments. + +--devtree's argument needs to be nonempty, not just pass -f. +Resolves: rhbz#1082318 + +Signed-off-by: Peter Jones +--- + new-kernel-pkg | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/new-kernel-pkg b/new-kernel-pkg +index 97e1839..034fa3b 100755 +--- a/new-kernel-pkg ++++ b/new-kernel-pkg +@@ -153,7 +153,7 @@ install() { + fi + + DEVTREE="" +- if [ -f $devtreefile ]; then ++ if [ "x$devtreefile" != "x" -a -f $devtreefile ]; then + [ -n "$verbose" ] && echo "found $devtreefile and using it with grubby" + DEVTREE="--devtree $devtreefile" + fi +-- +2.4.3 + diff --git a/SOURCES/0014-Support-filtering-update-kernel-by-title-as-well.patch b/SOURCES/0014-Support-filtering-update-kernel-by-title-as-well.patch deleted file mode 100644 index 6013d96..0000000 --- a/SOURCES/0014-Support-filtering-update-kernel-by-title-as-well.patch +++ /dev/null @@ -1,106 +0,0 @@ -From dad65a1811412fb6b5e9e7211f8cf9d397732255 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 15 Sep 2014 15:18:48 -0400 -Subject: [PATCH 14/16] Support filtering --update-kernel= by title as well. - -If there are two entries with the same kernel, we need to match the -title to uniquely identify one. - -Related: rhbz#957681 -Signed-off-by: Peter Jones ---- - grubby.c | 40 +++++++++++++++++++++++++++++++++++----- - 1 file changed, 35 insertions(+), 5 deletions(-) - -diff --git a/grubby.c b/grubby.c -index c82ab00..24c6df0 100644 ---- a/grubby.c -+++ b/grubby.c -@@ -3282,7 +3282,8 @@ int updateImage(struct grubConfig * cfg, const char * image, - } - - int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel, -- const char * image, const char * prefix, const char * initrd) { -+ const char * image, const char * prefix, const char * initrd, -+ const char * title) { - struct singleEntry * entry; - struct singleLine * line, * kernelLine, *endLine = NULL; - int index = 0; -@@ -3293,6 +3294,20 @@ int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel, - kernelLine = getLineByType(LT_MBMODULE, entry->lines); - if (!kernelLine) continue; - -+ /* if title is supplied, the entry's title must match it. */ -+ if (title) { -+ line = getLineByType(LT_TITLE|LT_MENUENTRY, entry->lines); -+ char *linetitle = extractTitle(line); -+ -+ if (!linetitle) -+ continue; -+ if (strcmp(title, linetitle)) { -+ free(linetitle); -+ continue; -+ } -+ free(linetitle); -+ } -+ - if (prefix) { - int prefixLen = strlen(prefix); - if (!strncmp(initrd, prefix, prefixLen)) -@@ -3318,7 +3333,7 @@ int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel, - } - - int updateInitrd(struct grubConfig * cfg, const char * image, -- const char * prefix, const char * initrd) { -+ const char * prefix, const char * initrd, const char * title) { - struct singleEntry * entry; - struct singleLine * line, * kernelLine, *endLine = NULL; - int index = 0; -@@ -3329,6 +3344,20 @@ int updateInitrd(struct grubConfig * cfg, const char * image, - kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); - if (!kernelLine) continue; - -+ /* if title is supplied, the entry's title must match it. */ -+ if (title) { -+ line = getLineByType(LT_TITLE|LT_MENUENTRY, entry->lines); -+ char *linetitle = extractTitle(line); -+ -+ if (!linetitle) -+ continue; -+ if (strcmp(title, linetitle)) { -+ free(linetitle); -+ continue; -+ } -+ free(linetitle); -+ } -+ - line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines); - if (line) - removeLine(entry, line); -@@ -4335,7 +4364,7 @@ int main(int argc, const char ** argv) { - if (newKernelPath && !newKernelTitle) { - fprintf(stderr, _("grubby: kernel title must be specified\n")); - return 1; -- } else if (!newKernelPath && (newKernelTitle || copyDefault || -+ } else if (!newKernelPath && (copyDefault || - (newKernelInitrd && !updateKernelPath)|| - makeDefault || extraInitrdCount > 0)) { - fprintf(stderr, _("grubby: kernel path expected\n")); -@@ -4557,11 +4586,12 @@ int main(int argc, const char ** argv) { - if (updateKernelPath && newKernelInitrd) { - if (newMBKernel) { - if (addMBInitrd(config, newMBKernel, updateKernelPath, -- bootPrefix, newKernelInitrd)) -+ bootPrefix, newKernelInitrd, -+ newKernelTitle)) - return 1; - } else { - if (updateInitrd(config, updateKernelPath, bootPrefix, -- newKernelInitrd)) -+ newKernelInitrd, newKernelTitle)) - return 1; - } - } --- -1.9.3 - diff --git a/SOURCES/0015-If-we-re-on-a-zipl-based-platform-use-banner-passed-.patch b/SOURCES/0015-If-we-re-on-a-zipl-based-platform-use-banner-passed-.patch deleted file mode 100644 index 0da9743..0000000 --- a/SOURCES/0015-If-we-re-on-a-zipl-based-platform-use-banner-passed-.patch +++ /dev/null @@ -1,55 +0,0 @@ -From f4ba2c9deba2a6575668c1c602621b3f596a7ea6 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 22 Jan 2014 17:16:06 -0500 -Subject: [PATCH 15/16] If we're on a zipl-based platform, use --banner passed - to us (sanitized.) - -"lilo" type bootloaders have gotten $version as their title since -forever, but on zipl that'll cause collisions when creating extra boot -images with the same version. So on that platform, choose to honor ---banner even though it has a lot of limitations, and attempt to get rid -of spaces in the result to avoid some of those problems. - -Related: rhbz#1032048 - -Signed-off-by: Peter Jones ---- - new-kernel-pkg | 14 ++++++++++---- - 1 file changed, 10 insertions(+), 4 deletions(-) - -diff --git a/new-kernel-pkg b/new-kernel-pkg -index fe0d55a..d9a9b67 100755 ---- a/new-kernel-pkg -+++ b/new-kernel-pkg -@@ -186,10 +186,16 @@ install() { - - - if [ -n "$banner" ]; then -- title="$banner ($version)" -+ if [ $ARCH = 's390' -o $ARCH = 's390x' ]; then -+ title=$(echo $banner | sed 's/ /_/g') -+ else -+ title="$banner ($version)" -+ fi -+ elif [ $ARCH = 's390' -o $ARCH = 's390x' ]; then -+ title=$(echo $version | sed 's/ /_/g') - elif [ -f /etc/os-release ]; then -- . /etc/os-release -- title="$NAME ($version) $VERSION" -+ . /etc/os-release -+ title="$NAME ($version) $VERSION" - elif [ -f /etc/redhat-release ]; then - title="$(sed 's/ release.*$//' < /etc/redhat-release) ($version)" - else -@@ -237,7 +243,7 @@ install() { - [ -n "$verbose" ] && echo "adding $version to $liloConfig" - - $grubby --add-kernel=$kernelImage $INITRD \ -- --copy-default $makedefault --title $version \ -+ --copy-default $makedefault --title "$title" \ - ${mbkernel:+--add-multiboot="$mbkernel"} ${mbargs:+--mbargs="$mbargs"} \ - --args="root=$rootdevice $kernargs" --remove-kernel="TITLE=$version" \ - --$liloFlag --- -1.9.3 - diff --git a/SOURCES/0015-Previous-ARM-64-bit-test-had-the-wrong-compiler-defi.patch b/SOURCES/0015-Previous-ARM-64-bit-test-had-the-wrong-compiler-defi.patch new file mode 100644 index 0000000..ccf1bd8 --- /dev/null +++ b/SOURCES/0015-Previous-ARM-64-bit-test-had-the-wrong-compiler-defi.patch @@ -0,0 +1,29 @@ +From 6e88cbad1b01fba9f849dfeea0d88d2a49d6c255 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 31 Mar 2014 15:43:10 -0400 +Subject: [PATCH 15/41] Previous ARM 64-bit test had the wrong compiler define + for aarch64. + +Yet one more reason that arch name is an incredibly stupid idea. + +Signed-off-by: Peter Jones +--- + grubby.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grubby.c b/grubby.c +index 3cded58..3485d4e 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -60,7 +60,7 @@ int debug = 0; /* Currently just for template debugging */ + + int isEfi = 0; + +-#if defined(__arch64__) ++#if defined(__aarch64__) + #define isEfiOnly 1 + #else + #define isEfiOnly 0 +-- +2.4.3 + diff --git a/SOURCES/0016-Actually-do-a-fix-for-rhbz-1082318-that-fixes-the-is.patch b/SOURCES/0016-Actually-do-a-fix-for-rhbz-1082318-that-fixes-the-is.patch new file mode 100644 index 0000000..cbf5734 --- /dev/null +++ b/SOURCES/0016-Actually-do-a-fix-for-rhbz-1082318-that-fixes-the-is.patch @@ -0,0 +1,32 @@ +From 1c21e19ae3847f7ca25d466c5af04d0137a28f36 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 1 Apr 2014 08:48:09 -0400 +Subject: [PATCH 16/41] Actually do a fix for rhbz#1082318 that fixes the issue + there. + +News: after all these years I'm still terrible at shell scripts, just +like everybody else. + +Related: rhbz#1063534 + +Signed-off-by: Peter Jones +--- + new-kernel-pkg | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/new-kernel-pkg b/new-kernel-pkg +index 034fa3b..d9a9b67 100755 +--- a/new-kernel-pkg ++++ b/new-kernel-pkg +@@ -153,7 +153,7 @@ install() { + fi + + DEVTREE="" +- if [ "x$devtreefile" != "x" -a -f $devtreefile ]; then ++ if [ "x$devtreefile" != "x" -a -f "$devtreefile" ]; then + [ -n "$verbose" ] && echo "found $devtreefile and using it with grubby" + DEVTREE="--devtree $devtreefile" + fi +-- +2.4.3 + diff --git a/SOURCES/0016-Conditionally-create-debug-entries-when-installing-k.patch b/SOURCES/0016-Conditionally-create-debug-entries-when-installing-k.patch deleted file mode 100644 index 18af0f4..0000000 --- a/SOURCES/0016-Conditionally-create-debug-entries-when-installing-k.patch +++ /dev/null @@ -1,310 +0,0 @@ -From 3639952b57652657a316de0d170d93fc7a34b20a Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 15 Sep 2014 15:20:34 -0400 -Subject: [PATCH 16/16] Conditionally create debug entries when installing - kernels. - -if /etc/sysconfig/kernel has MAKEDEBUG set to "yes", create non-default -entries that have systemd.debug set. - -Resolves: rhbz#957681 -Signed-off-by: Peter Jones ---- - new-kernel-pkg | 190 ++++++++++++++++++++++++++++++++++++--------------------- - 1 file changed, 119 insertions(+), 71 deletions(-) - -diff --git a/new-kernel-pkg b/new-kernel-pkg -index d9a9b67..70f6118 100755 ---- a/new-kernel-pkg -+++ b/new-kernel-pkg -@@ -50,6 +50,7 @@ grubConfig="" - grub2Config="" - grub2EfiConfig="" - extlinuxConfig="" -+ubootScript="/boot/boot.scr" - - ARCH=$(uname -m) - -@@ -120,6 +121,7 @@ mbkernel="$HYPERVISOR" - mbargs="$HYPERVISOR_ARGS" - adddracutargs="" - addplymouthinitrd="" -+DEBUGARG="systemd.debug" - - usage() { - echo "Usage: `basename $0` [-v] [--mkinitrd] [--rminitrd] [--dracut]" >&2 -@@ -134,6 +136,41 @@ usage() { - exit 1 - } - -+rungrubby() { -+ if [ "$1" == "--debug" ]; then -+ [ "$MAKEDEBUG" != "yes" ] && return 0 -+ [ -n "$verbose" ] && echo "- First, making a debug entry." -+ declare -x debugtitle=" with debugging" -+ declare -x debugargs="$DEBUGARG" -+ shift -+ else -+ [ -n "$verbose" ] && echo "- Making a normal entry." -+ fi -+ $(eval $grubby $@) -+ export -n debugargs -+ export -n debugtitle -+ unset debugargs -+ unset debugtitle -+} -+ -+set_title() { -+ if [ -n "$banner" ]; then -+ if [ $ARCH = 's390' -o $ARCH = 's390x' ]; then -+ title=$(echo $banner | sed 's/ /_/g') -+ else -+ title="$banner ($version)" -+ fi -+ elif [ $ARCH = 's390' -o $ARCH = 's390x' ]; then -+ title=$(echo $version | sed 's/ /_/g') -+ elif [ -f /etc/os-release ]; then -+ . /etc/os-release -+ title="$NAME ($version) $VERSION" -+ elif [ -f /etc/redhat-release ]; then -+ title="$(sed 's/ release.*$//' < /etc/redhat-release) ($version)" -+ else -+ title="Red Hat Linux ($version)" -+ fi -+} - - install() { - # XXX kernel should be able to be specified also (or work right on ia64) -@@ -184,57 +221,49 @@ install() { - cfgLilo="" - fi - -- -- if [ -n "$banner" ]; then -- if [ $ARCH = 's390' -o $ARCH = 's390x' ]; then -- title=$(echo $banner | sed 's/ /_/g') -- else -- title="$banner ($version)" -- fi -- elif [ $ARCH = 's390' -o $ARCH = 's390x' ]; then -- title=$(echo $version | sed 's/ /_/g') -- elif [ -f /etc/os-release ]; then -- . /etc/os-release -- title="$NAME ($version) $VERSION" -- elif [ -f /etc/redhat-release ]; then -- title="$(sed 's/ release.*$//' < /etc/redhat-release) ($version)" -- else -- title="Red Hat Linux ($version)" -- fi -- -+ set_title - - if [ -n "$cfgGrub" ]; then - [ -n "$verbose" ] && echo "adding $version to $grubConfig" - -- $grubby --grub -c $grubConfig \ -- --add-kernel=$kernelImage \ -- $INITRD --copy-default $makedefault --title "$title" \ -- ${mbkernel:+--add-multiboot="$mbkernel"} ${mbargs:+--mbargs="$mbargs"} \ -- --args="root=$rootdevice $kernargs" --remove-kernel="TITLE=$title" -+ ARGS="--grub -c $grubConfig --add-kernel=$kernelImage $INITRD \ -+ ${mbkernel:+--add-multiboot=\"$mbkernel\"} \ -+ ${mbargs:+--mbargs=\"$mbargs\"} \ -+ --title=\"$title\$debugtitle\" --copy-default \ -+ --args=\"root=$rootdevice $kernargs \$debugargs\" \ -+ --remove-kernel=\"TITLE=$title\$debugtitle\"" -+ -+ rungrubby --debug ${ARGS} -+ rungrubby ${ARGS} $makedefault - else - [ -n "$verbose" ] && echo "$grubConfig does not exist, not running grubby for grub 0.97" - fi - if [ -n "$cfgGrub2" ]; then - [ -n "$verbose" ] && echo "adding $version to $grub2Config" - -- $grubby --grub2 -c $grub2Config \ -- --add-kernel=$kernelImage \ -- $INITRD --copy-default $makedefault --title "$title" \ -- ${mbkernel:+--add-multiboot="$mbkernel"} \ -- ${mbargs:+--mbargs="$mbargs"} \ -- --args="root=$rootdevice $kernargs" --remove-kernel="TITLE=$title" -+ ARGS="--grub2 -c $grub2Config --add-kernel=$kernelImage $INITRD \ -+ --copy-default --title \"$title\$debugtitle\" \ -+ ${mbkernel:+--add-multiboot=\"$mbkernel\"} \ -+ ${mbargs:+--mbargs=\"$mbargs\"} \ -+ --args=\"root=$rootdevice $kernargs \$debugargs\" \ -+ --remove-kernel=\"TITLE=$title\$debugtitle\"" -+ rungrubby --debug ${ARGS} -+ rungrubby ${ARGS} $makedefault - else - [ -n "$verbose" ] && echo "$grub2Config does not exist, not running grubby for grub 2" - fi - if [ -n "$cfgGrub2Efi" ]; then - [ -n "$verbose" ] && echo "adding $version to $grub2EfiConfig" - -- $grubby --grub2 -c $grub2EfiConfig --efi \ -- --add-kernel=$kernelImage $DEVTREE \ -- $INITRD --copy-default $makedefault --title "$title" \ -- ${mbkernel:+--add-multiboot="$mbkernel"} \ -- ${mbargs:+--mbargs="$mbargs"} \ -- --args="root=$rootdevice $kernargs" --remove-kernel="TITLE=$title" -+ ARGS="--grub2 -c $grub2EfiConfig --efi \ -+ --add-kernel=$kernelImage $DEVTREE $INITRD \ -+ --copy-default --title \"$title\$debugtitle\" \ -+ ${mbkernel:+--add-multiboot=\"$mbkernel\"} \ -+ ${mbargs:+--mbargs=\"$mbargs\"} \ -+ --args=\"root=$rootdevice $kernargs \$debugargs\" \ -+ --remove-kernel=\"TITLE=$title\$debugtitle\"" -+ rungrubby --debug ${ARGS} -+ rungrubby ${ARGS} $makedefault - else - [ -n "$verbose" ] && echo "$grub2EfiConfig does not exist, not running grubby for grub 2 with UEFI" - fi -@@ -242,12 +271,15 @@ install() { - if [ -n "$cfgLilo" ]; then - [ -n "$verbose" ] && echo "adding $version to $liloConfig" - -- $grubby --add-kernel=$kernelImage $INITRD \ -- --copy-default $makedefault --title "$title" \ -- ${mbkernel:+--add-multiboot="$mbkernel"} ${mbargs:+--mbargs="$mbargs"} \ -- --args="root=$rootdevice $kernargs" --remove-kernel="TITLE=$version" \ -- --$liloFlag -+ ARGS="--$liloFlag --add-kernel=$kernelImage $INITRD \ -+ --copy-default --title \"$title\$debugtitle\" \ -+ ${mbkernel:+--add-multiboot=\"$mbkernel\"} \ -+ ${mbargs:+--mbargs=\"$mbargs\"} \ -+ --args=\"root=$rootdevice $kernargs \$debugargs\" \ -+ --remove-kernel=\"TITLE=$version\"" - -+ rungrubby --debug ${ARGS} -+ rungrubby ${ARGS} $makedefault - if [ -n "$runLilo" ]; then - [ -n "$verbose" ] && echo "running $lilo" - if [ ! -x $lilo ] ; then -@@ -263,11 +295,15 @@ install() { - if [ -n "$cfgExtlinux" ]; then - [ -n "$verbose" ] && echo "adding $version to $extlinuxConfig" - -- $grubby --extlinux -c $extlinuxConfig \ -- --add-kernel=$kernelImage \ -- $INITRD --copy-default $makedefault --title "$title" \ -- ${mbkernel:+--add-multiboot="$mbkernel"} ${mbargs:+--mbargs="$mbargs"} \ -- --args="root=$rootdevice $kernargs" --remove-kernel="TITLE=$title" -+ ARGS="--extlinux -c $extlinuxConfig --add-kernel=$kernelImage \ -+ $INITRD --copy-default --title \"$title\$debugtitle\" \ -+ ${mbkernel:+--add-multiboot=\"$mbkernel\"} \ -+ ${mbargs:+--mbargs=\"$mbargs\"} \ -+ --args=\"root=$rootdevice $kernargs \$debugargs\" \ -+ --remove-kernel=\"TITLE=$title\$debugtitle\"" -+ -+ rungrubby --debug ${ARGS} -+ rungrubby ${ARGS} $makedefault - else - [ -n "$verbose" ] && echo "$extlinuxConfig does not exist, not running grubby for extlinux" - fi -@@ -401,6 +437,8 @@ update() { - return - fi - -+ set_title -+ - INITRD="" - if [ -f $initrdfile ]; then - [ -n "$verbose" ] && echo "found $initrdfile and using it with grubby" -@@ -413,45 +451,53 @@ update() { - - if [ -n "$cfgGrub" ]; then - [ -n "$verbose" ] && echo "updating $version from $grubConfig" -- $grubby --grub -c $grubConfig \ -- --update-kernel=$kernelImage \ -- $INITRD \ -- ${kernargs:+--args="$kernargs"} \ -- ${removeargs:+--remove-args="$removeargs"} \ -- ${mbkernel:+--add-multiboot="$mbkernel"} -+ ARGS="--grub -c $grubConfig --update-kernel=$kernelImage $INITRD \ -+ ${kernargs:+--args=\"$kernargs\"} \ -+ ${removeargs:+--remove-args=\"$removeargs\"} \ -+ ${mbkernel:+--add-multiboot=\"$mbkernel\"} \ -+ --title=\"$title\$debugtitle\"" -+ -+ rungrubby --debug ${ARGS} -+ rungrubby ${ARGS} - else - [ -n "$verbose" ] && echo "$grubConfig does not exist, not running grubby" - fi - - if [ -n "$cfgGrub2" ]; then - [ -n "$verbose" ] && echo "updating $version from $grub2Config" -- $grubby --grub2 -c $grub2Config \ -- --update-kernel=$kernelImage \ -- $INITRD \ -- ${kernargs:+--args="$kernargs"} \ -- ${removeargs:+--remove-args="$removeargs"} -+ ARGS="--grub2 -c $grub2Config --update-kernel=$kernelImage $INITRD \ -+ ${kernargs:+--args=\"$kernargs\"} \ -+ ${removeargs:+--remove-args=\"$removeargs\"} \ -+ --title=\"$title\$debugtitle\"" -+ -+ rungrubby --debug ${ARGS} -+ rungrubby ${ARGS} - else - [ -n "$verbose" ] && echo "$grub2Config does not exist, not running grubby" - fi - - if [ -n "$cfgGrub2Efi" ]; then - [ -n "$verbose" ] && echo "updating $version from $grub2EfiConfig" -- $grubby --grub2 -c $grub2EfiConfig --efi \ -- --update-kernel=$kernelImage \ -- $INITRD \ -- ${kernargs:+--args="$kernargs"} \ -- ${removeargs:+--remove-args="$removeargs"} -+ ARGS="--grub2 -c $grub2EfiConfig --efi --update-kernel=$kernelImage \ -+ $INITRD ${kernargs:+--args=\"$kernargs\"} \ -+ ${removeargs:+--remove-args=\"$removeargs\"} \ -+ --title=\"$title\$debugtitle\"" -+ -+ rungrubby --debug ${ARGS} -+ rungrubby ${ARGS} - else - [ -n "$verbose" ] && echo "$grub2EfiConfig does not exist, not running grubby" - fi - - if [ -n "$cfgLilo" ]; then - [ -n "$verbose" ] && echo "updating $version from $liloConfig" -- $grubby --update-kernel=$kernelImage \ -- $INITRD \ -- ${kernargs:+--args="$kernargs"} \ -- ${removeargs:+--remove-args="$removeargs"} \ -- --$liloFlag -+ ARGS="--$liloFlag --update-kernel=$kernelImage $INITRD \ -+ ${kernargs:+--args=\"$kernargs\"} \ -+ ${removeargs:+--remove-args=\"$removeargs\"} \ -+ --title=\"$title\$debugtitle\"" -+ -+ rungrubby --debug ${ARGS} -+ rungrubby ${ARGS} - - if [ -n "$runLilo" ]; then - [ -n "$verbose" ] && echo "running $lilo" -@@ -497,11 +543,13 @@ update() { - - if [ -n "$cfgExtlinux" ]; then - [ -n "$verbose" ] && echo "updating $version from $extlinuxConfig" -- $grubby --extlinux -c $extlinuxConfig \ -- --update-kernel=$kernelImage \ -- $INITRD \ -- ${kernargs:+--args="$kernargs"} \ -- ${removeargs:+--remove-args="$removeargs"} -+ ARGS="--extlinux -c $extlinuxConfig --update-kernel=$kernelImage \ -+ $INITRD ${kernargs:+--args=\"$kernargs\"} \ -+ ${removeargs:+--remove-args=\"$removeargs\"} \ -+ --title=\"$title\$debugtitle\"" -+ -+ rungrubby --debug ${ARGS} -+ rungrubby ${ARGS} - else - [ -n "$verbose" ] && echo "$extlinuxConfig does not exist, not running grubby" - fi --- -1.9.3 - diff --git a/SOURCES/0017-Strip-the-LT_END-line-from-a-new-stanza-before-addin.patch b/SOURCES/0017-Strip-the-LT_END-line-from-a-new-stanza-before-addin.patch new file mode 100644 index 0000000..d4ace8c --- /dev/null +++ b/SOURCES/0017-Strip-the-LT_END-line-from-a-new-stanza-before-addin.patch @@ -0,0 +1,313 @@ +From c898c55191a129aade1ed8c3419996074b6f5ab9 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 21 May 2014 16:40:23 -0400 +Subject: [PATCH 17/41] Strip the LT_END line from a new stanza before adding + "missing" parts. + +When we get --copy-default on a --add-kernel with a --initrd option, and +the default stanza lacks an initrd, we wind up in the fallback path +where we add the default after the fact. When we do this, we later add +an LT_END line /if/ it doesn't exist. But we've already got one, and +when we add the initrd it's after it. + +So strip it out and re-mark it as needed so it'll be added at the end. + +Resolves: rhbz#1099627 +Related: rhbz#1096358 + +Signed-off-by: Peter Jones +--- + grubby.c | 7 +++ + test.sh | 5 ++ + test/grub2.14 | 111 +++++++++++++++++++++++++++++++++++++++++ + test/results/add/g2-1.14 | 126 +++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 249 insertions(+) + create mode 100644 test/grub2.14 + create mode 100644 test/results/add/g2-1.14 + +diff --git a/grubby.c b/grubby.c +index 3485d4e..4516b92 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -4014,6 +4014,13 @@ int addNewKernel(struct grubConfig * config, struct singleEntry * template, + } + } + ++ struct singleLine *endLine = NULL; ++ endLine = getLineByType(LT_ENTRY_END, new->lines); ++ if (endLine) { ++ removeLine(new, endLine); ++ needs |= NEED_END; ++ } ++ + /* add the remainder of the lines, i.e. those that either + * weren't present in the template, or in the case of no template, + * all the lines following the entryStart. +diff --git a/test.sh b/test.sh +index 50a2d25..57e4926 100755 +--- a/test.sh ++++ b/test.sh +@@ -511,6 +511,11 @@ if [ "$testgrub2" == "y" ]; then + grub2Test grub2.5 add/g2-1.5 --add-kernel=/boot/new-kernel.img \ + --title='title' --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ + --copy-default ++ grub2Test grub2.14 add/g2-1.14 \ ++ --add-kernel=/boot/vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 \ ++ --initrd /boot/initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img \ ++ --copy-default --title "Fedora 21 Rescue" --args=root=/fooooo \ ++ --remove-kernel=wtf + + testing="GRUB2 add initrd" + grub2Test grub2.2 add/g2-1.4 --update-kernel=/boot/new-kernel.img \ +diff --git a/test/grub2.14 b/test/grub2.14 +new file mode 100644 +index 0000000..cb0304e +--- /dev/null ++++ b/test/grub2.14 +@@ -0,0 +1,111 @@ ++# ++# DO NOT EDIT THIS FILE ++# ++# It is automatically generated by grub2-mkconfig using templates ++# from /etc/grub.d and settings from /etc/default/grub ++# ++ ++### BEGIN /etc/grub.d/00_header ### ++set pager=1 ++ ++if [ -s $prefix/grubenv ]; then ++ load_env ++fi ++if [ "${next_entry}" ] ; then ++ set default="${next_entry}" ++ set next_entry= ++ save_env next_entry ++ set boot_once=true ++else ++ set default="${saved_entry}" ++fi ++ ++if [ x"${feature_menuentry_id}" = xy ]; then ++ menuentry_id_option="--id" ++else ++ menuentry_id_option="" ++fi ++ ++export menuentry_id_option ++ ++if [ "${prev_saved_entry}" ]; then ++ set saved_entry="${prev_saved_entry}" ++ save_env saved_entry ++ set prev_saved_entry= ++ save_env prev_saved_entry ++ set boot_once=true ++fi ++ ++function savedefault { ++ if [ -z "${boot_once}" ]; then ++ saved_entry="${chosen}" ++ save_env saved_entry ++ fi ++} ++ ++function load_video { ++ if [ x$feature_all_video_module = xy ]; then ++ insmod all_video ++ else ++ insmod efi_gop ++ insmod efi_uga ++ insmod ieee1275_fb ++ insmod vbe ++ insmod vga ++ insmod video_bochs ++ insmod video_cirrus ++ fi ++} ++ ++terminal_output console ++if [ x$feature_timeout_style = xy ] ; then ++ set timeout_style=menu ++ set timeout=5 ++# Fallback normal timeout code in case the timeout_style feature is ++# unavailable. ++else ++ set timeout=5 ++fi ++### END /etc/grub.d/00_header ### ++ ++### BEGIN /etc/grub.d/10_linux ### ++menuentry 'Fedora, with Linux 3.15.0-0.rc5.git2.10.fc21.x86_64' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.15.0-0.rc5.git2.10.fc21.x86_64-advanced-a14e3dcb-ade3-42f7-832f-d9f66b5ae6a3' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod ext2 ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ else ++ search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ fi ++ linux16 /vmlinuz-3.15.0-0.rc5.git2.10.fc21.x86_64 root=/dev/mapper/fedora_uefi-root ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++} ++ ++### END /etc/grub.d/10_linux ### ++ ++### BEGIN /etc/grub.d/20_linux_xen ### ++ ++### END /etc/grub.d/20_linux_xen ### ++ ++### BEGIN /etc/grub.d/20_ppc_terminfo ### ++### END /etc/grub.d/20_ppc_terminfo ### ++ ++### BEGIN /etc/grub.d/30_os-prober ### ++### END /etc/grub.d/30_os-prober ### ++ ++### BEGIN /etc/grub.d/40_custom ### ++# This file provides an easy way to add custom menu entries. Simply type the ++# menu entries you want to add after this comment. Be careful not to change ++# the 'exec tail' line above. ++### END /etc/grub.d/40_custom ### ++ ++### BEGIN /etc/grub.d/41_custom ### ++if [ -f ${config_directory}/custom.cfg ]; then ++ source ${config_directory}/custom.cfg ++elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then ++ source $prefix/custom.cfg; ++fi ++### END /etc/grub.d/41_custom ### +diff --git a/test/results/add/g2-1.14 b/test/results/add/g2-1.14 +new file mode 100644 +index 0000000..0865bbc +--- /dev/null ++++ b/test/results/add/g2-1.14 +@@ -0,0 +1,126 @@ ++# ++# DO NOT EDIT THIS FILE ++# ++# It is automatically generated by grub2-mkconfig using templates ++# from /etc/grub.d and settings from /etc/default/grub ++# ++ ++### BEGIN /etc/grub.d/00_header ### ++set pager=1 ++ ++if [ -s $prefix/grubenv ]; then ++ load_env ++fi ++if [ "${next_entry}" ] ; then ++ set default="${next_entry}" ++ set next_entry= ++ save_env next_entry ++ set boot_once=true ++else ++ set default="${saved_entry}" ++fi ++ ++if [ x"${feature_menuentry_id}" = xy ]; then ++ menuentry_id_option="--id" ++else ++ menuentry_id_option="" ++fi ++ ++export menuentry_id_option ++ ++if [ "${prev_saved_entry}" ]; then ++ set saved_entry="${prev_saved_entry}" ++ save_env saved_entry ++ set prev_saved_entry= ++ save_env prev_saved_entry ++ set boot_once=true ++fi ++ ++function savedefault { ++ if [ -z "${boot_once}" ]; then ++ saved_entry="${chosen}" ++ save_env saved_entry ++ fi ++} ++ ++function load_video { ++ if [ x$feature_all_video_module = xy ]; then ++ insmod all_video ++ else ++ insmod efi_gop ++ insmod efi_uga ++ insmod ieee1275_fb ++ insmod vbe ++ insmod vga ++ insmod video_bochs ++ insmod video_cirrus ++ fi ++} ++ ++terminal_output console ++if [ x$feature_timeout_style = xy ] ; then ++ set timeout_style=menu ++ set timeout=5 ++# Fallback normal timeout code in case the timeout_style feature is ++# unavailable. ++else ++ set timeout=5 ++fi ++### END /etc/grub.d/00_header ### ++ ++### BEGIN /etc/grub.d/10_linux ### ++menuentry 'Fedora 21 Rescue' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.15.0-0.rc5.git2.10.fc21.x86_64-advanced-a14e3dcb-ade3-42f7-832f-d9f66b5ae6a3' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod ext2 ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ else ++ search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ fi ++ linux16 /vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 root=/fooooo ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++ initrd16 /initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img ++} ++menuentry 'Fedora, with Linux 3.15.0-0.rc5.git2.10.fc21.x86_64' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.15.0-0.rc5.git2.10.fc21.x86_64-advanced-a14e3dcb-ade3-42f7-832f-d9f66b5ae6a3' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod ext2 ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ else ++ search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ fi ++ linux16 /vmlinuz-3.15.0-0.rc5.git2.10.fc21.x86_64 root=/dev/mapper/fedora_uefi-root ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++} ++ ++### END /etc/grub.d/10_linux ### ++ ++### BEGIN /etc/grub.d/20_linux_xen ### ++ ++### END /etc/grub.d/20_linux_xen ### ++ ++### BEGIN /etc/grub.d/20_ppc_terminfo ### ++### END /etc/grub.d/20_ppc_terminfo ### ++ ++### BEGIN /etc/grub.d/30_os-prober ### ++### END /etc/grub.d/30_os-prober ### ++ ++### BEGIN /etc/grub.d/40_custom ### ++# This file provides an easy way to add custom menu entries. Simply type the ++# menu entries you want to add after this comment. Be careful not to change ++# the 'exec tail' line above. ++### END /etc/grub.d/40_custom ### ++ ++### BEGIN /etc/grub.d/41_custom ### ++if [ -f ${config_directory}/custom.cfg ]; then ++ source ${config_directory}/custom.cfg ++elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then ++ source $prefix/custom.cfg; ++fi ++### END /etc/grub.d/41_custom ### +-- +2.4.3 + diff --git a/SOURCES/0018-Fix-a-wrong-test-case-lacked-boot-filesystem.patch b/SOURCES/0018-Fix-a-wrong-test-case-lacked-boot-filesystem.patch new file mode 100644 index 0000000..223990d --- /dev/null +++ b/SOURCES/0018-Fix-a-wrong-test-case-lacked-boot-filesystem.patch @@ -0,0 +1,26 @@ +From ad075a4b29f5cfd682c65be4f5f4a6e9de9034c4 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 21 May 2014 17:37:23 -0400 +Subject: [PATCH 18/41] Fix a wrong test case (lacked --boot-filesystem=) + +Signed-off-by: Peter Jones +--- + test.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test.sh b/test.sh +index 57e4926..1d95ed3 100755 +--- a/test.sh ++++ b/test.sh +@@ -515,7 +515,7 @@ if [ "$testgrub2" == "y" ]; then + --add-kernel=/boot/vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 \ + --initrd /boot/initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img \ + --copy-default --title "Fedora 21 Rescue" --args=root=/fooooo \ +- --remove-kernel=wtf ++ --remove-kernel=wtf --boot-filesystem=/boot/ + + testing="GRUB2 add initrd" + grub2Test grub2.2 add/g2-1.4 --update-kernel=/boot/new-kernel.img \ +-- +2.4.3 + diff --git a/SOURCES/0019-Don-t-go-past-the-last-element-of-indexVars-in-findE.patch b/SOURCES/0019-Don-t-go-past-the-last-element-of-indexVars-in-findE.patch new file mode 100644 index 0000000..7d5e4ca --- /dev/null +++ b/SOURCES/0019-Don-t-go-past-the-last-element-of-indexVars-in-findE.patch @@ -0,0 +1,41 @@ +From 5851c34b92069dd955e862b856bb732eb263b058 Mon Sep 17 00:00:00 2001 +From: Yannick Brosseau +Date: Thu, 3 Jul 2014 13:55:19 -0700 +Subject: [PATCH 19/41] Don't go past the last element of indexVars in + findEntryByPath + +We add a chance of creating an infinite loop, because we +were reading memory past the last element of indexVars set to -1. + +This issue was only apparent with -O2, probably because the way the +memory was initialized. + +Signed-off-by: Yannick Brosseau +--- + grubby.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/grubby.c b/grubby.c +index 4516b92..4462fb9 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -1954,11 +1954,13 @@ struct singleEntry * findEntryByPath(struct grubConfig * config, + } + + indexVars[i + 1] = -1; +- ++ + i = 0; + if (index) { +- while (i < *index) i++; +- if (indexVars[i] == -1) return NULL; ++ while (i < *index) { ++ i++; ++ if (indexVars[i] == -1) return NULL; ++ } + } + + entry = findEntryByIndex(config, indexVars[i]); +-- +2.4.3 + diff --git a/SOURCES/0020-Tell-a-slightly-better-fib-about-default-bootloader-.patch b/SOURCES/0020-Tell-a-slightly-better-fib-about-default-bootloader-.patch new file mode 100644 index 0000000..575123a --- /dev/null +++ b/SOURCES/0020-Tell-a-slightly-better-fib-about-default-bootloader-.patch @@ -0,0 +1,46 @@ +From 0228a8f2a0db3f3b86860c610de5e6624c089a48 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 12 Sep 2014 15:50:05 -0400 +Subject: [PATCH 20/41] Tell a slightly better fib about default bootloader + config paths. + +It's not going to be right everywhere, but... whatever. + +Resolves: rhbz#1001664 +Signed-off-by: Peter Jones +--- + grubby.8 | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/grubby.8 b/grubby.8 +index d79e60e..9d7a1fd 100644 +--- a/grubby.8 ++++ b/grubby.8 +@@ -18,16 +18,18 @@ grubby \- command line tool for configuring grub, lilo, elilo, yaboot and zipl + + .SH DESCRIPTION + \fBgrubby\fR is a command line tool for updating and displaying information +-about the configuration files for the \fBgrub\fR, \fBlilo\fR, \fBelilo\fR ++about the configuration files for the \fBgrub\fR, \fBlilo\fR, \fBelilo\fR + (ia64), \fByaboot\fR (powerpc) and \fBzipl\fR (s390) boot loaders. It + is primarily designed to be used from scripts which install new + kernels and need to find information about the current boot environment. + +-On Intel x86 platforms, \fBgrub\fR is the default bootloader and the +-configuration file is in \fB/boot/grub/grub.conf\fR. On Intel ia64 platforms, +-\fBelilo\fR mode is used and the default location for the configuration file +-is \fB/boot/grub/grub.conf\fR. On PowerPC platforms, \fByaboot\fR parsing +-is used and the configuration file should be in \fB/etc/yaboot.conf\fR. ++On BIOS-based Intel x86 platforms, \fBgrub2\fR is the default bootloader and ++the configuration file is in \fB/boot/grub2/grub.cfg\fR. On UEFI-based Intel ++x86 platforms, \fBgrub2\fR is the default bootloader, and the configuration ++file is in \fB/boot/efi/EFI/redhat/grub.cfg\fR. On Intel ia64 platforms, ++\fBelilo\fR mode is used and the default location for the configuration file ++is \fB/boot/efi/EFI/redhat/elilo.conf\fR. On PowerPC platforms, \fByaboot\fR ++parsing is used and the configuration file should be in \fB/etc/yaboot.conf\fR. + + There are a number of ways to specify the kernel used for \fB-\-info\fR, + \fB-\-remove-kernel\fR, and \fB-\-update-kernel\fR. Specificying \fBDEFAULT\fR +-- +2.4.3 + diff --git a/SOURCES/0021-Make-findTemplate-actually-return-the-saved-default.patch b/SOURCES/0021-Make-findTemplate-actually-return-the-saved-default.patch new file mode 100644 index 0000000..0a7f22a --- /dev/null +++ b/SOURCES/0021-Make-findTemplate-actually-return-the-saved-default.patch @@ -0,0 +1,35 @@ +From e990379f5c3c2a2ffe9b9e4a1afae0df0d8dcf80 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 15 Sep 2014 14:31:01 -0400 +Subject: [PATCH 21/41] Make findTemplate actually return the saved default. + +Really not sure why this wasn't returning here before; going into the +loop below is just going to clobber all that it's done. + +Related: rhbz#957681 +Signed-off-by: Peter Jones +--- + grubby.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/grubby.c b/grubby.c +index 4462fb9..6670ff0 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -2114,8 +2114,12 @@ struct singleEntry * findTemplate(struct grubConfig * cfg, const char * prefix, + } else { + entry = findEntryByTitle(cfg, defTitle, &index); + } +- if (entry) ++ if (entry && suitableImage(entry, prefix, skipRemoved, flags)) { + cfg->defaultImage = index; ++ if (indexPtr) ++ *indexPtr = index; ++ return entry; ++ } + } + } + } else if (cfg->defaultImage > -1) { +-- +2.4.3 + diff --git a/SOURCES/0022-Support-filtering-update-kernel-by-title-as-well.patch b/SOURCES/0022-Support-filtering-update-kernel-by-title-as-well.patch new file mode 100644 index 0000000..1eabf94 --- /dev/null +++ b/SOURCES/0022-Support-filtering-update-kernel-by-title-as-well.patch @@ -0,0 +1,106 @@ +From bd9c532d853ac6b95ec83983e85e3266ebbcc004 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 15 Sep 2014 15:18:48 -0400 +Subject: [PATCH 22/41] Support filtering --update-kernel= by title as well. + +If there are two entries with the same kernel, we need to match the +title to uniquely identify one. + +Related: rhbz#957681 +Signed-off-by: Peter Jones +--- + grubby.c | 40 +++++++++++++++++++++++++++++++++++----- + 1 file changed, 35 insertions(+), 5 deletions(-) + +diff --git a/grubby.c b/grubby.c +index 6670ff0..f8e9c25 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -3288,7 +3288,8 @@ int updateImage(struct grubConfig * cfg, const char * image, + } + + int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel, +- const char * image, const char * prefix, const char * initrd) { ++ const char * image, const char * prefix, const char * initrd, ++ const char * title) { + struct singleEntry * entry; + struct singleLine * line, * kernelLine, *endLine = NULL; + int index = 0; +@@ -3299,6 +3300,20 @@ int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel, + kernelLine = getLineByType(LT_MBMODULE, entry->lines); + if (!kernelLine) continue; + ++ /* if title is supplied, the entry's title must match it. */ ++ if (title) { ++ line = getLineByType(LT_TITLE|LT_MENUENTRY, entry->lines); ++ char *linetitle = extractTitle(line); ++ ++ if (!linetitle) ++ continue; ++ if (strcmp(title, linetitle)) { ++ free(linetitle); ++ continue; ++ } ++ free(linetitle); ++ } ++ + if (prefix) { + int prefixLen = strlen(prefix); + if (!strncmp(initrd, prefix, prefixLen)) +@@ -3324,7 +3339,7 @@ int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel, + } + + int updateInitrd(struct grubConfig * cfg, const char * image, +- const char * prefix, const char * initrd) { ++ const char * prefix, const char * initrd, const char * title) { + struct singleEntry * entry; + struct singleLine * line, * kernelLine, *endLine = NULL; + int index = 0; +@@ -3335,6 +3350,20 @@ int updateInitrd(struct grubConfig * cfg, const char * image, + kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); + if (!kernelLine) continue; + ++ /* if title is supplied, the entry's title must match it. */ ++ if (title) { ++ line = getLineByType(LT_TITLE|LT_MENUENTRY, entry->lines); ++ char *linetitle = extractTitle(line); ++ ++ if (!linetitle) ++ continue; ++ if (strcmp(title, linetitle)) { ++ free(linetitle); ++ continue; ++ } ++ free(linetitle); ++ } ++ + line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines); + if (line) + removeLine(entry, line); +@@ -4365,7 +4394,7 @@ int main(int argc, const char ** argv) { + if (newKernelPath && !newKernelTitle) { + fprintf(stderr, _("grubby: kernel title must be specified\n")); + return 1; +- } else if (!newKernelPath && (newKernelTitle || copyDefault || ++ } else if (!newKernelPath && (copyDefault || + (newKernelInitrd && !updateKernelPath)|| + makeDefault || extraInitrdCount > 0)) { + fprintf(stderr, _("grubby: kernel path expected\n")); +@@ -4587,11 +4616,12 @@ int main(int argc, const char ** argv) { + if (updateKernelPath && newKernelInitrd) { + if (newMBKernel) { + if (addMBInitrd(config, newMBKernel, updateKernelPath, +- bootPrefix, newKernelInitrd)) ++ bootPrefix, newKernelInitrd, ++ newKernelTitle)) + return 1; + } else { + if (updateInitrd(config, updateKernelPath, bootPrefix, +- newKernelInitrd)) ++ newKernelInitrd, newKernelTitle)) + return 1; + } + } +-- +2.4.3 + diff --git a/SOURCES/0023-Conditionally-create-debug-entries-when-installing-k.patch b/SOURCES/0023-Conditionally-create-debug-entries-when-installing-k.patch new file mode 100644 index 0000000..a05ec3e --- /dev/null +++ b/SOURCES/0023-Conditionally-create-debug-entries-when-installing-k.patch @@ -0,0 +1,310 @@ +From 591c275f45202e8f0d2d8f1c719ef224a2ec325c Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 15 Sep 2014 15:20:34 -0400 +Subject: [PATCH 23/41] Conditionally create debug entries when installing + kernels. + +if /etc/sysconfig/kernel has MAKEDEBUG set to "yes", create non-default +entries that have systemd.debug set. + +Resolves: rhbz#957681 +Signed-off-by: Peter Jones +--- + new-kernel-pkg | 190 ++++++++++++++++++++++++++++++++++++--------------------- + 1 file changed, 119 insertions(+), 71 deletions(-) + +diff --git a/new-kernel-pkg b/new-kernel-pkg +index d9a9b67..70f6118 100755 +--- a/new-kernel-pkg ++++ b/new-kernel-pkg +@@ -50,6 +50,7 @@ grubConfig="" + grub2Config="" + grub2EfiConfig="" + extlinuxConfig="" ++ubootScript="/boot/boot.scr" + + ARCH=$(uname -m) + +@@ -120,6 +121,7 @@ mbkernel="$HYPERVISOR" + mbargs="$HYPERVISOR_ARGS" + adddracutargs="" + addplymouthinitrd="" ++DEBUGARG="systemd.debug" + + usage() { + echo "Usage: `basename $0` [-v] [--mkinitrd] [--rminitrd] [--dracut]" >&2 +@@ -134,6 +136,41 @@ usage() { + exit 1 + } + ++rungrubby() { ++ if [ "$1" == "--debug" ]; then ++ [ "$MAKEDEBUG" != "yes" ] && return 0 ++ [ -n "$verbose" ] && echo "- First, making a debug entry." ++ declare -x debugtitle=" with debugging" ++ declare -x debugargs="$DEBUGARG" ++ shift ++ else ++ [ -n "$verbose" ] && echo "- Making a normal entry." ++ fi ++ $(eval $grubby $@) ++ export -n debugargs ++ export -n debugtitle ++ unset debugargs ++ unset debugtitle ++} ++ ++set_title() { ++ if [ -n "$banner" ]; then ++ if [ $ARCH = 's390' -o $ARCH = 's390x' ]; then ++ title=$(echo $banner | sed 's/ /_/g') ++ else ++ title="$banner ($version)" ++ fi ++ elif [ $ARCH = 's390' -o $ARCH = 's390x' ]; then ++ title=$(echo $version | sed 's/ /_/g') ++ elif [ -f /etc/os-release ]; then ++ . /etc/os-release ++ title="$NAME ($version) $VERSION" ++ elif [ -f /etc/redhat-release ]; then ++ title="$(sed 's/ release.*$//' < /etc/redhat-release) ($version)" ++ else ++ title="Red Hat Linux ($version)" ++ fi ++} + + install() { + # XXX kernel should be able to be specified also (or work right on ia64) +@@ -184,57 +221,49 @@ install() { + cfgLilo="" + fi + +- +- if [ -n "$banner" ]; then +- if [ $ARCH = 's390' -o $ARCH = 's390x' ]; then +- title=$(echo $banner | sed 's/ /_/g') +- else +- title="$banner ($version)" +- fi +- elif [ $ARCH = 's390' -o $ARCH = 's390x' ]; then +- title=$(echo $version | sed 's/ /_/g') +- elif [ -f /etc/os-release ]; then +- . /etc/os-release +- title="$NAME ($version) $VERSION" +- elif [ -f /etc/redhat-release ]; then +- title="$(sed 's/ release.*$//' < /etc/redhat-release) ($version)" +- else +- title="Red Hat Linux ($version)" +- fi +- ++ set_title + + if [ -n "$cfgGrub" ]; then + [ -n "$verbose" ] && echo "adding $version to $grubConfig" + +- $grubby --grub -c $grubConfig \ +- --add-kernel=$kernelImage \ +- $INITRD --copy-default $makedefault --title "$title" \ +- ${mbkernel:+--add-multiboot="$mbkernel"} ${mbargs:+--mbargs="$mbargs"} \ +- --args="root=$rootdevice $kernargs" --remove-kernel="TITLE=$title" ++ ARGS="--grub -c $grubConfig --add-kernel=$kernelImage $INITRD \ ++ ${mbkernel:+--add-multiboot=\"$mbkernel\"} \ ++ ${mbargs:+--mbargs=\"$mbargs\"} \ ++ --title=\"$title\$debugtitle\" --copy-default \ ++ --args=\"root=$rootdevice $kernargs \$debugargs\" \ ++ --remove-kernel=\"TITLE=$title\$debugtitle\"" ++ ++ rungrubby --debug ${ARGS} ++ rungrubby ${ARGS} $makedefault + else + [ -n "$verbose" ] && echo "$grubConfig does not exist, not running grubby for grub 0.97" + fi + if [ -n "$cfgGrub2" ]; then + [ -n "$verbose" ] && echo "adding $version to $grub2Config" + +- $grubby --grub2 -c $grub2Config \ +- --add-kernel=$kernelImage \ +- $INITRD --copy-default $makedefault --title "$title" \ +- ${mbkernel:+--add-multiboot="$mbkernel"} \ +- ${mbargs:+--mbargs="$mbargs"} \ +- --args="root=$rootdevice $kernargs" --remove-kernel="TITLE=$title" ++ ARGS="--grub2 -c $grub2Config --add-kernel=$kernelImage $INITRD \ ++ --copy-default --title \"$title\$debugtitle\" \ ++ ${mbkernel:+--add-multiboot=\"$mbkernel\"} \ ++ ${mbargs:+--mbargs=\"$mbargs\"} \ ++ --args=\"root=$rootdevice $kernargs \$debugargs\" \ ++ --remove-kernel=\"TITLE=$title\$debugtitle\"" ++ rungrubby --debug ${ARGS} ++ rungrubby ${ARGS} $makedefault + else + [ -n "$verbose" ] && echo "$grub2Config does not exist, not running grubby for grub 2" + fi + if [ -n "$cfgGrub2Efi" ]; then + [ -n "$verbose" ] && echo "adding $version to $grub2EfiConfig" + +- $grubby --grub2 -c $grub2EfiConfig --efi \ +- --add-kernel=$kernelImage $DEVTREE \ +- $INITRD --copy-default $makedefault --title "$title" \ +- ${mbkernel:+--add-multiboot="$mbkernel"} \ +- ${mbargs:+--mbargs="$mbargs"} \ +- --args="root=$rootdevice $kernargs" --remove-kernel="TITLE=$title" ++ ARGS="--grub2 -c $grub2EfiConfig --efi \ ++ --add-kernel=$kernelImage $DEVTREE $INITRD \ ++ --copy-default --title \"$title\$debugtitle\" \ ++ ${mbkernel:+--add-multiboot=\"$mbkernel\"} \ ++ ${mbargs:+--mbargs=\"$mbargs\"} \ ++ --args=\"root=$rootdevice $kernargs \$debugargs\" \ ++ --remove-kernel=\"TITLE=$title\$debugtitle\"" ++ rungrubby --debug ${ARGS} ++ rungrubby ${ARGS} $makedefault + else + [ -n "$verbose" ] && echo "$grub2EfiConfig does not exist, not running grubby for grub 2 with UEFI" + fi +@@ -242,12 +271,15 @@ install() { + if [ -n "$cfgLilo" ]; then + [ -n "$verbose" ] && echo "adding $version to $liloConfig" + +- $grubby --add-kernel=$kernelImage $INITRD \ +- --copy-default $makedefault --title "$title" \ +- ${mbkernel:+--add-multiboot="$mbkernel"} ${mbargs:+--mbargs="$mbargs"} \ +- --args="root=$rootdevice $kernargs" --remove-kernel="TITLE=$version" \ +- --$liloFlag ++ ARGS="--$liloFlag --add-kernel=$kernelImage $INITRD \ ++ --copy-default --title \"$title\$debugtitle\" \ ++ ${mbkernel:+--add-multiboot=\"$mbkernel\"} \ ++ ${mbargs:+--mbargs=\"$mbargs\"} \ ++ --args=\"root=$rootdevice $kernargs \$debugargs\" \ ++ --remove-kernel=\"TITLE=$version\"" + ++ rungrubby --debug ${ARGS} ++ rungrubby ${ARGS} $makedefault + if [ -n "$runLilo" ]; then + [ -n "$verbose" ] && echo "running $lilo" + if [ ! -x $lilo ] ; then +@@ -263,11 +295,15 @@ install() { + if [ -n "$cfgExtlinux" ]; then + [ -n "$verbose" ] && echo "adding $version to $extlinuxConfig" + +- $grubby --extlinux -c $extlinuxConfig \ +- --add-kernel=$kernelImage \ +- $INITRD --copy-default $makedefault --title "$title" \ +- ${mbkernel:+--add-multiboot="$mbkernel"} ${mbargs:+--mbargs="$mbargs"} \ +- --args="root=$rootdevice $kernargs" --remove-kernel="TITLE=$title" ++ ARGS="--extlinux -c $extlinuxConfig --add-kernel=$kernelImage \ ++ $INITRD --copy-default --title \"$title\$debugtitle\" \ ++ ${mbkernel:+--add-multiboot=\"$mbkernel\"} \ ++ ${mbargs:+--mbargs=\"$mbargs\"} \ ++ --args=\"root=$rootdevice $kernargs \$debugargs\" \ ++ --remove-kernel=\"TITLE=$title\$debugtitle\"" ++ ++ rungrubby --debug ${ARGS} ++ rungrubby ${ARGS} $makedefault + else + [ -n "$verbose" ] && echo "$extlinuxConfig does not exist, not running grubby for extlinux" + fi +@@ -401,6 +437,8 @@ update() { + return + fi + ++ set_title ++ + INITRD="" + if [ -f $initrdfile ]; then + [ -n "$verbose" ] && echo "found $initrdfile and using it with grubby" +@@ -413,45 +451,53 @@ update() { + + if [ -n "$cfgGrub" ]; then + [ -n "$verbose" ] && echo "updating $version from $grubConfig" +- $grubby --grub -c $grubConfig \ +- --update-kernel=$kernelImage \ +- $INITRD \ +- ${kernargs:+--args="$kernargs"} \ +- ${removeargs:+--remove-args="$removeargs"} \ +- ${mbkernel:+--add-multiboot="$mbkernel"} ++ ARGS="--grub -c $grubConfig --update-kernel=$kernelImage $INITRD \ ++ ${kernargs:+--args=\"$kernargs\"} \ ++ ${removeargs:+--remove-args=\"$removeargs\"} \ ++ ${mbkernel:+--add-multiboot=\"$mbkernel\"} \ ++ --title=\"$title\$debugtitle\"" ++ ++ rungrubby --debug ${ARGS} ++ rungrubby ${ARGS} + else + [ -n "$verbose" ] && echo "$grubConfig does not exist, not running grubby" + fi + + if [ -n "$cfgGrub2" ]; then + [ -n "$verbose" ] && echo "updating $version from $grub2Config" +- $grubby --grub2 -c $grub2Config \ +- --update-kernel=$kernelImage \ +- $INITRD \ +- ${kernargs:+--args="$kernargs"} \ +- ${removeargs:+--remove-args="$removeargs"} ++ ARGS="--grub2 -c $grub2Config --update-kernel=$kernelImage $INITRD \ ++ ${kernargs:+--args=\"$kernargs\"} \ ++ ${removeargs:+--remove-args=\"$removeargs\"} \ ++ --title=\"$title\$debugtitle\"" ++ ++ rungrubby --debug ${ARGS} ++ rungrubby ${ARGS} + else + [ -n "$verbose" ] && echo "$grub2Config does not exist, not running grubby" + fi + + if [ -n "$cfgGrub2Efi" ]; then + [ -n "$verbose" ] && echo "updating $version from $grub2EfiConfig" +- $grubby --grub2 -c $grub2EfiConfig --efi \ +- --update-kernel=$kernelImage \ +- $INITRD \ +- ${kernargs:+--args="$kernargs"} \ +- ${removeargs:+--remove-args="$removeargs"} ++ ARGS="--grub2 -c $grub2EfiConfig --efi --update-kernel=$kernelImage \ ++ $INITRD ${kernargs:+--args=\"$kernargs\"} \ ++ ${removeargs:+--remove-args=\"$removeargs\"} \ ++ --title=\"$title\$debugtitle\"" ++ ++ rungrubby --debug ${ARGS} ++ rungrubby ${ARGS} + else + [ -n "$verbose" ] && echo "$grub2EfiConfig does not exist, not running grubby" + fi + + if [ -n "$cfgLilo" ]; then + [ -n "$verbose" ] && echo "updating $version from $liloConfig" +- $grubby --update-kernel=$kernelImage \ +- $INITRD \ +- ${kernargs:+--args="$kernargs"} \ +- ${removeargs:+--remove-args="$removeargs"} \ +- --$liloFlag ++ ARGS="--$liloFlag --update-kernel=$kernelImage $INITRD \ ++ ${kernargs:+--args=\"$kernargs\"} \ ++ ${removeargs:+--remove-args=\"$removeargs\"} \ ++ --title=\"$title\$debugtitle\"" ++ ++ rungrubby --debug ${ARGS} ++ rungrubby ${ARGS} + + if [ -n "$runLilo" ]; then + [ -n "$verbose" ] && echo "running $lilo" +@@ -497,11 +543,13 @@ update() { + + if [ -n "$cfgExtlinux" ]; then + [ -n "$verbose" ] && echo "updating $version from $extlinuxConfig" +- $grubby --extlinux -c $extlinuxConfig \ +- --update-kernel=$kernelImage \ +- $INITRD \ +- ${kernargs:+--args="$kernargs"} \ +- ${removeargs:+--remove-args="$removeargs"} ++ ARGS="--extlinux -c $extlinuxConfig --update-kernel=$kernelImage \ ++ $INITRD ${kernargs:+--args=\"$kernargs\"} \ ++ ${removeargs:+--remove-args=\"$removeargs\"} \ ++ --title=\"$title\$debugtitle\"" ++ ++ rungrubby --debug ${ARGS} ++ rungrubby ${ARGS} + else + [ -n "$verbose" ] && echo "$extlinuxConfig does not exist, not running grubby" + fi +-- +2.4.3 + diff --git a/SOURCES/0024-Always-error-check-getLineByType.patch b/SOURCES/0024-Always-error-check-getLineByType.patch new file mode 100644 index 0000000..f6e943c --- /dev/null +++ b/SOURCES/0024-Always-error-check-getLineByType.patch @@ -0,0 +1,62 @@ +From 9549dc0d747d8987dd11643340adfa7b6f799460 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 25 Sep 2014 13:24:15 -0400 +Subject: [PATCH 24/41] Always error check getLineByType() + +Signed-off-by: Peter Jones +--- + grubby.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/grubby.c b/grubby.c +index f8e9c25..febc1ad 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -2363,9 +2363,11 @@ void displayEntry(struct singleEntry * entry, const char * prefix, int index) { + } else { + char * title; + line = getLineByType(LT_MENUENTRY, entry->lines); +- title = grub2ExtractTitle(line); +- if (title) +- printf("title=%s\n", title); ++ if (!line) { ++ title = grub2ExtractTitle(line); ++ if (title) ++ printf("title=%s\n", title); ++ } + } + } + +@@ -3302,9 +3304,13 @@ int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel, + + /* if title is supplied, the entry's title must match it. */ + if (title) { ++ char *linetitle; ++ + line = getLineByType(LT_TITLE|LT_MENUENTRY, entry->lines); +- char *linetitle = extractTitle(line); ++ if (!line) ++ continue; + ++ linetitle = extractTitle(line); + if (!linetitle) + continue; + if (strcmp(title, linetitle)) { +@@ -3352,9 +3358,13 @@ int updateInitrd(struct grubConfig * cfg, const char * image, + + /* if title is supplied, the entry's title must match it. */ + if (title) { ++ char *linetitle; ++ + line = getLineByType(LT_TITLE|LT_MENUENTRY, entry->lines); +- char *linetitle = extractTitle(line); ++ if (!line) ++ continue; + ++ linetitle = extractTitle(line); + if (!linetitle) + continue; + if (strcmp(title, linetitle)) { +-- +2.4.3 + diff --git a/SOURCES/0025-Get-the-error-checking-on-getLineByType-return-right.patch b/SOURCES/0025-Get-the-error-checking-on-getLineByType-return-right.patch new file mode 100644 index 0000000..5bdf4f2 --- /dev/null +++ b/SOURCES/0025-Get-the-error-checking-on-getLineByType-return-right.patch @@ -0,0 +1,27 @@ +From d4fc18c1a9b9b3e8f8e73afa5c82c938555f5c4d Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 16 Oct 2014 14:07:01 -0400 +Subject: [PATCH 25/41] Get the error checking on getLineByType() return + /right/. + +Signed-off-by: Peter Jones +--- + grubby.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grubby.c b/grubby.c +index febc1ad..82a0f15 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -2363,7 +2363,7 @@ void displayEntry(struct singleEntry * entry, const char * prefix, int index) { + } else { + char * title; + line = getLineByType(LT_MENUENTRY, entry->lines); +- if (!line) { ++ if (line) { + title = grub2ExtractTitle(line); + if (title) + printf("title=%s\n", title); +-- +2.4.3 + diff --git a/SOURCES/0026-Fix-ppc-kernelName-when-invoked-by-installkernel.patch b/SOURCES/0026-Fix-ppc-kernelName-when-invoked-by-installkernel.patch new file mode 100644 index 0000000..deba8d8 --- /dev/null +++ b/SOURCES/0026-Fix-ppc-kernelName-when-invoked-by-installkernel.patch @@ -0,0 +1,86 @@ +From 487c264cb590c42b6122fd7d02d14c1d762214e5 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Thu, 11 Dec 2014 14:41:21 -0500 +Subject: [PATCH 26/41] Fix ppc kernelName when invoked by installkernel. + +During the installation of a new kernel on an existing system the +invocation of "make install" called installkernel and that provided +new-kernel-pkg with the incorrect kernelName on ppc systems. Added +new option --kernel-name to new-kernel-pkg and invoked it from +installkernel with the appropriate kernel name. + +Resolves: rhbz#979852 + +Signed-off-by: Robert Marshall +--- + installkernel | 6 +++--- + new-kernel-pkg | 22 +++++++++++++++------- + 2 files changed, 18 insertions(+), 10 deletions(-) + +diff --git a/installkernel b/installkernel +index 86fe2c3..b887929 100755 +--- a/installkernel ++++ b/installkernel +@@ -79,9 +79,9 @@ ln -fs ${RELATIVE_PATH}$INSTALL_PATH/System.map-$KERNEL_VERSION $LINK_PATH/Syste + + if [ -n "$cfgLoader" ] && [ -x /sbin/new-kernel-pkg ]; then + if [ -n "$(which dracut 2>/dev/null)" ]; then +- new-kernel-pkg --mkinitrd --dracut --host-only --depmod --install $KERNEL_VERSION ++ new-kernel-pkg --mkinitrd --dracut --host-only --depmod --install --kernel-name $KERNEL_NAME $KERNEL_VERSION + else +- new-kernel-pkg --mkinitrd --depmod --install $KERNEL_VERSION ++ new-kernel-pkg --mkinitrd --depmod --install --kernel-name $KERNEL_NAME $KERNEL_VERSION + fi +- new-kernel-pkg --rpmposttrans $KERNEL_VERSION ++ new-kernel-pkg --rpmposttrans --kernel-name $KERNEL_NAME $KERNEL_VERSION + fi +diff --git a/new-kernel-pkg b/new-kernel-pkg +index 70f6118..527f8fb 100755 +--- a/new-kernel-pkg ++++ b/new-kernel-pkg +@@ -588,6 +588,12 @@ doRmmoddep() { + fi + } + ++# kernel image for 2.4 is vmlinux ++if [ $ARCH = 'ppc64' -o $ARCH = 'ppc' ]; then ++ if [ "$kernelmajor" == "2.4" ]; then ++ kernelName=vmlinux ++ fi ++fi + + while [ $# -gt 0 ]; do + case $1 in +@@ -714,6 +720,15 @@ while [ $# -gt 0 ]; do + fi + ;; + ++ --kernel-name*) ++ if [[ $1 == --kernel-name\=* ]]; then ++ kernelName=${1#--kernel-name=} ++ else ++ kernelName="$2" ++ shift ++ fi ++ ;; ++ + -v) + verbose=-v + ;; +@@ -747,13 +762,6 @@ fi + + kernelmajor=`echo $kernel | cut -d . -f 1,2` + +-# kernel image for 2.4 is vmlinux +-if [ $ARCH = 'ppc64' -o $ARCH = 'ppc' ]; then +- if [ "$kernelmajor" == "2.4" ]; then +- kernelName=vmlinux +- fi +-fi +- + [[ $kernelImage ]] || kernelImage="$bootPrefix/$kernelName-$version" + + # set the initrd file based on arch; ia64 is the only currently known oddball +-- +2.4.3 + diff --git a/SOURCES/0027-Update-grubby-man-page-for-Power8-PPC64LE.patch b/SOURCES/0027-Update-grubby-man-page-for-Power8-PPC64LE.patch new file mode 100644 index 0000000..f6c259f --- /dev/null +++ b/SOURCES/0027-Update-grubby-man-page-for-Power8-PPC64LE.patch @@ -0,0 +1,34 @@ +From 33c06b169149a5acc91d8e5d2edd6483d8e2c7d0 Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Wed, 21 Jan 2015 15:51:12 -0500 +Subject: [PATCH 27/41] Update grubby man page for Power8 PPC64LE + +The grubby man page was up to date for Power7 PPC systems using +yaboot. Added the information for the grub2-based Power8 PPC64LE +system architecture. + +Resolves bz#1125540 +--- + grubby.8 | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/grubby.8 b/grubby.8 +index 9d7a1fd..5ff486f 100644 +--- a/grubby.8 ++++ b/grubby.8 +@@ -28,8 +28,10 @@ the configuration file is in \fB/boot/grub2/grub.cfg\fR. On UEFI-based Intel + x86 platforms, \fBgrub2\fR is the default bootloader, and the configuration + file is in \fB/boot/efi/EFI/redhat/grub.cfg\fR. On Intel ia64 platforms, + \fBelilo\fR mode is used and the default location for the configuration file +-is \fB/boot/efi/EFI/redhat/elilo.conf\fR. On PowerPC platforms, \fByaboot\fR +-parsing is used and the configuration file should be in \fB/etc/yaboot.conf\fR. ++is \fB/boot/efi/EFI/redhat/elilo.conf\fR. On PowerPC platforms, systems based ++on Power8 now support \fBgrub2\fR as a bootloader and store using a default ++config stored in \fB/boot/grub2/grub.cfg\fR. The earlier Power7 systems use \fByaboot\fR ++parsing and the configuration file should be in \fB/etc/yaboot.conf\fR. + + There are a number of ways to specify the kernel used for \fB-\-info\fR, + \fB-\-remove-kernel\fR, and \fB-\-update-kernel\fR. Specificying \fBDEFAULT\fR +-- +2.4.3 + diff --git a/SOURCES/0028-Update-man-page-to-include-default-config-file-for-s.patch b/SOURCES/0028-Update-man-page-to-include-default-config-file-for-s.patch new file mode 100644 index 0000000..5170e68 --- /dev/null +++ b/SOURCES/0028-Update-man-page-to-include-default-config-file-for-s.patch @@ -0,0 +1,35 @@ +From 938e2a19dcc775e2934cb276896fba4851f419cf Mon Sep 17 00:00:00 2001 +From: Robert Marshall +Date: Wed, 21 Jan 2015 11:27:32 -0500 +Subject: [PATCH 28/41] Update man page to include default config file for + s390x bootloader. + +The grubby man page defined the default config file for every +architecture's bootloader except s390. Added this information +to the man page. + +Resolves bz#1158904 + +Conflicts: + grubby.8 +--- + grubby.8 | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/grubby.8 b/grubby.8 +index 5ff486f..85e22c5 100644 +--- a/grubby.8 ++++ b/grubby.8 +@@ -31,7 +31,8 @@ file is in \fB/boot/efi/EFI/redhat/grub.cfg\fR. On Intel ia64 platforms, + is \fB/boot/efi/EFI/redhat/elilo.conf\fR. On PowerPC platforms, systems based + on Power8 now support \fBgrub2\fR as a bootloader and store using a default + config stored in \fB/boot/grub2/grub.cfg\fR. The earlier Power7 systems use \fByaboot\fR +-parsing and the configuration file should be in \fB/etc/yaboot.conf\fR. ++parsing and the configuration file should be in \fB/etc/yaboot.conf\fR. On ++s390 platforms the \fBzipl bootloader\fR will read from \fB/etc/zipl.conf\fR. + + There are a number of ways to specify the kernel used for \fB-\-info\fR, + \fB-\-remove-kernel\fR, and \fB-\-update-kernel\fR. Specificying \fBDEFAULT\fR +-- +2.4.3 + diff --git a/SOURCES/0029-Split-the-test-case-for-rescue-images-into-tests-wit.patch b/SOURCES/0029-Split-the-test-case-for-rescue-images-into-tests-wit.patch new file mode 100644 index 0000000..5126d59 --- /dev/null +++ b/SOURCES/0029-Split-the-test-case-for-rescue-images-into-tests-wit.patch @@ -0,0 +1,325 @@ +From 2f5d55122bacc0a04e069d936968324ff1c47115 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 17 Mar 2015 14:24:35 -0400 +Subject: [PATCH 29/41] Split the test case for rescue images into tests with + and without linux16. + +Right now the test is only a linux16 variety and it isn't only run on +x86; that'll fail. Split it into two tests, one which has no linux16, +and one that has it and only runs on x86. + +Resolves: rhbz#1202876 + +Signed-off-by: Peter Jones +--- + test.sh | 9 +++- + test/grub2.15 | 111 +++++++++++++++++++++++++++++++++++++++++ + test/results/add/g2-1.14 | 6 +-- + test/results/add/g2-1.15 | 126 +++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 248 insertions(+), 4 deletions(-) + create mode 100644 test/grub2.15 + create mode 100644 test/results/add/g2-1.15 + +diff --git a/test.sh b/test.sh +index 1d95ed3..3cfb965 100755 +--- a/test.sh ++++ b/test.sh +@@ -511,7 +511,7 @@ if [ "$testgrub2" == "y" ]; then + grub2Test grub2.5 add/g2-1.5 --add-kernel=/boot/new-kernel.img \ + --title='title' --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ + --copy-default +- grub2Test grub2.14 add/g2-1.14 \ ++ grub2Test grub2.15 add/g2-1.15 \ + --add-kernel=/boot/vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 \ + --initrd /boot/initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img \ + --copy-default --title "Fedora 21 Rescue" --args=root=/fooooo \ +@@ -607,6 +607,13 @@ if [ "$testgrub2" == "y" ]; then + testing="GRUB2 add initrd with linux16" + grub2Test grub2.11 add/g2-1.11 --update-kernel=/boot/new-kernel.img \ + --initrd=/boot/new-initrd --boot-filesystem=/boot/ ++ ++ testing="GRUB2 add rescue with linux16" ++ grub2Test grub2.14 add/g2-1.14 \ ++ --add-kernel=/boot/vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 \ ++ --initrd /boot/initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img \ ++ --copy-default --title "Fedora 21 Rescue" --args=root=/fooooo \ ++ --remove-kernel=wtf --boot-filesystem=/boot/ + fi + fi + +diff --git a/test/grub2.15 b/test/grub2.15 +new file mode 100644 +index 0000000..b7e7c16 +--- /dev/null ++++ b/test/grub2.15 +@@ -0,0 +1,111 @@ ++# ++# DO NOT EDIT THIS FILE ++# ++# It is automatically generated by grub2-mkconfig using templates ++# from /etc/grub.d and settings from /etc/default/grub ++# ++ ++### BEGIN /etc/grub.d/00_header ### ++set pager=1 ++ ++if [ -s $prefix/grubenv ]; then ++ load_env ++fi ++if [ "${next_entry}" ] ; then ++ set default="${next_entry}" ++ set next_entry= ++ save_env next_entry ++ set boot_once=true ++else ++ set default="${saved_entry}" ++fi ++ ++if [ x"${feature_menuentry_id}" = xy ]; then ++ menuentry_id_option="--id" ++else ++ menuentry_id_option="" ++fi ++ ++export menuentry_id_option ++ ++if [ "${prev_saved_entry}" ]; then ++ set saved_entry="${prev_saved_entry}" ++ save_env saved_entry ++ set prev_saved_entry= ++ save_env prev_saved_entry ++ set boot_once=true ++fi ++ ++function savedefault { ++ if [ -z "${boot_once}" ]; then ++ saved_entry="${chosen}" ++ save_env saved_entry ++ fi ++} ++ ++function load_video { ++ if [ x$feature_all_video_module = xy ]; then ++ insmod all_video ++ else ++ insmod efi_gop ++ insmod efi_uga ++ insmod ieee1275_fb ++ insmod vbe ++ insmod vga ++ insmod video_bochs ++ insmod video_cirrus ++ fi ++} ++ ++terminal_output console ++if [ x$feature_timeout_style = xy ] ; then ++ set timeout_style=menu ++ set timeout=5 ++# Fallback normal timeout code in case the timeout_style feature is ++# unavailable. ++else ++ set timeout=5 ++fi ++### END /etc/grub.d/00_header ### ++ ++### BEGIN /etc/grub.d/10_linux ### ++menuentry 'Fedora, with Linux 3.15.0-0.rc5.git2.10.fc21.x86_64' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.15.0-0.rc5.git2.10.fc21.x86_64-advanced-a14e3dcb-ade3-42f7-832f-d9f66b5ae6a3' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod ext2 ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ else ++ search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ fi ++ linux /vmlinuz-3.15.0-0.rc5.git2.10.fc21.x86_64 root=/dev/mapper/fedora_uefi-root ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++} ++ ++### END /etc/grub.d/10_linux ### ++ ++### BEGIN /etc/grub.d/20_linux_xen ### ++ ++### END /etc/grub.d/20_linux_xen ### ++ ++### BEGIN /etc/grub.d/20_ppc_terminfo ### ++### END /etc/grub.d/20_ppc_terminfo ### ++ ++### BEGIN /etc/grub.d/30_os-prober ### ++### END /etc/grub.d/30_os-prober ### ++ ++### BEGIN /etc/grub.d/40_custom ### ++# This file provides an easy way to add custom menu entries. Simply type the ++# menu entries you want to add after this comment. Be careful not to change ++# the 'exec tail' line above. ++### END /etc/grub.d/40_custom ### ++ ++### BEGIN /etc/grub.d/41_custom ### ++if [ -f ${config_directory}/custom.cfg ]; then ++ source ${config_directory}/custom.cfg ++elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then ++ source $prefix/custom.cfg; ++fi ++### END /etc/grub.d/41_custom ### +diff --git a/test/results/add/g2-1.14 b/test/results/add/g2-1.14 +index 0865bbc..68b2d2b 100644 +--- a/test/results/add/g2-1.14 ++++ b/test/results/add/g2-1.14 +@@ -81,8 +81,8 @@ menuentry 'Fedora 21 Rescue' --class fedora --class gnu-linux --class gnu --clas + else + search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b + fi +- linux16 /vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 root=/fooooo ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet +- initrd16 /initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img ++ linux /vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 root=/fooooo ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++ initrd /initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img + } + menuentry 'Fedora, with Linux 3.15.0-0.rc5.git2.10.fc21.x86_64' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.15.0-0.rc5.git2.10.fc21.x86_64-advanced-a14e3dcb-ade3-42f7-832f-d9f66b5ae6a3' { + load_video +@@ -96,7 +96,7 @@ menuentry 'Fedora, with Linux 3.15.0-0.rc5.git2.10.fc21.x86_64' --class fedora - + else + search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b + fi +- linux16 /vmlinuz-3.15.0-0.rc5.git2.10.fc21.x86_64 root=/dev/mapper/fedora_uefi-root ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++ linux /vmlinuz-3.15.0-0.rc5.git2.10.fc21.x86_64 root=/dev/mapper/fedora_uefi-root ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet + } + + ### END /etc/grub.d/10_linux ### +diff --git a/test/results/add/g2-1.15 b/test/results/add/g2-1.15 +new file mode 100644 +index 0000000..0865bbc +--- /dev/null ++++ b/test/results/add/g2-1.15 +@@ -0,0 +1,126 @@ ++# ++# DO NOT EDIT THIS FILE ++# ++# It is automatically generated by grub2-mkconfig using templates ++# from /etc/grub.d and settings from /etc/default/grub ++# ++ ++### BEGIN /etc/grub.d/00_header ### ++set pager=1 ++ ++if [ -s $prefix/grubenv ]; then ++ load_env ++fi ++if [ "${next_entry}" ] ; then ++ set default="${next_entry}" ++ set next_entry= ++ save_env next_entry ++ set boot_once=true ++else ++ set default="${saved_entry}" ++fi ++ ++if [ x"${feature_menuentry_id}" = xy ]; then ++ menuentry_id_option="--id" ++else ++ menuentry_id_option="" ++fi ++ ++export menuentry_id_option ++ ++if [ "${prev_saved_entry}" ]; then ++ set saved_entry="${prev_saved_entry}" ++ save_env saved_entry ++ set prev_saved_entry= ++ save_env prev_saved_entry ++ set boot_once=true ++fi ++ ++function savedefault { ++ if [ -z "${boot_once}" ]; then ++ saved_entry="${chosen}" ++ save_env saved_entry ++ fi ++} ++ ++function load_video { ++ if [ x$feature_all_video_module = xy ]; then ++ insmod all_video ++ else ++ insmod efi_gop ++ insmod efi_uga ++ insmod ieee1275_fb ++ insmod vbe ++ insmod vga ++ insmod video_bochs ++ insmod video_cirrus ++ fi ++} ++ ++terminal_output console ++if [ x$feature_timeout_style = xy ] ; then ++ set timeout_style=menu ++ set timeout=5 ++# Fallback normal timeout code in case the timeout_style feature is ++# unavailable. ++else ++ set timeout=5 ++fi ++### END /etc/grub.d/00_header ### ++ ++### BEGIN /etc/grub.d/10_linux ### ++menuentry 'Fedora 21 Rescue' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.15.0-0.rc5.git2.10.fc21.x86_64-advanced-a14e3dcb-ade3-42f7-832f-d9f66b5ae6a3' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod ext2 ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ else ++ search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ fi ++ linux16 /vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 root=/fooooo ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++ initrd16 /initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img ++} ++menuentry 'Fedora, with Linux 3.15.0-0.rc5.git2.10.fc21.x86_64' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.15.0-0.rc5.git2.10.fc21.x86_64-advanced-a14e3dcb-ade3-42f7-832f-d9f66b5ae6a3' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod ext2 ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ else ++ search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ fi ++ linux16 /vmlinuz-3.15.0-0.rc5.git2.10.fc21.x86_64 root=/dev/mapper/fedora_uefi-root ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++} ++ ++### END /etc/grub.d/10_linux ### ++ ++### BEGIN /etc/grub.d/20_linux_xen ### ++ ++### END /etc/grub.d/20_linux_xen ### ++ ++### BEGIN /etc/grub.d/20_ppc_terminfo ### ++### END /etc/grub.d/20_ppc_terminfo ### ++ ++### BEGIN /etc/grub.d/30_os-prober ### ++### END /etc/grub.d/30_os-prober ### ++ ++### BEGIN /etc/grub.d/40_custom ### ++# This file provides an easy way to add custom menu entries. Simply type the ++# menu entries you want to add after this comment. Be careful not to change ++# the 'exec tail' line above. ++### END /etc/grub.d/40_custom ### ++ ++### BEGIN /etc/grub.d/41_custom ### ++if [ -f ${config_directory}/custom.cfg ]; then ++ source ${config_directory}/custom.cfg ++elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then ++ source $prefix/custom.cfg; ++fi ++### END /etc/grub.d/41_custom ### +-- +2.4.3 + diff --git a/SOURCES/0030-Actually-get-the-test-from-a7800d8f-right.patch b/SOURCES/0030-Actually-get-the-test-from-a7800d8f-right.patch new file mode 100644 index 0000000..e103db8 --- /dev/null +++ b/SOURCES/0030-Actually-get-the-test-from-a7800d8f-right.patch @@ -0,0 +1,92 @@ +From f99b2809835f78ebb613899b7bf71c097b3bb91f Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 17 Mar 2015 14:50:35 -0400 +Subject: [PATCH 30/41] Actually get the test from a7800d8f right. + +Woops. + +Signed-off-by: Peter Jones +--- + test.sh | 2 +- + test/grub2.15 | 2 +- + test/results/add/g2-1.14 | 6 +++--- + test/results/add/g2-1.15 | 6 +++--- + 4 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/test.sh b/test.sh +index 3cfb965..fb13033 100755 +--- a/test.sh ++++ b/test.sh +@@ -515,7 +515,7 @@ if [ "$testgrub2" == "y" ]; then + --add-kernel=/boot/vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 \ + --initrd /boot/initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img \ + --copy-default --title "Fedora 21 Rescue" --args=root=/fooooo \ +- --remove-kernel=wtf --boot-filesystem=/boot/ ++ --remove-kernel=wtf --boot-filesystem=/boot/ --efi + + testing="GRUB2 add initrd" + grub2Test grub2.2 add/g2-1.4 --update-kernel=/boot/new-kernel.img \ +diff --git a/test/grub2.15 b/test/grub2.15 +index b7e7c16..ab0c2f8 100644 +--- a/test/grub2.15 ++++ b/test/grub2.15 +@@ -81,7 +81,7 @@ menuentry 'Fedora, with Linux 3.15.0-0.rc5.git2.10.fc21.x86_64' --class fedora - + else + search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b + fi +- linux /vmlinuz-3.15.0-0.rc5.git2.10.fc21.x86_64 root=/dev/mapper/fedora_uefi-root ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++ linuxefi /vmlinuz-3.15.0-0.rc5.git2.10.fc21.x86_64 root=/dev/mapper/fedora_uefi-root ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet + } + + ### END /etc/grub.d/10_linux ### +diff --git a/test/results/add/g2-1.14 b/test/results/add/g2-1.14 +index 68b2d2b..0865bbc 100644 +--- a/test/results/add/g2-1.14 ++++ b/test/results/add/g2-1.14 +@@ -81,8 +81,8 @@ menuentry 'Fedora 21 Rescue' --class fedora --class gnu-linux --class gnu --clas + else + search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b + fi +- linux /vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 root=/fooooo ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet +- initrd /initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img ++ linux16 /vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 root=/fooooo ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++ initrd16 /initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img + } + menuentry 'Fedora, with Linux 3.15.0-0.rc5.git2.10.fc21.x86_64' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.15.0-0.rc5.git2.10.fc21.x86_64-advanced-a14e3dcb-ade3-42f7-832f-d9f66b5ae6a3' { + load_video +@@ -96,7 +96,7 @@ menuentry 'Fedora, with Linux 3.15.0-0.rc5.git2.10.fc21.x86_64' --class fedora - + else + search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b + fi +- linux /vmlinuz-3.15.0-0.rc5.git2.10.fc21.x86_64 root=/dev/mapper/fedora_uefi-root ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++ linux16 /vmlinuz-3.15.0-0.rc5.git2.10.fc21.x86_64 root=/dev/mapper/fedora_uefi-root ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet + } + + ### END /etc/grub.d/10_linux ### +diff --git a/test/results/add/g2-1.15 b/test/results/add/g2-1.15 +index 0865bbc..b67c373 100644 +--- a/test/results/add/g2-1.15 ++++ b/test/results/add/g2-1.15 +@@ -81,8 +81,8 @@ menuentry 'Fedora 21 Rescue' --class fedora --class gnu-linux --class gnu --clas + else + search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b + fi +- linux16 /vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 root=/fooooo ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet +- initrd16 /initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img ++ linuxefi /vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 root=/fooooo ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++ initrdefi /initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img + } + menuentry 'Fedora, with Linux 3.15.0-0.rc5.git2.10.fc21.x86_64' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.15.0-0.rc5.git2.10.fc21.x86_64-advanced-a14e3dcb-ade3-42f7-832f-d9f66b5ae6a3' { + load_video +@@ -96,7 +96,7 @@ menuentry 'Fedora, with Linux 3.15.0-0.rc5.git2.10.fc21.x86_64' --class fedora - + else + search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b + fi +- linux16 /vmlinuz-3.15.0-0.rc5.git2.10.fc21.x86_64 root=/dev/mapper/fedora_uefi-root ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++ linuxefi /vmlinuz-3.15.0-0.rc5.git2.10.fc21.x86_64 root=/dev/mapper/fedora_uefi-root ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet + } + + ### END /etc/grub.d/10_linux ### +-- +2.4.3 + diff --git a/SOURCES/0031-Strdup-the-right-place-in-title-extraction.patch b/SOURCES/0031-Strdup-the-right-place-in-title-extraction.patch new file mode 100644 index 0000000..ff8a5b0 --- /dev/null +++ b/SOURCES/0031-Strdup-the-right-place-in-title-extraction.patch @@ -0,0 +1,36 @@ +From ea7810cf3f9abe63222b50424cab0684994daeea Mon Sep 17 00:00:00 2001 +From: Jan Stancek +Date: Tue, 11 Nov 2014 10:44:09 -0500 +Subject: [PATCH 31/41] Strdup the right place in title extraction. + +Instead of strduping and then incrementing, which means we free the +wrong location, strdup the incremented pointer. + +Resolves: rhbz#1152152 + +Signed-off-by: Peter Jones +--- + grubby.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/grubby.c b/grubby.c +index 82a0f15..f7209a9 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -821,11 +821,10 @@ static int isEntryStart(struct singleLine * line, + + /* extract the title from within brackets (for zipl) */ + static char * extractTitle(struct singleLine * line) { +- /* bracketed title... let's extract it (leaks a byte) */ ++ /* bracketed title... let's extract it */ + char * title = NULL; + if (line->type == LT_TITLE) { +- title = strdup(line->elements[0].item); +- title++; ++ title = strdup(line->elements[0].item + 1); + *(title + strlen(title) - 1) = '\0'; + } else if (line->type == LT_MENUENTRY) + title = strdup(line->elements[1].item); +-- +2.4.3 + diff --git a/SOURCES/0032-Make-the-cases-for-0cb78dab-actually-work-not-just-n.patch b/SOURCES/0032-Make-the-cases-for-0cb78dab-actually-work-not-just-n.patch new file mode 100644 index 0000000..47bf8b1 --- /dev/null +++ b/SOURCES/0032-Make-the-cases-for-0cb78dab-actually-work-not-just-n.patch @@ -0,0 +1,363 @@ +From 7d2fc73dad0e7000f7fbeb985bc6d80fbb0ea848 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 14 Apr 2015 14:34:10 -0400 +Subject: [PATCH 32/41] Make the cases for 0cb78dab /actually work/, not just + not crash. + +Resolves: rhbz#1204353 +Resolves: rhbz#1204888 +Resolves: rhbz#1206943 + +Signed-off-by: Peter Jones +--- + grubby.c | 30 +++++++++++----- + test.sh | 3 ++ + test/grub.14 | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++ + test/results/add/g1.7 | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 218 insertions(+), 8 deletions(-) + create mode 100644 test/grub.14 + create mode 100644 test/results/add/g1.7 + +diff --git a/grubby.c b/grubby.c +index f7209a9..e4358ad 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -217,6 +217,7 @@ struct configFileInfo grubConfigType = { + .mbHyperFirst = 1, + .mbInitRdIsModule = 1, + .mbAllowExtraInitRds = 1, ++ .titlePosition = 1, + }; + + struct keywordTypes grub2Keywords[] = { +@@ -586,6 +587,7 @@ struct configFileInfo eliloConfigType = { + .needsBootPrefix = 1, + .argsInQuotes = 1, + .mbConcatArgs = 1, ++ .titlePosition = 1, + }; + + struct configFileInfo liloConfigType = { +@@ -594,6 +596,7 @@ struct configFileInfo liloConfigType = { + .entryStart = LT_KERNEL, + .argsInQuotes = 1, + .maxTitleLength = 15, ++ .titlePosition = 1, + }; + + struct configFileInfo yabootConfigType = { +@@ -604,6 +607,7 @@ struct configFileInfo yabootConfigType = { + .argsInQuotes = 1, + .maxTitleLength = 15, + .mbAllowExtraInitRds = 1, ++ .titlePosition = 1, + }; + + struct configFileInfo siloConfigType = { +@@ -613,6 +617,7 @@ struct configFileInfo siloConfigType = { + .needsBootPrefix = 1, + .argsInQuotes = 1, + .maxTitleLength = 15, ++ .titlePosition = 1, + }; + + struct configFileInfo ziplConfigType = { +@@ -632,6 +637,7 @@ struct configFileInfo extlinuxConfigType = { + .maxTitleLength = 255, + .mbAllowExtraInitRds = 1, + .defaultIsUnquoted = 1, ++ .titlePosition = 1, + }; + + struct grubConfig { +@@ -820,12 +826,20 @@ static int isEntryStart(struct singleLine * line, + } + + /* extract the title from within brackets (for zipl) */ +-static char * extractTitle(struct singleLine * line) { ++static char * extractTitle(struct grubConfig *cfg, struct singleLine * line) { + /* bracketed title... let's extract it */ + char * title = NULL; ++ if (cfg->cfi == &grub2ConfigType) ++ return grub2ExtractTitle(line); + if (line->type == LT_TITLE) { +- title = strdup(line->elements[0].item + 1); +- *(title + strlen(title) - 1) = '\0'; ++ char *tmp = line->elements[cfg->cfi->titlePosition].item; ++ if (cfg->cfi->titleBracketed) { ++ tmp++; ++ title = strdup(tmp); ++ *(title + strlen(title) - 1) = '\0'; ++ } else { ++ title = strdup(tmp); ++ } + } else if (line->type == LT_MENUENTRY) + title = strdup(line->elements[1].item); + else +@@ -1433,7 +1447,7 @@ static struct grubConfig * readConfig(const char * inName, + line->elements[1].item)) break; + } else if (line) { + if (!strcmp(defaultLine->elements[1].item, +- extractTitle(line))) break; ++ extractTitle(cfg, line))) break; + } + i++; + entry = NULL; +@@ -1484,7 +1498,7 @@ static void writeDefault(FILE * out, char * indent, + if (!line) + line = getLineByType(LT_TITLE, entry->lines); + if (line) { +- title = extractTitle(line); ++ title = extractTitle(cfg, line); + if (title) + cfg->cfi->setEnv(cfg->cfi, "saved_entry", title); + } +@@ -1522,7 +1536,7 @@ static void writeDefault(FILE * out, char * indent, + else if (line && (line->numElements == 1) && + cfg->cfi->titleBracketed) { + fprintf(out, "%sdefault%s%s\n", indent, separator, +- extractTitle(line)); ++ extractTitle(cfg, line)); + } + } + } +@@ -3309,7 +3323,7 @@ int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel, + if (!line) + continue; + +- linetitle = extractTitle(line); ++ linetitle = extractTitle(cfg, line); + if (!linetitle) + continue; + if (strcmp(title, linetitle)) { +@@ -3363,7 +3377,7 @@ int updateInitrd(struct grubConfig * cfg, const char * image, + if (!line) + continue; + +- linetitle = extractTitle(line); ++ linetitle = extractTitle(cfg, line); + if (!linetitle) + continue; + if (strcmp(title, linetitle)) { +diff --git a/test.sh b/test.sh +index fb13033..30115d1 100755 +--- a/test.sh ++++ b/test.sh +@@ -269,6 +269,9 @@ grubTest grub.13 setdefaultindex/g.13.0 --set-default-index=0 + grubTest grub.13 setdefaultindex/g.13.1 --set-default-index=1 + grubTest grub.13 setdefaultindex/g.13.9 --set-default-index=9 + ++testing="GRUB add initrd" ++grubTest grub.14 add/g1.7 --boot-filesystem=/ --update-kernel=/vmlinuz-4.0.0-0.rc4.git1.4.fc23.x86_64 --initrd /initramfs-4.0.0-0.rc4.git1.4.fc23.x86_64.img '--args= LANG=en_US.UTF-8' '--title=Fedora (4.0.0-0.rc4.git1.4.fc23.x86_64) 23 (Rawhide)' ++ + testing="GRUB display default index" + grubDisplayTest grub.1 defaultindex/0 --default-index + grubDisplayTest grub.2 defaultindex/0 --default-index +diff --git a/test/grub.14 b/test/grub.14 +new file mode 100644 +index 0000000..5c0b9b3 +--- /dev/null ++++ b/test/grub.14 +@@ -0,0 +1,96 @@ ++# grub.conf generated by anaconda ++# ++# Note that you do not have to rerun grub after making changes to this file ++# NOTICE: You have a partition. This means that ++# all kernel and initrd paths are relative to /, eg. ++# root (hd0,0) ++# kernel /vmlinuz-version ro root=/dev/d2/root ++# initrd /initrd-version.img ++#boot=/dev/hda ++timeout=5 ++splashimage=(hd0,0)/grub/splash.xpm.gz ++default=0 ++hiddenmenu ++title Fedora (4.0.0-0.rc4.git1.4.fc23.x86_64) 23 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-4.0.0-0.rc4.git1.4.fc23.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++title Fedora (4.0.0-0.rc4.git0.1.fc23.x86_64) 23 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-4.0.0-0.rc4.git0.1.fc23.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-4.0.0-0.rc4.git0.1.fc23.x86_64.img ++title Fedora (4.0.0-0.rc1.git1.2.fc23.x86_64) 23 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-4.0.0-0.rc1.git1.2.fc23.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-4.0.0-0.rc1.git1.2.fc23.x86_64.img ++title Fedora (4.0.0-0.rc1.git0.1.fc23.x86_64) 23 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-4.0.0-0.rc1.git0.1.fc23.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-4.0.0-0.rc1.git0.1.fc23.x86_64.img ++title Fedora (3.20.0-0.rc0.git9.2.fc23.x86_64) 23 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.20.0-0.rc0.git9.2.fc23.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.20.0-0.rc0.git9.2.fc23.x86_64.img ++title Fedora (3.20.0-0.rc0.git6.2.fc23.x86_64) 23 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.20.0-0.rc0.git6.2.fc23.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.20.0-0.rc0.git6.2.fc23.x86_64.img ++title Fedora (3.19.0-1.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-1.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-1.fc22.x86_64.img ++title Fedora (3.19.0-0.rc7.git1.2.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-0.rc7.git1.2.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-0.rc7.git1.2.fc22.x86_64.img ++title Fedora (3.19.0-0.rc7.git0.1.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-0.rc7.git0.1.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-0.rc7.git0.1.fc22.x86_64.img ++title Fedora (3.19.0-0.rc6.git0.1.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-0.rc6.git0.1.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-0.rc6.git0.1.fc22.x86_64.img ++title Fedora (3.19.0-0.rc5.git0.1.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-0.rc5.git0.1.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-0.rc5.git0.1.fc22.x86_64.img ++title Fedora (3.19.0-0.rc4.git2.2.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-0.rc4.git2.2.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-0.rc4.git2.2.fc22.x86_64.img ++title Fedora (3.19.0-0.rc4.git0.1.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-0.rc4.git0.1.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-0.rc4.git0.1.fc22.x86_64.img ++title Fedora (3.19.0-0.rc3.git0.1.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-0.rc3.git0.1.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-0.rc3.git0.1.fc22.x86_64.img ++title Fedora (3.18.1-2.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.18.1-2.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.18.1-2.fc22.x86_64.img ++title Fedora (3.17.1-302.fc21.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.17.1-302.fc21.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.17.1-302.fc21.x86_64.img ++title Fedora 20 Rescue 4b741960432e833443a6bc004563501d (3.10.0-0.rc4.git0.1.fc20.x86_64) ++ root (hd0,0) ++ kernel /vmlinuz-0-rescue-4b741960432e833443a6bc004563501d ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-0-rescue-4b741960432e833443a6bc004563501d.img ++title Fedora 20 Rescue 4b741960432e833443a6bc004563501d (3.9.0-0.rc4.git0.1.fc20.x86_64) ++ root (hd0,0) ++ kernel /vmlinuz-0-rescue-4b741960432e833443a6bc004563501d ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-0-rescue-4b741960432e833443a6bc004563501d.img ++title Memtest86+ (4.20) ++ root (hd0,0) ++ kernel /elf-memtest86+-4.20 ++title Fedora (2.6.29.5-191.fc11.x86_64) ++ root (hd0,0) ++ kernel /vmlinuz-2.6.29.5-191.fc11.x86_64 ro root=/dev/d2/rescue64 ++ initrd /initrd-2.6.29.5-191.fc11.x86_64.img ++title install ++ kernel /f10vz ++ initrd /f10ird.img ++title gittest ++ kernel /gittest +diff --git a/test/results/add/g1.7 b/test/results/add/g1.7 +new file mode 100644 +index 0000000..dc77c0f +--- /dev/null ++++ b/test/results/add/g1.7 +@@ -0,0 +1,97 @@ ++# grub.conf generated by anaconda ++# ++# Note that you do not have to rerun grub after making changes to this file ++# NOTICE: You have a partition. This means that ++# all kernel and initrd paths are relative to /, eg. ++# root (hd0,0) ++# kernel /vmlinuz-version ro root=/dev/d2/root ++# initrd /initrd-version.img ++#boot=/dev/hda ++timeout=5 ++splashimage=(hd0,0)/grub/splash.xpm.gz ++default=0 ++hiddenmenu ++title Fedora (4.0.0-0.rc4.git1.4.fc23.x86_64) 23 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-4.0.0-0.rc4.git1.4.fc23.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-4.0.0-0.rc4.git1.4.fc23.x86_64.img ++title Fedora (4.0.0-0.rc4.git0.1.fc23.x86_64) 23 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-4.0.0-0.rc4.git0.1.fc23.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-4.0.0-0.rc4.git0.1.fc23.x86_64.img ++title Fedora (4.0.0-0.rc1.git1.2.fc23.x86_64) 23 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-4.0.0-0.rc1.git1.2.fc23.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-4.0.0-0.rc1.git1.2.fc23.x86_64.img ++title Fedora (4.0.0-0.rc1.git0.1.fc23.x86_64) 23 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-4.0.0-0.rc1.git0.1.fc23.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-4.0.0-0.rc1.git0.1.fc23.x86_64.img ++title Fedora (3.20.0-0.rc0.git9.2.fc23.x86_64) 23 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.20.0-0.rc0.git9.2.fc23.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.20.0-0.rc0.git9.2.fc23.x86_64.img ++title Fedora (3.20.0-0.rc0.git6.2.fc23.x86_64) 23 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.20.0-0.rc0.git6.2.fc23.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.20.0-0.rc0.git6.2.fc23.x86_64.img ++title Fedora (3.19.0-1.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-1.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-1.fc22.x86_64.img ++title Fedora (3.19.0-0.rc7.git1.2.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-0.rc7.git1.2.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-0.rc7.git1.2.fc22.x86_64.img ++title Fedora (3.19.0-0.rc7.git0.1.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-0.rc7.git0.1.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-0.rc7.git0.1.fc22.x86_64.img ++title Fedora (3.19.0-0.rc6.git0.1.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-0.rc6.git0.1.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-0.rc6.git0.1.fc22.x86_64.img ++title Fedora (3.19.0-0.rc5.git0.1.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-0.rc5.git0.1.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-0.rc5.git0.1.fc22.x86_64.img ++title Fedora (3.19.0-0.rc4.git2.2.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-0.rc4.git2.2.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-0.rc4.git2.2.fc22.x86_64.img ++title Fedora (3.19.0-0.rc4.git0.1.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-0.rc4.git0.1.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-0.rc4.git0.1.fc22.x86_64.img ++title Fedora (3.19.0-0.rc3.git0.1.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.19.0-0.rc3.git0.1.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.19.0-0.rc3.git0.1.fc22.x86_64.img ++title Fedora (3.18.1-2.fc22.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.18.1-2.fc22.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.18.1-2.fc22.x86_64.img ++title Fedora (3.17.1-302.fc21.x86_64) 22 (Rawhide) ++ root (hd0,0) ++ kernel /vmlinuz-3.17.1-302.fc21.x86_64 ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-3.17.1-302.fc21.x86_64.img ++title Fedora 20 Rescue 4b741960432e833443a6bc004563501d (3.10.0-0.rc4.git0.1.fc20.x86_64) ++ root (hd0,0) ++ kernel /vmlinuz-0-rescue-4b741960432e833443a6bc004563501d ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-0-rescue-4b741960432e833443a6bc004563501d.img ++title Fedora 20 Rescue 4b741960432e833443a6bc004563501d (3.9.0-0.rc4.git0.1.fc20.x86_64) ++ root (hd0,0) ++ kernel /vmlinuz-0-rescue-4b741960432e833443a6bc004563501d ro root=/dev/sda1 SYSFONT=latarcyrheb-sun16 LANG=en_US.UTF-8 KEYTABLE=us rd_plytheme=charge ++ initrd /initramfs-0-rescue-4b741960432e833443a6bc004563501d.img ++title Memtest86+ (4.20) ++ root (hd0,0) ++ kernel /elf-memtest86+-4.20 ++title Fedora (2.6.29.5-191.fc11.x86_64) ++ root (hd0,0) ++ kernel /vmlinuz-2.6.29.5-191.fc11.x86_64 ro root=/dev/d2/rescue64 ++ initrd /initrd-2.6.29.5-191.fc11.x86_64.img ++title install ++ kernel /f10vz ++ initrd /f10ird.img ++title gittest ++ kernel /gittest +-- +2.4.3 + diff --git a/SOURCES/0033-grub2ExtractTitle-and-extractTitle-don-t-do-the-same.patch b/SOURCES/0033-grub2ExtractTitle-and-extractTitle-don-t-do-the-same.patch new file mode 100644 index 0000000..21ba7bd --- /dev/null +++ b/SOURCES/0033-grub2ExtractTitle-and-extractTitle-don-t-do-the-same.patch @@ -0,0 +1,32 @@ +From aa0091e098aa8f4cccd66484c13684b3617af322 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 15 Apr 2015 15:36:00 -0400 +Subject: [PATCH 33/41] grub2ExtractTitle and extractTitle don't do the same + thing. + +So don't try to use grub2ExtractTitle in extractTitle, which actually +already knows how to do that thing right. + +Resolves: rhbz#1211887 + +Signed-off-by: Peter Jones +--- + grubby.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/grubby.c b/grubby.c +index e4358ad..5ee20e3 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -829,8 +829,6 @@ static int isEntryStart(struct singleLine * line, + static char * extractTitle(struct grubConfig *cfg, struct singleLine * line) { + /* bracketed title... let's extract it */ + char * title = NULL; +- if (cfg->cfi == &grub2ConfigType) +- return grub2ExtractTitle(line); + if (line->type == LT_TITLE) { + char *tmp = line->elements[cfg->cfi->titlePosition].item; + if (cfg->cfi->titleBracketed) { +-- +2.4.3 + diff --git a/SOURCES/0034-Set-envFile-from-env-when-bootloader-is-not-specifie.patch b/SOURCES/0034-Set-envFile-from-env-when-bootloader-is-not-specifie.patch new file mode 100644 index 0000000..72e9c8a --- /dev/null +++ b/SOURCES/0034-Set-envFile-from-env-when-bootloader-is-not-specifie.patch @@ -0,0 +1,30 @@ +From 92d813aeec67ee19b7340d3df29347c5b149b8e2 Mon Sep 17 00:00:00 2001 +From: "Brian C. Lane" +Date: Mon, 13 Apr 2015 13:57:33 -0700 +Subject: [PATCH 34/41] Set envFile from --env when bootloader is not specified + +--- + grubby.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/grubby.c b/grubby.c +index 5ee20e3..232704a 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -4371,9 +4371,11 @@ int main(int argc, const char ** argv) { + } + + if (!cfi) { +- if (grub2FindConfig(&grub2ConfigType)) ++ if (grub2FindConfig(&grub2ConfigType)) { + cfi = &grub2ConfigType; +- else ++ if (envPath) ++ cfi->envFile = envPath; ++ } else + #ifdef __ia64__ + cfi = &eliloConfigType; + #elif __powerpc__ +-- +2.4.3 + diff --git a/SOURCES/0035-grubby-properly-handle-mixed-and-and-nested-quotes.patch b/SOURCES/0035-grubby-properly-handle-mixed-and-and-nested-quotes.patch new file mode 100644 index 0000000..ccfb4dd --- /dev/null +++ b/SOURCES/0035-grubby-properly-handle-mixed-and-and-nested-quotes.patch @@ -0,0 +1,162 @@ +From 280f1ed9a0066cb508d77fe6d072c7c5aa772967 Mon Sep 17 00:00:00 2001 +From: Nishanth Aravamudan +Date: Tue, 16 Jun 2015 10:43:21 -0700 +Subject: [PATCH 35/41] grubby: properly handle mixed ' and " and nested quotes + +The SLES12 grub2.cfg file on ppc64le by default contains a line like: + + submenu "Bootable snapshot #$snapshot_num" { + menuentry "If OK, run 'snapper rollback $snapshot_num' reboot." { true; } + } + +On any grubby (tested with 8.40) invocation that updates the config +file, the combination of nested quotes and mixed quotes leads to a +generated file content like: + + submenu "Bootable snapshot #$snapshot_num" { + menuentry 'If OK, run snapper rollback $snapshot_num' rollback $snapshot_num' and reboot." { true; } + } + +which includes both a change from " to ', but also improperly quoted +strings and trailing characters relative to the string. This actually +leads to a failure to boot from the disk by default when using grubby +(e.g., Autotest) on SLES12 ppc64le. Whether SLES12 should be adding an +entry like this by default or not is probably open to debate, but grubby +should be able to hand this input file. + +To fix the issue, three changes were necessary: + +1) grub2ExtractTitle needs to check that if the second element starts +with a quote, that the matching element found ends with the same +quote-type (' vs. ") + +2) lineWrite needs to output the right kind of quote based upon if the +string to be outputted itself contains quotes. This is not currently +possible in the code, because quotes are stripped out normally by +readConfig, but with the change in 3), that only happens now for the +quotes that actually delineate a string. + +3) readConfig needs to check that when it is extracting titles and +determining extras, it uses matching quotes. + +With these changes, a simple grubby --set-default=SLES12 (for example), +now produces: + + submenu "Bootable snapshot #$snapshot_num" { + menuentry "If OK, run 'snapper rollback $snapshot_num' and reboot." { true; } + } + +as expected. + +Signed-off-by: Nishanth Aravamudan +--- + grubby.c | 42 +++++++++++++++++++++++++++++++++--------- + 1 file changed, 33 insertions(+), 9 deletions(-) + +diff --git a/grubby.c b/grubby.c +index 232704a..407c65d 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -446,6 +446,8 @@ char *grub2ExtractTitle(struct singleLine * line) { + * whose last character is also quote (assuming it's the closing one) */ + int resultMaxSize; + char * result; ++ /* need to ensure that ' does not match " as we search */ ++ char quote_char = *current; + + resultMaxSize = sizeOfSingleLine(line); + result = malloc(resultMaxSize); +@@ -459,7 +461,7 @@ char *grub2ExtractTitle(struct singleLine * line) { + current_indent_len = strlen(current_indent); + + strncat(result, current_indent, current_indent_len); +- if (!isquote(current[current_len-1])) { ++ if (current[current_len-1] != quote_char) { + strncat(result, current, current_len); + } else { + strncat(result, current, current_len - 1); +@@ -921,10 +923,23 @@ static int lineWrite(FILE * out, struct singleLine * line, + /* Need to handle this, because we strip the quotes from + * menuentry when read it. */ + if (line->type == LT_MENUENTRY && i == 1) { +- if(!isquote(*line->elements[i].item)) +- fprintf(out, "\'%s\'", line->elements[i].item); +- else ++ if(!isquote(*line->elements[i].item)) { ++ int substring = 0; ++ /* If the line contains nested quotes, we did not strip ++ * the "interna" quotes and we must use the right quotes ++ * again when writing the updated file. */ ++ for (int j = i; j < line->numElements; j++) { ++ if (strchr(line->elements[i].item, '\'') != NULL) { ++ substring = 1; ++ fprintf(out, "\"%s\"", line->elements[i].item); ++ break; ++ } ++ } ++ if (!substring) ++ fprintf(out, "\'%s\'", line->elements[i].item); ++ } else { + fprintf(out, "%s", line->elements[i].item); ++ } + fprintf(out, "%s", line->elements[i].indent); + + continue; +@@ -1260,6 +1275,8 @@ static struct grubConfig * readConfig(const char * inName, + len = 0; + char *extras; + char *title; ++ /* initially unseen value */ ++ char quote_char = '\0'; + + for (int i = 1; i < line->numElements; i++) { + len += strlen(line->elements[i].item); +@@ -1276,13 +1293,16 @@ static struct grubConfig * readConfig(const char * inName, + for (int i = 0; i < line->numElements; i++) { + if (!strcmp(line->elements[i].item, "menuentry")) + continue; +- if (isquote(*line->elements[i].item)) ++ if (isquote(*line->elements[i].item) && quote_char == '\0') { ++ /* ensure we properly pair off quotes */ ++ quote_char = *line->elements[i].item; + title = line->elements[i].item + 1; +- else ++ } else { + title = line->elements[i].item; ++ } + + len = strlen(title); +- if (isquote(title[len-1])) { ++ if (title[len-1] == quote_char) { + strncat(buf, title,len-1); + break; + } else { +@@ -1293,6 +1313,7 @@ static struct grubConfig * readConfig(const char * inName, + + /* get extras */ + int count = 0; ++ quote_char = '\0'; + for (int i = 0; i < line->numElements; i++) { + if (count >= 2) { + strcat(extras, line->elements[i].item); +@@ -1303,12 +1324,15 @@ static struct grubConfig * readConfig(const char * inName, + continue; + + /* count ' or ", there should be two in menuentry line. */ +- if (isquote(*line->elements[i].item)) ++ if (isquote(*line->elements[i].item) && quote_char == '\0') { ++ /* ensure we properly pair off quotes */ ++ quote_char = *line->elements[i].item; + count++; ++ } + + len = strlen(line->elements[i].item); + +- if (isquote(line->elements[i].item[len -1])) ++ if (line->elements[i].item[len -1] == quote_char) + count++; + + /* ok, we get the final ' or ", others are extras. */ +-- +2.4.3 + diff --git a/SOURCES/0036-Don-t-put-spaces-in-debug-entries-on-zipl-platforms.patch b/SOURCES/0036-Don-t-put-spaces-in-debug-entries-on-zipl-platforms.patch new file mode 100644 index 0000000..c44db1e --- /dev/null +++ b/SOURCES/0036-Don-t-put-spaces-in-debug-entries-on-zipl-platforms.patch @@ -0,0 +1,34 @@ +From 9d37eca5d9ec131d9129d320d983bd02fbac4f02 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 11 Nov 2014 10:46:08 -0500 +Subject: [PATCH 36/41] Don't put spaces in debug entries on zipl platforms. + +Because of course zipl can't handle spaces. + +Related: rhbz#1152152 + +Signed-off-by: Peter Jones +--- + new-kernel-pkg | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/new-kernel-pkg b/new-kernel-pkg +index 527f8fb..f6369e4 100755 +--- a/new-kernel-pkg ++++ b/new-kernel-pkg +@@ -140,7 +140,11 @@ rungrubby() { + if [ "$1" == "--debug" ]; then + [ "$MAKEDEBUG" != "yes" ] && return 0 + [ -n "$verbose" ] && echo "- First, making a debug entry." +- declare -x debugtitle=" with debugging" ++ if [ $ARCH = 's390' -o $ARCH = 's390x' ]; then ++ declare -x debugtitle="_with_debugging" ++ else ++ declare -x debugtitle=" with debugging" ++ fi + declare -x debugargs="$DEBUGARG" + shift + else +-- +2.4.3 + diff --git a/SOURCES/0037-Drop-SEGV-handler.patch b/SOURCES/0037-Drop-SEGV-handler.patch new file mode 100644 index 0000000..0248053 --- /dev/null +++ b/SOURCES/0037-Drop-SEGV-handler.patch @@ -0,0 +1,52 @@ +From b901efc638080e552fb94d7842775f1aaf95c0dd Mon Sep 17 00:00:00 2001 +From: Lubomir Rintel +Date: Thu, 27 Feb 2014 10:35:59 +0100 +Subject: [PATCH 37/41] Drop SEGV handler + +The generated tracebacks are mostly useless without debuginfo (which is likely +not present if the crash is not anticipated) and prevent ABRT from doing a +better job. + +Signed-off-by: Lubomir Rintel +--- + grubby.c | 17 ----------------- + 1 file changed, 17 deletions(-) + +diff --git a/grubby.c b/grubby.c +index 407c65d..a2b0d55 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -4163,21 +4163,6 @@ int addNewKernel(struct grubConfig * config, struct singleEntry * template, + return 0; + } + +-static void traceback(int signum) +-{ +- void *array[40]; +- size_t size; +- +- signal(SIGSEGV, SIG_DFL); +- memset(array, '\0', sizeof (array)); +- size = backtrace(array, 40); +- +- fprintf(stderr, "grubby received SIGSEGV! Backtrace (%ld):\n", +- (unsigned long)size); +- backtrace_symbols_fd(array, size, STDERR_FILENO); +- exit(1); +-} +- + int main(int argc, const char ** argv) { + poptContext optCon; + const char * grubConfig = NULL; +@@ -4316,8 +4301,6 @@ int main(int argc, const char ** argv) { + + useextlinuxmenu=0; + +- signal(SIGSEGV, traceback); +- + int i = 0; + for (int j = 1; j < argc; j++) + i += strlen(argv[j]) + 1; +-- +2.4.3 + diff --git a/SOURCES/0038-Add-a-bunch-of-tests-for-various-default-kernel-titl.patch b/SOURCES/0038-Add-a-bunch-of-tests-for-various-default-kernel-titl.patch new file mode 100644 index 0000000..a53c4f4 --- /dev/null +++ b/SOURCES/0038-Add-a-bunch-of-tests-for-various-default-kernel-titl.patch @@ -0,0 +1,182 @@ +From 78b6384b47585fc7d8f4020920ad72100623ce3b Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 2 Jul 2015 12:34:30 -0400 +Subject: [PATCH 38/41] Add a bunch of tests for various + --default-{kernel,title,index}. + +... and fix some failures where we see them. + +Related: rhbz#1184014 + +(though I can't actually replicate his failure.) + +Signed-off-by: Peter Jones +--- + grubby.c | 50 ++++++++++++++++++++++++----------------- + test.sh | 10 +++++++++ + test/results/defaultkernel/g.1 | 1 + + test/results/defaultkernel/l1.1 | 1 + + test/results/defaultkernel/z.1 | 1 + + test/results/defaulttitle/z.1 | 1 + + 6 files changed, 44 insertions(+), 20 deletions(-) + create mode 100644 test/results/defaultkernel/g.1 + create mode 100644 test/results/defaultkernel/l1.1 + create mode 100644 test/results/defaultkernel/z.1 + create mode 100644 test/results/defaulttitle/z.1 + +diff --git a/grubby.c b/grubby.c +index a2b0d55..ecd0e9b 100644 +--- a/grubby.c ++++ b/grubby.c +@@ -423,7 +423,7 @@ char *grub2ExtractTitle(struct singleLine * line) { + + /* bail out if line does not start with menuentry */ + if (strcmp(line->elements[0].item, "menuentry")) +- return NULL; ++ return NULL; + + i = 1; + current = line->elements[i].item; +@@ -432,10 +432,12 @@ char *grub2ExtractTitle(struct singleLine * line) { + /* if second word is quoted, strip the quotes and return single word */ + if (isquote(*current) && isquote(current[current_len - 1])) { + char *tmp; +- +- tmp = strdup(current); +- *(tmp + current_len - 1) = '\0'; +- return ++tmp; ++ ++ tmp = strdup(current+1); ++ if (!tmp) ++ return NULL; ++ tmp[strlen(tmp)-1] = '\0'; ++ return tmp; + } + + /* if no quotes, return second word verbatim */ +@@ -448,11 +450,11 @@ char *grub2ExtractTitle(struct singleLine * line) { + char * result; + /* need to ensure that ' does not match " as we search */ + char quote_char = *current; +- ++ + resultMaxSize = sizeOfSingleLine(line); + result = malloc(resultMaxSize); + snprintf(result, resultMaxSize, "%s", ++current); +- ++ + i++; + for (; i < line->numElements; ++i) { + current = line->elements[i].item; +@@ -4596,27 +4598,35 @@ int main(int argc, const char ** argv) { + struct singleLine * line; + struct singleEntry * entry; + +- if (config->defaultImage == -1) return 0; ++ if (config->defaultImage == -1) ++ return 0; + if (config->defaultImage == DEFAULT_SAVED_GRUB2 && + cfi->defaultIsSaved) + config->defaultImage = 0; + entry = findEntryByIndex(config, config->defaultImage); +- if (!entry) return 0; ++ if (!entry) ++ return 0; + + if (!configureGrub2) { +- line = getLineByType(LT_TITLE, entry->lines); +- if (!line) return 0; +- printf("%s\n", line->elements[1].item); +- ++ char *title; ++ line = getLineByType(LT_TITLE, entry->lines); ++ if (!line) ++ return 0; ++ title = extractTitle(config, line); ++ if (!title) ++ return 0; ++ printf("%s\n", title); ++ free(title); + } else { +- char * title; ++ char * title; + +- dbgPrintf("This is GRUB2, default title is embeded in menuentry\n"); +- line = getLineByType(LT_MENUENTRY, entry->lines); +- if (!line) return 0; +- title = grub2ExtractTitle(line); +- if (title) +- printf("%s\n", title); ++ dbgPrintf("This is GRUB2, default title is embeded in menuentry\n"); ++ line = getLineByType(LT_MENUENTRY, entry->lines); ++ if (!line) ++ return 0; ++ title = grub2ExtractTitle(line); ++ if (title) ++ printf("%s\n", title); + } + return 0; + +diff --git a/test.sh b/test.sh +index 30115d1..efd9e84 100755 +--- a/test.sh ++++ b/test.sh +@@ -298,6 +298,9 @@ grubDisplayTest grub.9 defaulttitle/g.9 --default-title + grubDisplayTest grub.10 defaulttitle/g.10 --default-title + grubDisplayTest grub.11 defaulttitle/g.11 --default-title + ++testing="GRUB display default kernel" ++grubDisplayTest grub.1 defaultkernel/g.1 --default-kernel ++ + testing="LILO default directive" + liloTest lilo.1 default/l1.1 --set-default=/boot/vmlinuz-2.4.18-4 + liloTest lilo.1 default/l1.2 --remove-kernel=/boot/vmlinuz-2.4.18-4smp +@@ -305,10 +308,17 @@ liloTest lilo.1 default/l1.3 --add-kernel /boot/kernel --title label \ + --copy-default + liloTest lilo.1 default/l1.4 --add-kernel /boot/kernel --title label \ + --copy-default --make-default ++liloDisplayTest lilo.1 defaultkernel/l1.1 --default-kernel + + testing="Z/IPL default directive" + ziplTest zipl.1 default/z1.1 --add-kernel /boot/new-kernel --title test + ziplTest zipl.1 default/z1.2 --add-kernel /boot/new-kernel --title test --make-default ++testing="Z/IPL display default index" ++ziplDisplayTest zipl.1 defaultindex/0 --default-index ++testing="Z/IPL display default title" ++ziplDisplayTest zipl.1 defaulttitle/z.1 --default-title ++testing="Z/IPL display default kernel" ++ziplDisplayTest zipl.1 defaultkernel/z.1 --default-kernel + + testing="GRUB fallback directive" + grubTest grub.5 fallback/g5.1 --remove-kernel=/boot/vmlinuz-2.4.7-ac3 \ +diff --git a/test/results/defaultkernel/g.1 b/test/results/defaultkernel/g.1 +new file mode 100644 +index 0000000..2c3ac11 +--- /dev/null ++++ b/test/results/defaultkernel/g.1 +@@ -0,0 +1 @@ ++/boot/vmlinuz-2.4.7-2 +diff --git a/test/results/defaultkernel/l1.1 b/test/results/defaultkernel/l1.1 +new file mode 100644 +index 0000000..fd22b1b +--- /dev/null ++++ b/test/results/defaultkernel/l1.1 +@@ -0,0 +1 @@ ++/boot/vmlinuz-2.4.18-4smp +diff --git a/test/results/defaultkernel/z.1 b/test/results/defaultkernel/z.1 +new file mode 100644 +index 0000000..2c62e98 +--- /dev/null ++++ b/test/results/defaultkernel/z.1 +@@ -0,0 +1 @@ ++/boot/vmlinuz-2.4.9-37 +diff --git a/test/results/defaulttitle/z.1 b/test/results/defaulttitle/z.1 +new file mode 100644 +index 0000000..a08e1f3 +--- /dev/null ++++ b/test/results/defaulttitle/z.1 +@@ -0,0 +1 @@ ++linux +-- +2.4.3 + diff --git a/SOURCES/0039-Emit-better-systemd-debug-settings-on-debug-entries.patch b/SOURCES/0039-Emit-better-systemd-debug-settings-on-debug-entries.patch new file mode 100644 index 0000000..102218a --- /dev/null +++ b/SOURCES/0039-Emit-better-systemd-debug-settings-on-debug-entries.patch @@ -0,0 +1,28 @@ +From fe41880f07b93914ce8a6132f4e5526c78772935 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 2 Jul 2015 12:44:51 -0400 +Subject: [PATCH 39/41] Emit better systemd debug settings on debug entries. + +Resolves: rhbz#1212128 + +Signed-off-by: Peter Jones +--- + new-kernel-pkg | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/new-kernel-pkg b/new-kernel-pkg +index f6369e4..f547336 100755 +--- a/new-kernel-pkg ++++ b/new-kernel-pkg +@@ -121,7 +121,7 @@ mbkernel="$HYPERVISOR" + mbargs="$HYPERVISOR_ARGS" + adddracutargs="" + addplymouthinitrd="" +-DEBUGARG="systemd.debug" ++DEBUGARG="systemd.log_level=debug systemd.log_target=kmsg" + + usage() { + echo "Usage: `basename $0` [-v] [--mkinitrd] [--rminitrd] [--dracut]" >&2 +-- +2.4.3 + diff --git a/SOURCES/0040-Make-the-grub1-defaultkernel-test-more-reliable.patch b/SOURCES/0040-Make-the-grub1-defaultkernel-test-more-reliable.patch new file mode 100644 index 0000000..c483030 --- /dev/null +++ b/SOURCES/0040-Make-the-grub1-defaultkernel-test-more-reliable.patch @@ -0,0 +1,41 @@ +From 62ad4dfa328dc24b4786d9c0c35ebcbd1fe574b9 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 2 Jul 2015 14:30:09 -0400 +Subject: [PATCH 40/41] Make the grub1 "defaultkernel" test more reliable. + +Basically just do it twice with various incarnations of +--boot-filesystem={/,/boot} + +Related: rhbz#1184014 + +Signed-off-by: Peter Jones +--- + test.sh | 3 ++- + test/results/defaultkernel/g.2 | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + create mode 100644 test/results/defaultkernel/g.2 + +diff --git a/test.sh b/test.sh +index efd9e84..74857af 100755 +--- a/test.sh ++++ b/test.sh +@@ -299,7 +299,8 @@ grubDisplayTest grub.10 defaulttitle/g.10 --default-title + grubDisplayTest grub.11 defaulttitle/g.11 --default-title + + testing="GRUB display default kernel" +-grubDisplayTest grub.1 defaultkernel/g.1 --default-kernel ++grubDisplayTest grub.1 defaultkernel/g.1 --boot-filesystem=/boot --default-kernel ++grubDisplayTest grub.1 defaultkernel/g.2 --boot-filesystem=/ --default-kernel + + testing="LILO default directive" + liloTest lilo.1 default/l1.1 --set-default=/boot/vmlinuz-2.4.18-4 +diff --git a/test/results/defaultkernel/g.2 b/test/results/defaultkernel/g.2 +new file mode 100644 +index 0000000..d15855e +--- /dev/null ++++ b/test/results/defaultkernel/g.2 +@@ -0,0 +1 @@ ++/vmlinuz-2.4.7-2 +-- +2.4.3 + diff --git a/SOURCES/0041-Work-around-aarch64-not-having-quite-the-same-grub-c.patch b/SOURCES/0041-Work-around-aarch64-not-having-quite-the-same-grub-c.patch new file mode 100644 index 0000000..9947df9 --- /dev/null +++ b/SOURCES/0041-Work-around-aarch64-not-having-quite-the-same-grub-c.patch @@ -0,0 +1,186 @@ +From d9009de3ff466ed12604d93f92329000aca7b33e Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 2 Jul 2015 15:06:15 -0400 +Subject: [PATCH 41/41] Work around aarch64 not having quite the same grub + commands as x86. + +A workaround for a workaround :/ + +Related: rhbz#1200045 +Related: rhbz#1142545 +Related: rhbz#1184014 + +Signed-off-by: Peter Jones +--- + test.sh | 21 +++++-- + test/results/add/g2-1.15.aarch64 | 126 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 142 insertions(+), 5 deletions(-) + create mode 100644 test/results/add/g2-1.15.aarch64 + +diff --git a/test.sh b/test.sh +index 74857af..c2a66e2 100755 +--- a/test.sh ++++ b/test.sh +@@ -525,11 +525,22 @@ if [ "$testgrub2" == "y" ]; then + grub2Test grub2.5 add/g2-1.5 --add-kernel=/boot/new-kernel.img \ + --title='title' --initrd=/boot/new-initrd --boot-filesystem=/boot/ \ + --copy-default +- grub2Test grub2.15 add/g2-1.15 \ +- --add-kernel=/boot/vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 \ +- --initrd /boot/initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img \ +- --copy-default --title "Fedora 21 Rescue" --args=root=/fooooo \ +- --remove-kernel=wtf --boot-filesystem=/boot/ --efi ++ case $ARCH in ++ aarch64) ++ grub2Test grub2.15 add/g2-1.15.aarch64 \ ++ --add-kernel=/boot/vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 \ ++ --initrd /boot/initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img \ ++ --copy-default --title "Fedora 21 Rescue" --args=root=/fooooo \ ++ --remove-kernel=wtf --boot-filesystem=/boot/ --efi ++ ;; ++ *) ++ grub2Test grub2.15 add/g2-1.15 \ ++ --add-kernel=/boot/vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 \ ++ --initrd /boot/initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img \ ++ --copy-default --title "Fedora 21 Rescue" --args=root=/fooooo \ ++ --remove-kernel=wtf --boot-filesystem=/boot/ --efi ++ ;; ++ esac + + testing="GRUB2 add initrd" + grub2Test grub2.2 add/g2-1.4 --update-kernel=/boot/new-kernel.img \ +diff --git a/test/results/add/g2-1.15.aarch64 b/test/results/add/g2-1.15.aarch64 +new file mode 100644 +index 0000000..ee5f868 +--- /dev/null ++++ b/test/results/add/g2-1.15.aarch64 +@@ -0,0 +1,126 @@ ++# ++# DO NOT EDIT THIS FILE ++# ++# It is automatically generated by grub2-mkconfig using templates ++# from /etc/grub.d and settings from /etc/default/grub ++# ++ ++### BEGIN /etc/grub.d/00_header ### ++set pager=1 ++ ++if [ -s $prefix/grubenv ]; then ++ load_env ++fi ++if [ "${next_entry}" ] ; then ++ set default="${next_entry}" ++ set next_entry= ++ save_env next_entry ++ set boot_once=true ++else ++ set default="${saved_entry}" ++fi ++ ++if [ x"${feature_menuentry_id}" = xy ]; then ++ menuentry_id_option="--id" ++else ++ menuentry_id_option="" ++fi ++ ++export menuentry_id_option ++ ++if [ "${prev_saved_entry}" ]; then ++ set saved_entry="${prev_saved_entry}" ++ save_env saved_entry ++ set prev_saved_entry= ++ save_env prev_saved_entry ++ set boot_once=true ++fi ++ ++function savedefault { ++ if [ -z "${boot_once}" ]; then ++ saved_entry="${chosen}" ++ save_env saved_entry ++ fi ++} ++ ++function load_video { ++ if [ x$feature_all_video_module = xy ]; then ++ insmod all_video ++ else ++ insmod efi_gop ++ insmod efi_uga ++ insmod ieee1275_fb ++ insmod vbe ++ insmod vga ++ insmod video_bochs ++ insmod video_cirrus ++ fi ++} ++ ++terminal_output console ++if [ x$feature_timeout_style = xy ] ; then ++ set timeout_style=menu ++ set timeout=5 ++# Fallback normal timeout code in case the timeout_style feature is ++# unavailable. ++else ++ set timeout=5 ++fi ++### END /etc/grub.d/00_header ### ++ ++### BEGIN /etc/grub.d/10_linux ### ++menuentry 'Fedora 21 Rescue' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.15.0-0.rc5.git2.10.fc21.x86_64-advanced-a14e3dcb-ade3-42f7-832f-d9f66b5ae6a3' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod ext2 ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ else ++ search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ fi ++ linuxefi /vmlinuz-0-rescue-5a94251776a14678911d4ae0949500f5 root=/fooooo ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++ initrd /initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img ++} ++menuentry 'Fedora, with Linux 3.15.0-0.rc5.git2.10.fc21.x86_64' --class fedora --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.15.0-0.rc5.git2.10.fc21.x86_64-advanced-a14e3dcb-ade3-42f7-832f-d9f66b5ae6a3' { ++ load_video ++ set gfxpayload=keep ++ insmod gzio ++ insmod part_msdos ++ insmod ext2 ++ set root='hd0,msdos1' ++ if [ x$feature_platform_search_hint = xy ]; then ++ search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ else ++ search --no-floppy --fs-uuid --set=root 6169b46f-0257-4319-b2e4-caaed2a8e06b ++ fi ++ linuxefi /vmlinuz-3.15.0-0.rc5.git2.10.fc21.x86_64 root=/dev/mapper/fedora_uefi-root ro rd.lvm.lv=fedora_uefi/root rd.lvm.lv=fedora_uefi/swap rhgb quiet ++} ++ ++### END /etc/grub.d/10_linux ### ++ ++### BEGIN /etc/grub.d/20_linux_xen ### ++ ++### END /etc/grub.d/20_linux_xen ### ++ ++### BEGIN /etc/grub.d/20_ppc_terminfo ### ++### END /etc/grub.d/20_ppc_terminfo ### ++ ++### BEGIN /etc/grub.d/30_os-prober ### ++### END /etc/grub.d/30_os-prober ### ++ ++### BEGIN /etc/grub.d/40_custom ### ++# This file provides an easy way to add custom menu entries. Simply type the ++# menu entries you want to add after this comment. Be careful not to change ++# the 'exec tail' line above. ++### END /etc/grub.d/40_custom ### ++ ++### BEGIN /etc/grub.d/41_custom ### ++if [ -f ${config_directory}/custom.cfg ]; then ++ source ${config_directory}/custom.cfg ++elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then ++ source $prefix/custom.cfg; ++fi ++### END /etc/grub.d/41_custom ### +-- +2.4.3 + diff --git a/SPECS/grubby.spec b/SPECS/grubby.spec index 0889e5c..afc8670 100644 --- a/SPECS/grubby.spec +++ b/SPECS/grubby.spec @@ -1,29 +1,60 @@ Name: grubby Version: 8.28 -Release: 11%{?dist} +Release: 17%{?dist} Summary: Command line tool for updating bootloader configs Group: System Environment/Base License: GPLv2+ URL: http://git.fedorahosted.org/git/grubby.git Source0: https://git.fedorahosted.org/cgit/grubby.git/snapshot/%{name}-%{version}-1.tar.bz2 -Patch0001: 0001-Use-PREFIX-during-make-install.patch -Patch0002: 0002-Honor-linux16-and-initrd16.patch -Patch0003: 0003-Only-set-RPM_OPT_FLAGS-if-undefined.patch -Patch0004: 0004-Drop-SEGV-handler.patch -Patch0005: 0005-grub-Fix-a-crash-with-kernel-line-without-being-prec.patch +Patch0001: 0001-Only-set-RPM_OPT_FLAGS-if-undefined.patch +Patch0002: 0002-If-we-re-using-multiboot-add-a-new-mbmodule-not-an-i.patch +Patch0003: 0003-Use-PREFIX-during-make-install.patch +Patch0004: 0004-Honor-linux16-and-initrd16.patch +Patch0005: 0005-If-we-re-on-a-zipl-based-platform-use-banner-passed-.patch Patch0006: 0006-Support-devicetree-directive-in-grub2.patch Patch0007: 0007-Actually-USE-DEVTREE-in-new-kernel-pkg.patch -Patch0008: 0008-Fix-bad-check-for-new-kernel-pkg-s-command-line-argu.patch -Patch0009: 0009-Actually-do-a-fix-for-rhbz-1082318-that-fixes-the-is.patch -Patch0010: 0010-Use-the-correct-load-commands-for-aarch64-efi.patch -Patch0011: 0011-Tell-a-slightly-better-fib-about-default-bootloader-.patch -Patch0012: 0012-Make-findTemplate-actually-return-the-saved-default.patch -Patch0013: 0013-If-we-re-using-multiboot-add-a-new-mbmodule-not-an-i.patch -Patch0014: 0014-Support-filtering-update-kernel-by-title-as-well.patch -Patch0015: 0015-If-we-re-on-a-zipl-based-platform-use-banner-passed-.patch -Patch0016: 0016-Conditionally-create-debug-entries-when-installing-k.patch -Patch0017: 0001-Don-t-put-spaces-in-debug-entries-on-zipl-platforms.patch -Patch0018: 0002-Strdup-the-right-place-in-title-extraction.patch +Patch0008: 0008-Use-the-correct-load-commands-for-aarch64-efi.patch +Patch0009: 0009-Always-choose-linux-initrd-on-efi-only-platforms.patch +Patch0010: 0010-extlinux-Understand-default-properly.patch +Patch0011: 0011-extlinux-Add-test-suite.patch +Patch0012: 0012-grub-Fix-a-crash-with-kernel-line-without-being-prec.patch +Patch0013: 0013-grub-Remove-a-redundant-test.patch +Patch0014: 0014-Fix-bad-check-for-new-kernel-pkg-s-command-line-argu.patch +Patch0015: 0015-Previous-ARM-64-bit-test-had-the-wrong-compiler-defi.patch +Patch0016: 0016-Actually-do-a-fix-for-rhbz-1082318-that-fixes-the-is.patch +Patch0017: 0017-Strip-the-LT_END-line-from-a-new-stanza-before-addin.patch +Patch0018: 0018-Fix-a-wrong-test-case-lacked-boot-filesystem.patch +Patch0019: 0019-Don-t-go-past-the-last-element-of-indexVars-in-findE.patch +Patch0020: 0020-Tell-a-slightly-better-fib-about-default-bootloader-.patch +Patch0021: 0021-Make-findTemplate-actually-return-the-saved-default.patch +Patch0022: 0022-Support-filtering-update-kernel-by-title-as-well.patch +Patch0023: 0023-Conditionally-create-debug-entries-when-installing-k.patch +Patch0024: 0024-Always-error-check-getLineByType.patch +Patch0025: 0025-Get-the-error-checking-on-getLineByType-return-right.patch +Patch0026: 0026-Fix-ppc-kernelName-when-invoked-by-installkernel.patch +Patch0027: 0027-Update-grubby-man-page-for-Power8-PPC64LE.patch +Patch0028: 0028-Update-man-page-to-include-default-config-file-for-s.patch +Patch0029: 0029-Split-the-test-case-for-rescue-images-into-tests-wit.patch +Patch0030: 0030-Actually-get-the-test-from-a7800d8f-right.patch +Patch0031: 0031-Strdup-the-right-place-in-title-extraction.patch +Patch0032: 0032-Make-the-cases-for-0cb78dab-actually-work-not-just-n.patch +Patch0033: 0033-grub2ExtractTitle-and-extractTitle-don-t-do-the-same.patch +Patch0034: 0034-Set-envFile-from-env-when-bootloader-is-not-specifie.patch +Patch0035: 0035-grubby-properly-handle-mixed-and-and-nested-quotes.patch +Patch0036: 0036-Don-t-put-spaces-in-debug-entries-on-zipl-platforms.patch +Patch0037: 0037-Drop-SEGV-handler.patch +Patch0038: 0038-Add-a-bunch-of-tests-for-various-default-kernel-titl.patch +Patch0039: 0039-Emit-better-systemd-debug-settings-on-debug-entries.patch +Patch0040: 0040-Make-the-grub1-defaultkernel-test-more-reliable.patch +Patch0041: 0041-Work-around-aarch64-not-having-quite-the-same-grub-c.patch +Patch0042: 0001-ppc64le-sync-grub.cfg-changes-to-disk-1212114.patch +Patch0043: 0001-Make-it-possible-to-run-test.sh-verbose-from-the-mak.patch +Patch0044: 0001-Don-t-leak-from-one-extractTitle-call.patch +Patch0045: 0002-Better-formatting.patch +Patch0046: 0003-Make-SET_VARIABLE-get-handled-individually-in-GetNex.patch +Patch0047: 0001-Specify-bootloader-directory-in-the-test-case-for-11.patch +Patch0048: 0001-Fix-some-coverity-concerns.patch +Patch0049: 0001-Always-do-the-rungrubby-debug-after-the-normal-kerne.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: pkgconfig glib2-devel popt-devel @@ -94,6 +125,43 @@ rm -rf $RPM_BUILD_ROOT %endif %changelog +* Mon Oct 26 2015 Peter Jones - 8.28-17 +- Fix the ordering of creating the debug entries, so they don't get picked + when we're choosing kernel command line defaults on upgrades. + Related: rhbz#1212128 + +* Thu Sep 10 2015 Peter Jones - 8.28-16 +- Fix some coverity concerns and other issues with 8.28-15... + Resolves: rhbz#1152550 + +* Thu Sep 10 2015 Peter Jones - 8.28-15 +- Fix some coverity concerns and other issues with 8.28-14 (sigh) + Resolves: rhbz#1152550 + +* Tue Sep 01 2015 Peter Jones - 8.28-14 +- Handle "set variable" commands separately from other parsing in grubby's + GetNextLine() + Resolves: rhbz#1152550 + +* Wed Aug 05 2015 Robert Marshall - 8.28-13 +- Ensure file changes sync to disk on ppc64le platform. + Related: rhbz#1212114 + +* Thu Jul 02 2015 Peter Jones - 8.28-12 +- Do a better job recognizing "title" and "default" position and formatting + on extlinux + Resolves: rhbz#1200045 +- Do a better job recognizing stanza names and defaults on grub1 and grub2 + Related: rhbz#1142545 +- (reordered some patches to match the ordering in master) + Related: rhbz#1200045 + Related: rhbz#1142545 +- Add test suite coverage and minor fixes related to zipl and + --default-{kernel,index,title} + Related: rhbz#1184014 +- Use systemd debug options that work on RHEL 7 + Resolves: rhbz#1212128 + * Tue Nov 11 2014 Peter Jones - 8.28-11 - Fix a memory corruption issue we're hitting on s390/s390x Resolves: rhbz#1152152