diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2ac8fd7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/grubby-8.28-1.tar.bz2
diff --git a/.grubby.metadata b/.grubby.metadata
new file mode 100644
index 0000000..f409427
--- /dev/null
+++ b/.grubby.metadata
@@ -0,0 +1 @@
+95fe18b3e22a7fea3cfbdb11f80f4351411b310a SOURCES/grubby-8.28-1.tar.bz2
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" <dmarlin@redhat.com>
+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 <dmarlin@redhat.com>
+---
+ 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/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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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/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 <pjones@redhat.com>
+Date: Fri, 13 Sep 2013 10:37:10 -0400
+Subject: [PATCH 03/41] Use $(PREFIX) during make install.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ 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-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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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/0006-Support-devicetree-directive-in-grub2.patch b/SOURCES/0006-Support-devicetree-directive-in-grub2.patch
new file mode 100644
index 0000000..e77261b
--- /dev/null
+++ b/SOURCES/0006-Support-devicetree-directive-in-grub2.patch
@@ -0,0 +1,65 @@
+From 87408a542b2626078e69ba019d2c581ebabc104e Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 11 Feb 2014 10:24:48 -0500
+Subject: [PATCH 06/41] Support "devicetree" directive in grub2.
+
+Resolves: rhbz#1063534
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ new-kernel-pkg | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/new-kernel-pkg b/new-kernel-pkg
+index 4fa94b7..7479557 100755
+--- a/new-kernel-pkg
++++ b/new-kernel-pkg
+@@ -111,6 +111,7 @@ initrd=""
+ dracut=""
+ dracuthostonly=""
+ initrdfile=""
++devtreefile=""
+ moddep=""
+ verbose=""
+ makedefault=""
+@@ -127,7 +128,7 @@ usage() {
+     echo "       [--banner=<banner>] [--multiboot=multiboot]" >&2
+     echo "       [--mbargs=mbargs] [--make-default] [--add-dracut-args]" >&2
+     echo "       [--add-plymouth-initrd]" >&2
+-    echo "       [--host-only]" >&2
++    echo "       [--host-only] [--devtree=<devicetree.dtb>]" >&2
+     echo "       <--install | --remove | --update | --rpmposttrans> <kernel-version>" >&2
+     echo "       (ex: `basename $0` --mkinitrd --depmod --install 2.4.7-2)" >&2
+     exit 1
+@@ -151,6 +152,12 @@ install() {
+ 	fi
+     fi
+ 
++    DEVTREE=""
++    if [ -f $devtreefile ]; then
++	[ -n "$verbose" ] && echo "found $devtreefile and using it with grubby"
++	DEVTREE="--devtree $devtreefile"
++    fi
++
+     # 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"
+@@ -544,6 +551,15 @@ while [ $# -gt 0 ]; do
+ 	    initrd="remove"
+ 	    ;;
+ 
++	--devtree*)
++	    if [[ $1 == --devtree\=* ]]; then
++		devtreefile=${1#--devtreefile=}
++	    else
++		devtreefile=$2
++		shift
++	    fi
++	    ;;
++
+ 	--dracut)
+ 	    dracut=--dracut
+ 	    ;;
+-- 
+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
new file mode 100644
index 0000000..d8b008d
--- /dev/null
+++ b/SOURCES/0007-Actually-USE-DEVTREE-in-new-kernel-pkg.patch
@@ -0,0 +1,28 @@
+From b8ad9832948f86bf051c15d212fe2c978313c7f8 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 12 Feb 2014 10:58:48 -0500
+Subject: [PATCH 07/41] Actually /USE/ $DEVTREE in new-kernel-pkg.
+
+Resolves: rhbz#1063534
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ new-kernel-pkg | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/new-kernel-pkg b/new-kernel-pkg
+index 7479557..97e1839 100755
+--- a/new-kernel-pkg
++++ b/new-kernel-pkg
+@@ -230,7 +230,7 @@ install() {
+ 	[ -n "$verbose" ] && echo "adding $version to $grub2EfiConfig"
+ 
+ 	$grubby --grub2 -c $grub2EfiConfig --efi \
+-	    --add-kernel=$kernelImage \
++	    --add-kernel=$kernelImage $DEVTREE \
+ 	    $INITRD --copy-default $makedefault --title "$title" \
+ 	    ${mbkernel:+--add-multiboot="$mbkernel"} \
+ 	    ${mbargs:+--mbargs="$mbargs"} \
+-- 
+2.4.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 <noone@example.com>
+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-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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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-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 <lkundrak@v3.sk>
+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 <lkundrak@v3.sk>
+---
+ 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-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 <lkundrak@v3.sk>
+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 <lkundrak@v3.sk>
+---
+ 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-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 <lkundrak@v3.sk>
+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 <lkundrak@v3.sk>
+---
+ 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-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 <lkundrak@v3.sk>
+Date: Wed, 27 Nov 2013 16:59:47 +0100
+Subject: [PATCH 13/41] grub: Remove a redundant test
+
+Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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/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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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/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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <scientist@fb.com>
+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 <scientist@fb.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <pjones@redhat.com>
+Date: Thu, 25 Sep 2014 13:24:15 -0400
+Subject: [PATCH 24/41] Always error check getLineByType()
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <rmarshall@redhat.com>
+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 <rmarshall@redhat.com>
+---
+ 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 <rmarshall@redhat.com>
+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 <rmarshall@redhat.com>
+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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <jstancek@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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" <bcl@redhat.com>
+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 <nacc@linux.vnet.ibm.com>
+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 <nacc@linux.vnet.ibm.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <lkundrak@v3.sk>
+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 <lkundrak@v3.sk>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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/SOURCES/0042-ppc64le-sync-grub.cfg-changes-to-disk-1212114.patch b/SOURCES/0042-ppc64le-sync-grub.cfg-changes-to-disk-1212114.patch
new file mode 100644
index 0000000..f4971af
--- /dev/null
+++ b/SOURCES/0042-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 <dzickus@redhat.com>
+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/0043-Make-it-possible-to-run-test.sh-verbose-from-the-mak.patch b/SOURCES/0043-Make-it-possible-to-run-test.sh-verbose-from-the-mak.patch
new file mode 100644
index 0000000..8ccf23b
--- /dev/null
+++ b/SOURCES/0043-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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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/0044-Don-t-leak-from-one-extractTitle-call.patch b/SOURCES/0044-Don-t-leak-from-one-extractTitle-call.patch
new file mode 100644
index 0000000..6489935
--- /dev/null
+++ b/SOURCES/0044-Don-t-leak-from-one-extractTitle-call.patch
@@ -0,0 +1,85 @@
+From 7713f8e23e326dcf1258a715e2554a4bf53dec59 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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/0045-Better-formatting.patch b/SOURCES/0045-Better-formatting.patch
new file mode 100644
index 0000000..fafdd95
--- /dev/null
+++ b/SOURCES/0045-Better-formatting.patch
@@ -0,0 +1,9034 @@
+From aaea1dbe7731a481a1f62b312a5dd5ac77c10926 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 10 Sep 2015 18:27:31 -0400
+Subject: [PATCH] Reformat to make this easier to work on.
+
+Signed-off-by: Peter Jones <noone@example.com>
+---
+ 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, &copyDefault, 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, &copyDefault, 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/0046-Make-SET_VARIABLE-get-handled-individually-in-GetNex.patch b/SOURCES/0046-Make-SET_VARIABLE-get-handled-individually-in-GetNex.patch
new file mode 100644
index 0000000..08a32e5
--- /dev/null
+++ b/SOURCES/0046-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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ .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/0047-Specify-bootloader-directory-in-the-test-case-for-11.patch b/SOURCES/0047-Specify-bootloader-directory-in-the-test-case-for-11.patch
new file mode 100644
index 0000000..79639f8
--- /dev/null
+++ b/SOURCES/0047-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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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/0048-Fix-some-coverity-concerns.patch b/SOURCES/0048-Fix-some-coverity-concerns.patch
new file mode 100644
index 0000000..a00bdde
--- /dev/null
+++ b/SOURCES/0048-Fix-some-coverity-concerns.patch
@@ -0,0 +1,613 @@
+From 916d5770b5c8fb87503a99f98c13a5232a7dafbf Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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/0049-Always-do-the-rungrubby-debug-after-the-normal-kerne.patch b/SOURCES/0049-Always-do-the-rungrubby-debug-after-the-normal-kerne.patch
new file mode 100644
index 0000000..4e31618
--- /dev/null
+++ b/SOURCES/0049-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 <pjones@redhat.com>
+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 <pjones@redhat.com>
+---
+ 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/0050-grubby-add-set-index-to-specify-which-position-to-ad.patch b/SOURCES/0050-grubby-add-set-index-to-specify-which-position-to-ad.patch
new file mode 100644
index 0000000..8eba68e
--- /dev/null
+++ b/SOURCES/0050-grubby-add-set-index-to-specify-which-position-to-ad.patch
@@ -0,0 +1,297 @@
+From ddf482232a47f5d2db9b3d40d89ee4094a6ac936 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 22 Jun 2016 14:07:49 -0400
+Subject: [PATCH 50/55] grubby: add --set-index to specify which position to
+ add new entries as
+
+This adds an option, "--set-index N", to grubby, and will cause creation
+of any new entry to be at a particular zero-indexed position in the
+resulting configuration file.
+
+Related: rhbz#1285601
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ .gitignore             |  1 +
+ grubby.8               | 10 +++++++---
+ grubby.c               | 26 +++++++++++++++++++++-----
+ test.sh                | 14 ++++++++++++++
+ test/grub.15           | 19 +++++++++++++++++++
+ test/results/add/g1.10 | 22 ++++++++++++++++++++++
+ test/results/add/g1.17 | 19 +++++++++++++++++++
+ test/results/add/g1.8  | 22 ++++++++++++++++++++++
+ test/results/add/g1.9  | 22 ++++++++++++++++++++++
+ 9 files changed, 147 insertions(+), 8 deletions(-)
+ create mode 100644 test/grub.15
+ create mode 100644 test/results/add/g1.10
+ create mode 100644 test/results/add/g1.17
+ create mode 100644 test/results/add/g1.8
+ create mode 100644 test/results/add/g1.9
+
+diff --git a/.gitignore b/.gitignore
+index e78a392..1c00ff7 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -3,3 +3,4 @@ version.h
+ *.o
+ core.*
+ vgcore.*
++*.tar.*
+diff --git a/grubby.8 b/grubby.8
+index 85e22c5..b2a5447 100644
+--- a/grubby.8
++++ b/grubby.8
+@@ -8,10 +8,10 @@ grubby \- command line tool for configuring grub, lilo, elilo, yaboot and zipl
+        [--bootloader-probe] [--config-file \fIpath\fR] [--copy-default]
+        [--debug] [--default-kernel] [--default-index] [--default-title]
+        [--grub] [--lilo] [--yaboot] [--silo] [--zipl]
+-       [--info=\fIkernel-path\fR] [--initrd=\fIinitrd-path\fR] 
+-       [--make-default] [-o path] [--version]
++       [--info=\fIkernel-path\fR] [--initrd=\fIinitrd-path\fR]
++       [--make-default] [-o path] [--version] [--set-entry=\fIentry-index\fR]
+        [--remove-kernel=\fIkernel-path\fR] [--remove-args=\fIargs\fR]
+-       [--set-default=\fIkernel-path\fR] [--set-default-index=\fientry-index\fR]
++       [--set-default=\fIkernel-path\fR] [--set-default-index=\fIentry-index\fR]
+        [--title=entry-title] [--add-multiboot=\fImultiboot-path\fR]
+        [--mbargs=\fIargs\fR] [--remove-multiboot=\fImultiboot-path\fR]
+        [--remove-mbargs=\fIargs\fR]
+@@ -48,6 +48,10 @@ with that title are used.
+ Add a new boot entry for the kernel located at \fIkernel-path\fR.
+ 
+ .TP
++\fB-\-set-entry\fR=\fIentry-index\fR
++Set the position at which to add a new entry created with \fB-\-add-kernel\fR.
++
++.TP
+ \fB-\-args\fR=\fIkernel-args\fR
+ When a new kernel is added, this specifies the command line arguments
+ which should be passed to the kernel by default (note they are merged
+diff --git a/grubby.c b/grubby.c
+index ad2b662..0c260f2 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -4286,9 +4286,10 @@ int addNewKernel(struct grubConfig *config, struct singleEntry *template,
+ 		 const char *newKernelPath, const char *newKernelTitle,
+ 		 const char *newKernelArgs, const char *newKernelInitrd,
+ 		 const char **extraInitrds, int extraInitrdCount,
+-		 const char *newMBKernel, const char *newMBKernelArgs)
++		 const char *newMBKernel, const char *newMBKernelArgs
++		 int newIndex)
+ {
+-	struct singleEntry *new;
++	struct singleEntry *new, *entry, *prev = NULL;
+ 	struct singleLine *newLine = NULL, *tmplLine = NULL, *masterLine = NULL;
+ 	int needs;
+ 	char *chptr;
+@@ -4318,9 +4319,20 @@ int addNewKernel(struct grubConfig *config, struct singleEntry *template,
+ 	new = malloc(sizeof(*new));
+ 	new->skip = 0;
+ 	new->multiboot = 0;
+-	new->next = config->entries;
+ 	new->lines = NULL;
+-	config->entries = new;
++	entry = config->entries;
++	for (unsigned int i = 0; i < newIndex; i++) {
++		if (!entry)
++			break;
++		prev = entry;
++		entry = entry->next;
++	}
++	new->next = entry;
++
++	if (prev)
++		prev->next = new;
++	else
++		config->entries = new;
+ 
+ 	/* copy/update from the template */
+ 	needs = NEED_KERNEL | NEED_TITLE;
+@@ -4771,6 +4783,7 @@ int main(int argc, const char **argv)
+ 	char *newKernelVersion = NULL;
+ 	char *newMBKernel = NULL;
+ 	char *newMBKernelArgs = NULL;
++	int newIndex = 0;
+ 	char *removeMBKernelArgs = NULL;
+ 	char *removeMBKernel = NULL;
+ 	char *bootPrefix = NULL;
+@@ -4873,6 +4886,9 @@ int main(int argc, const char **argv)
+ 		{"set-default-index", 0, POPT_ARG_INT, &defaultIndex, 0,
+ 		 _("make the given entry index the default entry"),
+ 		 _("entry-index")},
++		{"set-index", 0, POPT_ARG_INT, &newIndex, 0,
++		 _("use the given index when creating a new entry"),
++		 _("entry-index")},
+ 		{"silo", 0, POPT_ARG_NONE, &configureSilo, 0,
+ 		 _("configure silo bootloader")},
+ 		{"title", 0, POPT_ARG_STRING, &newKernelTitle, 0,
+@@ -5289,7 +5305,7 @@ int main(int argc, const char **argv)
+ 	if (addNewKernel(config, template, bootPrefix, newKernelPath,
+ 			 newKernelTitle, newKernelArgs, newKernelInitrd,
+ 			 (const char **)extraInitrds, extraInitrdCount,
+-			 newMBKernel, newMBKernelArgs))
++			 newMBKernel, newMBKernelArgs, newIndex))
+ 		return 1;
+ 
+ 	if (numEntries(config) == 0) {
+diff --git a/test.sh b/test.sh
+index b90798c..9ac0ec9 100755
+--- a/test.sh
++++ b/test.sh
+@@ -485,6 +485,20 @@ grubTest grub.8 add/g8.2 --add-kernel=/boot/new-kernel.img --title='title' \
+ grubTest grub.11 add/g11.1 --add-kernel=/boot/new-kernel.img --title='title' \
+     --initrd=/boot/new-initrd --boot-filesystem=/boot --copy-default \
+     --args='console=tty0 console=ttyS1,9600n81 single'
++grubTest grub.1 add/g1.1 --add-kernel=/boot/new-kernel.img --title='title' \
++    --initrd=/boot/new-initrd --boot-filesystem=/ --set-index 0
++grubTest grub.1 add/g1.17 --add-kernel=/boot/new-kernel.img --title='title' \
++    --initrd=/boot/new-initrd --boot-filesystem=/ --set-index 1
++grubTest grub.1 add/g1.17 --add-kernel=/boot/new-kernel.img --title='title' \
++    --initrd=/boot/new-initrd --boot-filesystem=/ --set-index 2
++grubTest grub.15 add/g1.10 --add-kernel=/boot/new-kernel.img --title='title' \
++    --initrd=/boot/new-initrd --boot-filesystem=/ --set-index 0
++grubTest grub.15 add/g1.8 --add-kernel=/boot/new-kernel.img --title='title' \
++    --initrd=/boot/new-initrd --boot-filesystem=/ --set-index 1
++grubTest grub.15 add/g1.9 --add-kernel=/boot/new-kernel.img --title='title' \
++    --initrd=/boot/new-initrd --boot-filesystem=/ --set-index 2
++grubTest grub.15 add/g1.9 --add-kernel=/boot/new-kernel.img --title='title' \
++    --initrd=/boot/new-initrd --boot-filesystem=/ --set-index 5
+ 
+ testgrub2=n
+ ARCH=$(uname -m | sed s,i[3456789]86,ia32,)
+diff --git a/test/grub.15 b/test/grub.15
+new file mode 100644
+index 0000000..e1c5f8a
+--- /dev/null
++++ b/test/grub.15
+@@ -0,0 +1,19 @@
++# grub.conf generated by anaconda
++#
++# Note that you do not have to rerun grub after making changes to this file
++# NOTICE:  You have a /boot partition.  This means that
++#          all kernel and initrd paths are relative to /boot/, eg.
++#          root (hd0,0)
++#          kernel /vmlinuz-version ro root=/dev/sda1
++#          initrd /initrd-version.img
++#boot=/dev/hda
++default=1
++timeout=10
++splashimage=(hd0,0)/grub/splash.xpm.gz
++title Red Hat Linux (2.4.7-2)
++	root (hd0,0)
++	kernel /vmlinuz-2.4.7-2 ro root=/dev/sda1
++	initrd /initrd-2.4.7-2.img
++title zonk
++	kernel /boot/new-kernel.img
++	initrd /boot/new-initrd
+diff --git a/test/results/add/g1.10 b/test/results/add/g1.10
+new file mode 100644
+index 0000000..dcdd8a8
+--- /dev/null
++++ b/test/results/add/g1.10
+@@ -0,0 +1,22 @@
++# grub.conf generated by anaconda
++#
++# Note that you do not have to rerun grub after making changes to this file
++# NOTICE:  You have a /boot partition.  This means that
++#          all kernel and initrd paths are relative to /boot/, eg.
++#          root (hd0,0)
++#          kernel /vmlinuz-version ro root=/dev/sda1
++#          initrd /initrd-version.img
++#boot=/dev/hda
++default=2
++timeout=10
++splashimage=(hd0,0)/grub/splash.xpm.gz
++title title
++	kernel /boot/new-kernel.img
++	initrd /boot/new-initrd
++title Red Hat Linux (2.4.7-2)
++	root (hd0,0)
++	kernel /vmlinuz-2.4.7-2 ro root=/dev/sda1
++	initrd /initrd-2.4.7-2.img
++title zonk
++	kernel /boot/new-kernel.img
++	initrd /boot/new-initrd
+diff --git a/test/results/add/g1.17 b/test/results/add/g1.17
+new file mode 100644
+index 0000000..6a38822
+--- /dev/null
++++ b/test/results/add/g1.17
+@@ -0,0 +1,19 @@
++# grub.conf generated by anaconda
++#
++# Note that you do not have to rerun grub after making changes to this file
++# NOTICE:  You have a /boot partition.  This means that
++#          all kernel and initrd paths are relative to /boot/, eg.
++#          root (hd0,0)
++#          kernel /vmlinuz-version ro root=/dev/sda1
++#          initrd /initrd-version.img
++#boot=/dev/hda
++default=1
++timeout=10
++splashimage=(hd0,0)/grub/splash.xpm.gz
++title Red Hat Linux (2.4.7-2)
++	root (hd0,0)
++	kernel /vmlinuz-2.4.7-2 ro root=/dev/sda1
++	initrd /initrd-2.4.7-2.img
++title title
++	kernel /boot/new-kernel.img
++	initrd /boot/new-initrd
+diff --git a/test/results/add/g1.8 b/test/results/add/g1.8
+new file mode 100644
+index 0000000..5893a2f
+--- /dev/null
++++ b/test/results/add/g1.8
+@@ -0,0 +1,22 @@
++# grub.conf generated by anaconda
++#
++# Note that you do not have to rerun grub after making changes to this file
++# NOTICE:  You have a /boot partition.  This means that
++#          all kernel and initrd paths are relative to /boot/, eg.
++#          root (hd0,0)
++#          kernel /vmlinuz-version ro root=/dev/sda1
++#          initrd /initrd-version.img
++#boot=/dev/hda
++default=2
++timeout=10
++splashimage=(hd0,0)/grub/splash.xpm.gz
++title Red Hat Linux (2.4.7-2)
++	root (hd0,0)
++	kernel /vmlinuz-2.4.7-2 ro root=/dev/sda1
++	initrd /initrd-2.4.7-2.img
++title title
++	kernel /boot/new-kernel.img
++	initrd /boot/new-initrd
++title zonk
++	kernel /boot/new-kernel.img
++	initrd /boot/new-initrd
+diff --git a/test/results/add/g1.9 b/test/results/add/g1.9
+new file mode 100644
+index 0000000..310623d
+--- /dev/null
++++ b/test/results/add/g1.9
+@@ -0,0 +1,22 @@
++# grub.conf generated by anaconda
++#
++# Note that you do not have to rerun grub after making changes to this file
++# NOTICE:  You have a /boot partition.  This means that
++#          all kernel and initrd paths are relative to /boot/, eg.
++#          root (hd0,0)
++#          kernel /vmlinuz-version ro root=/dev/sda1
++#          initrd /initrd-version.img
++#boot=/dev/hda
++default=2
++timeout=10
++splashimage=(hd0,0)/grub/splash.xpm.gz
++title Red Hat Linux (2.4.7-2)
++	root (hd0,0)
++	kernel /vmlinuz-2.4.7-2 ro root=/dev/sda1
++	initrd /initrd-2.4.7-2.img
++title zonk
++	kernel /boot/new-kernel.img
++	initrd /boot/new-initrd
++title title
++	kernel /boot/new-kernel.img
++	initrd /boot/new-initrd
+-- 
+2.5.5
+
diff --git a/SOURCES/0051-Fix-thinko-on-set-index-naming.patch b/SOURCES/0051-Fix-thinko-on-set-index-naming.patch
new file mode 100644
index 0000000..e6f163d
--- /dev/null
+++ b/SOURCES/0051-Fix-thinko-on-set-index-naming.patch
@@ -0,0 +1,37 @@
+From 694e8328e37d0f71a4e535b36c6bd1a937956cc0 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 23 Jun 2016 14:45:35 -0400
+Subject: [PATCH 51/55] Fix thinko on --set-index naming.
+
+Related: rhbz#1285601
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grubby.8 | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/grubby.8 b/grubby.8
+index b2a5447..709a539 100644
+--- a/grubby.8
++++ b/grubby.8
+@@ -9,7 +9,7 @@ grubby \- command line tool for configuring grub, lilo, elilo, yaboot and zipl
+        [--debug] [--default-kernel] [--default-index] [--default-title]
+        [--grub] [--lilo] [--yaboot] [--silo] [--zipl]
+        [--info=\fIkernel-path\fR] [--initrd=\fIinitrd-path\fR]
+-       [--make-default] [-o path] [--version] [--set-entry=\fIentry-index\fR]
++       [--make-default] [-o path] [--version] [--set-index=\fIentry-index\fR]
+        [--remove-kernel=\fIkernel-path\fR] [--remove-args=\fIargs\fR]
+        [--set-default=\fIkernel-path\fR] [--set-default-index=\fIentry-index\fR]
+        [--title=entry-title] [--add-multiboot=\fImultiboot-path\fR]
+@@ -48,7 +48,7 @@ with that title are used.
+ Add a new boot entry for the kernel located at \fIkernel-path\fR.
+ 
+ .TP
+-\fB-\-set-entry\fR=\fIentry-index\fR
++\fB-\-set-index\fR=\fIentry-index\fR
+ Set the position at which to add a new entry created with \fB-\-add-kernel\fR.
+ 
+ .TP
+-- 
+2.5.5
+
diff --git a/SOURCES/0052-Fix-a-typo-on-the-rhel-7.3-branch.patch b/SOURCES/0052-Fix-a-typo-on-the-rhel-7.3-branch.patch
new file mode 100644
index 0000000..4c7585f
--- /dev/null
+++ b/SOURCES/0052-Fix-a-typo-on-the-rhel-7.3-branch.patch
@@ -0,0 +1,29 @@
+From 2cb2f8a419f10c5cf808572c80f51c1df09d1de0 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 23 Jun 2016 16:10:29 -0400
+Subject: [PATCH 52/55] Fix a typo on the rhel-7.3 branch...
+
+Apparently introduced an error resolving a conflict on this branch,
+woops.
+
+Related: rhbz#1285601
+---
+ grubby.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grubby.c b/grubby.c
+index 0c260f2..2402116 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -4286,7 +4286,7 @@ int addNewKernel(struct grubConfig *config, struct singleEntry *template,
+ 		 const char *newKernelPath, const char *newKernelTitle,
+ 		 const char *newKernelArgs, const char *newKernelInitrd,
+ 		 const char **extraInitrds, int extraInitrdCount,
+-		 const char *newMBKernel, const char *newMBKernelArgs
++		 const char *newMBKernel, const char *newMBKernelArgs,
+ 		 int newIndex)
+ {
+ 	struct singleEntry *new, *entry, *prev = NULL;
+-- 
+2.5.5
+
diff --git a/SOURCES/0053-Add-a-test-case-for-a-failure-rmarshall-saw-in-set-i.patch b/SOURCES/0053-Add-a-test-case-for-a-failure-rmarshall-saw-in-set-i.patch
new file mode 100644
index 0000000..1a69e77
--- /dev/null
+++ b/SOURCES/0053-Add-a-test-case-for-a-failure-rmarshall-saw-in-set-i.patch
@@ -0,0 +1,386 @@
+From e6d22da1ef26780c73b610c4d64552da84b7fa34 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Fri, 24 Jun 2016 16:13:41 -0400
+Subject: [PATCH 53/55] Add a test case for a failure rmarshall saw in
+ --set-index=
+
+Related: rhbz#1285601
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ test.sh                            |   9 ++
+ test/grub2-support_files/grubenv.3 |   3 +
+ test/grub2.18                      | 154 ++++++++++++++++++++++++++++++++++
+ test/results/add/g2-1.18           | 168 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+)
+ create mode 100644 test/grub2-support_files/grubenv.3
+ create mode 100644 test/grub2.18
+ create mode 100644 test/results/add/g2-1.18
+
+diff --git a/test.sh b/test.sh
+index 9ac0ec9..dbf7507 100755
+--- a/test.sh
++++ b/test.sh
+@@ -570,6 +570,15 @@ if [ "$testgrub2" == "y" ]; then
+         --copy-default --title 'Red Hat Enterprise Linux Server' \
+         --args=root=/dev/mapper/foo--
+ 
++    # copy a stanza and add arguments as well, while using --set-index=
++    testing="GRUB2 add stanza and new args with --set-index="
++    grub2Test grub2.18 add/g2-1.18  --env grubenv.3 \
++        --add-kernel=/boot/vmlinuz-3.10.0-327.22.2.el7.x86_64.debug \
++        --boot-filesystem=/boot --copy-default \
++        --title "Red Hat Enterprise Linux Server (3.10.0-327.22.2.el7.x86_64.debug) 7.2 (Maipo) with debugging" \
++        --args="root=/dev/mapper/rhel_team--area--222-root systemd.log_level=debug systemd.log_target=kmsg" \
++        --set-index=1
++
+     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-support_files/grubenv.3 b/test/grub2-support_files/grubenv.3
+new file mode 100644
+index 0000000..b9a8c79
+--- /dev/null
++++ b/test/grub2-support_files/grubenv.3
+@@ -0,0 +1,3 @@
++# GRUB Environment Block
++saved_entry=Red Hat Enterprise Linux Server (3.10.0-327.22.2.el7.x86_64.debug) 7.2 (Maipo) with debugging
++#############################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################
+\ No newline at end of file
+diff --git a/test/grub2.18 b/test/grub2.18
+new file mode 100644
+index 0000000..529608d
+--- /dev/null
++++ b/test/grub2.18
+@@ -0,0 +1,154 @@
++#
++# 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/00_tuned ###
++set tuned_params=""
++### 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-327.22.2.el7.x86_64.debug) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-327.el7.x86_64-advanced-91b16928-66bf-4801-8aed-fab3f1a6876c' {
++	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'  7e972fc0-6cf8-4a58-ace6-1b381e52733d
++	else
++	  search --no-floppy --fs-uuid --set=root 7e972fc0-6cf8-4a58-ace6-1b381e52733d
++	fi
++	linux16 /vmlinuz-3.10.0-327.22.2.el7.x86_64.debug root=/dev/mapper/rhel_team--area--222-root ro crashkernel=auto rd.lvm.lv=rhel_team-area-222/root rd.lvm.lv=rhel_team-area-222/swap rhgb quiet LANG=en_US.UTF-8
++}
++menuentry 'Red Hat Enterprise Linux Server (3.10.0-327.el7.x86_64) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-327.el7.x86_64-advanced-91b16928-66bf-4801-8aed-fab3f1a6876c' {
++	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'  7e972fc0-6cf8-4a58-ace6-1b381e52733d
++	else
++	  search --no-floppy --fs-uuid --set=root 7e972fc0-6cf8-4a58-ace6-1b381e52733d
++	fi
++	linux16 /vmlinuz-3.10.0-327.el7.x86_64 root=/dev/mapper/rhel_team--area--222-root ro crashkernel=auto rd.lvm.lv=rhel_team-area-222/root rd.lvm.lv=rhel_team-area-222/swap rhgb quiet LANG=en_US.UTF-8
++	initrd16 /initramfs-3.10.0-327.el7.x86_64.img
++}
++menuentry 'Red Hat Enterprise Linux Server (0-rescue-925cd320373b6a4a9a66a26371afccd2) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-925cd320373b6a4a9a66a26371afccd2-advanced-91b16928-66bf-4801-8aed-fab3f1a6876c' {
++	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'  7e972fc0-6cf8-4a58-ace6-1b381e52733d
++	else
++	  search --no-floppy --fs-uuid --set=root 7e972fc0-6cf8-4a58-ace6-1b381e52733d
++	fi
++	linux16 /vmlinuz-0-rescue-925cd320373b6a4a9a66a26371afccd2 root=/dev/mapper/rhel_team--area--222-root ro crashkernel=auto rd.lvm.lv=rhel_team-area-222/root rd.lvm.lv=rhel_team-area-222/swap rhgb quiet
++	initrd16 /initramfs-0-rescue-925cd320373b6a4a9a66a26371afccd2.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/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.18 b/test/results/add/g2-1.18
+new file mode 100644
+index 0000000..ca5fe23
+--- /dev/null
++++ b/test/results/add/g2-1.18
+@@ -0,0 +1,168 @@
++#
++# 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/00_tuned ###
++set tuned_params=""
++### 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-327.22.2.el7.x86_64.debug) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-327.el7.x86_64-advanced-91b16928-66bf-4801-8aed-fab3f1a6876c' {
++	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'  7e972fc0-6cf8-4a58-ace6-1b381e52733d
++	else
++	  search --no-floppy --fs-uuid --set=root 7e972fc0-6cf8-4a58-ace6-1b381e52733d
++	fi
++	linux16 /vmlinuz-3.10.0-327.22.2.el7.x86_64.debug root=/dev/mapper/rhel_team--area--222-root ro crashkernel=auto rd.lvm.lv=rhel_team-area-222/root rd.lvm.lv=rhel_team-area-222/swap rhgb quiet LANG=en_US.UTF-8
++}
++menuentry 'Red Hat Enterprise Linux Server (3.10.0-327.22.2.el7.x86_64.debug) 7.2 (Maipo) with debugging' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-327.el7.x86_64-advanced-91b16928-66bf-4801-8aed-fab3f1a6876c' {
++	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'  7e972fc0-6cf8-4a58-ace6-1b381e52733d
++	else
++	  search --no-floppy --fs-uuid --set=root 7e972fc0-6cf8-4a58-ace6-1b381e52733d
++	fi
++	linux16 /vmlinuz-3.10.0-327.22.2.el7.x86_64.debug root=/dev/mapper/rhel_team--area--222-root ro crashkernel=auto rd.lvm.lv=rhel_team-area-222/root rd.lvm.lv=rhel_team-area-222/swap rhgb quiet LANG=en_US.UTF-8 systemd.log_level=debug systemd.log_target=kmsg
++}
++menuentry 'Red Hat Enterprise Linux Server (3.10.0-327.el7.x86_64) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-327.el7.x86_64-advanced-91b16928-66bf-4801-8aed-fab3f1a6876c' {
++	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'  7e972fc0-6cf8-4a58-ace6-1b381e52733d
++	else
++	  search --no-floppy --fs-uuid --set=root 7e972fc0-6cf8-4a58-ace6-1b381e52733d
++	fi
++	linux16 /vmlinuz-3.10.0-327.el7.x86_64 root=/dev/mapper/rhel_team--area--222-root ro crashkernel=auto rd.lvm.lv=rhel_team-area-222/root rd.lvm.lv=rhel_team-area-222/swap rhgb quiet LANG=en_US.UTF-8
++	initrd16 /initramfs-3.10.0-327.el7.x86_64.img
++}
++menuentry 'Red Hat Enterprise Linux Server (0-rescue-925cd320373b6a4a9a66a26371afccd2) 7.2 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-925cd320373b6a4a9a66a26371afccd2-advanced-91b16928-66bf-4801-8aed-fab3f1a6876c' {
++	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'  7e972fc0-6cf8-4a58-ace6-1b381e52733d
++	else
++	  search --no-floppy --fs-uuid --set=root 7e972fc0-6cf8-4a58-ace6-1b381e52733d
++	fi
++	linux16 /vmlinuz-0-rescue-925cd320373b6a4a9a66a26371afccd2 root=/dev/mapper/rhel_team--area--222-root ro crashkernel=auto rd.lvm.lv=rhel_team-area-222/root rd.lvm.lv=rhel_team-area-222/swap rhgb quiet
++	initrd16 /initramfs-0-rescue-925cd320373b6a4a9a66a26371afccd2.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/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.5.5
+
diff --git a/SOURCES/0054-Ensure-command-line-updates-also-honor-set-index.patch b/SOURCES/0054-Ensure-command-line-updates-also-honor-set-index.patch
new file mode 100644
index 0000000..022d0c9
--- /dev/null
+++ b/SOURCES/0054-Ensure-command-line-updates-also-honor-set-index.patch
@@ -0,0 +1,46 @@
+From d4d7954a983f9cf68cd49c181e8deb1493e76e9e Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Fri, 24 Jun 2016 16:05:45 -0400
+Subject: [PATCH 54/55] Ensure command line updates also honor --set-index
+
+Related: rhbz#1285601
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grubby.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/grubby.c b/grubby.c
+index 2402116..c379388 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -4292,11 +4292,17 @@ int addNewKernel(struct grubConfig *config, struct singleEntry *template,
+ 	struct singleEntry *new, *entry, *prev = NULL;
+ 	struct singleLine *newLine = NULL, *tmplLine = NULL, *masterLine = NULL;
+ 	int needs;
++	char *indexs;
+ 	char *chptr;
++	int rc;
+ 
+ 	if (!newKernelPath)
+ 		return 0;
+ 
++	rc = asprintf(&indexs, "%d", newIndex);
++	if (rc < 0)
++		return 1;
++
+ 	/* 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 */
+@@ -4753,7 +4759,7 @@ int addNewKernel(struct grubConfig *config, struct singleEntry *template,
+ 		abort();
+ 	}
+ 
+-	if (updateImage(config, "0", prefix, newKernelArgs, NULL,
++	if (updateImage(config, indexs, prefix, newKernelArgs, NULL,
+ 			newMBKernelArgs, NULL))
+ 		return 1;
+ 
+-- 
+2.5.5
+
diff --git a/SOURCES/0055-Change-debug-entry-insertion-order-rhbz-1285601.patch b/SOURCES/0055-Change-debug-entry-insertion-order-rhbz-1285601.patch
new file mode 100644
index 0000000..71ddd3c
--- /dev/null
+++ b/SOURCES/0055-Change-debug-entry-insertion-order-rhbz-1285601.patch
@@ -0,0 +1,67 @@
+From 089057d3c574ec804c967dcd4ae8a0368e7ee90f Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Thu, 23 Jun 2016 14:41:12 -0400
+Subject: [PATCH 55/55] Change debug entry insertion order (rhbz#1285601)
+
+Customer reports indicated that it was confusing to have the debugging
+entries before non-debugging entries. Altered the insertion code to use
+the --set-index feature on the debug kernels to force them to insert
+after the initial non-debugging entry.
+
+Resolves: rhbz#1285601
+---
+ new-kernel-pkg | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/new-kernel-pkg b/new-kernel-pkg
+index bd28634..847e959 100755
+--- a/new-kernel-pkg
++++ b/new-kernel-pkg
+@@ -238,7 +238,7 @@ install() {
+ 		--remove-kernel=\"TITLE=$title\$debugtitle\""
+ 
+ 	rungrubby ${ARGS} $makedefault
+-	rungrubby --debug ${ARGS}
++	rungrubby --debug ${ARGS} --set-index=1
+     else
+ 	[ -n "$verbose" ] && echo "$grubConfig does not exist, not running grubby for grub 0.97"
+     fi
+@@ -252,7 +252,7 @@ install() {
+ 		--args=\"root=$rootdevice $kernargs \$debugargs\" \
+ 		--remove-kernel=\"TITLE=$title\$debugtitle\""
+ 	rungrubby ${ARGS} $makedefault
+-	rungrubby --debug ${ARGS}
++	rungrubby --debug ${ARGS} --set-index=1
+     else
+ 	[ -n "$verbose" ] && echo "$grub2Config does not exist, not running grubby for grub 2"
+     fi
+@@ -267,7 +267,7 @@ install() {
+ 		--args=\"root=$rootdevice $kernargs \$debugargs\" \
+ 		--remove-kernel=\"TITLE=$title\$debugtitle\""
+ 	rungrubby ${ARGS} $makedefault
+-	rungrubby --debug ${ARGS}
++	rungrubby --debug ${ARGS} --set-index=1
+     else
+ 	[ -n "$verbose" ] && echo "$grub2EfiConfig does not exist, not running grubby for grub 2 with UEFI"
+     fi
+@@ -283,7 +283,7 @@ install() {
+ 		--remove-kernel=\"TITLE=$version\""
+ 
+ 	rungrubby ${ARGS} $makedefault
+-	rungrubby --debug ${ARGS}
++	rungrubby --debug ${ARGS} --set-index=1
+ 	if [ -n "$runLilo" ]; then
+ 	    [ -n "$verbose" ] && echo "running $lilo"
+ 	    if [ ! -x $lilo ] ; then
+@@ -307,7 +307,7 @@ install() {
+ 	    --remove-kernel=\"TITLE=$title\$debugtitle\""
+ 
+ 	rungrubby ${ARGS} $makedefault
+-	rungrubby --debug ${ARGS}
++	rungrubby --debug ${ARGS} --set-index=1
+     else
+ 	[ -n "$verbose" ] && echo "$extlinuxConfig does not exist, not running grubby for extlinux"
+     fi
+-- 
+2.5.5
+
diff --git a/SOURCES/0056-Reorganize-grubby-man-page-1232168.patch b/SOURCES/0056-Reorganize-grubby-man-page-1232168.patch
new file mode 100644
index 0000000..ac0e298
--- /dev/null
+++ b/SOURCES/0056-Reorganize-grubby-man-page-1232168.patch
@@ -0,0 +1,339 @@
+From 31537e66c2830783c4037ebace6801356b7ba520 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Fri, 1 Jul 2016 14:54:30 -0400
+Subject: [PATCH 56/60] Reorganize grubby man page (#1232168)
+
+Broke the grubby man page into clearer sections and re-organized the
+content by general use case for easier reading.
+
+Related: rhbz#1232168
+---
+ grubby.8 | 197 +++++++++++++++++++++++++++++++++++----------------------------
+ 1 file changed, 109 insertions(+), 88 deletions(-)
+
+diff --git a/grubby.8 b/grubby.8
+index 709a539..005a6c2 100644
+--- a/grubby.8
++++ b/grubby.8
+@@ -1,10 +1,13 @@
+ .TH GRUBBY 8 "Tue Jan 18 2005"
++
+ .SH NAME
++
+ grubby \- command line tool for configuring grub, lilo, elilo, yaboot and zipl
+ 
+ .SH SYNOPSIS
+-\fBgrubby\fR [--add-kernel=\fIkernel-path\fR] [--args=\fIargs\fR] 
+-       [--bad-image-okay] [--boot-filesystem=\fIbootfs\fR] 
++
++\fBgrubby\fR [--add-kernel=\fIkernel-path\fR] [--args=\fIargs\fR]
++       [--bad-image-okay] [--boot-filesystem=\fIbootfs\fR]
+        [--bootloader-probe] [--config-file \fIpath\fR] [--copy-default]
+        [--debug] [--default-kernel] [--default-index] [--default-title]
+        [--grub] [--lilo] [--yaboot] [--silo] [--zipl]
+@@ -17,12 +20,17 @@ grubby \- command line tool for configuring grub, lilo, elilo, yaboot and zipl
+        [--remove-mbargs=\fIargs\fR]
+ 
+ .SH DESCRIPTION
++
++.SS General Information
++
+ \fBgrubby\fR is a command line tool for updating and displaying information
+ 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.
+ 
++.SS Architecture Support
++
+ 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
+@@ -34,6 +42,8 @@ config stored in \fB/boot/grub2/grub.cfg\fR. The earlier Power7 systems use \fBy
+ 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.
+ 
++.SS Special Arguments
++
+ 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
+ or \fBALL\fR selects the default entry and all of the entries, respectively.
+@@ -43,13 +53,24 @@ be specified by using \fBTITLE=\fItitle\fR as the argument; all entries
+ with that title are used.
+ 
+ .SH OPTIONS
++
++.SS Basic Options
++
+ .TP
+ \fB-\-add-kernel\fR=\fIkernel-path\fR
+ Add a new boot entry for the kernel located at \fIkernel-path\fR.
+ 
+ .TP
+-\fB-\-set-index\fR=\fIentry-index\fR
+-Set the position at which to add a new entry created with \fB-\-add-kernel\fR.
++\fB-\-remove-kernel\fR=\fIkernel-path\fR
++Removes all boot entries which match \fIkernel-path\fR. This may be used
++along with -\-add-kernel, in which case the new kernel being added will
++never be removed.
++
++.TP
++\fB-\-update-kernel\fR=\fIkernel-path\fR
++The entries for kernels matching \fRkernel-path\fR are updated. Currently
++the only items that can be updated is the kernel argument list, which is
++modified via the \fB-\-args\fR and \fB-\-remove-args\fR options.
+ 
+ .TP
+ \fB-\-args\fR=\fIkernel-args\fR
+@@ -64,49 +85,53 @@ file has special handling for specifying the root filesystem (like
+ lilo.conf does).
+ 
+ .TP
+-\fB-\-bad-image-okay\fR
+-When \fBgrubby\fR is looking for a entry to use for something (such
+-as a template or a default boot entry) it uses sanity checks, such as
+-ensuring that the kernel exists in the filesystem, to make sure
+-entries that obviously won't work aren't selected. This option overrides
+-that behavior, and is designed primarily for testing.
++\fB-\-remove-args\fR=\fIkernel-args\fR
++The arguments specified by \fIkernel-args\fR are removed from the
++kernels specified by \fB-\-update-kernel\fR. The \fBroot\fR argument
++gets special handling for configuration files that support separate root
++filesystem configuration.
+ 
+ .TP
+-\fB-\-boot-filesystem\fR=\fIbootfs\fR
+-The \fBgrub\fR boot loader expects file paths listed in it's configuration
+-path to be relative to the top of the filesystem they are on, rather then
+-relative to the current root filesystem. By default \fBgrubby\fR searches
+-the list of currently mounted filesystems to determine this. If this option
+-is given \fBgrubby\fR acts as if the specified filesystem was the filesystem
+-containing the kernel (this option is designed primarily for testing).
++\fB-\-copy-default\fR
++\fBgrubby\fR will copy as much information (such as kernel arguments and
++root device) as possible from the current default kernel. The kernel path
++and initrd path will never be copied.
+ 
+ .TP
+-\fB-\-bootloader-probe\fR
+-\fBgrubby\fR tries to determine if \fBgrub\fR or \fBlilo\fR is currently 
+-installed. When one of those bootloaders is found the name of that bootloader
+-is displayed on stdout.  Both could be installed (on different devices), and
+-grubby will print out the names of both bootloaders, one per line. The probe
+-for \fBgrub\fR requires a commented out boot directive \fBgrub.conf\fR
+-identical to the standard directive in the lilo configuration file. If this
+-is not present \fBgrubby\fR will assume grub is not installed (note 
+-that \fBanaconda\fR places this directive in \fBgrub.conf\fR files it creates).
+-This option is only available on ia32 platforms. 
++\fB-\-title\fR=\fIentry-title\fR
++When a new kernel entry is added \fIentry-title\fR is used as the title
++(\fBlilo\fR label) for the entry. If \fIentry-title\fR is longer then maximum
++length allowed by the bootloader (15 for lilo, unlimited for grub and elilo)
++the title is shortened to a (unique) entry.
+ 
++.TP
++\fB-\-initrd\fR=\fIinitrd-path\fR
++Use \fIinitrd-path\fR as the path to an initial ram disk for a new kernel
++being added.
+ 
+ .TP
+-\fB-\-config-file\fR=\fIpath\fR
+-Use \fIpath\fR as the configuration file rather then the default.
++\fB-\-set-default\fR=\fIkernel-path\fR
++The first entry which boots the specified kernel is made the default
++boot entry.
+ 
+ .TP
+-\fB-\-copy-default\fR
+-\fBgrubby\fR will copy as much information (such as kernel arguments and
+-root device) as possible from the current default kernel. The kernel path
+-and initrd path will never be copied.
++\fB-\-set-default-index\fR=\fIentry-index\fR
++Makes the given entry number the default boot entry.
++
++.TP
++\fB-\-make-default\fR
++Make the new kernel entry being added the default entry.
++
++.TP
++\fB-\-set-index\fR=\fIentry-index\fR
++Set the position at which to add a new entry created with \fB-\-add-kernel\fR.
+ 
+ .TP
+ \fB-\-debug\fR
+ Display extra debugging information for failures.
+ 
++.SS Display Options
++
+ .TP
+ \fB-\-default-kernel\fR
+ Display the full path to the current default kernel and exit.
+@@ -120,79 +145,73 @@ Display the numeric index of the current default boot entry and exit.
+ Display the title of the current default boot entry and exit.
+ 
+ .TP
+-\fB-\-elilo\fR
+-Use an \fBelilo\fR style configuration file.
+-
+-.TP
+-\fB-\-grub\fR
+-Use a \fBgrub\fR style configuration file instead of \fBlilo\fR style. This
+-is the default on ia32 platforms.
+-
+-.TP
+ \fB-\-info\fR=\fIkernel-path\fR
+ Display information on all boot entries which match \fIkernel-path\fR. I
+ 
+ .TP
+-\fB-\-initrd\fR=\fIinitrd-path\fR
+-Use \fIinitrd-path\fR as the path to an initial ram disk for a new kernel
+-being added.
++\fB-\-bootloader-probe\fR
++\fBgrubby\fR tries to determine if \fBgrub\fR or \fBlilo\fR is currently
++installed. When one of those bootloaders is found the name of that bootloader
++is displayed on stdout.  Both could be installed (on different devices), and
++grubby will print out the names of both bootloaders, one per line. The probe
++for \fBgrub\fR requires a commented out boot directive \fBgrub.conf\fR
++identical to the standard directive in the lilo configuration file. If this
++is not present \fBgrubby\fR will assume grub is not installed (note
++that \fBanaconda\fR places this directive in \fBgrub.conf\fR files it creates).
++This option is only available on ia32 platforms.
+ 
+ .TP
+-\fB-\-lilo\fR
+-Use a \fBlilo\fR style configuration file.
++\fB-\-version\fR
++Display the version of \fBgrubby\fR being run and then exit immediately.
+ 
+-.TP
+-\fB-\-make-default\fR
+-Make the new kernel entry being added the default entry.
++.SS Output Format Options
+ 
+ .TP
+-\fB-\-remove-args\fR=\fIkernel-args\fR
+-The arguments specified by \fIkernel-args\fR are removed from the 
+-kernels specified by \fB-\-update-kernel\fR. The \fBroot\fR argument
+-gets special handling for configuration files that support separate root
+-filesystem configuration.
++\fB-\-elilo\fR
++Use an \fBelilo\fR style configuration file.
+ 
+ .TP
+-\fB-\-remove-kernel\fR=\fIkernel-path\fR
+-Removes all boot entries which match \fIkernel-path\fR. This may be used
+-along with -\-add-kernel, in which case the new kernel being added will
+-never be removed.
++\fB-\-grub\fR
++Use a \fBgrub\fR style configuration file instead of \fBlilo\fR style. This
++is the default on ia32 platforms.
+ 
+ .TP
+-\fB-\-set-default\fR=\fIkernel-path\fR
+-The first entry which boots the specified kernel is made the default
+-boot entry.
++\fB-\-lilo\fR
++Use a \fBlilo\fR style configuration file.
+ 
+ .TP
+-\fB-\-set-default-index\fR=\fIentry-index\fR
+-Makes the given entry number the default boot entry.
++\fB-\-yaboot\fR
++Use an \fByaboot\fR style configuration file.
+ 
+ .TP
+-\fB-\-title\fR=\fIentry-title\fR
+-When a new kernel entry is added \fIentry-title\fR is used as the title
+-(\fBlilo\fR label) for the entry. If \fIentry-title\fR is longer then maximum
+-length allowed by the bootloader (15 for lilo, unlimited for grub and elilo)
+-the title is shortened to a (unique) entry.
++\fB-\-zipl\fR
++Use an \fBzipl\fR style configuration file.
+ 
+-.TP
+-\fB-\-update-kernel\fR=\fIkernel-path\fR
+-The entries for kernels matching \fRkernel-path\fR are updated. Currently
+-the only items that can be updated is the kernel argument list, which is
+-modified via the \fB-\-args\fR and \fB-\-remove-args\fR options.
++.SS Override Options
+ 
+ .TP
+-\fB-\-version\fR
+-Display the version of \fBgrubby\fR being run and then exit immediately.
++\fB-\-bad-image-okay\fR
++When \fBgrubby\fR is looking for a entry to use for something (such
++as a template or a default boot entry) it uses sanity checks, such as
++ensuring that the kernel exists in the filesystem, to make sure
++entries that obviously won't work aren't selected. This option overrides
++that behavior, and is designed primarily for testing.
+ 
+ .TP
+-\fB-\-yaboot\fR
+-Use an \fByaboot\fR style configuration file.
++\fB-\-boot-filesystem\fR=\fIbootfs\fR
++The \fBgrub\fR boot loader expects file paths listed in it's configuration
++path to be relative to the top of the filesystem they are on, rather then
++relative to the current root filesystem. By default \fBgrubby\fR searches
++the list of currently mounted filesystems to determine this. If this option
++is given \fBgrubby\fR acts as if the specified filesystem was the filesystem
++containing the kernel (this option is designed primarily for testing).
+ 
+ .TP
+-\fB-\-zipl\fR
+-Use an \fBzipl\fR style configuration file.
++\fB-\-config-file\fR=\fIpath\fR
++Use \fIpath\fR as the configuration file rather then the default.
++
++.SS Multiboot Options
+ 
+-.SH MULTIBOOT OPTIONS
+ The Multiboot Specification provides a genreic interface for boot
+ loaders and operating systems.  It is supported by the GRUB bootloader.
+ 
+@@ -204,34 +223,36 @@ Add a new boot entry for the multiboot kernel located at
+ 
+ .TP
+ \fB-\-remove-multiboot\fR=\fImultiboot-path\fR
+-Removes all boot entries which match \fImultiboot-path\fR. 
++Removes all boot entries which match \fImultiboot-path\fR.
+ 
+ .TP
+ \fB-\-mbargs\fR=\fImultiboot-args\fR
+-When a new multiboot kernel is added, this specifies the command line 
+-arguments which should be passed to that kernel by default 
++When a new multiboot kernel is added, this specifies the command line
++arguments which should be passed to that kernel by default
+ When \fB-\-update-kernel\fR is used, this specifies new arguments to add
+ to the argument list. Multiple, space separated arguments may be used. If
+-an argument already exists the new value replaces the old values. 
++an argument already exists the new value replaces the old values.
+ 
+ .TP
+ \fB-\-remove-mbargs\fR=\fImultiboot-args\fR
+-The arguments specified by \fImultiboot-args\fR are removed from the 
+-kernels specified by \fB-\-update-kernel\fR. 
+-
++The arguments specified by \fImultiboot-args\fR are removed from the
++kernels specified by \fB-\-update-kernel\fR.
+ 
+ .SH "BUGS"
++
+ The command line syntax is more than a little baroque. This probably
+ won't be fixed as \fBgrubby\fR is only intended to be called from shell
+ scripts which can get it right.
+ 
+ .SH "SEE ALSO"
++
+ .BR grub (8),
+ .BR lilo (8),
+ .BR yaboot (8),
+ .BR mkinitrd (8)
+ 
+ .SH AUTHORS
++
+ .nf
+ Erik Troan
+ Jeremy Katz
+-- 
+2.5.5
+
diff --git a/SOURCES/0057-Update-grubby-man-page-contents-bz1232168.patch b/SOURCES/0057-Update-grubby-man-page-contents-bz1232168.patch
new file mode 100644
index 0000000..9d2d710
--- /dev/null
+++ b/SOURCES/0057-Update-grubby-man-page-contents-bz1232168.patch
@@ -0,0 +1,355 @@
+From ffc9203275b76bbc4d721b54157f68bfec5e1a2d Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Fri, 1 Jul 2016 15:18:07 -0400
+Subject: [PATCH 57/60] Update grubby man page contents (#bz1232168)
+
+The grubby man page was missing several options that were added in
+previous releases. Added those to the man page as well as updated the
+text on others to provide further clarity.
+
+Added an EXAMPLE section containing some basic use cases.
+
+Resolves: rhbz#1232168
+---
+ grubby.8 | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++-------------
+ 1 file changed, 165 insertions(+), 43 deletions(-)
+
+diff --git a/grubby.8 b/grubby.8
+index 005a6c2..5e1b521 100644
+--- a/grubby.8
++++ b/grubby.8
+@@ -2,50 +2,69 @@
+ 
+ .SH NAME
+ 
+-grubby \- command line tool for configuring grub, lilo, elilo, yaboot and zipl
++grubby \- command line tool used to configure bootloader menu entries across multiple architectures
+ 
+ .SH SYNOPSIS
+ 
+-\fBgrubby\fR [--add-kernel=\fIkernel-path\fR] [--args=\fIargs\fR]
+-       [--bad-image-okay] [--boot-filesystem=\fIbootfs\fR]
+-       [--bootloader-probe] [--config-file \fIpath\fR] [--copy-default]
+-       [--debug] [--default-kernel] [--default-index] [--default-title]
+-       [--grub] [--lilo] [--yaboot] [--silo] [--zipl]
+-       [--info=\fIkernel-path\fR] [--initrd=\fIinitrd-path\fR]
+-       [--make-default] [-o path] [--version] [--set-index=\fIentry-index\fR]
+-       [--remove-kernel=\fIkernel-path\fR] [--remove-args=\fIargs\fR]
+-       [--set-default=\fIkernel-path\fR] [--set-default-index=\fIentry-index\fR]
+-       [--title=entry-title] [--add-multiboot=\fImultiboot-path\fR]
+-       [--mbargs=\fIargs\fR] [--remove-multiboot=\fImultiboot-path\fR]
+-       [--remove-mbargs=\fIargs\fR]
++\fBgrubby\fR [\fIOPTIONS...\fR]
+ 
+ .SH DESCRIPTION
+ 
+ .SS General Information
+ 
+ \fBgrubby\fR is a command line tool for updating and displaying information
+-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.
++about the configuration files for various architecture specific bootloaders.
++It is primarily designed to be used from scripts which install new kernels
++and need to find information about the current boot environment.
+ 
+ .SS Architecture Support
+ 
+-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, 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.  On
+-s390 platforms the \fBzipl bootloader\fR will read from \fB/etc/zipl.conf\fR.
++The \fBgrubby\fR executable has full support for the \fBgrub2\fR
++bootloader on \fBx86_64\fR systems using legacy BIOS or modern
++UEFI firmware and \fBppc64\fR and \fBppc64le\fR hardware using
++OPAL or SLOF as firmware.
++
++Legacy \fBs390\fR and the current \fBs390x\fR architectures
++and their \fBzipl\fR bootloader are fully supported.
++
++Support for \fByaboot\fR has been deprecated as all ppc architecture
++hardware since the Power8 system uses \fBgrub2\fR or petitboot
++which both use the grub2 configuration file format.
++
++Legacy bootloaders \fBLILO\fR, \fBSILO\fR, and \fBELILO\fR
++are deprecated in favor of previously mentioned bootloaders. The
++\fBSILO\fR bootloader should also be considered unsupported.
++
++.SS Default Behavior
++
++The default architecture is chosen at compile time. The grubby executable
++has a series of built in assumptions about what bootloader is being used and
++where its configuration file lives. If no output format option is specified
++on the command line then grubby will use these default settings to first
++search for an existing configuration and, if it is not found, assume that
++it should be placed in the standard location. These default assumptions are
++listed in the table below.
++
++.TS
++allbox;
++lbw6 lbw10 lbw18
++l l l.
++ Arch	Bootloader	Configuration File
++ x86_64 [BIOS]	grub2	/boot/grub2/grub.cfg
++ x86_64 [UEFI]	grub2	/boot/efi/EFI/redhat/grub.cfg
++ i386	grub2	/boot/grub2/grub.cfg
++ ia64	elilo	/boot/efi/EFI/redhat/elilo.conf
++ ppc [>=Power8]	grub2	/boot/grub2/grub.cfg
++ ppc [<=Power7]	yaboot	/etc/yaboot.conf
++ s390	zipl	/etc/zipl.conf
++ s390x	zipl	/etc/zipl.conf
++.TE
++
+ 
+ .SS Special Arguments
+ 
+ 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
++\fB-\-remove-kernel\fR, and \fB-\-update-kernel\fR. Specifying \fBDEFAULT\fR
+ or \fBALL\fR selects the default entry and all of the entries, respectively.
+ If a comma separated list of numbers is given, the boot entries indexed
+ by those numbers are selected. Finally, the title of a boot entry may
+@@ -58,12 +77,17 @@ with that title are used.
+ 
+ .TP
+ \fB-\-add-kernel\fR=\fIkernel-path\fR
+-Add a new boot entry for the kernel located at \fIkernel-path\fR.
++Add a new boot entry for the kernel located at \fIkernel-path\fR. A title for
++the boot entry must be set using \fB-\-title\fR. Most invocations should also
++include \fB-\-initrd\fR with memtest86 as a notable exception.
++
++The \fB-\-update-kernel\fR
++option may not be used in the same invocation. 
+ 
+ .TP
+ \fB-\-remove-kernel\fR=\fIkernel-path\fR
+ Removes all boot entries which match \fIkernel-path\fR. This may be used
+-along with -\-add-kernel, in which case the new kernel being added will
++along with \fB-\-add-kernel\fR, in which case the new kernel being added will
+ never be removed.
+ 
+ .TP
+@@ -110,13 +134,18 @@ Use \fIinitrd-path\fR as the path to an initial ram disk for a new kernel
+ being added.
+ 
+ .TP
++\fB-\-efi\fR
++Use linuxefi and initrdefi when constructing bootloader stanzas instead of linux and initrd.
++
++.TP
+ \fB-\-set-default\fR=\fIkernel-path\fR
+ The first entry which boots the specified kernel is made the default
+-boot entry.
++boot entry. This may not be invoked with \fB-\-set-default-index\fR.
+ 
+ .TP
+ \fB-\-set-default-index\fR=\fIentry-index\fR
+-Makes the given entry number the default boot entry.
++Makes the given entry number the default boot entry. This may not
++be invoked with \fB-\-set-default\fR.
+ 
+ .TP
+ \fB-\-make-default\fR
+@@ -130,8 +159,17 @@ Set the position at which to add a new entry created with \fB-\-add-kernel\fR.
+ \fB-\-debug\fR
+ Display extra debugging information for failures.
+ 
++.TP
++\fB-i\fR, \fB-\-extra-initrd\fR=\fIinitrd-path\fR
++Use \fIinitrd-path\fR as the path for an auxiliary initrd image.
++
+ .SS Display Options
+ 
++Passing the display option to grubby will cause it to print out the
++requested information about the current bootloader configuration and
++then immediately exit.  These options should not be used in any
++script intended to update the bootloader configuration.
++
+ .TP
+ \fB-\-default-kernel\fR
+ Display the full path to the current default kernel and exit.
+@@ -158,34 +196,56 @@ for \fBgrub\fR requires a commented out boot directive \fBgrub.conf\fR
+ identical to the standard directive in the lilo configuration file. If this
+ is not present \fBgrubby\fR will assume grub is not installed (note
+ that \fBanaconda\fR places this directive in \fBgrub.conf\fR files it creates).
+-This option is only available on ia32 platforms.
++
++\fIThis option is only available on i386 platforms.\fR
+ 
+ .TP
+-\fB-\-version\fR
++\fB-v\fR, \fB-\-version\fR
+ Display the version of \fBgrubby\fR being run and then exit immediately.
+ 
+ .SS Output Format Options
+ 
++Sane default options for the current platform are compiled into grubby on
++a per platform basis. These defaults determine the format and layout of
++the generated bootloader configuration file. A different configuration file
++format may be specified on the command line if the system uses a supported
++alternative bootloader.
++
+ .TP
+ \fB-\-elilo\fR
+-Use an \fBelilo\fR style configuration file.
++Use an \fBelilo\fR style configuration file. This is the default on ia64 platforms. This format is deprecated.
++
++.TP
++\fB-\-extlinux\fR
++Use an \fBextlinux\fR style configuration file. This format is deprecated.
+ 
+ .TP
+ \fB-\-grub\fR
+-Use a \fBgrub\fR style configuration file instead of \fBlilo\fR style. This
+-is the default on ia32 platforms.
++Use a \fBgrub\fR style configuration file. This is the default on ia32 platforms.
++
++.TP
++\fB-\-grub2\fR
++Use a \fBgrub2\fR style configuration file. This is the default on \fBx86_64\fR
++architecture as well as the \fBppc64\fR and \fBppc64le\fR architectures
++running on Power8 or later hardware.
+ 
+ .TP
+ \fB-\-lilo\fR
+ Use a \fBlilo\fR style configuration file.
+ 
+ .TP
++\fB-\-silo\fR
++Use a \fBsilo\fR style configuration file. This is the default on SPARC systems. This format is legacy, deprecated, and unsupported.
++
++.TP
+ \fB-\-yaboot\fR
+-Use an \fByaboot\fR style configuration file.
++Use a \fByaboot\fR style configuration file. This is the default for
++the \fBppc\fR architecture on on Power7 and earlier hardware.
+ 
+ .TP
+ \fB-\-zipl\fR
+-Use an \fBzipl\fR style configuration file.
++Use a \fBzipl\fR style configuration file. This is the default on the
++legacy s390 and current s390x architectures.
+ 
+ .SS Override Options
+ 
+@@ -199,7 +259,7 @@ that behavior, and is designed primarily for testing.
+ 
+ .TP
+ \fB-\-boot-filesystem\fR=\fIbootfs\fR
+-The \fBgrub\fR boot loader expects file paths listed in it's configuration
++The \fBgrub\fR boot loader expects file paths listed in its configuration
+ path to be relative to the top of the filesystem they are on, rather then
+ relative to the current root filesystem. By default \fBgrubby\fR searches
+ the list of currently mounted filesystems to determine this. If this option
+@@ -207,19 +267,28 @@ is given \fBgrubby\fR acts as if the specified filesystem was the filesystem
+ containing the kernel (this option is designed primarily for testing).
+ 
+ .TP
+-\fB-\-config-file\fR=\fIpath\fR
++\fB-\-env\fR=\fIpath\fR
++Path for the file where grub environment data is stored.
++
++.TP
++\fB-c\fR, \fB-\-config-file\fR=\fIpath\fR
+ Use \fIpath\fR as the configuration file rather then the default.
+ 
++.TP
++\fB-o\fR, \fB-\-output-file\fR=\fIfile_path\fR
++The destination path for the updated configuration file. Use "-" to
++send it to stdout.
++
+ .SS Multiboot Options
+ 
+-The Multiboot Specification provides a genreic interface for boot
++The Multiboot Specification provides a generic interface for boot
+ loaders and operating systems.  It is supported by the GRUB bootloader.
+ 
+ .TP
+ \fB-\-add-multiboot\fR=\fImultiboot-path\fR
+ Add a new boot entry for the multiboot kernel located at
+ \fImultiboot-path\fR.  Note that this is generally accompanied with a
+-\fI--add-kernel\fR option.
++\fB--add-kernel\fR option.
+ 
+ .TP
+ \fB-\-remove-multiboot\fR=\fImultiboot-path\fR
+@@ -244,11 +313,63 @@ The command line syntax is more than a little baroque. This probably
+ won't be fixed as \fBgrubby\fR is only intended to be called from shell
+ scripts which can get it right.
+ 
++.SH EXAMPLE
++
++The following examples assume the following:
++
++.TS
++allbox;
++rbw15 l.
++cfg_file	Full path to bootloader config file
++new_kernel	Full path to kernel image to be installed
++old_kernel	Full path to old kernel image to be removed
++current_kernel	Full path to a currently installed kernel
++entry_title	Title that appears on bootloader menu
++new_initrd	Full path to initrd for a new kernel
++kernel_args	Set of arguments for the kernel
++menu_index	Index number of a menu entry
++.TE
++
++The examples below quote strings that may have spaces or other whitespace in them. It is also
++perfectly valid to backslash escape these strings if that is more convenient.
++
++.PP
++Add a new kernel entry and copy all options from the current default kernel. This is the behavior
++that most users will want.
++.IP
++\fBgrubby\fR --add-kernel=\fInew_kernel\fR --title="\fIentry_title\fR" --initrd="\fInew_initrd\fR" --copy-default
++.PP
++Add a new kernel entry with custom arguments
++.IP
++\fBgrubby\fR --add-kernel=\fInew_kernel\fR --title="\fIentry_title\fR" --initrd="\fInew_initrd\fR" --args=\fIkernel_args\fR
++.PP
++Remove \fBall menu entries\fR for a specified kernel.
++.IP
++\fBgrubby\fR --remove-kernel=\fIold_kernel\fR
++.PP
++Target a single menu entry to remove without targetting other entries with the same kernel.
++.IP
++\fBgrubby\fR --info=\fIold_kernel\fR
++
++\fBgrubby\fR --remove-kernel=\fImenu_index\fR
++.PP
++Update the arguments for all entries of a specific kernel. New arguments get added while existing arguments get updated values.
++.IP
++\fBgrubby\fR --update-kernel=\fIcurrent_kernel\fR --args="\fIkernel_args\fR"
++.PP
++Remove the arguments for a single entry of a specific kernel.
++.IP
++\fBgrubby\fR --info=\fIcurrent_kernel\fR
++
++\fBgrubby\fR --remove-args=\fImenu_index\fR --args="\fIkernel_args\fR"
++
+ .SH "SEE ALSO"
+ 
+ .BR grub (8),
+ .BR lilo (8),
+ .BR yaboot (8),
++.BR zipl (8),
++.BR dracut (8),
+ .BR mkinitrd (8)
+ 
+ .SH AUTHORS
+@@ -257,4 +378,5 @@ scripts which can get it right.
+ Erik Troan
+ Jeremy Katz
+ Peter Jones
++Robert Marshall
+ .fi
+-- 
+2.5.5
+
diff --git a/SOURCES/0058-Fix-inline-help-typo-1232168.patch b/SOURCES/0058-Fix-inline-help-typo-1232168.patch
new file mode 100644
index 0000000..a444ca2
--- /dev/null
+++ b/SOURCES/0058-Fix-inline-help-typo-1232168.patch
@@ -0,0 +1,29 @@
+From e016fa8fdcd15b9db94b847de6b09b369e5805b6 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Fri, 1 Jul 2016 15:19:24 -0400
+Subject: [PATCH 58/60] Fix inline help typo (#1232168)
+
+Discovered a typo while synchronizing the inline help with the man pages
+and fixed it.
+
+Related: rhbz#1232168
+---
+ grubby.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grubby.c b/grubby.c
+index c379388..ab2c025 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -4824,7 +4824,7 @@ int main(int argc, const char **argv)
+ 		 NULL},
+ 		{"boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0,
+ 		 _
+-		 ("filestystem which contains /boot directory (for testing only)"),
++		 ("filesystem 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,
+-- 
+2.5.5
+
diff --git a/SOURCES/0059-More-edits-for-grubby.8-1232168.patch b/SOURCES/0059-More-edits-for-grubby.8-1232168.patch
new file mode 100644
index 0000000..51f6e30
--- /dev/null
+++ b/SOURCES/0059-More-edits-for-grubby.8-1232168.patch
@@ -0,0 +1,200 @@
+From 944864e679b37423b0e159d0a6cfc4267e609541 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 28 Jun 2016 16:50:37 -0400
+Subject: [PATCH 59/60] More edits for grubby.8 (#1232168)
+
+- Don't switch between the passive and active voice between the option
+  descriptions
+- keep the same point of view between options ("[it] removes all
+  entries" vs "remove all entries")
+- line wrap everywhere except the example envocations at <80 columns,
+  not 100.
+- consistent use of i386 vs ia32
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+Related: rhbz#1232168
+---
+ grubby.8 | 82 +++++++++++++++++++++++++++++++++++-----------------------------
+ 1 file changed, 45 insertions(+), 37 deletions(-)
+
+diff --git a/grubby.8 b/grubby.8
+index 5e1b521..1197109 100644
+--- a/grubby.8
++++ b/grubby.8
+@@ -2,11 +2,12 @@
+ 
+ .SH NAME
+ 
+-grubby \- command line tool used to configure bootloader menu entries across multiple architectures
++grubby \- command line tool used to configure bootloader menu entries across
++multiple architectures
+ 
+ .SH SYNOPSIS
+ 
+-\fBgrubby\fR [\fIOPTIONS...\fR]
++\fBgrubby\fR [\fIOPTIONS\fR]
+ 
+ .SH DESCRIPTION
+ 
+@@ -37,13 +38,13 @@ are deprecated in favor of previously mentioned bootloaders. The
+ 
+ .SS Default Behavior
+ 
+-The default architecture is chosen at compile time. The grubby executable
+-has a series of built in assumptions about what bootloader is being used and
+-where its configuration file lives. If no output format option is specified
+-on the command line then grubby will use these default settings to first
+-search for an existing configuration and, if it is not found, assume that
+-it should be placed in the standard location. These default assumptions are
+-listed in the table below.
++The default bootloader target is primarily determined by the architecture
++for which grubby has been built.  Each architecture has a preferred
++bootloader, and each bootloader has its own configuration file.  If no
++bootloader is selected on the command line, grubby will use these default
++settings to search for an existing configuration.  If no bootloader
++configuration file is found, grubby will use the default value for that
++architecture.  These defaults are listed in the table below.
+ 
+ .TS
+ allbox;
+@@ -81,19 +82,18 @@ Add a new boot entry for the kernel located at \fIkernel-path\fR. A title for
+ the boot entry must be set using \fB-\-title\fR. Most invocations should also
+ include \fB-\-initrd\fR with memtest86 as a notable exception.
+ 
+-The \fB-\-update-kernel\fR
+-option may not be used in the same invocation. 
++The \fB-\-update-kernel\fR option may not be used in the same invocation.
+ 
+ .TP
+ \fB-\-remove-kernel\fR=\fIkernel-path\fR
+-Removes all boot entries which match \fIkernel-path\fR. This may be used
+-along with \fB-\-add-kernel\fR, in which case the new kernel being added will
+-never be removed.
++Remove all boot entries which match \fIkernel-path\fR. This may be used
++along with \fB-\-add-kernel\fR, in which case the new entry being added will
++not be removed.
+ 
+ .TP
+ \fB-\-update-kernel\fR=\fIkernel-path\fR
+-The entries for kernels matching \fRkernel-path\fR are updated. Currently
+-the only items that can be updated is the kernel argument list, which is
++Update the entries for kernels matching \fRkernel-path\fR. Currently
++the only item that can be updated is the kernel argument list, which is
+ modified via the \fB-\-args\fR and \fB-\-remove-args\fR options.
+ 
+ .TP
+@@ -135,7 +135,7 @@ being added.
+ 
+ .TP
+ \fB-\-efi\fR
+-Use linuxefi and initrdefi when constructing bootloader stanzas instead of linux and initrd.
++Use appropriate bootloader commands for EFI on this architecture.
+ 
+ .TP
+ \fB-\-set-default\fR=\fIkernel-path\fR
+@@ -188,16 +188,18 @@ Display information on all boot entries which match \fIkernel-path\fR. I
+ 
+ .TP
+ \fB-\-bootloader-probe\fR
++Attempt to probe for installed bootloaders.  If this option is specified,
+ \fBgrubby\fR tries to determine if \fBgrub\fR or \fBlilo\fR is currently
+-installed. When one of those bootloaders is found the name of that bootloader
+-is displayed on stdout.  Both could be installed (on different devices), and
+-grubby will print out the names of both bootloaders, one per line. The probe
+-for \fBgrub\fR requires a commented out boot directive \fBgrub.conf\fR
+-identical to the standard directive in the lilo configuration file. If this
+-is not present \fBgrubby\fR will assume grub is not installed (note
+-that \fBanaconda\fR places this directive in \fBgrub.conf\fR files it creates).
++installed. When one of those bootloaders is found the name of that
++bootloader is displayed on stdout.  Both could be installed (on different
++devices), and grubby will print out the names of both bootloaders, one per
++line. The probe for \fBgrub\fR requires a commented out boot directive
++\fBgrub.conf\fR identical to the standard directive in the lilo
++configuration file. If this is not present \fBgrubby\fR will assume grub is
++not installed (note that \fBanaconda\fR places this directive in
++\fBgrub.conf\fR files it creates).
+ 
+-\fIThis option is only available on i386 platforms.\fR
++\fIThis option is only available on x86 BIOS platforms.\fR
+ 
+ .TP
+ \fB-v\fR, \fB-\-version\fR
+@@ -213,7 +215,8 @@ alternative bootloader.
+ 
+ .TP
+ \fB-\-elilo\fR
+-Use an \fBelilo\fR style configuration file. This is the default on ia64 platforms. This format is deprecated.
++Use an \fBelilo\fR style configuration file. This is the default on ia64
++platforms. This format is deprecated.
+ 
+ .TP
+ \fB-\-extlinux\fR
+@@ -221,13 +224,14 @@ Use an \fBextlinux\fR style configuration file. This format is deprecated.
+ 
+ .TP
+ \fB-\-grub\fR
+-Use a \fBgrub\fR style configuration file. This is the default on ia32 platforms.
++Use a \fBgrub\fR style configuration file. This is the default on the i386
++architecture.
+ 
+ .TP
+ \fB-\-grub2\fR
+-Use a \fBgrub2\fR style configuration file. This is the default on \fBx86_64\fR
+-architecture as well as the \fBppc64\fR and \fBppc64le\fR architectures
+-running on Power8 or later hardware.
++Use a \fBgrub2\fR style configuration file. This is the default on
++\fBx86_64\fR architecture as well as the \fBppc64\fR and \fBppc64le\fR
++architectures running on Power8 or later hardware.
+ 
+ .TP
+ \fB-\-lilo\fR
+@@ -235,7 +239,8 @@ Use a \fBlilo\fR style configuration file.
+ 
+ .TP
+ \fB-\-silo\fR
+-Use a \fBsilo\fR style configuration file. This is the default on SPARC systems. This format is legacy, deprecated, and unsupported.
++Use a \fBsilo\fR style configuration file. This is the default on SPARC
++systems. This format is legacy, deprecated, and unsupported.
+ 
+ .TP
+ \fB-\-yaboot\fR
+@@ -330,12 +335,13 @@ kernel_args	Set of arguments for the kernel
+ menu_index	Index number of a menu entry
+ .TE
+ 
+-The examples below quote strings that may have spaces or other whitespace in them. It is also
+-perfectly valid to backslash escape these strings if that is more convenient.
++The examples below quote strings that may have spaces or other whitespace in
++them. It is also perfectly valid to backslash escape these strings if that
++is more convenient.
+ 
+ .PP
+-Add a new kernel entry and copy all options from the current default kernel. This is the behavior
+-that most users will want.
++Add a new kernel entry and copy all options from the current default kernel.
++This is the behavior that most users will want.
+ .IP
+ \fBgrubby\fR --add-kernel=\fInew_kernel\fR --title="\fIentry_title\fR" --initrd="\fInew_initrd\fR" --copy-default
+ .PP
+@@ -347,13 +353,15 @@ Remove \fBall menu entries\fR for a specified kernel.
+ .IP
+ \fBgrubby\fR --remove-kernel=\fIold_kernel\fR
+ .PP
+-Target a single menu entry to remove without targetting other entries with the same kernel.
++Target a single menu entry to remove without targetting other entries with
++the same kernel.
+ .IP
+ \fBgrubby\fR --info=\fIold_kernel\fR
+ 
+ \fBgrubby\fR --remove-kernel=\fImenu_index\fR
+ .PP
+-Update the arguments for all entries of a specific kernel. New arguments get added while existing arguments get updated values.
++Update the arguments for all entries of a specific kernel. New arguments get
++added while existing arguments get updated values.
+ .IP
+ \fBgrubby\fR --update-kernel=\fIcurrent_kernel\fR --args="\fIkernel_args\fR"
+ .PP
+-- 
+2.5.5
+
diff --git a/SOURCES/0060-Minor-man-page-changes-1232168.patch b/SOURCES/0060-Minor-man-page-changes-1232168.patch
new file mode 100644
index 0000000..1a9eb71
--- /dev/null
+++ b/SOURCES/0060-Minor-man-page-changes-1232168.patch
@@ -0,0 +1,36 @@
+From 3cb6a97baa11eedc772ea83f8958691bfa3d3c26 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Fri, 1 Jul 2016 15:24:34 -0400
+Subject: [PATCH 60/60] Minor man page changes (#1232168)
+
+Minor wording changes made in the Architecture section after placing the
+initial draft up for public comment.
+
+Related: rhbz#1232168
+---
+ grubby.8 | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/grubby.8 b/grubby.8
+index 1197109..7789b9a 100644
+--- a/grubby.8
++++ b/grubby.8
+@@ -29,12 +29,12 @@ Legacy \fBs390\fR and the current \fBs390x\fR architectures
+ and their \fBzipl\fR bootloader are fully supported.
+ 
+ Support for \fByaboot\fR has been deprecated as all ppc architecture
+-hardware since the Power8 system uses \fBgrub2\fR or petitboot
++hardware since the Power8 uses \fBgrub2\fR or petitboot
+ which both use the grub2 configuration file format.
+ 
+ Legacy bootloaders \fBLILO\fR, \fBSILO\fR, and \fBELILO\fR
+-are deprecated in favor of previously mentioned bootloaders. The
+-\fBSILO\fR bootloader should also be considered unsupported.
++are deprecated and no longer receiving active support in favor of
++previously mentioned bootloaders.
+ 
+ .SS Default Behavior
+ 
+-- 
+2.5.5
+
diff --git a/SOURCES/0061-Rename-setDefaultImage-variables.patch b/SOURCES/0061-Rename-setDefaultImage-variables.patch
new file mode 100644
index 0000000..f547282
--- /dev/null
+++ b/SOURCES/0061-Rename-setDefaultImage-variables.patch
@@ -0,0 +1,66 @@
+From 1b4d2938c4b7cf8d166561214bf12a44c345258d Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Thu, 8 Dec 2016 13:39:22 -0500
+Subject: [PATCH 61/69] Rename setDefaultImage variables
+
+The variable names in setDefaultImage did not match well with
+how they were being used inside the function. Refactored the
+variable names as a precursor to refactoring the function.
+
+Related: rhbz#1285601
+---
+ grubby.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/grubby.c b/grubby.c
+index ab2c025..344f1da 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -2589,19 +2589,19 @@ void markRemovedImage(struct grubConfig *cfg, const char *image,
+ 		entry->skip = 1;
+ }
+ 
+-void setDefaultImage(struct grubConfig *config, int hasNew,
+-		     const char *defaultKernelPath, int newIsDefault,
+-		     const char *prefix, int flags, int index)
++void setDefaultImage(struct grubConfig *config, int isUserSpecifiedKernelPath,
++		     const char *defaultKernelPath, int newBootEntryIsDefault,
++		     const char *prefix, int flags, int newDefaultBootEntryIndex)
+ {
+ 	struct singleEntry *entry, *entry2, *newDefault;
+ 	int i, j;
+ 
+-	if (newIsDefault) {
++	if (newBootEntryIsDefault) {
+ 		config->defaultImage = 0;
+ 		return;
+-	} else if ((index >= 0) && config->cfi->defaultIsIndex) {
+-		if (findEntryByIndex(config, index))
+-			config->defaultImage = index;
++	} else if ((newDefaultBootEntryIndex >= 0) && config->cfi->defaultIsIndex) {
++		if (findEntryByIndex(config, newDefaultBootEntryIndex))
++			config->defaultImage = newDefaultBootEntryIndex;
+ 		else
+ 			config->defaultImage = -1;
+ 		return;
+@@ -2629,7 +2629,7 @@ void setDefaultImage(struct grubConfig *config, int hasNew,
+ 
+ 	if (entry && !entry->skip) {
+ 		/* we can preserve the default */
+-		if (hasNew)
++		if (isUserSpecifiedKernelPath)
+ 			config->defaultImage++;
+ 
+ 		/* count the number of entries erased before this one */
+@@ -2638,7 +2638,7 @@ void setDefaultImage(struct grubConfig *config, int hasNew,
+ 			if (entry2->skip)
+ 				config->defaultImage--;
+ 		}
+-	} else if (hasNew) {
++	} else if (isUserSpecifiedKernelPath) {
+ 		config->defaultImage = 0;
+ 	} else {
+ 		/* Either we just erased the default (or the default line was bad
+-- 
+2.9.3
+
diff --git a/SOURCES/0062-Add-index-constant-definitions-instead-of-open-coded.patch b/SOURCES/0062-Add-index-constant-definitions-instead-of-open-coded.patch
new file mode 100644
index 0000000..9b52d9b
--- /dev/null
+++ b/SOURCES/0062-Add-index-constant-definitions-instead-of-open-coded.patch
@@ -0,0 +1,198 @@
+From d1586b86da52810014bd95e46fd5c86a458fca3e Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Tue, 13 Dec 2016 14:36:31 -0500
+Subject: [PATCH 62/69] Add index constant definitions instead of open-coded
+ values.
+
+Added numeric constants NO_DEFAULT_ENTRY and FIRST_ENTRY_INDEX. This
+clarifies the intent of various assignment operations throughout the
+source file.
+
+Related: rhbz#1285601
+---
+ grubby.c | 44 ++++++++++++++++++++++++--------------------
+ 1 file changed, 24 insertions(+), 20 deletions(-)
+
+diff --git a/grubby.c b/grubby.c
+index 344f1da..bece23a 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -130,6 +130,10 @@ struct singleEntry {
+ #define NEED_END     (1 << 5)
+ 
+ #define MAIN_DEFAULT	    (1 << 0)
++#define FIRST_ENTRY_INDEX    0	/* boot entry index value begin and increment
++				   from this initial value */
++#define NO_DEFAULT_ENTRY    -1	/* indicates that no specific default boot
++				   entry was set or currently exists */
+ #define DEFAULT_SAVED       -2
+ #define DEFAULT_SAVED_GRUB2 -3
+ 
+@@ -1712,7 +1716,7 @@ static struct grubConfig *readConfig(const char *inName,
+ 						*end == ' ' || *end == '\t'))
+ 					end++;
+ 				if (*end)
+-					cfg->defaultImage = -1;
++					cfg->defaultImage = NO_DEFAULT_ENTRY;
+ 			} else if (defaultLine->numElements == 3) {
+ 				char *value = defaultLine->elements[2].item;
+ 				while (*value && (*value == '"' ||
+@@ -1725,7 +1729,7 @@ static struct grubConfig *readConfig(const char *inName,
+ 						*end == ' ' || *end == '\t'))
+ 					end++;
+ 				if (*end)
+-					cfg->defaultImage = -1;
++					cfg->defaultImage = NO_DEFAULT_ENTRY;
+ 			}
+ 		} else if (cfi->defaultSupportSaved &&
+ 			   !strncmp(defaultLine->elements[1].item, "saved",
+@@ -1735,7 +1739,7 @@ static struct grubConfig *readConfig(const char *inName,
+ 			cfg->defaultImage =
+ 			    strtol(defaultLine->elements[1].item, &end, 10);
+ 			if (*end)
+-				cfg->defaultImage = -1;
++				cfg->defaultImage = NO_DEFAULT_ENTRY;
+ 		} else if (defaultLine->numElements >= 2) {
+ 			int i = 0;
+ 			while ((entry = findEntryByIndex(cfg, i))) {
+@@ -1763,7 +1767,7 @@ static struct grubConfig *readConfig(const char *inName,
+ 			if (entry) {
+ 				cfg->defaultImage = i;
+ 			} else {
+-				cfg->defaultImage = -1;
++				cfg->defaultImage = NO_DEFAULT_ENTRY;
+ 			}
+ 		}
+ 	} else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) {
+@@ -1780,7 +1784,7 @@ static struct grubConfig *readConfig(const char *inName,
+ 				cfg->defaultImage = index;
+ 		}
+ 	} else {
+-		cfg->defaultImage = 0;
++		cfg->defaultImage = FIRST_ENTRY_INDEX;
+ 	}
+ 
+ 	return cfg;
+@@ -1800,7 +1804,7 @@ static void writeDefault(FILE * out, char *indent,
+ 		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) {
++		if (cfg->defaultImage >= FIRST_ENTRY_INDEX && cfg->cfi->setEnv) {
+ 			char *title;
+ 			entry = findEntryByIndex(cfg, cfg->defaultImage);
+ 			line = getLineByType(LT_MENUENTRY, entry->lines);
+@@ -1813,7 +1817,7 @@ static void writeDefault(FILE * out, char *indent,
+ 							 "saved_entry", title);
+ 			}
+ 		}
+-	} else if (cfg->defaultImage > -1) {
++	} else if (cfg->defaultImage >= FIRST_ENTRY_INDEX) {
+ 		if (cfg->cfi->defaultIsIndex) {
+ 			if (cfg->cfi->defaultIsVariable) {
+ 				fprintf(out, "%sset default=\"%d\"\n", indent,
+@@ -2515,7 +2519,7 @@ struct singleEntry *findTemplate(struct grubConfig *cfg, const char *prefix,
+ 				}
+ 			}
+ 		}
+-	} else if (cfg->defaultImage > -1) {
++	} else if (cfg->defaultImage >= FIRST_ENTRY_INDEX) {
+ 		entry = findEntryByIndex(cfg, cfg->defaultImage);
+ 		if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {
+ 			if (indexPtr)
+@@ -2597,20 +2601,20 @@ void setDefaultImage(struct grubConfig *config, int isUserSpecifiedKernelPath,
+ 	int i, j;
+ 
+ 	if (newBootEntryIsDefault) {
+-		config->defaultImage = 0;
++		config->defaultImage = FIRST_ENTRY_INDEX;
+ 		return;
+ 	} else if ((newDefaultBootEntryIndex >= 0) && config->cfi->defaultIsIndex) {
+ 		if (findEntryByIndex(config, newDefaultBootEntryIndex))
+ 			config->defaultImage = newDefaultBootEntryIndex;
+ 		else
+-			config->defaultImage = -1;
++			config->defaultImage = NO_DEFAULT_ENTRY;
+ 		return;
+ 	} else if (defaultKernelPath) {
+ 		i = 0;
+ 		if (findEntryByPath(config, defaultKernelPath, prefix, &i)) {
+ 			config->defaultImage = i;
+ 		} else {
+-			config->defaultImage = -1;
++			config->defaultImage = NO_DEFAULT_ENTRY;
+ 			return;
+ 		}
+ 	}
+@@ -2622,7 +2626,7 @@ void setDefaultImage(struct grubConfig *config, int isUserSpecifiedKernelPath,
+ 		/* default is set to saved, we don't want to change it */
+ 		return;
+ 
+-	if (config->defaultImage > -1)
++	if (config->defaultImage >= FIRST_ENTRY_INDEX)
+ 		entry = findEntryByIndex(config, config->defaultImage);
+ 	else
+ 		entry = NULL;
+@@ -2639,7 +2643,7 @@ void setDefaultImage(struct grubConfig *config, int isUserSpecifiedKernelPath,
+ 				config->defaultImage--;
+ 		}
+ 	} else if (isUserSpecifiedKernelPath) {
+-		config->defaultImage = 0;
++		config->defaultImage = FIRST_ENTRY_INDEX;
+ 	} 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
+@@ -2648,7 +2652,7 @@ void setDefaultImage(struct grubConfig *config, int isUserSpecifiedKernelPath,
+ 		    findTemplate(config, prefix, &config->defaultImage, 1,
+ 				 flags);
+ 		if (!newDefault)
+-			config->defaultImage = -1;
++			config->defaultImage = NO_DEFAULT_ENTRY;
+ 	}
+ }
+ 
+@@ -5210,11 +5214,11 @@ int main(int argc, const char **argv)
+ 		struct singleEntry *entry;
+ 		char *rootspec;
+ 
+-		if (config->defaultImage == -1)
++		if (config->defaultImage == NO_DEFAULT_ENTRY)
+ 			return 0;
+ 		if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
+ 		    cfi->defaultIsSaved)
+-			config->defaultImage = 0;
++			config->defaultImage = FIRST_ENTRY_INDEX;
+ 		entry = findEntryByIndex(config, config->defaultImage);
+ 		if (!entry)
+ 			return 0;
+@@ -5237,11 +5241,11 @@ int main(int argc, const char **argv)
+ 		struct singleLine *line;
+ 		struct singleEntry *entry;
+ 
+-		if (config->defaultImage == -1)
++		if (config->defaultImage == NO_DEFAULT_ENTRY)
+ 			return 0;
+ 		if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
+ 		    cfi->defaultIsSaved)
+-			config->defaultImage = 0;
++			config->defaultImage = FIRST_ENTRY_INDEX;
+ 		entry = findEntryByIndex(config, config->defaultImage);
+ 		if (!entry)
+ 			return 0;
+@@ -5271,11 +5275,11 @@ int main(int argc, const char **argv)
+ 		return 0;
+ 
+ 	} else if (displayDefaultIndex) {
+-		if (config->defaultImage == -1)
++		if (config->defaultImage == NO_DEFAULT_ENTRY)
+ 			return 0;
+ 		if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
+ 		    cfi->defaultIsSaved)
+-			config->defaultImage = 0;
++			config->defaultImage = FIRST_ENTRY_INDEX;
+ 		printf("%i\n", config->defaultImage);
+ 		return 0;
+ 
+-- 
+2.9.3
+
diff --git a/SOURCES/0063-Track-configuration-modifications.patch b/SOURCES/0063-Track-configuration-modifications.patch
new file mode 100644
index 0000000..8766729
--- /dev/null
+++ b/SOURCES/0063-Track-configuration-modifications.patch
@@ -0,0 +1,50 @@
+From db71a9ef9363f9ce01ee1746c827f8a2feac73e7 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Thu, 8 Dec 2016 16:52:45 -0500
+Subject: [PATCH 63/69] Track configuration modifications
+
+The setDefaultImage function had a subtle dependency on being run before
+addNewKernel is invoked. Added the ability to track invocation to
+prevent them from being so tightly coupled.
+
+Related: rhbz#1285601
+---
+ grubby.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/grubby.c b/grubby.c
+index bece23a..3929212 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -671,6 +671,8 @@ struct grubConfig {
+ 	int fallbackImage;	/* just like defaultImage */
+ 	int flags;
+ 	struct configFileInfo *cfi;
++	int isModified;		/* assumes only one entry added
++				   per invocation of grubby */
+ };
+ 
+ blkid_cache blkid;
+@@ -1399,6 +1401,7 @@ static struct grubConfig *readConfig(const char *inName,
+ 	cfg->theLines = NULL;
+ 	cfg->entries = NULL;
+ 	cfg->fallbackImage = 0;
++	cfg->isModified = 0;
+ 
+ 	/* copy everything we have */
+ 	while (*head) {
+@@ -4764,8 +4767,10 @@ int addNewKernel(struct grubConfig *config, struct singleEntry *template,
+ 	}
+ 
+ 	if (updateImage(config, indexs, prefix, newKernelArgs, NULL,
+-			newMBKernelArgs, NULL))
++			newMBKernelArgs, NULL)) {
++		config->isModified = 1;
+ 		return 1;
++	}
+ 
+ 	return 0;
+ }
+-- 
+2.9.3
+
diff --git a/SOURCES/0064-Fix-some-test-cases-where-the-resulting-default-inde.patch b/SOURCES/0064-Fix-some-test-cases-where-the-resulting-default-inde.patch
new file mode 100644
index 0000000..b127d11
--- /dev/null
+++ b/SOURCES/0064-Fix-some-test-cases-where-the-resulting-default-inde.patch
@@ -0,0 +1,65 @@
+From 2b4b56143e6af082263cf28ecbd3ff049d697a7f Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Thu, 15 Dec 2016 21:47:28 -0500
+Subject: [PATCH 64/69] Fix some test cases where the resulting default index
+ is wrong
+
+Fix two issues with tests where removing a kernel or adding a boot entry
+at a user specified index had the wrong default index selected in the
+expected output.
+
+One of these issues is the --set-index test cases for grub 1, which
+expect --make-default is implied where it should not be.
+
+The third is a removal test, where the default index in the result data
+is off by one when we've removed 2 entries keyed off of the kernel
+filesystem path.
+
+This change causes these test cases to fail.
+
+Resolves: rhbz#1285601
+---
+ test/results/add/g1.17   | 2 +-
+ test/results/add/g1.9    | 2 +-
+ test/results/remove/g7.1 | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/test/results/add/g1.17 b/test/results/add/g1.17
+index 6a38822..eda4e93 100644
+--- a/test/results/add/g1.17
++++ b/test/results/add/g1.17
+@@ -7,7 +7,7 @@
+ #          kernel /vmlinuz-version ro root=/dev/sda1
+ #          initrd /initrd-version.img
+ #boot=/dev/hda
+-default=1
++default=0
+ timeout=10
+ splashimage=(hd0,0)/grub/splash.xpm.gz
+ title Red Hat Linux (2.4.7-2)
+diff --git a/test/results/add/g1.9 b/test/results/add/g1.9
+index 310623d..8976e76 100644
+--- a/test/results/add/g1.9
++++ b/test/results/add/g1.9
+@@ -7,7 +7,7 @@
+ #          kernel /vmlinuz-version ro root=/dev/sda1
+ #          initrd /initrd-version.img
+ #boot=/dev/hda
+-default=2
++default=1
+ timeout=10
+ splashimage=(hd0,0)/grub/splash.xpm.gz
+ title Red Hat Linux (2.4.7-2)
+diff --git a/test/results/remove/g7.1 b/test/results/remove/g7.1
+index ea1a6fb..611d7a1 100644
+--- a/test/results/remove/g7.1
++++ b/test/results/remove/g7.1
+@@ -1,4 +1,4 @@
+-default=1
++default=0
+ timeout=10
+ splashimage=(hd0,5)/boot/grub/splash.xpm.gz
+ 
+-- 
+2.9.3
+
diff --git a/SOURCES/0065-Don-t-assume-make-default-just-because-set-index-was.patch b/SOURCES/0065-Don-t-assume-make-default-just-because-set-index-was.patch
new file mode 100644
index 0000000..6d3292a
--- /dev/null
+++ b/SOURCES/0065-Don-t-assume-make-default-just-because-set-index-was.patch
@@ -0,0 +1,196 @@
+From 0343d901cade475b6b92134cd45184316d80039f Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Tue, 13 Dec 2016 18:20:15 -0500
+Subject: [PATCH 65/69] Don't assume --make-default just because --set-index
+ was passed.
+
+grubby previously made the assumption that every time a new
+boot entry gets added using --set-index, it should be the default. Due
+to this behavior, it also masked an logic error that prevented the
+selection of the proper index in cases where it was necessary to
+dynamically pick a new default boot entry, or to keep the existing
+default boot entry when its position in the config file moved.
+
+Resolves: rhbz#1285601
+---
+ grubby.c | 136 ++++++++++++++++++++++++++++++++++++++++++++-------------------
+ 1 file changed, 96 insertions(+), 40 deletions(-)
+
+diff --git a/grubby.c b/grubby.c
+index 3929212..4e872c0 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -2596,66 +2596,121 @@ void markRemovedImage(struct grubConfig *cfg, const char *image,
+ 		entry->skip = 1;
+ }
+ 
+-void setDefaultImage(struct grubConfig *config, int isUserSpecifiedKernelPath,
++void setDefaultImage(struct grubConfig *config, int isAddingBootEntry,
+ 		     const char *defaultKernelPath, int newBootEntryIsDefault,
+-		     const char *prefix, int flags, int newDefaultBootEntryIndex)
++		     const char *prefix, int flags,
++		     int newDefaultBootEntryIndex, int newBootEntryIndex)
+ {
+-	struct singleEntry *entry, *entry2, *newDefault;
+-	int i, j;
++	struct singleEntry *bootEntry, *newDefault;
++	int indexToVerify, firstKernelEntryIndex, currentLookupIndex;
++
++	/* handle the two cases where the user explictly picks the default
++	 * boot entry index as it would exist post-modification */
+ 
++	/* Case 1: user chose to make the latest boot entry the default */
+ 	if (newBootEntryIsDefault) {
+-		config->defaultImage = FIRST_ENTRY_INDEX;
++		config->defaultImage = newBootEntryIndex;
+ 		return;
+-	} else if ((newDefaultBootEntryIndex >= 0) && config->cfi->defaultIsIndex) {
+-		if (findEntryByIndex(config, newDefaultBootEntryIndex))
++	}
++
++	/* Case 2: user picked an arbitrary index as the default boot entry */
++	if (newDefaultBootEntryIndex >= FIRST_ENTRY_INDEX
++	    && config->cfi->defaultIsIndex) {
++		indexToVerify = newDefaultBootEntryIndex;
++
++		/* user chose to make latest boot entry the default */
++		if (newDefaultBootEntryIndex == newBootEntryIndex) {
++			config->defaultImage = newBootEntryIndex;
++			return;
++		}
++
++		/* the user picks the default index based on the
++		 * order of the bootloader configuration after
++		 * modification; ensure we are checking for the
++		 * existence of the correct entry */
++		if (newBootEntryIndex < newDefaultBootEntryIndex) {
++			if (!config->isModified)
++				indexToVerify--;
++		}
++
++		/* verify the user selected index will exist */
++		if (findEntryByIndex(config, indexToVerify)) {
+ 			config->defaultImage = newDefaultBootEntryIndex;
+-		else
++		} else {
+ 			config->defaultImage = NO_DEFAULT_ENTRY;
++		}
++
+ 		return;
+-	} else if (defaultKernelPath) {
+-		i = 0;
+-		if (findEntryByPath(config, defaultKernelPath, prefix, &i)) {
+-			config->defaultImage = i;
+-		} else {
++	}
++
++	/* handle cases where the index value may shift */
++
++	/* check validity of existing default or first-entry-found
++	   selection */
++	if (defaultKernelPath) {
++		/* user requested first-entry-found */
++		if (!findEntryByPath(config, defaultKernelPath,
++				     prefix, &firstKernelEntryIndex)) {
++			/* don't change default if can't find match */
+ 			config->defaultImage = NO_DEFAULT_ENTRY;
+ 			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;
++		config->defaultImage = firstKernelEntryIndex;
+ 
+-	if (config->defaultImage >= FIRST_ENTRY_INDEX)
+-		entry = findEntryByIndex(config, config->defaultImage);
+-	else
+-		entry = NULL;
++		/* this is where we start looking for decrement later */
++		currentLookupIndex = config->defaultImage;
+ 
+-	if (entry && !entry->skip) {
+-		/* we can preserve the default */
+-		if (isUserSpecifiedKernelPath)
++		if (isAddingBootEntry && !config->isModified &&
++		    (newBootEntryIndex < config->defaultImage)) {
++			/* increment because new entry added before default */
+ 			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 (isUserSpecifiedKernelPath) {
+-		config->defaultImage = FIRST_ENTRY_INDEX;
+ 	} 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. */
++		/* use pre-existing default entry */
++		currentLookupIndex = config->defaultImage;
++
++		if (isAddingBootEntry
++		    && (newBootEntryIndex <= config->defaultImage)) {
++			config->defaultImage++;
++
++			if (config->isModified) {
++				currentLookupIndex++;
++			}
++		}
++	}
++
++	/* sanity check - is this entry index valid? */
++	bootEntry = findEntryByIndex(config, currentLookupIndex);
++
++	if ((bootEntry && bootEntry->skip) || !bootEntry) {
++		/* entry is to be skipped or is invalid */
++		if (isAddingBootEntry) {
++			config->defaultImage = newBootEntryIndex;
++			return;
++		}
+ 		newDefault =
+ 		    findTemplate(config, prefix, &config->defaultImage, 1,
+ 				 flags);
+-		if (!newDefault)
++		if (!newDefault) {
+ 			config->defaultImage = NO_DEFAULT_ENTRY;
++		}
++
++		return;
++	}
++
++	currentLookupIndex--;
++
++	/* decrement index by the total number of entries deleted */
++
++	for (indexToVerify = currentLookupIndex;
++	     indexToVerify >= FIRST_ENTRY_INDEX; indexToVerify--) {
++
++		bootEntry = findEntryByIndex(config, indexToVerify);
++
++		if (bootEntry && bootEntry->skip) {
++			config->defaultImage--;
++		}
+ 	}
+ }
+ 
+@@ -5300,7 +5355,8 @@ int main(int argc, const char **argv)
+ 	markRemovedImage(config, removeKernelPath, bootPrefix);
+ 	markRemovedImage(config, removeMBKernel, bootPrefix);
+ 	setDefaultImage(config, newKernelPath != NULL, defaultKernel,
+-			makeDefault, bootPrefix, flags, defaultIndex);
++			makeDefault, bootPrefix, flags, defaultIndex,
++			newIndex);
+ 	setFallbackImage(config, newKernelPath != NULL);
+ 	if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,
+ 			removeArgs, newMBKernelArgs, removeMBKernelArgs))
+-- 
+2.9.3
+
diff --git a/SOURCES/0066-Clarify-set-default-index-in-the-man-page.patch b/SOURCES/0066-Clarify-set-default-index-in-the-man-page.patch
new file mode 100644
index 0000000..0630d86
--- /dev/null
+++ b/SOURCES/0066-Clarify-set-default-index-in-the-man-page.patch
@@ -0,0 +1,32 @@
+From 778ec42a36c02da40fd6044ac42fdee0e186c7fc Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Thu, 15 Dec 2016 21:53:31 -0500
+Subject: [PATCH 66/69] Clarify --set-default-index in the man page.
+
+This changes the man page to say that the index value provided with
+--set-default-index applies to the boot entry list after modifications.
+
+Resolves: rhbz#1285601
+---
+ grubby.8 | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/grubby.8 b/grubby.8
+index 7789b9a..465df32 100644
+--- a/grubby.8
++++ b/grubby.8
+@@ -144,8 +144,9 @@ boot entry. This may not be invoked with \fB-\-set-default-index\fR.
+ 
+ .TP
+ \fB-\-set-default-index\fR=\fIentry-index\fR
+-Makes the given entry number the default boot entry. This may not
+-be invoked with \fB-\-set-default\fR.
++Makes the given entry number the default boot entry. This may not be invoked
++with \fB-\-set-default\fR.  The given value represents the index in the
++post-modification boot entry list.
+ 
+ .TP
+ \fB-\-make-default\fR
+-- 
+2.9.3
+
diff --git a/SOURCES/0067-Add-multi-entry-removal-test-1285601.patch b/SOURCES/0067-Add-multi-entry-removal-test-1285601.patch
new file mode 100644
index 0000000..473c610
--- /dev/null
+++ b/SOURCES/0067-Add-multi-entry-removal-test-1285601.patch
@@ -0,0 +1,261 @@
+From ef74333dffe359aa5cf9ea1313ab9ccb7ed3b192 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Thu, 22 Dec 2016 17:40:52 -0500
+Subject: [PATCH 67/69] Add multi-entry removal test (#1285601)
+
+Test what happens to the default entry set in the grub environment after
+removing the first two boot entries.
+
+Related: rhbz#1285601
+---
+ test.sh                            |   7 +++
+ test/grub2-support_files/grubenv.4 |   3 +
+ test/grub2.19                      | 112 +++++++++++++++++++++++++++++++++++++
+ test/results/remove/g2.19          |  88 +++++++++++++++++++++++++++++
+ 4 files changed, 210 insertions(+)
+ create mode 100644 test/grub2-support_files/grubenv.4
+ create mode 100644 test/grub2.19
+ create mode 100644 test/results/remove/g2.19
+
+diff --git a/test.sh b/test.sh
+index dbf7507..3631ed0 100755
+--- a/test.sh
++++ b/test.sh
+@@ -570,6 +570,13 @@ if [ "$testgrub2" == "y" ]; then
+         --copy-default --title 'Red Hat Enterprise Linux Server' \
+         --args=root=/dev/mapper/foo--
+ 
++    grub2Test grub2.19 remove/g2.19 --env grubenv.4 \
++        --remove-kernel=/boot/vmlinuz-2.6.38.2-9.fc15.x86_64 \
++        --boot-filesystem=/boot/
++    commandTest "saved_default output" \
++        "grub2-editenv test/grub2-support_files/env_temp list" \
++        "saved_entry=Linux, with Fedora 2.6.38.8-32.fc15.x86_64"
++
+     # copy a stanza and add arguments as well, while using --set-index=
+     testing="GRUB2 add stanza and new args with --set-index="
+     grub2Test grub2.18 add/g2-1.18  --env grubenv.3 \
+diff --git a/test/grub2-support_files/grubenv.4 b/test/grub2-support_files/grubenv.4
+new file mode 100644
+index 0000000..1311638
+--- /dev/null
++++ b/test/grub2-support_files/grubenv.4
+@@ -0,0 +1,3 @@
++# GRUB Environment Block
++saved_entry=Linux, with Fedora 2.6.38.8-32.fc15.x86_64
++################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################
+diff --git a/test/grub2.19 b/test/grub2.19
+new file mode 100644
+index 0000000..be07b3e
+--- /dev/null
++++ b/test/grub2.19
+@@ -0,0 +1,112 @@
++#
++# 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
++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 {
++  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 'First Title To Remove' --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 ...'
++	linux	/vmlinuz-2.6.38.2-9.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb
++	echo	'Loading initial ramdisk ...'
++	initrd	/initramfs-2.6.38.2-9.fc15.x86_64.img
++}
++menuentry 'Second Title To Remove' --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 ...'
++	linux	/vmlinuz-2.6.38.2-9.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb
++	echo	'Loading initial ramdisk ...'
++	initrd	/initramfs-2.6.38.2-9.fc15.x86_64.img
++}
++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 ...'
++	linux	/vmlinuz-2.6.38.8-32.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb
++	echo	'Loading initial ramdisk ...'
++	initrd	/initramfs-2.6.38.8-32.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/remove/g2.19 b/test/results/remove/g2.19
+new file mode 100644
+index 0000000..f65edd5
+--- /dev/null
++++ b/test/results/remove/g2.19
+@@ -0,0 +1,88 @@
++#
++# 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
++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 {
++  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 ...'
++	linux	/vmlinuz-2.6.38.8-32.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root ro quiet rhgb
++	echo	'Loading initial ramdisk ...'
++	initrd	/initramfs-2.6.38.8-32.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.9.3
+
diff --git a/SOURCES/0068-Fix-findTemplate-index-logic-1285601.patch b/SOURCES/0068-Fix-findTemplate-index-logic-1285601.patch
new file mode 100644
index 0000000..eeb03d4
--- /dev/null
+++ b/SOURCES/0068-Fix-findTemplate-index-logic-1285601.patch
@@ -0,0 +1,40 @@
+From 3d6e04814d4578a4f57cfc98709ec0640428977e Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Thu, 22 Dec 2016 17:52:14 -0500
+Subject: [PATCH 68/69] Fix findTemplate index logic (#1285601)
+
+The fallback case where findTemplate has to look for the first entry
+contained a logic flaw that could return an incorrect index. This
+discovered index should be reduced by one for each boot entry that will
+be skipped in the final output. The flaw occurred because the index
+variable was used for the loop upper bound at the same time as it was
+being decremented within the actual loop body. The loop would thus fail
+to examine a number of boot entries equal to the total number of
+iterations the loop performed.
+
+Related: rhbz#1285601
+---
+ grubby.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/grubby.c b/grubby.c
+index 4e872c0..57c1ed7 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -2534,8 +2534,11 @@ struct singleEntry *findTemplate(struct grubConfig *cfg, const char *prefix,
+ 	index = 0;
+ 	while ((entry = findEntryByIndex(cfg, index))) {
+ 		if (suitableImage(entry, prefix, skipRemoved, flags)) {
+-			int j;
+-			for (j = 0; j < index; j++) {
++			int j, unmodifiedIndex;
++
++			unmodifiedIndex = index;
++
++			for (j = 0; j < unmodifiedIndex; j++) {
+ 				entry2 = findEntryByIndex(cfg, j);
+ 				if (entry2->skip)
+ 					index--;
+-- 
+2.9.3
+
diff --git a/SOURCES/0069-Write-correct-default-to-environment-1285601.patch b/SOURCES/0069-Write-correct-default-to-environment-1285601.patch
new file mode 100644
index 0000000..3c32338
--- /dev/null
+++ b/SOURCES/0069-Write-correct-default-to-environment-1285601.patch
@@ -0,0 +1,43 @@
+From 23355786a334e05a99b60b6c7769665ffeb3bdc4 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Thu, 22 Dec 2016 17:56:44 -0500
+Subject: [PATCH 69/69] Write correct default to environment (#1285601)
+
+grubby writes the title of the default boot entry to the bootloader
+environment. The title lookup did not correctly account for the offset
+required if some boot entries were marked for removal.
+
+Related: rhbz#1285601
+---
+ grubby.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/grubby.c b/grubby.c
+index 57c1ed7..9d9d748 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -1809,7 +1809,20 @@ static void writeDefault(FILE * out, char *indent,
+ 		fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);
+ 		if (cfg->defaultImage >= FIRST_ENTRY_INDEX && cfg->cfi->setEnv) {
+ 			char *title;
+-			entry = findEntryByIndex(cfg, cfg->defaultImage);
++			int trueIndex, currentIndex;
++
++			trueIndex = 0;
++			currentIndex = 0;
++
++			while ((entry = findEntryByIndex(cfg, currentIndex))) {
++				if (!entry->skip) {
++					if (trueIndex == cfg->defaultImage) {
++						break;
++					}
++					trueIndex++;
++				}
++				currentIndex++;
++			}
+ 			line = getLineByType(LT_MENUENTRY, entry->lines);
+ 			if (!line)
+ 				line = getLineByType(LT_TITLE, entry->lines);
+-- 
+2.9.3
+
diff --git a/SOURCES/0070-Initialize-variable-for-ppc-environment-1285601.patch b/SOURCES/0070-Initialize-variable-for-ppc-environment-1285601.patch
new file mode 100644
index 0000000..0d8badc
--- /dev/null
+++ b/SOURCES/0070-Initialize-variable-for-ppc-environment-1285601.patch
@@ -0,0 +1,29 @@
+From 7f4bde0a1c7889f088c704d441323fefd12acffc Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Mon, 27 Feb 2017 15:59:53 -0500
+Subject: [PATCH] Initialize variable for ppc environment (#1285601)
+
+Building on PPC does not default the value of an uninitialized integer
+to zero which caused test failures.
+
+Related: rhbz#1285601
+---
+ grubby.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/grubby.c b/grubby.c
+index 9544212..7cd5c90 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -2259,6 +2259,8 @@ void setDefaultImage(struct grubConfig *config, int isAddingBootEntry,
+ 	/* check validity of existing default or first-entry-found
+ 	   selection */
+ 	if (defaultKernelPath) {
++                /* we must initialize this */
++                firstKernelEntryIndex = 0;
+ 		/* user requested first-entry-found */
+ 		if (!findEntryByPath(config, defaultKernelPath,
+ 				     prefix, &firstKernelEntryIndex)) {
+-- 
+2.9.3
+
diff --git a/SOURCES/0071-Fix-initial-saved_entry-read-issue-1285601.patch b/SOURCES/0071-Fix-initial-saved_entry-read-issue-1285601.patch
new file mode 100644
index 0000000..51df2da
--- /dev/null
+++ b/SOURCES/0071-Fix-initial-saved_entry-read-issue-1285601.patch
@@ -0,0 +1,64 @@
+From 332ec67718959920c26283854ec9280e4023a437 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Mon, 6 Mar 2017 15:57:54 -0500
+Subject: [PATCH] Fix initial saved_entry read issue (#1285601)
+
+If a system has never had a kernel upgrade/rollback then grubby
+does not read saved_entry properly.  Added a guard to catch
+saved_entry and read it to pick the proper index in these cases.
+
+Resolves: rhbz#1285601
+---
+ grubby.c | 29 +++++++++++++++++++++++++++--
+ 1 file changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/grubby.c b/grubby.c
+index de76b56..4d3834b 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -2620,6 +2620,9 @@ void setDefaultImage(struct grubConfig *config, int isAddingBootEntry,
+ 	struct singleEntry *bootEntry, *newDefault;
+ 	int indexToVerify, firstKernelEntryIndex, currentLookupIndex;
+ 
++        /* initialize */
++        currentLookupIndex = FIRST_ENTRY_INDEX;
++
+ 	/* handle the two cases where the user explictly picks the default
+ 	 * boot entry index as it would exist post-modification */
+ 
+@@ -2685,8 +2688,30 @@ void setDefaultImage(struct grubConfig *config, int isAddingBootEntry,
+ 			config->defaultImage++;
+ 		}
+ 	} else {
+-		/* use pre-existing default entry */
+-		currentLookupIndex = config->defaultImage;
++                /* check to see if the default is stored in the environment */
++                if (config->defaultImage < FIRST_ENTRY_INDEX) {
++                    if (config->defaultImage == DEFAULT_SAVED || config->defaultImage == DEFAULT_SAVED_GRUB2)
++                    {
++                        if (config->cfi->defaultIsSaved) {
++                            if (config->cfi->getEnv) {
++                                char *defaultTitle = config->cfi->getEnv(config->cfi, "saved_entry");
++
++                                if (defaultTitle) {
++                                    if (isnumber(defaultTitle)) {
++                                        currentLookupIndex = atoi(defaultTitle);
++                                    } else {
++                                        findEntryByTitle(config, defaultTitle, &currentLookupIndex);
++                                    }
++                                    /* set the default Image to an actual index */
++                                    config->defaultImage = currentLookupIndex;
++                                }
++                            }
++                         }
++                    }
++                } else {
++                        /* use pre-existing default entry from the file*/
++                        currentLookupIndex = config->defaultImage;
++                }
+ 
+ 		if (isAddingBootEntry
+ 		    && (newBootEntryIndex <= config->defaultImage)) {
+-- 
+2.9.3
+
diff --git a/SOURCES/0072-Add-s390-s390x-info-test-1285601.patch b/SOURCES/0072-Add-s390-s390x-info-test-1285601.patch
new file mode 100644
index 0000000..1d9a579
--- /dev/null
+++ b/SOURCES/0072-Add-s390-s390x-info-test-1285601.patch
@@ -0,0 +1,74 @@
+From 70e36b1a4e67a162c44a692bcde6bec6b6bdc9ee Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Tue, 14 Mar 2017 22:55:27 -0400
+Subject: [PATCH 72/75] Add s390/s390x --info test (#1285601)
+
+Running the --info grubby option on s390/s390x platforms always returned
+the (null) value. Added a test to look at --info and ensure it comes out
+as a user would expect.
+
+Resolves: rhbz#1285601
+---
+ test.sh                |  2 ++
+ test/results/info/z2.1 |  6 ++++++
+ test/zipl.2            | 22 ++++++++++++++++++++++
+ 3 files changed, 30 insertions(+)
+ create mode 100644 test/results/info/z2.1
+ create mode 100644 test/zipl.2
+
+diff --git a/test.sh b/test.sh
+index 3631ed0..34ba4d7 100755
+--- a/test.sh
++++ b/test.sh
+@@ -320,6 +320,8 @@ 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="Z/IPL display entry information"
++ziplDisplayTest zipl.2 info/z2.1 --info=1
+ 
+ testing="GRUB fallback directive"
+ grubTest grub.5 fallback/g5.1 --remove-kernel=/boot/vmlinuz-2.4.7-ac3 \
+diff --git a/test/results/info/z2.1 b/test/results/info/z2.1
+new file mode 100644
+index 0000000..e5ce3a1
+--- /dev/null
++++ b/test/results/info/z2.1
+@@ -0,0 +1,6 @@
++index=1
++kernel=/boot/vmlinuz-3.10.0-514.6.2.el7.s390x
++args="crashkernel=auto rd.dasd=0.0.0120 rd.dasd=0.0.0121 rd.dasd=0.0.0122 rd.dasd=0.0.0123 rd.lvm.lv=rhel_ibm-z-68/root rd.lvm.lv=rhel_ibm-z-68/swap rd.znet=qeth,0.0.8000,0.0.8001,0.0.8002,layer2=1,portname=z-68,portno=0 LANG=en_US.UTF-8 systemd.log_level=debug systemd.log_target=kmsg"
++root=/dev/mapper/rhel_ibm--z--68-root
++initrd=/boot/initramfs-3.10.0-514.6.2.el7.s390x.img
++title=3.10.0-514.6.2.el7.s390x_with_debugging
+diff --git a/test/zipl.2 b/test/zipl.2
+new file mode 100644
+index 0000000..f064b2a
+--- /dev/null
++++ b/test/zipl.2
+@@ -0,0 +1,22 @@
++[defaultboot]
++defaultauto
++prompt=1
++timeout=5
++default=3.10.0-514.6.2.el7.s390x_with_debugging
++target=/boot
++[3.10.0-514.6.2.el7.s390x]
++	image=/boot/vmlinuz-3.10.0-514.6.2.el7.s390x
++	parameters="root=/dev/mapper/rhel_ibm--z--68-root crashkernel=auto rd.dasd=0.0.0120 rd.dasd=0.0.0121 rd.dasd=0.0.0122 rd.dasd=0.0.0123 rd.lvm.lv=rhel_ibm-z-68/root rd.lvm.lv=rhel_ibm-z-68/swap rd.znet=qeth,0.0.8000,0.0.8001,0.0.8002,layer2=1,portname=z-68,portno=0 LANG=en_US.UTF-8"
++	ramdisk=/boot/initramfs-3.10.0-514.6.2.el7.s390x.img
++[3.10.0-514.6.2.el7.s390x_with_debugging]
++	image=/boot/vmlinuz-3.10.0-514.6.2.el7.s390x
++	parameters="root=/dev/mapper/rhel_ibm--z--68-root crashkernel=auto rd.dasd=0.0.0120 rd.dasd=0.0.0121 rd.dasd=0.0.0122 rd.dasd=0.0.0123 rd.lvm.lv=rhel_ibm-z-68/root rd.lvm.lv=rhel_ibm-z-68/swap rd.znet=qeth,0.0.8000,0.0.8001,0.0.8002,layer2=1,portname=z-68,portno=0 LANG=en_US.UTF-8 systemd.log_level=debug systemd.log_target=kmsg"
++	ramdisk=/boot/initramfs-3.10.0-514.6.2.el7.s390x.img
++[linux]
++	image=/boot/vmlinuz-3.10.0-514.el7.s390x
++	ramdisk=/boot/initramfs-3.10.0-514.el7.s390x.img
++	parameters="root=/dev/mapper/rhel_ibm--z--68-root crashkernel=auto rd.dasd=0.0.0120 rd.dasd=0.0.0121 rd.dasd=0.0.0122 rd.dasd=0.0.0123 rd.lvm.lv=rhel_ibm-z-68/root rd.lvm.lv=rhel_ibm-z-68/swap rd.znet=qeth,0.0.8000,0.0.8001,0.0.8002,layer2=1,portname=z-68,portno=0 LANG=en_US.UTF-8"
++[linux-0-rescue-196fd0394b7442a6838686745f03fd04]
++	image=/boot/vmlinuz-0-rescue-196fd0394b7442a6838686745f03fd04
++	ramdisk=/boot/initramfs-0-rescue-196fd0394b7442a6838686745f03fd04.img
++	parameters="root=/dev/mapper/rhel_ibm--z--68-root crashkernel=auto rd.dasd=0.0.0120 rd.dasd=0.0.0121 rd.dasd=0.0.0122 rd.dasd=0.0.0123 rd.lvm.lv=rhel_ibm-z-68/root rd.lvm.lv=rhel_ibm-z-68/swap rd.znet=qeth,0.0.8000,0.0.8001,0.0.8002,layer2=1,portname=z-68,portno=0"
+-- 
+2.9.3
+
diff --git a/SOURCES/0073-Fix-info-for-s390x-s390-1285601.patch b/SOURCES/0073-Fix-info-for-s390x-s390-1285601.patch
new file mode 100644
index 0000000..aa14b71
--- /dev/null
+++ b/SOURCES/0073-Fix-info-for-s390x-s390-1285601.patch
@@ -0,0 +1,59 @@
+From dab391a5c52622b4c08f87dc394f133419da218a Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Tue, 14 Mar 2017 15:20:53 -0400
+Subject: [PATCH 73/75] Fix --info for s390x/s390 (#1285601)
+
+The --info flag for grubby on s390/s390x always returned (null). Fixed
+codepath to use extractTitle where necessary and get the actual title.
+
+Related: rhbz#1285601
+---
+ grubby.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/grubby.c b/grubby.c
+index 4d3834b..f960ebd 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -2782,7 +2782,7 @@ void setFallbackImage(struct grubConfig *config, int hasNew)
+ 	}
+ }
+ 
+-void displayEntry(struct singleEntry *entry, const char *prefix, int index)
++void displayEntry(struct grubConfig *config, struct singleEntry *entry, const char *prefix, int index)
+ {
+ 	struct singleLine *line;
+ 	char *root = NULL;
+@@ -2877,7 +2877,14 @@ void displayEntry(struct singleEntry *entry, const char *prefix, int index)
+ 
+ 	line = getLineByType(LT_TITLE, entry->lines);
+ 	if (line) {
+-		printf("title=%s\n", line->elements[1].item);
++                char *entryTitle;
++                /* if we can extractTitle, then it's a zipl config and
++                 * if not then we go ahead with what's existed prior */
++                entryTitle = extractTitle(config, line);
++                if (!entryTitle) {
++                    entryTitle=line->elements[1].item;
++                }
++		printf("title=%s\n", entryTitle);
+ 	} else {
+ 		char *title;
+ 		line = getLineByType(LT_MENUENTRY, entry->lines);
+@@ -3277,11 +3284,11 @@ int displayInfo(struct grubConfig *config, char *kernel, const char *prefix)
+ 			printf("lba\n");
+ 	}
+ 
+-	displayEntry(entry, prefix, i);
++	displayEntry(config, entry, prefix, i);
+ 
+ 	i++;
+ 	while ((entry = findEntryByPath(config, kernel, prefix, &i))) {
+-		displayEntry(entry, prefix, i);
++		displayEntry(config, entry, prefix, i);
+ 		i++;
+ 	}
+ 
+-- 
+2.9.3
+
diff --git a/SOURCES/0074-Add-s390-s390x-set-default-index-test-1285601.patch b/SOURCES/0074-Add-s390-s390x-set-default-index-test-1285601.patch
new file mode 100644
index 0000000..08022cf
--- /dev/null
+++ b/SOURCES/0074-Add-s390-s390x-set-default-index-test-1285601.patch
@@ -0,0 +1,59 @@
+From 34a70a8041862757b951fb25fa060386c9c7db0e Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Tue, 14 Mar 2017 22:39:20 -0400
+Subject: [PATCH 74/75] Add s390/s390x set-default-index test (#1285601)
+
+Adds a test to ensure set-default-index actually works for s390 and
+s390x platforms.
+
+Related: rhbz#1285601
+---
+ test.sh                   |  2 ++
+ test/results/default/z2.1 | 22 ++++++++++++++++++++++
+ 2 files changed, 24 insertions(+)
+ create mode 100644 test/results/default/z2.1
+
+diff --git a/test.sh b/test.sh
+index 34ba4d7..7225c9f 100755
+--- a/test.sh
++++ b/test.sh
+@@ -314,6 +314,8 @@ 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 default index directive"
++ziplTest zipl.2 default/z2.1 --set-default-index=0
+ testing="Z/IPL display default index"
+ ziplDisplayTest zipl.1 defaultindex/0 --default-index
+ testing="Z/IPL display default title"
+diff --git a/test/results/default/z2.1 b/test/results/default/z2.1
+new file mode 100644
+index 0000000..93e7491
+--- /dev/null
++++ b/test/results/default/z2.1
+@@ -0,0 +1,22 @@
++[defaultboot]
++defaultauto
++prompt=1
++timeout=5
++default=3.10.0-514.6.2.el7.s390x
++target=/boot
++[3.10.0-514.6.2.el7.s390x]
++	image=/boot/vmlinuz-3.10.0-514.6.2.el7.s390x
++	parameters="root=/dev/mapper/rhel_ibm--z--68-root crashkernel=auto rd.dasd=0.0.0120 rd.dasd=0.0.0121 rd.dasd=0.0.0122 rd.dasd=0.0.0123 rd.lvm.lv=rhel_ibm-z-68/root rd.lvm.lv=rhel_ibm-z-68/swap rd.znet=qeth,0.0.8000,0.0.8001,0.0.8002,layer2=1,portname=z-68,portno=0 LANG=en_US.UTF-8"
++	ramdisk=/boot/initramfs-3.10.0-514.6.2.el7.s390x.img
++[3.10.0-514.6.2.el7.s390x_with_debugging]
++	image=/boot/vmlinuz-3.10.0-514.6.2.el7.s390x
++	parameters="root=/dev/mapper/rhel_ibm--z--68-root crashkernel=auto rd.dasd=0.0.0120 rd.dasd=0.0.0121 rd.dasd=0.0.0122 rd.dasd=0.0.0123 rd.lvm.lv=rhel_ibm-z-68/root rd.lvm.lv=rhel_ibm-z-68/swap rd.znet=qeth,0.0.8000,0.0.8001,0.0.8002,layer2=1,portname=z-68,portno=0 LANG=en_US.UTF-8 systemd.log_level=debug systemd.log_target=kmsg"
++	ramdisk=/boot/initramfs-3.10.0-514.6.2.el7.s390x.img
++[linux]
++	image=/boot/vmlinuz-3.10.0-514.el7.s390x
++	ramdisk=/boot/initramfs-3.10.0-514.el7.s390x.img
++	parameters="root=/dev/mapper/rhel_ibm--z--68-root crashkernel=auto rd.dasd=0.0.0120 rd.dasd=0.0.0121 rd.dasd=0.0.0122 rd.dasd=0.0.0123 rd.lvm.lv=rhel_ibm-z-68/root rd.lvm.lv=rhel_ibm-z-68/swap rd.znet=qeth,0.0.8000,0.0.8001,0.0.8002,layer2=1,portname=z-68,portno=0 LANG=en_US.UTF-8"
++[linux-0-rescue-196fd0394b7442a6838686745f03fd04]
++	image=/boot/vmlinuz-0-rescue-196fd0394b7442a6838686745f03fd04
++	ramdisk=/boot/initramfs-0-rescue-196fd0394b7442a6838686745f03fd04.img
++	parameters="root=/dev/mapper/rhel_ibm--z--68-root crashkernel=auto rd.dasd=0.0.0120 rd.dasd=0.0.0121 rd.dasd=0.0.0122 rd.dasd=0.0.0123 rd.lvm.lv=rhel_ibm-z-68/root rd.lvm.lv=rhel_ibm-z-68/swap rd.znet=qeth,0.0.8000,0.0.8001,0.0.8002,layer2=1,portname=z-68,portno=0"
+-- 
+2.9.3
+
diff --git a/SOURCES/0075-Fix-setDefaultImage-for-s390-s390x-1285601.patch b/SOURCES/0075-Fix-setDefaultImage-for-s390-s390x-1285601.patch
new file mode 100644
index 0000000..fe8c8cf
--- /dev/null
+++ b/SOURCES/0075-Fix-setDefaultImage-for-s390-s390x-1285601.patch
@@ -0,0 +1,32 @@
+From 6a55388a609d0c9f237a651a356df77d165b3e83 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Tue, 14 Mar 2017 22:25:02 -0400
+Subject: [PATCH 75/75] Fix setDefaultImage for s390/s390x (#1285601)
+
+The setDefaultImage routine has never actually supported s390/s390x when
+picking an arbitrary index because a zipl config never has the property
+defaultIsIndex set to 1. Eliminating the extraneous check resolved the
+issue on s390/s390x and does not appear to break other platforms.
+
+Related: rhbz#1285601
+---
+ grubby.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/grubby.c b/grubby.c
+index f960ebd..7219d64 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -2633,8 +2633,7 @@ void setDefaultImage(struct grubConfig *config, int isAddingBootEntry,
+ 	}
+ 
+ 	/* Case 2: user picked an arbitrary index as the default boot entry */
+-	if (newDefaultBootEntryIndex >= FIRST_ENTRY_INDEX
+-	    && config->cfi->defaultIsIndex) {
++	if (newDefaultBootEntryIndex >= FIRST_ENTRY_INDEX) {
+ 		indexToVerify = newDefaultBootEntryIndex;
+ 
+ 		/* user chose to make latest boot entry the default */
+-- 
+2.9.3
+
diff --git a/SOURCES/0076-grubby-Make-sure-configure-BOOTLOADER-variables-are-.patch b/SOURCES/0076-grubby-Make-sure-configure-BOOTLOADER-variables-are-.patch
new file mode 100644
index 0000000..6bbd350
--- /dev/null
+++ b/SOURCES/0076-grubby-Make-sure-configure-BOOTLOADER-variables-are-.patch
@@ -0,0 +1,59 @@
+From 5a1f21830cb727b7b8d5b2428a0992bec726c330 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 31 Jan 2018 13:06:48 -0500
+Subject: [PATCH] grubby: Make sure configure$BOOTLOADER variables are set
+ correctly.
+
+When we've chosen a bootloader because it's default for a platform, and
+we've already determined it's not overridden by the command line, set
+the configure$BOOTLOADER variable to 1 so that our checks for which
+bootloader are selected work correctly.
+
+Resolves: rhbz#1340893
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grubby.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/grubby.c b/grubby.c
+index 9af04de..c1b4104 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -5151,22 +5151,27 @@ int main(int argc, const char **argv)
+ 	if (!cfi) {
+ 		if (grub2FindConfig(&grub2ConfigType)) {
+ 			cfi = &grub2ConfigType;
++			configureGrub2 = 1;
+ 			if (envPath)
+ 				cfi->envFile = envPath;
+-		} else
++		} else {
+ #ifdef __ia64__
+ 			cfi = &eliloConfigType;
+-#elif __powerpc__
++			configureLilo = 1;
++#elif defined(__powerpc__)
+ 			cfi = &yabootConfigType;
+-#elif __sparc__
++			configureYaboot = 1;
++#elif defined(__sparc__)
+ 			cfi = &siloConfigType;
+-#elif __s390__
++			configureSilo = 1;
++#elif defined(__s390__) || defined(__s390x__)
+ 			cfi = &ziplConfigType;
+-#elif __s390x__
+-			cfi = &ziplConfigtype;
++			configureZipl = 1;
+ #else
+ 			cfi = &grubConfigType;
++			configureGrub = 1;
+ #endif
++		}
+ 	}
+ 
+ 	if (!grubConfig) {
+-- 
+2.14.3
+
diff --git a/SOURCES/0077-Fix-incorrect-test-case-and-remove-args-with-a-value.patch b/SOURCES/0077-Fix-incorrect-test-case-and-remove-args-with-a-value.patch
new file mode 100644
index 0000000..2b55585
--- /dev/null
+++ b/SOURCES/0077-Fix-incorrect-test-case-and-remove-args-with-a-value.patch
@@ -0,0 +1,168 @@
+From 605367b51d425df0bbbcca830e6fe0c50895c83f Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 27 Sep 2017 11:28:00 -0400
+Subject: [PATCH] Fix incorrect test case and --remove-args with a value.
+
+Currently we have this test case:
+
+  grubTest grub.3 updargs/g3.4 --update-kernel=ALL --remove-args="hdd=foobar"
+
+This fails to notice that the actual argument in grub.3 is hdd=ide-scsi,
+and removes it anyway, and the data in g3.4 supports that behavior.
+This is clearly wrong, and so this patch introduces updargs/g3.5, which
+leaves hdd=ide-scsi intact, and fixes the code so that it won't modify
+the command line in that case.
+
+Resolves: rhbz#1476273
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grubby.c                  | 71 ++++++++++++++++++++++++++++++++-------
+ test.sh                   |  2 +-
+ test/results/updargs/g3.5 | 16 +++++++++
+ 3 files changed, 76 insertions(+), 13 deletions(-)
+ create mode 100644 test/results/updargs/g3.5
+
+diff --git a/grubby.c b/grubby.c
+index 5202485a5411..863ec4e7ef0b 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -3536,23 +3536,67 @@ static void removeElement(struct singleLine *line, int removeHere)
+ 	line->numElements--;
+ }
+ 
+-int argMatch(const char *one, const char *two)
++static int argNameMatch(const char *one, const char *two)
+ {
+ 	char *first, *second;
+-	char *chptr;
++	char *chptra, *chptrb;
++	int rc;
+ 
+ 	first = strcpy(alloca(strlen(one) + 1), one);
+ 	second = strcpy(alloca(strlen(two) + 1), two);
+ 
+-	chptr = strchr(first, '=');
+-	if (chptr)
+-		*chptr = '\0';
++	chptra = strchr(first, '=');
++	if (chptra)
++		*chptra = '\0';
+ 
+-	chptr = strchr(second, '=');
++	chptrb = strchr(second, '=');
++	if (chptrb)
++		*chptrb = '\0';
++
++	rc = strcmp(first, second);
++
++	if (chptra)
++		*chptra = '=';
++	if (chptrb)
++		*chptrb = '=';
++
++	return rc;
++}
++
++static int argHasValue(const char *arg)
++{
++	char *chptr;
++
++	chptr = strchr(arg, '=');
+ 	if (chptr)
+-		*chptr = '\0';
++		return 1;
++	return 0;
++}
++
++static int argValueMatch(const char *one, const char *two)
++{
++	char *first, *second;
++	char *chptra, *chptrb;
++
++	first = strcpy(alloca(strlen(one) + 1), one);
++	second = strcpy(alloca(strlen(two) + 1), two);
+ 
+-	return strcmp(first, second);
++	chptra = strchr(first, '=');
++	if (chptra)
++		chptra += 1;
++
++	chptrb = strchr(second, '=');
++	if (chptrb)
++		chptrb += 1;
++
++	if (!chptra && !chptrb)
++		return 0;
++	else if (!chptra)
++		return *chptrb - 0;
++	else if (!chptrb)
++		return 0 - *chptra;
++	else
++		return strcmp(chptra, chptrb);
+ }
+ 
+ int updateActualImage(struct grubConfig *cfg, const char *image,
+@@ -3696,7 +3740,7 @@ int updateActualImage(struct grubConfig *cfg, const char *image,
+ 				}
+ 				if (usedElements[i])
+ 					continue;
+-				if (!argMatch(line->elements[i].item, *arg)) {
++				if (!argNameMatch(line->elements[i].item, *arg)) {
+ 					usedElements[i] = 1;
+ 					break;
+ 				}
+@@ -3755,9 +3799,12 @@ int updateActualImage(struct grubConfig *cfg, const char *image,
+ 				    !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;
++				if (!argNameMatch(line->elements[i].item, *arg)) {
++					if (!argHasValue(*arg) ||
++					    !argValueMatch(line->elements[i].item, *arg)) {
++						removeElement(line, i);
++						break;
++					}
+ 				}
+ 			}
+ 			/* handle removing LT_ROOT line too */
+diff --git a/test.sh b/test.sh
+index 533bda0acbf5..b5fe21ca5850 100755
+--- a/test.sh
++++ b/test.sh
+@@ -386,7 +386,7 @@ grubTest grub.3 updargs/g3.2 --update-kernel=DEFAULT \
+     --args "root=/dev/hdd1 hdd=notide-scsi"
+ grubTest grub.3 updargs/g3.4 --update-kernel=ALL --remove-args="hdd"
+ grubTest grub.3 updargs/g3.4 --update-kernel=ALL --remove-args="hdd=ide-scsi"
+-grubTest grub.3 updargs/g3.4 --update-kernel=ALL --remove-args="hdd=foobar"
++grubTest grub.3 updargs/g3.5 --update-kernel=ALL --remove-args="hdd=foobar"
+ grubTest grub.3 updargs/g3.7 --update-kernel=ALL \
+     --remove-args="hdd root ro"
+ grubTest grub.7 updargs/g7.2 --boot-filesystem=/    \
+diff --git a/test/results/updargs/g3.5 b/test/results/updargs/g3.5
+new file mode 100644
+index 000000000000..7d50bb87d845
+--- /dev/null
++++ b/test/results/updargs/g3.5
+@@ -0,0 +1,16 @@
++#boot=/dev/hda
++timeout=10
++splashimage=(hd0,1)/grub/splash.xpm.gz
++title Red Hat Linux (2.4.7-2smp)
++	root (hd0,1)
++	kernel /vmlinuz-2.4.7-2smp ro root=/dev/hda5 hdd=ide-scsi
++	initrd /initrd-2.4.7-2smp.img
++title Red Hat Linux-up (2.4.7-2)
++	root (hd0,1)
++	kernel /vmlinuz-2.4.7-2 ro root=/dev/hda5 hdd=ide-scsi
++	initrd /initrd-2.4.7-2.img
++title DOS
++	rootnoverify (hd0,0)
++	chainloader +1
++
++
+-- 
+2.17.1
+
diff --git a/SOURCES/0078-Check-that-pointers-are-not-NULL-before-dereferencin.patch b/SOURCES/0078-Check-that-pointers-are-not-NULL-before-dereferencin.patch
new file mode 100644
index 0000000..ba3523d
--- /dev/null
+++ b/SOURCES/0078-Check-that-pointers-are-not-NULL-before-dereferencin.patch
@@ -0,0 +1,37 @@
+From c3d6d7dd1feb5a7f02778304a5233cf882c651c4 Mon Sep 17 00:00:00 2001
+From: Javier Martinez Canillas <javierm@redhat.com>
+Date: Fri, 15 Mar 2019 10:14:42 +0100
+Subject: [PATCH] Check that pointers are not NULL before dereferencing them
+
+The coverity scan complains that the argValueMatch() function derefences
+the chptra and chptrb pointers when these may be NULL. That's not really
+true since the function first checks if both aren't NULL and then only
+dereferences one when the other is NULL.
+
+But still this confuses coverity, so to make it happy let's just check
+if the pointer isn't NULL before derefencing them.
+
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+---
+ grubby.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/grubby.c b/grubby.c
+index 947b45895fc..9c506aeb438 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -3761,9 +3761,9 @@ static int argValueMatch(const char *one, const char *two)
+ 
+ 	if (!chptra && !chptrb)
+ 		return 0;
+-	else if (!chptra)
++	else if (!chptra && chptrb)
+ 		return *chptrb - 0;
+-	else if (!chptrb)
++	else if (!chptrb && chptra)
+ 		return 0 - *chptra;
+ 	else
+ 		return strcmp(chptra, chptrb);
+-- 
+2.20.1
+
diff --git a/SOURCES/0079-Improve-man-page-for-info-option.patch b/SOURCES/0079-Improve-man-page-for-info-option.patch
new file mode 100644
index 0000000..f8d0c72
--- /dev/null
+++ b/SOURCES/0079-Improve-man-page-for-info-option.patch
@@ -0,0 +1,30 @@
+From e15806969cbae83a94068d99e4f1d295dab95eac Mon Sep 17 00:00:00 2001
+From: Jan Stodola <jstodola@redhat.com>
+Date: Tue, 20 Nov 2018 15:02:19 +0100
+Subject: [PATCH] Improve man page for --info option
+
+1) commit 941d4a0b removed description of --info DEFAULT
+2) Add description of --info ALL
+---
+ grubby.8 | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/grubby.8 b/grubby.8
+index 1e8f140c4df..8b98433960c 100644
+--- a/grubby.8
++++ b/grubby.8
+@@ -185,7 +185,10 @@ Display the title of the current default boot entry and exit.
+ 
+ .TP
+ \fB-\-info\fR=\fIkernel-path\fR
+-Display information on all boot entries which match \fIkernel-path\fR. I
++Display information on all boot entries which match \fIkernel-path\fR. If
++\fIkernel-path\fR is \fBDEFAULT\fR, then information on the default kernel
++is displayed. If \fIkernel-path\fR is \fBALL\fR, then information on all boot
++entries are displayed.
+ 
+ .TP
+ \fB-\-bootloader-probe\fR
+-- 
+2.20.1
+
diff --git a/SOURCES/0080-Print-default-image-even-if-isn-t-a-suitable-one.patch b/SOURCES/0080-Print-default-image-even-if-isn-t-a-suitable-one.patch
new file mode 100644
index 0000000..a9e1db0
--- /dev/null
+++ b/SOURCES/0080-Print-default-image-even-if-isn-t-a-suitable-one.patch
@@ -0,0 +1,50 @@
+From ee49b7b71d017097be5b4a0f32bff83379b0a86e Mon Sep 17 00:00:00 2001
+From: Javier Martinez Canillas <javierm@redhat.com>
+Date: Mon, 18 Mar 2019 12:53:23 +0100
+Subject: [PATCH] Print default image even if isn't a suitable one
+
+The grubby --default-kernel option only prints the default kernel if this
+is a suitable one. That is if its associated kernel cmdline root param is
+the same than the partition currently mounted as the filesystem root.
+
+But the grubby --set-default option doesn't have that restriction, it is
+able to set a kernel as the default even if its root is for a different
+partition. So make the --default-kernel option to also print the kernel
+in this case. Still check if is a suitable image so --debug can tell it.
+
+Resolves: rhbz#1323842
+
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+---
+ grubby.c                | 5 +++--
+ test/results/debug/g2.1 | 1 +
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/grubby.c b/grubby.c
+index 9c506aeb438..a7f823cb58c 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -5531,8 +5531,9 @@ int main(int argc, const char **argv)
+ 		entry = findEntryByIndex(config, config->defaultImage);
+ 		if (!entry)
+ 			return 0;
+-		if (!suitableImage(entry, bootPrefix, 0, flags))
+-			return 0;
++
++		/* check if is a suitable image but still print it */
++		suitableImage(entry, bootPrefix, 0, flags);
+ 
+ 		line =
+ 		    getLineByType(LT_KERNEL | LT_HYPER | LT_KERNEL_EFI |
+diff --git a/test/results/debug/g2.1 b/test/results/debug/g2.1
+index f5187f5f4b5..d579b59e59f 100644
+--- a/test/results/debug/g2.1
++++ b/test/results/debug/g2.1
+@@ -12,3 +12,4 @@ DBG: 	linux	/vmlinuz-2.6.38.8-32.fc15.x86_64 root=/dev/mapper/vg_pjones5-lv_root
+ DBG: 	echo	'Loading initial ramdisk ...'
+ DBG: 	initrd	/initramfs-2.6.38.8-32.fc15.x86_64.img
+ DBG: }
++/boot/vmlinuz-2.6.38.8-32.fc15.x86_64
+-- 
+2.20.1
+
diff --git a/SOURCES/prune_debug b/SOURCES/prune_debug
new file mode 100755
index 0000000..7aa086b
--- /dev/null
+++ b/SOURCES/prune_debug
@@ -0,0 +1,173 @@
+#!/bin/sh
+
+######################################################################
+# Prune undesired systemd.debug entries in kernels that are not
+# marked for debugging. See Red Hat bugzilla 1285601.
+######################################################################
+
+PATH=/usr/bin:/usr/sbin
+EPOCH_DATE=$(date +"%s")
+LOG_DIR="/var/log"
+LOG_FILE="${LOG_DIR}/grubby_prune_debug"
+
+display_event()
+{
+    EVENT_LABEL="$1"
+    EVENT_DATA="$2"
+    JUSTIFIED_LABEL=$(printf "%-12s" "${EVENT_LABEL}")
+    LOG_TIMESTAMP=$(date +"%s")
+    echo "[${LOG_TIMESTAMP}] ${JUSTIFIED_LABEL}: ${EVENT_DATA}" >> "${LOG_FILE}"
+}
+
+exit_event()
+{
+    display_event "Exit" "Exiting script"
+    exit $1
+}
+
+find_entry_by_title()
+{
+    SEARCH_TITLE=$1
+
+    display_event "Examine" "Searching for entry title - ${SEARCH_TITLE}"
+
+    for current_index in $(grubby --info=ALL|grep "^index="| sed 's/^index=//') ; do
+        CURRENT_TITLE=$(grubby --info="${current_index}" 2> /dev/null |grep "^title=" | sed 's/^title=//')
+
+        # do not do anything if this was empty
+        [ -z "${CURRENT_TITLE}" ] && continue
+
+        if [ "${CURRENT_TITLE}" = "${SEARCH_TITLE}" ]; then
+            echo "${current_index}"
+            break;
+        fi
+    done
+}
+
+[ -d "${LOG_DIR}" ] || mkdir -p -m 0755 "${LOG_DIR}"
+
+display_event "Start" "Begin search for extraneous debug arguments"
+
+if [ "$(id -u)" -ne 0 ]; then
+    display_event "Error" "This script may only run as root."
+    exit_event 0
+fi
+
+######################################################################
+# Back up the grub.cfg for sanity
+######################################################################
+BOOTLOADER_CFG=
+BOOTLOADER_CFG_BK=
+
+if [ -f "/etc/grub2.cfg" ]; then
+    BOOTLOADER_CFG=$(realpath "/etc/grub2.cfg")
+    BOOTLOADER_CFG_BK="${BOOTLOADER_CFG}.${EPOCH_DATE}.rpmsave"
+elif [ -f "/etc/grub2-efi.cfg" ]; then
+    BOOTLOADER_CFG=$(realpath "/etc/grub2-efi.cfg")
+    BOOTLOADER_CFG_BK="${BOOTLOADER_CFG}.${EPOCH_DATE}.rpmsave"
+elif [ -f "/etc/zipl.conf" ]; then
+    BOOTLOADER_CFG=$(realpath "/etc/zipl.conf")
+    BOOTLOADER_CFG_BK="${BOOTLOADER_CFG}.${EPOCH_DATE}.rpmsave"
+elif [ -f "/etc/yaboot.conf" ]; then
+    BOOTLOADER_CFG=$(realpath "/etc/yaboot.conf")
+    BOOTLOADER_CFG_BK="${BOOTLOADER_CFG}.${EPOCH_DATE}.rpmsave"
+fi
+
+if [ -z "${BOOTLOADER_CFG}" ]; then
+    display_event "Error" "Could not find a bootloader configuration to back up"
+    exit_event 0
+fi
+
+if [ -f "${BOOTLOADER_CFG}" ]; then
+    if cp -a "${BOOTLOADER_CFG}" "${BOOTLOADER_CFG_BK}" 2> /dev/null; then
+        display_event "Copied" \
+            "Current configuration backed up to ${BOOTLOADER_CFG_BK}"
+    else
+        display_event "Error" "Could not write ${BOOTLOADER_CFG_BK}"
+        exit_event 0
+    fi
+fi
+
+######################################################################
+#  Figure out what the debugging tag will look like
+######################################################################
+ARCH=$(uname -m)
+if [ $ARCH = 's390' -o $ARCH = 's390x' ]; then
+    DEBUGGING_TAG="_with_debugging"
+else
+    DEBUGGING_TAG=" with debugging"
+fi
+
+######################################################################
+# Remove the systemd.debug kernel arguments from standard non-debug
+# kernel entries only
+######################################################################
+display_event "Examine" "Searching for distribution provided debugging entries"
+for entry_index in $(grubby --info=ALL|grep "^index="| sed 's/^index=//') ; do
+    INDEX_TITLE=$(grubby --info="${entry_index}" 2> /dev/null |grep "^title=" | sed 's/^title=//')
+
+    # do not do anything if this was empty
+    [ -z "${INDEX_TITLE}" ] && continue
+
+    if echo "${INDEX_TITLE}" | grep -q "${DEBUGGING_TAG}$"; then
+        display_event "Found" "Found distribution provided debugging entry - ${INDEX_TITLE}"
+        NON_DEBUG_TITLE=$(echo "${INDEX_TITLE}" | sed "s/${DEBUGGING_TAG}$//")
+        NON_DEBUG_INDEX=$(find_entry_by_title "${NON_DEBUG_TITLE}")
+
+        if [ -n "${NON_DEBUG_INDEX}" ]; then
+            display_event "Found" "Found matching non-debugging entry - ${NON_DEBUG_TITLE}"
+            KERNEL_ARGS=$(grubby --info="${NON_DEBUG_INDEX}" 2> /dev/null |grep "^args=")
+            if echo "${KERNEL_ARGS}" | grep -E -q 'systemd.debug|systemd.log_level=debug|systemd.log_target=kmsg'; then
+                if grubby --update-kernel="${NON_DEBUG_INDEX}" --remove-args="systemd.debug systemd.log_level=debug systemd.log_target=kmsg"; then
+                    display_event "Update" "Removed debugging arguments for ${NON_DEBUG_TITLE}"
+                else
+                    display_event "Error" "grubby failed to remove debug argument from ${NON_DEBUG_TITLE}"
+                fi
+            else
+                display_event "Skip" "No debugging arguments to remove for ${NON_DEBUG_TITLE}"
+            fi
+        else
+            display_event "Error" "Could not find the matching non-debugging entry - ${NON_DEBUG_TITLE}"
+        fi
+    fi
+done
+
+######################################################################
+# The default entry should not have debugging statements
+######################################################################
+
+# source of ALLOW_DEBUGGING_DEFAULT
+[ -f /etc/sysconfig/kernel ] && . /etc/sysconfig/kernel
+
+CURRENT_DEFAULT_INDEX=$(grubby --default-index)
+CURRENT_TITLE=$(grubby --info="${CURRENT_DEFAULT_INDEX}" 2> /dev/null |grep "^title=" | sed 's/^title=//')
+if echo "${CURRENT_TITLE}" | grep -q "${DEBUGGING_TAG}$"; then
+    case "${ALLOW_DEBUGGING_DEFAULT}" in
+        [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|1)
+            display_event "Examine" "Detected user preference to allow debugging default entries if present"
+            exit_event 0
+            ;;
+    esac
+
+    display_event "Examine" "Search for entry without debugging to replace default entry - ${CURRENT_TITLE}"
+
+    unset NON_DEBUG_INDEX
+    unset NON_DEBUG_TITLE
+
+    ARCH=$(uname -m)
+    NON_DEBUG_TITLE=$(echo "${CURRENT_TITLE}" | sed "s/${DEBUGGING_TAG}$//")
+
+    NON_DEBUG_INDEX=$(find_entry_by_title "${NON_DEBUG_TITLE}")
+
+    if [ -n "${NON_DEBUG_INDEX}" ]; then
+        if grubby --set-default-index="${NON_DEBUG_INDEX}"; then
+            display_event "Update" "Selected ${NON_DEBUG_TITLE} as the new default entry"
+        else
+            display_event "Error" "Could not set ${NON_DEBUG_TITLE} as default"
+        fi
+    else
+        display_event "Error" "Could not find the matching non-debugging entry"
+    fi
+fi
+
+exit_event 0
diff --git a/SPECS/grubby.spec b/SPECS/grubby.spec
new file mode 100644
index 0000000..edbe503
--- /dev/null
+++ b/SPECS/grubby.spec
@@ -0,0 +1,576 @@
+Name: grubby
+Version: 8.28
+Release: 26%{?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
+Source1: prune_debug
+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-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: 0042-ppc64le-sync-grub.cfg-changes-to-disk-1212114.patch
+Patch0043: 0043-Make-it-possible-to-run-test.sh-verbose-from-the-mak.patch
+Patch0044: 0044-Don-t-leak-from-one-extractTitle-call.patch
+Patch0045: 0045-Better-formatting.patch
+Patch0046: 0046-Make-SET_VARIABLE-get-handled-individually-in-GetNex.patch
+Patch0047: 0047-Specify-bootloader-directory-in-the-test-case-for-11.patch
+Patch0048: 0048-Fix-some-coverity-concerns.patch
+Patch0049: 0049-Always-do-the-rungrubby-debug-after-the-normal-kerne.patch
+Patch0050: 0050-grubby-add-set-index-to-specify-which-position-to-ad.patch
+Patch0051: 0051-Fix-thinko-on-set-index-naming.patch
+Patch0052: 0052-Fix-a-typo-on-the-rhel-7.3-branch.patch
+Patch0053: 0053-Add-a-test-case-for-a-failure-rmarshall-saw-in-set-i.patch
+Patch0054: 0054-Ensure-command-line-updates-also-honor-set-index.patch
+Patch0055: 0055-Change-debug-entry-insertion-order-rhbz-1285601.patch
+Patch0056: 0056-Reorganize-grubby-man-page-1232168.patch
+Patch0057: 0057-Update-grubby-man-page-contents-bz1232168.patch
+Patch0058: 0058-Fix-inline-help-typo-1232168.patch
+Patch0059: 0059-More-edits-for-grubby.8-1232168.patch
+Patch0060: 0060-Minor-man-page-changes-1232168.patch
+Patch0061: 0061-Rename-setDefaultImage-variables.patch
+Patch0062: 0062-Add-index-constant-definitions-instead-of-open-coded.patch
+Patch0063: 0063-Track-configuration-modifications.patch
+Patch0064: 0064-Fix-some-test-cases-where-the-resulting-default-inde.patch
+Patch0065: 0065-Don-t-assume-make-default-just-because-set-index-was.patch
+Patch0066: 0066-Clarify-set-default-index-in-the-man-page.patch
+Patch0067: 0067-Add-multi-entry-removal-test-1285601.patch
+Patch0068: 0068-Fix-findTemplate-index-logic-1285601.patch
+Patch0069: 0069-Write-correct-default-to-environment-1285601.patch
+Patch0070: 0070-Initialize-variable-for-ppc-environment-1285601.patch
+Patch0071: 0071-Fix-initial-saved_entry-read-issue-1285601.patch
+Patch0072: 0072-Add-s390-s390x-info-test-1285601.patch
+Patch0073: 0073-Fix-info-for-s390x-s390-1285601.patch
+Patch0074: 0074-Add-s390-s390x-set-default-index-test-1285601.patch
+Patch0075: 0075-Fix-setDefaultImage-for-s390-s390x-1285601.patch
+Patch0076: 0076-grubby-Make-sure-configure-BOOTLOADER-variables-are-.patch
+Patch0077: 0077-Fix-incorrect-test-case-and-remove-args-with-a-value.patch
+Patch0078: 0078-Check-that-pointers-are-not-NULL-before-dereferencin.patch
+Patch0079: 0079-Improve-man-page-for-info-option.patch
+Patch0080: 0080-Print-default-image-even-if-isn-t-a-suitable-one.patch
+
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+BuildRequires: pkgconfig glib2-devel popt-devel 
+BuildRequires: libblkid-devel git
+# for make test / getopt:
+BuildRequires: util-linux-ng
+%ifarch aarch64 x86_64 ppc ppc64
+BuildRequires: grub2-tools-minimal
+%endif
+%ifarch s390 s390x
+Requires: s390utils-base
+%endif
+%ifarch %{arm}
+Requires: uboot-tools
+%endif
+Requires: system-release
+
+ExcludeArch: %{?ix86}
+
+%description
+grubby  is  a command line tool for updating and displaying information about 
+the configuration files for the grub, lilo, elilo (ia64),  yaboot (powerpc)  
+and zipl (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.
+
+%prep
+%setup -q -n %{name}-%{version}-1
+
+git init
+git config user.email "noone@example.com"
+git config user.name "no one"
+git add .
+git commit -a -q -m "%{version} baseline"
+git am %{patches} </dev/null
+git config --unset user.email
+git config --unset user.name
+
+%build
+make %{?_smp_mflags}
+
+%check
+make test
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make install DESTDIR=$RPM_BUILD_ROOT PREFIX=%{_prefix} mandir=%{_mandir}
+install -d -m 0755 $RPM_BUILD_ROOT/usr/libexec/grubby/
+install -m 0755 %{SOURCE1} $RPM_BUILD_ROOT/usr/libexec/grubby/
+%ifarch %{arm}
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/
+install -p uboot $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/uboot
+touch $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/kernel
+chmod 0644 $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/kernel
+mkdir -p $RPM_BUILD_ROOT/boot
+echo " " >> $RPM_BUILD_ROOT/boot/boot.scr
+%endif
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+/usr/libexec/grubby/prune_debug
+
+%files
+%defattr(-,root,root,-)
+%doc COPYING
+%{_prefix}/sbin/installkernel
+%{_prefix}/sbin/new-kernel-pkg
+%{_prefix}/sbin/grubby
+%{_mandir}/man8/*.8*
+/usr/libexec/grubby/prune_debug
+%ghost %attr(0644,-,-) %config(noreplace) %{_sysconfdir}/sysconfig/kernel
+%ifarch %{arm}
+%config(noreplace) %{_sysconfdir}/sysconfig/uboot
+%config(noreplace) /boot/boot.scr
+%endif
+
+%changelog
+* Mon Mar 18 2019 Javier Martinez Canillas <javierm@redhat.com> - 8.28-26
+- Exclude building on i686
+  Related: rhbz#1476273
+- Fix grubby removing wrong kernel command line parameter
+  Resolves: rhbz#1476273
+- Improve man page for --info option (jstodola)
+  Resolves: rhbz#1651673
+- Print default image even if isn't a suitable one
+  Resolves: rhbz#1323842
+
+* Tue Aug 14 2018 Peter Jones <pjones@redhat.com> - 8.28-25
+- Ensure /etc/sysconfig/kernel has a stable mode, now that rpm handles ghost
+  files differently.
+  Resolves: rhbz#1584313
+
+* Fri Jun 22 2018 Peter Jones <pjones@redhat.com> - 8.28-24
+- Ensure "grubby --default-title" takes the bootloader selection into
+  account
+  Resolves: rhbz#1340893
+
+* Tue Mar 21 2017 rmarshall@redhat.com - 8.28-23
+- Fixes --info flag on s390/s390x.
+  Related: rhbz#1285601
+- Fixes --set-default-index on s390/s390x.
+  Related: rhbz#1285601
+- Allows prune_debug to run on s390/s390x.
+  Resolves: rhbz#1285601
+
+* Mon Mar 06 2017 rmarshall@redhat.com - 8.28-22
+- Resolve issues found by coverity scan.
+  Resolves: rhbz#1285601
+
+* Mon Mar 06 2017 rmarshall@redhat.com - 8.28-21
+- Resolve issues with the recent grubby logic patches that
+  appeared on the ppc platform. Fix a problem that occurred
+  on systems where no kernel update had ever been installed.
+  Resolves: rhbz#1285601
+- Specify the actual prune_debug file in sources.
+  Resolves: rhbz#1285601
+
+* Thu Feb 09 2017 rmarshall@redhat.com - 8.28-20
+- Added invocations for prune_debug to spec file
+  Resolves: #1285601
+
+* Thu Feb 09 2017 rmarshall@redhat.com - 8.28-19
+- Fixed an issue where grubby's logic set the wrong default
+  boot entry.
+  Resolves: #1285601
+
+* Fri Jul 01 2016 rmarshall@redhat.com - 8.28-18
+- Patched new-kernel-pkg so that kernel installations when MAKEDEBUG is
+  set would put the debugging entries after the non-debugging entries.
+  Resolves: #1285601
+- Re-numbered the last set of patches to go with the flow. No actual
+  changes to the patches; just a git mv to rename.
+- Re-organized and updated the grubby man page contents to include some
+  features that were not documented as well as correct typos and
+  re-write some entries for better clarity.
+  Resolves: #1232168
+
+* Mon Oct 26 2015 Peter Jones <pjones@redhat.com> - 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 <pjones@redhat.com> - 8.28-16
+- Fix some coverity concerns and other issues with 8.28-15...
+  Resolves: rhbz#1152550
+
+* Thu Sep 10 2015 Peter Jones <pjones@redhat.com> - 8.28-15
+- Fix some coverity concerns and other issues with 8.28-14 (sigh)
+  Resolves: rhbz#1152550
+
+* Tue Sep 01 2015 Peter Jones <pjones@redhat.com> - 8.28-14
+- Handle "set variable" commands separately from other parsing in grubby's
+  GetNextLine()
+  Resolves: rhbz#1152550
+
+* Wed Aug 05 2015 Robert Marshall <rmarshall@redhat.com> - 8.28-13
+- Ensure file changes sync to disk on ppc64le platform.
+  Related: rhbz#1212114
+
+* Thu Jul 02 2015 Peter Jones <pjones@redhat.com> - 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 <pjones@redhat.com> - 8.28-11
+- Fix a memory corruption issue we're hitting on s390/s390x
+  Resolves: rhbz#1152152
+- Don't use spaces on zipl platforms to describe debugging entries
+  Related: rhbz#1152152
+
+* Thu Sep 25 2014 Peter Jones <pjones@redhat.com> - 8.28-10
+- Use the correct load commands for aarch64 efi.
+  Resolves: rhbz#1081269
+- Support "devicetree" directive in grub2.
+  Resolves: rhbz#1063534
+- Explain the default bootloaders and configuration paths slightly better
+  in the manual.
+  Resolves: rhbz#1001664
+- Conditionally create debug entries when installing kernels.
+  Resolves: rhbz#957681
+- Make sure --banner from the command line is used correctly.
+  Resolves: rhbz#1032048
+
+* Thu Mar 06 2014 Peter Jones <pjones@redhat.com> - 8.28-8
+- Fix crash when config file doesn't match command line.
+  Related: rhbz#1070646
+- Make crashes work with abrt better.
+  Resolves: rhbz#1070646
+
+* Wed Jan 29 2014 Peter Jones <pjones@redhat.com> - 8.28-7
+- Update to make sure the source url is correct.
+  Related: rhbz#1034743
+
+* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 8.28-6
+- Mass rebuild 2014-01-24
+
+* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 8.28-5
+- Mass rebuild 2013-12-27
+
+* Fri Dec 06 2013 Peter Jones <pjones@redhat.com> - 8.28-4
+- Make patch from -3 only do that on x86.
+  Resolves: rhbz#1034743
+
+* Wed Nov 27 2013 d.marlin <dmarlin@redhat.com>
+- Only set RPM_OPT_FLAGS if undefined to avoid overwriting 
+  the platform defaults.
+  Resolves: rhbz#1023793
+
+* Mon Nov 18 2013 Peter Jones <pjones@redhat.com> - 8.28-3
+- Honor linux16 and initrd16 in grub.cfg
+  Resolves: rhbz#1031192
+
+* Fri Sep 13 2013 Peter Jones <pjones@redhat.com> - 8.28-2
+- Use %%{_prefix} during "make install" (rpmdiff)
+
+* Fri Aug 02 2013 Peter Jones <pjones@redhat.com> - 8.28-1
+- More work on grub's "saved_entry" system.
+  Resolves: rhbz#808021
+
+* Tue Jul 30 2013 Peter Jones <pjones@redhat.com> - 8.27-1
+- Make grubby understand grub's "saved_entry" system
+  Resolves: rhbz#808021
+- BuildRequire grub2 on appropriate platforms, for the test suite.
+  Related: rhbz#808021
+
+* Fri Jun 07 2013 Dennis Gilmore <dennis@ausil.us> - 8.26-2
+- add patch to update extlinux.conf file on arm if it exists
+
+* Fri May 10 2013 Peter Jones <pjones@redhat.com> - 8.26-1
+- Conditionally call arm-boot-config's boot.scr generator if available
+  Resolves: rhbz#952428
+
+* Tue Apr 09 2013 Peter Jones <pjones@redhat.com> - 8.25-1
+- Error instead of segfaulting if we can't find any working config
+  Resolves: rhbz#912873
+  Resolves: rhbz#751608
+
+* Tue Mar 19 2013 Peter Jones <pjones@redhat.com> - 8.24-1
+- Fix module remove code from Harald (#923441)
+
+* Mon Mar 11 2013 Peter Jones <pjones@redhat.com> - 8.23-1
+- Update to 8.23
+- Fix empty root device in case of an empty /etc/fstab (lemenkov)
+- General refactoring and cleanup (harald)
+- Don't clean up modules.* so aggressively (harald)
+
+* Wed Feb 20 2013 Peter Jones <pjones@redhat.com> - 8.22-3
+- Add --debug style logging (for both success and failures) to /var/log/grubby
+
+* Thu Feb 14 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 8.22-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
+
+* Fri Jan 04 2013 Peter Jones <pjones@redhat.com> - 8.22-1
+- Revert test case for rhbz#742885 - it's a work in progress that isn't
+  ready yet.
+
+* Fri Jan 04 2013 Peter Jones <pjones@redhat.com> - 8.21-1
+- Use systemd vconsole.conf and locale.conf if present
+  Resolves rhbz#881908
+- Avoid unnecessary stat calls (from Ville Skyttä)
+  Resolves rhbz#741135
+- Spelling fixes (Ville Skyttä)
+- Add a test case for rhbz#742885
+- Handle case-insensitive extlinux config files properly (from Johannes Weiner)
+
+* Tue Oct 02 2012 Peter Jones <pjones@redhat.com> - 8.20-1
+- Handle linuxefi initrd and removal correctly.
+  Resolves: rhbz#859285
+
+* Wed Sep 26 2012 Peter Jones <pjones@redhat.com> - 8.19-1
+- Don't accidentally migrate from linuxefi back to linux
+  Related: rhbz#859285
+
+* Fri Sep 21 2012 Peter Jones <pjones@redhat.com> - 8.18-1
+- Change the way the kernel load address is determined for ARM U-Boot.
+
+* Wed Aug 08 2012 Peter Jones <pjones@redhat.com> - 8.17-1
+- Update to 8.17
+- Fixes a "make test" failure.
+
+* Wed Aug 08 2012 Peter Jones <pjones@redhat.com> - 8.16-1
+- Update to 8.16
+- Handle "linuxefi" directive on grub2/uefi machines.
+
+* Thu Jul 19 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 8.15-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Mon Jun 25 2012 Peter Jones <pjones@redhat.com> - 8.15-1
+- Update to 8.15
+- Revert dirname change from 8.13; it was wrong.
+
+* Thu Jun 14 2012 Peter Jones <pjones@redhat.com> - 8.14-1
+- Update to 8.14 to fix a build problem.
+
+* Thu Jun 14 2012 Peter Jones <pjones@redhat.com> - 8.13-1
+- Update to 8.13
+- Add some more ARM tweaks (dmartin)
+- Better support for other distros (crosa)
+
+* Tue Jun 12 2012 Peter Jones <pjones@redhat.com> - 8.12-2
+- Support UBOOT_IMGADDR override on ARM (blc)
+
+* Thu May 31 2012 Peter Jones <pjones@redhat.com> - 8.12-1
+- Update to 8.12
+- Preserve trailing indentation when splitting line elements (mads)
+  Resolves: rhbz#742720
+- Pick last device mounted on / (pjones,bcl)
+  Related: rhbz#820340
+  Related: rhbz#820351
+
+* Wed Mar 21 2012 Peter Jones <pjones@redhat.com> - 8.11-1
+- Update to 8.11
+  Resolves: rhbz#805310
+
+* Thu Mar 15 2012 Peter Jones <pjones@redhat.com> - 8.10-1
+- Update to 8.10
+- Use "isquote" where appropriate
+- Make --remove-kenrel support titles in grub2 (jianzhong.huang)
+- Use grub2 if it's there on ppc.
+
+* Fri Mar 02 2012 Peter Jones <pjones@redhat.com> - 8.9-1
+- Refactor grub2 title extraction, making it a function (Cleber Rosa)
+- Include prefix when printing kernel information (Cleber Rosa)
+- Implement support for "default saved" for grub2 (Cleber Rosa)
+- Try to display title when printing information with '--info' (Cleber Rosa)
+- new-kernel-pkg fails to find U-Boot. (D. Marlin)
+- Add support to new-kernel-pkg to recognize ARCH == armv5tel needed for Kir
+  (D.Marlin)
+- Include a / when one is missing in paths (#769641)
+- Fix hard coded paths so kernel's "make install" will DTRT.
+- Fix endswith() to correctly test its input for validity.
+
+* Tue Feb 07 2012 Dennis Gilmore <dennis@ausil.us> - 8.8-3
+- add uboot-tools requires on arm arches
+- add uboot config file on arm arches
+
+* Fri Jan 13 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 8.8-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
+
+* Tue Dec 20 2011 Peter Jones <pjones@redhat.com> - 8.8-1
+- Fix test cases from 8.7 to work on a system without /boot mounted.
+
+* Tue Dec 20 2011 Peter Jones <pjones@redhat.com> - 8.7-1
+- Add a --debug to try to help diagnose "No suitable template". (sandeen,pjones)
+
+* Mon Dec 19 2011 Peter Jones <pjones@redhat.com> - 8.6-1
+- Fix a "make test" errors introduced in 8.4-1
+
+* Sat Dec 17 2011 Peter Jones <pjones@redhat.com> - 8.5-1
+- Don't hardcode dracut path
+  Resolves: #768645
+
+* Thu Dec 08 2011 Adam Williamson <awilliam@redhat.com> - 8.4-1
+- Update to 8.4:
+  - fix Loading... line for updated kernels
+  - Add new '--default-title' feature
+  - Add new '--default-index' feature
+  - add feature for testing the output of a grubby command
+  - Fix detection when comparing stage1 to MBR
+  - do not link against glib-2.0
+  - Don't crash if grubConfig not found
+  - Adding extlinux support for new-kernel-pkg
+  - Look for Debian / Ubuntu grub config files (#703260)
+  - Make grubby recognize Ubuntu's spin of Grub2 (#703260)
+
+* Thu Sep 29 2011 Peter Jones <pjones@redhat.com> - 8.3-1
+- Fix new-kernel-pkg invocation of grubby for grub (patch from Mads Kiilerich)
+  Resolves: rhbz#725185
+
+* Wed Sep 14 2011 Peter Jones <pjones@redhat.com> - 8.2-1
+- Fixes for xen (from Michael Petullo)
+  Resolves: rhbz#658387
+
+* Fri Jul 22 2011 Peter Jones <pjones@redhat.com> - 8.1-1
+- Update to 8.1
+- Fix miss-spelled variable name in new-kernel-pkg
+
+* Thu Jul 21 2011 Peter Jones <pjones@redhat.com> - 8.0-1
+- Add support for grub2.
+
+* Tue Jun 07 2011 Brian C. Lane <bcl@redhat.com> - 7.0.18-1
+- Bump version to 7.0.18 (bcl)
+- Fixup new-kernel-pkg errors (#711493) (bcl)
+
+* Mon Jun 06 2011 Peter Jones <pjones@redhat.com> - 7.0.17-1
+- Fix references to wrong program name in new-kernel-pkg.8
+  Resolves: rhbz#663981
+
+* Wed Feb 09 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 7.0.16-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Mon Jan 24 2011 Karsten Hopp <karsten@redhat.com> 7.0.16-2
+- add BR utils-linux-ng for getopt
+
+* Tue Jul 13 2010 Brian C. Lane <bcl@redhat.com> - 7.0.16-1
+- Update to 7.0.16
+- Add patch to check the return value of getuuidbydev
+- Resolves: rhbz#592294
+
+* Wed Apr 14 2010 Peter Jones <pjones@redhat.com> - 7.0.15-1
+- Update to 7.0.15
+- Add man pages for installkernel and new-kernel-pkg
+  Resolves: rhbz#529333
+
+* Wed Apr 14 2010 Peter Jones <pjones@redhat.com> - 7.0.14-1
+- Update to 7.0.14
+
+* Thu Feb 11 2010 Peter Jones <pjones@redhat.com> - 7.0.13-1
+- Strip boot partition prefix from initrd path if present during --update.
+  Related: rhbz#557922
+- add host only support for local kernel compiles (airlied)
+
+* Mon Feb 08 2010 Peter Jones <pjones@redhat.com> - 7.0.12-1
+- compare rootdev using uuid instead of stat, for better btrfs support (josef)
+  Resolves: rhbz#530108
+
+* Mon Feb 08 2010 Peter Jones <pjones@redhat.com> - 7.0.11-1
+- Make it possible to update the initrd without any other change.
+  Related: rhbz#557922
+
+* Fri Feb 05 2010 Peter Jones <pjones@redhat.com> - 7.0.10-1
+- Make --update able to add an initramfs.
+  Related: rhbz#557922
+
+* Mon Nov 30 2009 Peter Jones <pjones@redhat.com> - 7.0.9-3
+- Use s390utils-base as the s390 dep, not s390utils
+  Related: rhbz#540565
+
+* Tue Nov 24 2009 Peter Jones <pjones@redhat.com> - 7.0.9-2
+- Add s390utils dep when on s390, since new-kernel-package needs it.
+  Resolves: rhbz#540565
+
+* Fri Oct 30 2009 Peter Jones <pjones@redhat.com> - 7.0.9-1
+- Add support for dracut to installkernel (notting)
+
+* Thu Oct  1 2009 Hans de Goede <hdegoede@redhat.com> - 7.0.8-1
+- Stop using nash
+
+* Fri Sep 11 2009 Hans de Goede <hdegoede@redhat.com> - 7.0.7-1
+- Remove writing rd_plytheme=$theme to kernel args in dracut mode (hansg)
+- Add a couple of test cases for extra initrds (rstrode)
+- Allow tmplLine to be NULL in getInitrdVal (rstrode)
+
+* Fri Sep 11 2009 Peter Jones <pjones@redhat.com> - 7.0.6-1
+- Fix test case breakage from 7.0.5 (rstrode)
+
+* Fri Sep 11 2009 Peter Jones <pjones@redhat.com> - 7.0.5-1
+- Add support for plymouth as a second initrd. (rstrode)
+  Resolves: rhbz#520515
+
+* Wed Sep 09 2009 Hans de Goede <hdegoede@redhat.com> - 7.0.4-1
+- Add --dracut cmdline argument for %%post generation of dracut initrd
+
+* Wed Aug 26 2009 Hans de Goede <hdegoede@redhat.com> - 7.0.3-1
+- Silence error when no /etc/sysconfig/keyboard (#517187)
+
+* Fri Aug  7 2009 Hans de Goede <hdegoede@redhat.com> - 7.0.2-1
+- Add --add-dracut-args new-kernel-pkg cmdline option
+
+* Fri Jul 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 7.0.1-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Fri Jul 17 2009 Jeremy Katz <katzj@redhat.com> - 7.0.1-1
+- Fix blkid usage (#124246)
+
+* Wed Jun 24 2009 Jeremy Katz <katzj@redhat.com> - 7.0-1
+- BR libblkid-devel now instead of e2fsprogs-devel
+- Add bits to switch to using dracut for new-kernel-pkg
+
+* Wed Jun  3 2009 Jeremy Katz <katzj@redhat.com> - 6.0.86-2
+- add instructions for checking out from git
+
+* Tue Jun  2 2009 Jeremy Katz <katzj@redhat.com> - 6.0.86-1
+- initial build after splitting out from mkinitrd
+