diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..20be72c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/8.40-1.tar.gz
diff --git a/.grubby.metadata b/.grubby.metadata
new file mode 100644
index 0000000..6085fc6
--- /dev/null
+++ b/.grubby.metadata
@@ -0,0 +1 @@
+97ae8d113b74538c05f05083dcff4f44012fd0cd SOURCES/8.40-1.tar.gz
diff --git a/SOURCES/0001-remove-the-old-crufty-u-boot-support.patch b/SOURCES/0001-remove-the-old-crufty-u-boot-support.patch
new file mode 100644
index 0000000..f6f5e97
--- /dev/null
+++ b/SOURCES/0001-remove-the-old-crufty-u-boot-support.patch
@@ -0,0 +1,235 @@
+From aa4472dbc10f3d669e24ac07293d7ac19e606866 Mon Sep 17 00:00:00 2001
+From: Dennis Gilmore <dennis@ausil.us>
+Date: Wed, 30 Aug 2017 14:03:45 -0500
+Subject: [PATCH 1/8] remove the old crufty u-boot support
+
+Fedora has only supported extlinux.conf for a few releases now
+as a result it should be the only way we boot systems. Remove
+the no longer needed uboot file
+
+Signed-off-by: Dennis Gilmore <dennis@ausil.us>
+---
+ new-kernel-pkg | 116 -------------------------------------------------
+ uboot          |  43 ------------------
+ 2 files changed, 159 deletions(-)
+ delete mode 100644 uboot
+
+diff --git a/new-kernel-pkg b/new-kernel-pkg
+index b634388a83f..962008e3c9d 100755
+--- a/new-kernel-pkg
++++ b/new-kernel-pkg
+@@ -37,7 +37,6 @@ else
+ fi
+ 
+ [ -f /etc/sysconfig/kernel ] && . /etc/sysconfig/kernel
+-[ -f /etc/sysconfig/uboot ] && . /etc/sysconfig/uboot
+ 
+ cfgGrub2=""
+ cfgGrub2Efi=""
+@@ -50,7 +49,6 @@ grubConfig=""
+ grub2Config=""
+ grub2EfiConfig=""
+ extlinuxConfig=""
+-ubootScript="/boot/boot.scr"
+ 
+ ARCH=$(uname -m)
+ 
+@@ -84,13 +82,6 @@ elif [[ ${ARCH} =~ armv[5|7].*l ]] ; then
+     liloConfig=""
+     bootPrefix=/boot
+     extlinuxConfig=$(readlink -f /etc/extlinux.conf 2>/dev/null)
+-    ubootDir=${UBOOT_DIR:-"/boot"}
+-    ubootScript=$ubootDir/${UBOOT_SCR:-"boot.scr"}
+-    ubootKList=${UBOOT_KLIST:-"klist.txt"}
+-    ubootDevice=/dev/${UBOOT_DEVICE:-"mmcblk0p1"}
+-    ubootDefaultImage=${UBOOT_UIMAGE:-"uImage"}
+-    ubootDefaultInitrd=${UBOOT_UINITRD:-"uInitrd"}
+-    ubootAddress=${UBOOT_IMGADDR:-"0x00008000"}
+     mounted=""
+     liloFlag=""
+     isx86=""
+@@ -382,53 +373,6 @@ remove() {
+ 	[ -n "$verbose" ] && echo "$liloConfig does not exist, not running grubby"
+     fi
+ 
+-    if [ -n "$cfguBoot" ]; then
+-	[ -n "$verbose" ] && echo "removing $version from $ubootDir..."
+-
+-	if [ -f $ubootDir/$ubootKList ]; then
+-	    tmpKList=`mktemp $ubootDir/$ubootKList.XXXX`
+-	    curversion=`tail -n1 $ubootDir/$ubootKList`
+-	    sed "/$version$/d" $ubootDir/$ubootKList > $tmpKList
+-	    newversion=`tail -n1 $tmpKList`
+-	    if [ -f $ubootDir/uImage-$newversion ] && [ -f $ubootDir/uInitrd-$newversion ]; then
+-		if [ "$curversion" != "$newversion" ]; then
+-		    cp -fp $ubootDir/uImage-$newversion $ubootDir/${ubootDefaultImage}
+-		    if [ $? -ne 0 ]; then
+-			[ -n "$verbose" ] && echo "copy uImage-$newversion error, default kernel not replaced!" && exit
+-		    fi
+-		    cp -fp $ubootDir/uInitrd-$newversion $ubootDir/${ubootDefaultInitrd}
+-		    if [ $? -ne 0 ]; then
+-			[ -n "$verbose" ] && echo "copy uInitrd-$newversion error, default Initrd not replaced!" && exit
+-		    fi
+-		fi
+-
+-		[ -n "$verbose" ] && echo "removing uImage-$version"
+-		if [ -f $ubootDir/uImage-$version ]; then
+-		    rm -f $ubootDir/uImage-$version
+-		else
+-		    [ -n "$verbose" ] && echo "uImage-$version did not exist!"
+-		fi
+-
+-		[ -n "$verbose" ] && echo "removing uInitrd-$version"
+-		if [ -f $ubootDir/uInitrd-$version ]; then
+-		    rm -f $ubootDir/uInitrd-$version
+-		else
+-		    [ -n "$verbose" ] && echo "uInitrd-$version did not exist!"
+-		fi
+-
+-		mv $tmpKList $ubootDir/$ubootKList
+-		[ -x /sbin/a-b-c ] && /sbin/a-b-c
+-	    else
+-		[ -n "$verbose" ] && echo "uImage $newversion does not exist!"
+-		[ -f $tmpKList ] && rm -f $tmpKList
+-	    fi
+-        else
+-            [ -n "$verbose" ] && echo "No previous kernel version.  U-Boot images not removed!"
+-        fi
+-    else
+-	[ -n "$verbose" ] && echo "$ubootScript does not exist, not modifying $ubootDir"
+-    fi
+-
+     if [ -n "$cfgExtlinux" ]; then
+ 	[ -n "$verbose" ] && echo "removing $version from $extlinuxConfig"
+ 	$grubby --extlinux -c $extlinuxConfig \
+@@ -530,36 +474,6 @@ update() {
+ 	[ -n "$verbose" ] && echo "$liloConfig does not exist, not running grubby"
+     fi
+ 
+-    if [ -n "$cfguBoot" ]; then
+-	[ -n "$verbose" ] && echo "adding $version to $ubootDir..."
+-
+-	[ -n "$verbose" ] && echo "creating uImage-$version"
+-	mkimage -A arm -O linux -T kernel -C none -a $ubootAddress \
+-		-e $ubootAddress -n $version \
+-		-d $kernelImage $ubootDir/uImage-$version
+-
+-	[ -n "$verbose" ] && echo "creating uInitrd-$version"
+-	mkimage -A arm -O linux -T ramdisk -C none -a 0 -e 0 \
+-		-n initramfs -d $initrdfile $ubootDir/uInitrd-$version
+-
+-	if [ -f $ubootDir/uImage-$version ] && [ -f $ubootDir/uInitrd-$version ]; then
+-	    cp -fp $ubootDir/uImage-$version $ubootDir/${ubootDefaultImage}
+-	    if [ $? -ne 0 ]; then
+-		[ -n "$verbose" ] && echo "copy uImage-$version error, kernel not installed!" && exit
+-	    fi
+-	    cp -fp $ubootDir/uInitrd-$version $ubootDir/${ubootDefaultInitrd}
+-	    if [ $? -ne 0 ]; then
+-		[ -n "$verbose" ] && echo "copy uInitrd-$version error, kernel not installed!" && exit
+-	    fi
+-	    echo $version >> $ubootDir/$ubootKList
+-	    [ -x /sbin/a-b-c ] && /sbin/a-b-c
+-	else
+-	    [ -n "$verbose" ] && echo "cannot make $version the default"
+-	fi
+-    else
+-	[ -n "$verbose" ] && echo "$ubootScript does not exist, not setting up $ubootDir"
+-    fi
+-
+     if [ -n "$cfgExtlinux" ]; then
+ 	[ -n "$verbose" ] && echo "updating $version from $extlinuxConfig"
+ 	ARGS="--extlinux -c $extlinuxConfig --update-kernel=$kernelImage \
+@@ -877,33 +791,6 @@ fi
+ [ -n "$liloConfig" ] && [ -f "$liloConfig" ] && cfgLilo=1;
+ [ -n "$extlinuxConfig" ] && [ -f "$extlinuxConfig" ] && cfgExtlinux=1;
+ 
+-# if we have a U-Boot directory, but no boot script, check if the directory
+-# is mounted.  If not, mount it, and then check if a boot script exists.
+-if [ -n "$ubootDir" ]; then
+-    if [ -f "$ubootScript" ]; then
+-        cfguBoot=1
+-    else
+-	mountEntry=`mount | grep $ubootDir`
+-	if [ -z "$mountEntry" ]; then
+-	    mount $ubootDevice $ubootDir
+-	    mounted=1
+-	fi
+-	[ -f "$ubootScript" ] && cfguBoot=1;
+-    fi
+-fi
+-
+-# if we're using U-Boot, check if the default load address should change
+-if [ -n "$cfguBoot" -a -z "$UBOOT_IMGADDR" ]; then
+-    [[ $version  =~ .([^.]*)$ ]]
+-    platform=${BASH_REMATCH[1]}
+-    # A few platforms use an alternate kernel load address
+-    if [ "$platform" = "omap" ]; then
+-        ubootAddress=0x80008000
+-    elif [ "$platform" = "imx" ]; then
+-        ubootAddress=0x90008000
+-    fi
+-fi
+-
+ # if we have a lilo config on an x86 box, see if the default boot loader
+ # is lilo to determine if it should be run
+ if [ -n "$cfgLilo" -a -n "$isx86" ]; then
+@@ -920,7 +807,4 @@ elif [ "$mode" == "--rpmposttrans" ]; then
+     rpmposttrans
+ fi
+ 
+-# if we mounted the U-Boot directory, unmount it.
+-[ -n "$mounted" ] && umount $ubootDir
+-
+ exit 0
+diff --git a/uboot b/uboot
+deleted file mode 100644
+index 07d8671822f..00000000000
+--- a/uboot
++++ /dev/null
+@@ -1,43 +0,0 @@
+-# Settings for uBoot setup in /sbin/new-kernel-pkg
+-#
+-# Default values are provided below (as comments)
+-#
+-# WARNING: These values affect where grubby installs and removes
+-#          uBoot kernel images.  Changing these _after_ kernels have
+-#          been installed may cause removing a kernel image to fail.
+-
+-# directory where uBoot images and scripts are found
+-#UBOOT_DIR=/boot
+-
+-# Override the load address when running mkimage on the kernel.
+-# OMAP such as Beagleboard and Pandaboard: Use 0x80008000
+-# Tegra such as Trimslice: Use 0x00008000
+-# IMX such as Efika mx51 smarttop: Use 0x90008000
+-# Kirkwood such as Dreamplug, Guruplug, Sheevaplug: Use 0x00008000
+-# If left undefined grubby will use defults for Tegra or OMAP depending
+-# upon the contents of /proc/cpuinfo.
+-#UBOOT_IMGADDR=0x0x00008000
+-
+-# name of the text file containing the list of installed kernel versions
+-# NOTE: The versions are in order of installation.  The last entry should
+-#       always be the default boot kernel version.
+-#UBOOT_KLIST=klist.txt
+-
+-# device partition where uBoot images reside; mounted on $UBOOT_DIR
+-#UBOOT_DEVICE=mmcblk0p1
+-
+-
+-# NOTE: Both of the following files are automatically overwritte
+-#       when a kernel package is installed or removed.
+-
+-# default kernel uImage file name
+-#UBOOT_UIMAGE=uImage
+-
+-# default initrd uInitrd file name
+-#UBOOT_UINITRD=uInitrd
+-
+-# defualt for platform shipping an onboard dtb.
+-#SHIPSDTB=no
+-
+-# option to tell new-kernel-pkg a specific dtb file to load in extlinux.conf
+-#dtbfile=foo.dtb
+-- 
+2.17.1
+
diff --git a/SOURCES/0002-Change-return-type-in-getRootSpecifier.patch b/SOURCES/0002-Change-return-type-in-getRootSpecifier.patch
new file mode 100644
index 0000000..f2a1978
--- /dev/null
+++ b/SOURCES/0002-Change-return-type-in-getRootSpecifier.patch
@@ -0,0 +1,143 @@
+From 3afc4c0ed28d443bb71956b07fd45c8cfb07566f Mon Sep 17 00:00:00 2001
+From: Nathaniel McCallum <npmccallum@redhat.com>
+Date: Fri, 2 Mar 2018 14:59:32 -0500
+Subject: [PATCH 2/8] Change return type in getRootSpecifier()
+
+Rather than returning a new allocation of the prefix, just return the
+length of the prefix. This change accomplishes a couple things. First,
+it reduces some memory leaks since the return value was often never
+freed.  Second, it simplifies the caller who is usually only interested
+in the length of the prefix.
+---
+ grubby.c | 54 +++++++++++++++++++++++++++---------------------------
+ 1 file changed, 27 insertions(+), 27 deletions(-)
+
+diff --git a/grubby.c b/grubby.c
+index d4ebb86168d..a062ef8e567 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -675,7 +675,7 @@ 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 size_t getRootSpecifier(const char *str);
+ static void requote(struct singleLine *line, struct configFileInfo * cfi);
+ static void insertElement(struct singleLine * line,
+ 			  const char * item, int insertHere,
+@@ -1840,7 +1840,7 @@ int suitableImage(struct singleEntry * entry, const char * bootPrefix,
+     char * fullName;
+     int i;
+     char * dev;
+-    char * rootspec;
++    size_t rs;
+     char * rootdev;
+ 
+     if (skipRemoved && entry->skip) {
+@@ -1866,12 +1866,11 @@ int suitableImage(struct singleEntry * entry, const char * bootPrefix,
+ 
+     fullName = alloca(strlen(bootPrefix) + 
+ 		      strlen(line->elements[1].item) + 1);
+-    rootspec = getRootSpecifier(line->elements[1].item);
+-    int rootspec_offset = rootspec ? strlen(rootspec) : 0;
++    rs = getRootSpecifier(line->elements[1].item);
+     int hasslash = endswith(bootPrefix, '/') ||
+-    	beginswith(line->elements[1].item + rootspec_offset, '/');
++	    beginswith(line->elements[1].item + rs, '/');
+     sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/",
+-            line->elements[1].item + rootspec_offset);
++		line->elements[1].item + rs);
+     if (access(fullName, R_OK)) {
+ 	notSuitablePrintf(entry, 0, "access to %s failed\n", fullName);
+ 	return 0;
+@@ -1952,7 +1951,6 @@ struct singleEntry * findEntryByPath(struct grubConfig * config,
+     struct singleLine * line;
+     int i;
+     char * chptr;
+-    char * rootspec = NULL;
+     enum lineType_e checkType = LT_KERNEL;
+ 
+     if (isdigit(*kernel)) {
+@@ -2044,11 +2042,10 @@ struct singleEntry * findEntryByPath(struct grubConfig * config,
+ 
+ 		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 (!strcmp(line->elements[1].item +
++                               getRootSpecifier(line->elements[1].item),
++                               kernel + strlen(prefix)))
++                           break;
+ 		}
+ 		if(line->type == LT_MENUENTRY &&
+ 			!strcmp(line->elements[1].item, kernel))
+@@ -2797,11 +2794,11 @@ struct singleLine * addLineTmpl(struct singleEntry * entry,
+ 
+ 	/* 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);
++            size_t rs = getRootSpecifier(tmplLine->elements[1].item);
++            if (rs > 0) {
++                free(newLine->elements[1].item);
++                newLine->elements[1].item = sdupprintf("%.*s%s", (int) rs,
++                    tmplLine->elements[1].item, val);
+ 	    }
+ 	}
+     }
+@@ -3729,15 +3726,19 @@ int checkForElilo(struct grubConfig * config) {
+     return 1;
+ }
+ 
+-static char * getRootSpecifier(char * str) {
+-    char * idx, * rootspec = NULL;
++static size_t getRootSpecifier(const char *str)
++{
++    size_t rs = 0;
+ 
+     if (*str == '(') {
+-        idx = rootspec = strdup(str);
+-        while(*idx && (*idx != ')') && (!isspace(*idx))) idx++;
+-        *(++idx) = '\0';
++        for (; str[rs] != ')' && !isspace(str[rs]); rs++) {
++	    if (!str[rs])
++                return rs;
++        }
++        rs++;
+     }
+-    return rootspec;
++
++    return rs;
+ }
+ 
+ static char * getInitrdVal(struct grubConfig * config,
+@@ -4616,7 +4617,7 @@ int main(int argc, const char ** argv) {
+     if (displayDefault) {
+ 	struct singleLine * line;
+ 	struct singleEntry * entry;
+-        char * rootspec;
++        size_t rs;
+ 
+ 	if (config->defaultImage == -1) return 0;
+ 	if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
+@@ -4629,9 +4630,8 @@ int main(int argc, const char ** argv) {
+ 	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));
++        rs = getRootSpecifier(line->elements[1].item);
++        printf("%s%s\n", bootPrefix, line->elements[1].item + rs);
+ 
+ 	return 0;
+ 
+-- 
+2.17.1
+
diff --git a/SOURCES/0003-Add-btrfs-subvolume-support-for-grub2.patch b/SOURCES/0003-Add-btrfs-subvolume-support-for-grub2.patch
new file mode 100644
index 0000000..583c5de
--- /dev/null
+++ b/SOURCES/0003-Add-btrfs-subvolume-support-for-grub2.patch
@@ -0,0 +1,209 @@
+From 112b6e5fc690b2a73b6ad8c92dc4645db08503b6 Mon Sep 17 00:00:00 2001
+From: Nathaniel McCallum <npmccallum@redhat.com>
+Date: Fri, 2 Mar 2018 08:40:18 -0500
+Subject: [PATCH 3/8] Add btrfs subvolume support for grub2
+
+In order to find the subvolume prefix from a given path, we parse
+/proc/mounts. In cases where /proc/mounts doesn't contain the
+filesystem, the caller can use the --mounts option to specify his own
+mounts file.
+
+Btrfs subvolumes are already supported by grub2 and by grub2-mkconfig.
+
+Fixes #22
+---
+ grubby.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 143 insertions(+), 5 deletions(-)
+
+diff --git a/grubby.c b/grubby.c
+index a062ef8e567..96d252a0a83 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -68,6 +68,8 @@ int isEfi = 0;
+ 
+ char *saved_command_line = NULL;
+ 
++const char *mounts = "/proc/mounts";
++
+ /* comments get lumped in with indention */
+ struct lineElement {
+     char * item;
+@@ -1834,6 +1836,129 @@ static int endswith(const char *s, char c)
+ 	return s[slen] == c;
+ }
+ 
++typedef struct {
++	const char *start;
++	size_t      chars;
++} field;
++
++static int iscomma(int c)
++{
++	return c == ',';
++}
++
++static int isequal(int c)
++{
++	return c == '=';
++}
++
++static field findField(const field *in, typeof(isspace) *isdelim, field *out)
++{
++	field nxt = {};
++	size_t off = 0;
++
++	while (off < in->chars && isdelim(in->start[off]))
++		off++;
++
++	if (off == in->chars)
++		return nxt;
++
++	out->start = &in->start[off];
++	out->chars = 0;
++
++	while (off + out->chars < in->chars && !isdelim(out->start[out->chars]))
++		out->chars++;
++
++	nxt.start = out->start + out->chars;
++	nxt.chars = in->chars - off - out->chars;
++	return nxt;
++}
++
++static int fieldEquals(const field *in, const char *str)
++{
++	return in->chars == strlen(str) &&
++		strncmp(in->start, str, in->chars) == 0;
++}
++
++/* Parse /proc/mounts to determine the subvolume prefix. */
++static size_t subvolPrefix(const char *str)
++{
++	FILE *file = NULL;
++	char *line = NULL;
++	size_t prfx = 0;
++	size_t size = 0;
++
++	file = fopen(mounts, "r");
++	if (!file)
++		return 0;
++
++	for (ssize_t s; (s = getline(&line, &size, file)) >= 0; ) {
++		field nxt = { line, s };
++		field dev = {};
++		field path = {};
++		field type = {};
++		field opts = {};
++		field opt = {};
++
++		nxt = findField(&nxt, isspace, &dev);
++		if (!nxt.start)
++			continue;
++
++		nxt = findField(&nxt, isspace, &path);
++		if (!nxt.start)
++			continue;
++
++		nxt = findField(&nxt, isspace, &type);
++		if (!nxt.start)
++			continue;
++
++		nxt = findField(&nxt, isspace, &opts);
++		if (!nxt.start)
++			continue;
++
++		if (!fieldEquals(&type, "btrfs"))
++			continue;
++
++		/* We have found a btrfs mount point. */
++
++		nxt = opts;
++		while ((nxt = findField(&nxt, iscomma, &opt)).start) {
++			field key = {};
++			field val = {};
++
++			opt = findField(&opt, isequal, &key);
++			if (!opt.start)
++				continue;
++
++			opt = findField(&opt, isequal, &val);
++			if (!opt.start)
++				continue;
++
++			if (!fieldEquals(&key, "subvol"))
++				continue;
++
++			/* We have found a btrfs subvolume mount point. */
++
++			if (strncmp(val.start, str, val.chars))
++				continue;
++
++			if (val.start[val.chars - 1] != '/' &&
++				str[val.chars] != '/')
++				continue;
++
++			/* The subvolume mount point matches our input. */
++
++			if (prfx < val.chars)
++				prfx = val.chars;
++		}
++	}
++
++	dbgPrintf("%s(): str: '%s', prfx: '%s'\n", __FUNCTION__, str, prfx);
++
++	fclose(file);
++	free(line);
++	return prfx;
++}
++
+ int suitableImage(struct singleEntry * entry, const char * bootPrefix,
+ 		  int skipRemoved, int flags) {
+     struct singleLine * line;
+@@ -2794,12 +2919,22 @@ struct singleLine * addLineTmpl(struct singleEntry * entry,
+ 
+ 	/* 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)) {
+-            size_t rs = getRootSpecifier(tmplLine->elements[1].item);
++            const char *prfx = tmplLine->elements[1].item;
++            size_t rs = getRootSpecifier(prfx);
++            if (isinitrd(tmplLine->type)) {
++                for (struct singleLine *l = entry->lines;
++                     rs == 0 && l; l = l->next) {
++                    if (iskernel(l->type)) {
++                        prfx = l->elements[1].item;
++                        rs = getRootSpecifier(prfx);
++                    }
++                }
++            }
+             if (rs > 0) {
+                 free(newLine->elements[1].item);
+-                newLine->elements[1].item = sdupprintf("%.*s%s", (int) rs,
+-                    tmplLine->elements[1].item, val);
+-	    }
++                newLine->elements[1].item = sdupprintf("%.*s%s",
++						       (int) rs, prfx, val);
++            }
+ 	}
+     }
+ 
+@@ -3738,7 +3873,7 @@ static size_t getRootSpecifier(const char *str)
+         rs++;
+     }
+ 
+-    return rs;
++	return rs + subvolPrefix(str + rs);
+ }
+ 
+ static char * getInitrdVal(struct grubConfig * config,
+@@ -4253,6 +4388,9 @@ int main(int argc, const char ** argv) {
+ 	{ "mbargs", 0, POPT_ARG_STRING, &newMBKernelArgs, 0, 
+ 	    _("default arguments for the new multiboot kernel or "
+               "new arguments for multiboot kernel being updated"), NULL },
++	{ "mounts", 0, POPT_ARG_STRING, &mounts, 0,
++            _("path to fake /proc/mounts file (for testing only)"),
++            _("mounts") },
+ 	{ "bad-image-okay", 0, 0, &badImageOkay, 0,
+ 	    _("don't sanity check images in boot entries (for testing only)"), 
+ 	    NULL },
+-- 
+2.17.1
+
diff --git a/SOURCES/0004-Add-tests-for-btrfs-support.patch b/SOURCES/0004-Add-tests-for-btrfs-support.patch
new file mode 100644
index 0000000..f4b8ec8
--- /dev/null
+++ b/SOURCES/0004-Add-tests-for-btrfs-support.patch
@@ -0,0 +1,1871 @@
+From e319f73ca691b9cc138def3a9c19f1cb6e581475 Mon Sep 17 00:00:00 2001
+From: Gene Czarcinski <gczarcinski@gmail.com>
+Date: Mon, 9 Jun 2014 21:11:37 -0400
+Subject: [PATCH 4/8] Add tests for btrfs support
+
+The tests performed are:
+- add kernel with /boot on btrfs subvol (20)
+- update kernel/add initrd with /boot on btrfs subvol (21)
+- add kernel with rootfs on btrfs subvol and /boot a directory (22)
+- update kernel/add initrd with rootfs on btrfs subvol and
+  /boot a directory (23)
+- add kernel and initrd with /boot on btrfs subvol (24)
+- add kernel and initrd with rootfs on btrfs subvol and /boot
+  a directory (25)
+---
+ test.sh                               |  40 +++++++
+ test/grub2-support_files/g2.20-mounts |   2 +
+ test/grub2-support_files/g2.21-mounts |   1 +
+ test/grub2-support_files/g2.22-mounts |   1 +
+ test/grub2-support_files/g2.23-mounts |   1 +
+ test/grub2-support_files/g2.24-mounts |   1 +
+ test/grub2-support_files/g2.25-mounts |   1 +
+ test/grub2.20                         | 126 ++++++++++++++++++++++
+ test/grub2.21                         | 140 +++++++++++++++++++++++++
+ test/grub2.22                         | 128 +++++++++++++++++++++++
+ test/grub2.23                         | 143 +++++++++++++++++++++++++
+ test/grub2.24                         | 126 ++++++++++++++++++++++
+ test/grub2.25                         | 128 +++++++++++++++++++++++
+ test/results/add/g2-1.20              | 140 +++++++++++++++++++++++++
+ test/results/add/g2-1.21              | 141 +++++++++++++++++++++++++
+ test/results/add/g2-1.22              | 143 +++++++++++++++++++++++++
+ test/results/add/g2-1.23              | 144 ++++++++++++++++++++++++++
+ test/results/add/g2-1.24              | 141 +++++++++++++++++++++++++
+ test/results/add/g2-1.25              | 144 ++++++++++++++++++++++++++
+ 19 files changed, 1691 insertions(+)
+ create mode 100644 test/grub2-support_files/g2.20-mounts
+ create mode 120000 test/grub2-support_files/g2.21-mounts
+ create mode 100644 test/grub2-support_files/g2.22-mounts
+ create mode 120000 test/grub2-support_files/g2.23-mounts
+ create mode 120000 test/grub2-support_files/g2.24-mounts
+ create mode 120000 test/grub2-support_files/g2.25-mounts
+ create mode 100644 test/grub2.20
+ create mode 100644 test/grub2.21
+ create mode 100644 test/grub2.22
+ create mode 100644 test/grub2.23
+ create mode 100644 test/grub2.24
+ create mode 100644 test/grub2.25
+ create mode 100644 test/results/add/g2-1.20
+ create mode 100644 test/results/add/g2-1.21
+ create mode 100644 test/results/add/g2-1.22
+ create mode 100644 test/results/add/g2-1.23
+ create mode 100644 test/results/add/g2-1.24
+ create mode 100644 test/results/add/g2-1.25
+
+diff --git a/test.sh b/test.sh
+index 6379698c6de..c35bfca1c89 100755
+--- a/test.sh
++++ b/test.sh
+@@ -629,6 +629,46 @@ if [ "$testgrub2" == "y" ]; then
+             --initrd /boot/initramfs-0-rescue-5a94251776a14678911d4ae0949500f5.img \
+             --copy-default --title "Fedora 21 Rescue" --args=root=/fooooo \
+             --remove-kernel=wtf --boot-filesystem=/boot/
++
++        testing="GRUB2 add kernel with boot on btrfs subvol"
++        grub2Test grub2.20 add/g2-1.20 --add-kernel=/boot/new-kernel.img \
++            --title='title' \
++            --boot-filesystem=/boot/ \
++            --copy-default \
++            --mounts='test/grub2-support_files/g2.20-mounts'
++
++        testing="GRUB2 add initrd with boot on btrfs subvol"
++        grub2Test grub2.21 add/g2-1.21 --update-kernel=/boot/new-kernel.img \
++            --initrd=/boot/new-initrd --boot-filesystem=/boot/ \
++            --mounts='test/grub2-support_files/g2.21-mounts'
++
++        testing="GRUB2 add kernel with rootfs on btrfs subvol and boot directory"
++        grub2Test grub2.22 add/g2-1.22 --add-kernel=/boot/new-kernel.img \
++            --title='title' \
++            --boot-filesystem= \
++            --copy-default \
++            --mounts='test/grub2-support_files/g2.22-mounts'
++
++        testing="GRUB2 add initrd with rootfs on btrfs subvol and boot directory"
++        grub2Test grub2.23 add/g2-1.23 --update-kernel=/boot/new-kernel.img \
++            --initrd=/boot/new-initrd --boot-filesystem= \
++            --mounts='test/grub2-support_files/g2.23-mounts'
++
++        testing="GRUB2 add kernel and initrd with boot on btrfs subvol"
++        grub2Test grub2.24 add/g2-1.24 --add-kernel=/boot/new-kernel.img \
++            --title='title' \
++            --initrd=/boot/new-initrd \
++            --boot-filesystem=/boot/ \
++            --copy-default \
++            --mounts='test/grub2-support_files/g2.24-mounts'
++
++        testing="GRUB2 add kernel and initrd with rootfs on btrfs subvol and boot directory"
++        grub2Test grub2.25 add/g2-1.25 --add-kernel=/boot/new-kernel.img \
++            --title='title' \
++            --initrd=/boot/new-initrd \
++            --boot-filesystem= \
++            --copy-default \
++            --mounts='test/grub2-support_files/g2.25-mounts'
+     fi
+ fi
+ 
+diff --git a/test/grub2-support_files/g2.20-mounts b/test/grub2-support_files/g2.20-mounts
+new file mode 100644
+index 00000000000..00bdb48e4ab
+--- /dev/null
++++ b/test/grub2-support_files/g2.20-mounts
+@@ -0,0 +1,2 @@
++/dev/sda	/	btrfs	subvol=/root6,defaults	0 0
++/dev/sda	/boot	btrfs	subvol=/boot6,defaults	0 0
+diff --git a/test/grub2-support_files/g2.21-mounts b/test/grub2-support_files/g2.21-mounts
+new file mode 120000
+index 00000000000..42ef3fd4272
+--- /dev/null
++++ b/test/grub2-support_files/g2.21-mounts
+@@ -0,0 +1 @@
++g2.20-mounts
+\ No newline at end of file
+diff --git a/test/grub2-support_files/g2.22-mounts b/test/grub2-support_files/g2.22-mounts
+new file mode 100644
+index 00000000000..5b664e72519
+--- /dev/null
++++ b/test/grub2-support_files/g2.22-mounts
+@@ -0,0 +1 @@
++/dev/sda	/	btrfs	defaults,subvol=/root4,ro	0 0
+diff --git a/test/grub2-support_files/g2.23-mounts b/test/grub2-support_files/g2.23-mounts
+new file mode 120000
+index 00000000000..74f036fc4a3
+--- /dev/null
++++ b/test/grub2-support_files/g2.23-mounts
+@@ -0,0 +1 @@
++g2.22-mounts
+\ No newline at end of file
+diff --git a/test/grub2-support_files/g2.24-mounts b/test/grub2-support_files/g2.24-mounts
+new file mode 120000
+index 00000000000..42ef3fd4272
+--- /dev/null
++++ b/test/grub2-support_files/g2.24-mounts
+@@ -0,0 +1 @@
++g2.20-mounts
+\ No newline at end of file
+diff --git a/test/grub2-support_files/g2.25-mounts b/test/grub2-support_files/g2.25-mounts
+new file mode 120000
+index 00000000000..74f036fc4a3
+--- /dev/null
++++ b/test/grub2-support_files/g2.25-mounts
+@@ -0,0 +1 @@
++g2.22-mounts
+\ No newline at end of file
+diff --git a/test/grub2.20 b/test/grub2.20
+new file mode 100644
+index 00000000000..23b75fa8d3c
+--- /dev/null
++++ b/test/grub2.20
+@@ -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=15
++# Fallback normal timeout code in case the timeout_style feature is
++# unavailable.
++else
++  set timeout=15
++fi
++### END /etc/grub.d/00_header ###
++
++### BEGIN /etc/grub.d/10_linux ###
++menuentry 'Fedora, with Linux 3.15.0-0.rc7.git2.1.fc21.x86_64' --class gnu-linux --class gnu --class os {
++	load_video
++	set gfxpayload=keep
++	insmod gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/vmlinuz-3.15.0-0.rc7.git2.1.fc21.x86_64 root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++	initrd16 /boot6/initramfs-3.15.0-0.rc7.git2.1.fc21.x86_64.img
++}
++menuentry 'Fedora, with Linux 0-rescue-81378818f7a24478b496ebef90e1dd69' --class gnu-linux --class gnu --class os {
++	load_video
++	insmod gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/vmlinuz-0-rescue-81378818f7a24478b496ebef90e1dd69 root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++	initrd16 /boot6/initramfs-0-rescue-81378818f7a24478b496ebef90e1dd69.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/grub2.21 b/test/grub2.21
+new file mode 100644
+index 00000000000..579c2f6744a
+--- /dev/null
++++ b/test/grub2.21
+@@ -0,0 +1,140 @@
++#
++# 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=15
++# Fallback normal timeout code in case the timeout_style feature is
++# unavailable.
++else
++  set timeout=15
++fi
++### 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 gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/new-kernel.img root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++}
++menuentry 'Fedora, with Linux 3.15.0-0.rc7.git2.1.fc21.x86_64' --class gnu-linux --class gnu --class os {
++	load_video
++	set gfxpayload=keep
++	insmod gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/vmlinuz-3.15.0-0.rc7.git2.1.fc21.x86_64 root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++	initrd16 /boot6/initramfs-3.15.0-0.rc7.git2.1.fc21.x86_64.img
++}
++menuentry 'Fedora, with Linux 0-rescue-81378818f7a24478b496ebef90e1dd69' --class gnu-linux --class gnu --class os {
++	load_video
++	insmod gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/vmlinuz-0-rescue-81378818f7a24478b496ebef90e1dd69 root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++	initrd16 /boot6/initramfs-0-rescue-81378818f7a24478b496ebef90e1dd69.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/grub2.22 b/test/grub2.22
+new file mode 100644
+index 00000000000..9466bc35153
+--- /dev/null
++++ b/test/grub2.22
+@@ -0,0 +1,128 @@
++#
++# 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=15
++# Fallback normal timeout code in case the timeout_style feature is
++# unavailable.
++else
++  set timeout=15
++fi
++### END /etc/grub.d/00_header ###
++
++### BEGIN /etc/grub.d/10_linux ###
++menuentry 'Fedora, with Linux 3.15.0-0.rc7.git2.1.fc21.x86_64' --class gnu-linux --class gnu --class os {
++	load_video
++	set gfxpayload=keep
++	insmod gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/vmlinuz-3.15.0-0.rc7.git2.1.fc21.x86_64 root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++	initrd16 /root4/boot/initramfs-3.15.0-0.rc7.git2.1.fc21.x86_64.img
++}
++menuentry 'Fedora, with Linux 0-rescue-20e7024f4e9c4b70b1042b91acd434c6' --class gnu-linux --class gnu --class os {
++	load_video
++	insmod gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/vmlinuz-0-rescue-20e7024f4e9c4b70b1042b91acd434c6 root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++	initrd16 /root4/boot/initramfs-0-rescue-20e7024f4e9c4b70b1042b91acd434c6.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 ###
++###
++
++### 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/grub2.23 b/test/grub2.23
+new file mode 100644
+index 00000000000..5cb240fc1de
+--- /dev/null
++++ b/test/grub2.23
+@@ -0,0 +1,143 @@
++#
++# 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=15
++# Fallback normal timeout code in case the timeout_style feature is
++# unavailable.
++else
++  set timeout=15
++fi
++### 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 gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/new-kernel.img root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++}
++menuentry 'Fedora, with Linux 3.15.0-0.rc7.git2.1.fc21.x86_64' --class gnu-linux --class gnu --class os {
++	load_video
++	set gfxpayload=keep
++	insmod gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/vmlinuz-3.15.0-0.rc7.git2.1.fc21.x86_64 root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++	initrd16 /root4/boot/initramfs-3.15.0-0.rc7.git2.1.fc21.x86_64.img
++}
++menuentry 'Fedora, with Linux 0-rescue-20e7024f4e9c4b70b1042b91acd434c6' --class gnu-linux --class gnu --class os {
++	load_video
++	insmod gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/vmlinuz-0-rescue-20e7024f4e9c4b70b1042b91acd434c6 root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++	initrd16 /root4/boot/initramfs-0-rescue-20e7024f4e9c4b70b1042b91acd434c6.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 ###
++###
++
++### 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/grub2.24 b/test/grub2.24
+new file mode 100644
+index 00000000000..23b75fa8d3c
+--- /dev/null
++++ b/test/grub2.24
+@@ -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=15
++# Fallback normal timeout code in case the timeout_style feature is
++# unavailable.
++else
++  set timeout=15
++fi
++### END /etc/grub.d/00_header ###
++
++### BEGIN /etc/grub.d/10_linux ###
++menuentry 'Fedora, with Linux 3.15.0-0.rc7.git2.1.fc21.x86_64' --class gnu-linux --class gnu --class os {
++	load_video
++	set gfxpayload=keep
++	insmod gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/vmlinuz-3.15.0-0.rc7.git2.1.fc21.x86_64 root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++	initrd16 /boot6/initramfs-3.15.0-0.rc7.git2.1.fc21.x86_64.img
++}
++menuentry 'Fedora, with Linux 0-rescue-81378818f7a24478b496ebef90e1dd69' --class gnu-linux --class gnu --class os {
++	load_video
++	insmod gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/vmlinuz-0-rescue-81378818f7a24478b496ebef90e1dd69 root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++	initrd16 /boot6/initramfs-0-rescue-81378818f7a24478b496ebef90e1dd69.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/grub2.25 b/test/grub2.25
+new file mode 100644
+index 00000000000..9466bc35153
+--- /dev/null
++++ b/test/grub2.25
+@@ -0,0 +1,128 @@
++#
++# 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=15
++# Fallback normal timeout code in case the timeout_style feature is
++# unavailable.
++else
++  set timeout=15
++fi
++### END /etc/grub.d/00_header ###
++
++### BEGIN /etc/grub.d/10_linux ###
++menuentry 'Fedora, with Linux 3.15.0-0.rc7.git2.1.fc21.x86_64' --class gnu-linux --class gnu --class os {
++	load_video
++	set gfxpayload=keep
++	insmod gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/vmlinuz-3.15.0-0.rc7.git2.1.fc21.x86_64 root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++	initrd16 /root4/boot/initramfs-3.15.0-0.rc7.git2.1.fc21.x86_64.img
++}
++menuentry 'Fedora, with Linux 0-rescue-20e7024f4e9c4b70b1042b91acd434c6' --class gnu-linux --class gnu --class os {
++	load_video
++	insmod gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/vmlinuz-0-rescue-20e7024f4e9c4b70b1042b91acd434c6 root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++	initrd16 /root4/boot/initramfs-0-rescue-20e7024f4e9c4b70b1042b91acd434c6.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 ###
++###
++
++### 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.20 b/test/results/add/g2-1.20
+new file mode 100644
+index 00000000000..579c2f6744a
+--- /dev/null
++++ b/test/results/add/g2-1.20
+@@ -0,0 +1,140 @@
++#
++# 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=15
++# Fallback normal timeout code in case the timeout_style feature is
++# unavailable.
++else
++  set timeout=15
++fi
++### 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 gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/new-kernel.img root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++}
++menuentry 'Fedora, with Linux 3.15.0-0.rc7.git2.1.fc21.x86_64' --class gnu-linux --class gnu --class os {
++	load_video
++	set gfxpayload=keep
++	insmod gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/vmlinuz-3.15.0-0.rc7.git2.1.fc21.x86_64 root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++	initrd16 /boot6/initramfs-3.15.0-0.rc7.git2.1.fc21.x86_64.img
++}
++menuentry 'Fedora, with Linux 0-rescue-81378818f7a24478b496ebef90e1dd69' --class gnu-linux --class gnu --class os {
++	load_video
++	insmod gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/vmlinuz-0-rescue-81378818f7a24478b496ebef90e1dd69 root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++	initrd16 /boot6/initramfs-0-rescue-81378818f7a24478b496ebef90e1dd69.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.21 b/test/results/add/g2-1.21
+new file mode 100644
+index 00000000000..c0dded9724c
+--- /dev/null
++++ b/test/results/add/g2-1.21
+@@ -0,0 +1,141 @@
++#
++# 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=15
++# Fallback normal timeout code in case the timeout_style feature is
++# unavailable.
++else
++  set timeout=15
++fi
++### 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 gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/new-kernel.img root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++	initrd16 /boot6/new-initrd
++}
++menuentry 'Fedora, with Linux 3.15.0-0.rc7.git2.1.fc21.x86_64' --class gnu-linux --class gnu --class os {
++	load_video
++	set gfxpayload=keep
++	insmod gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/vmlinuz-3.15.0-0.rc7.git2.1.fc21.x86_64 root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++	initrd16 /boot6/initramfs-3.15.0-0.rc7.git2.1.fc21.x86_64.img
++}
++menuentry 'Fedora, with Linux 0-rescue-81378818f7a24478b496ebef90e1dd69' --class gnu-linux --class gnu --class os {
++	load_video
++	insmod gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/vmlinuz-0-rescue-81378818f7a24478b496ebef90e1dd69 root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++	initrd16 /boot6/initramfs-0-rescue-81378818f7a24478b496ebef90e1dd69.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.22 b/test/results/add/g2-1.22
+new file mode 100644
+index 00000000000..5cb240fc1de
+--- /dev/null
++++ b/test/results/add/g2-1.22
+@@ -0,0 +1,143 @@
++#
++# 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=15
++# Fallback normal timeout code in case the timeout_style feature is
++# unavailable.
++else
++  set timeout=15
++fi
++### 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 gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/new-kernel.img root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++}
++menuentry 'Fedora, with Linux 3.15.0-0.rc7.git2.1.fc21.x86_64' --class gnu-linux --class gnu --class os {
++	load_video
++	set gfxpayload=keep
++	insmod gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/vmlinuz-3.15.0-0.rc7.git2.1.fc21.x86_64 root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++	initrd16 /root4/boot/initramfs-3.15.0-0.rc7.git2.1.fc21.x86_64.img
++}
++menuentry 'Fedora, with Linux 0-rescue-20e7024f4e9c4b70b1042b91acd434c6' --class gnu-linux --class gnu --class os {
++	load_video
++	insmod gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/vmlinuz-0-rescue-20e7024f4e9c4b70b1042b91acd434c6 root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++	initrd16 /root4/boot/initramfs-0-rescue-20e7024f4e9c4b70b1042b91acd434c6.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 ###
++###
++
++### 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.23 b/test/results/add/g2-1.23
+new file mode 100644
+index 00000000000..c3e87cf7897
+--- /dev/null
++++ b/test/results/add/g2-1.23
+@@ -0,0 +1,144 @@
++#
++# 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=15
++# Fallback normal timeout code in case the timeout_style feature is
++# unavailable.
++else
++  set timeout=15
++fi
++### 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 gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/new-kernel.img root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++	initrd16 /root4/boot/new-initrd
++}
++menuentry 'Fedora, with Linux 3.15.0-0.rc7.git2.1.fc21.x86_64' --class gnu-linux --class gnu --class os {
++	load_video
++	set gfxpayload=keep
++	insmod gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/vmlinuz-3.15.0-0.rc7.git2.1.fc21.x86_64 root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++	initrd16 /root4/boot/initramfs-3.15.0-0.rc7.git2.1.fc21.x86_64.img
++}
++menuentry 'Fedora, with Linux 0-rescue-20e7024f4e9c4b70b1042b91acd434c6' --class gnu-linux --class gnu --class os {
++	load_video
++	insmod gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/vmlinuz-0-rescue-20e7024f4e9c4b70b1042b91acd434c6 root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++	initrd16 /root4/boot/initramfs-0-rescue-20e7024f4e9c4b70b1042b91acd434c6.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 ###
++###
++
++### 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.24 b/test/results/add/g2-1.24
+new file mode 100644
+index 00000000000..c0dded9724c
+--- /dev/null
++++ b/test/results/add/g2-1.24
+@@ -0,0 +1,141 @@
++#
++# 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=15
++# Fallback normal timeout code in case the timeout_style feature is
++# unavailable.
++else
++  set timeout=15
++fi
++### 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 gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/new-kernel.img root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++	initrd16 /boot6/new-initrd
++}
++menuentry 'Fedora, with Linux 3.15.0-0.rc7.git2.1.fc21.x86_64' --class gnu-linux --class gnu --class os {
++	load_video
++	set gfxpayload=keep
++	insmod gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/vmlinuz-3.15.0-0.rc7.git2.1.fc21.x86_64 root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++	initrd16 /boot6/initramfs-3.15.0-0.rc7.git2.1.fc21.x86_64.img
++}
++menuentry 'Fedora, with Linux 0-rescue-81378818f7a24478b496ebef90e1dd69' --class gnu-linux --class gnu --class os {
++	load_video
++	insmod gzio
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	else
++	  search --no-floppy --fs-uuid --set=root 1bab15a4-93ce-4373-8d7d-b77f907fd0c6
++	fi
++	linux16 /boot6/vmlinuz-0-rescue-81378818f7a24478b496ebef90e1dd69 root=UUID=1bab15a4-93ce-4373-8d7d-b77f907fd0c6 ro rootflags=subvol=root6 rhgb quiet
++	initrd16 /boot6/initramfs-0-rescue-81378818f7a24478b496ebef90e1dd69.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.25 b/test/results/add/g2-1.25
+new file mode 100644
+index 00000000000..c3e87cf7897
+--- /dev/null
++++ b/test/results/add/g2-1.25
+@@ -0,0 +1,144 @@
++#
++# 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=15
++# Fallback normal timeout code in case the timeout_style feature is
++# unavailable.
++else
++  set timeout=15
++fi
++### 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 gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/new-kernel.img root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++	initrd16 /root4/boot/new-initrd
++}
++menuentry 'Fedora, with Linux 3.15.0-0.rc7.git2.1.fc21.x86_64' --class gnu-linux --class gnu --class os {
++	load_video
++	set gfxpayload=keep
++	insmod gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/vmlinuz-3.15.0-0.rc7.git2.1.fc21.x86_64 root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++	initrd16 /root4/boot/initramfs-3.15.0-0.rc7.git2.1.fc21.x86_64.img
++}
++menuentry 'Fedora, with Linux 0-rescue-20e7024f4e9c4b70b1042b91acd434c6' --class gnu-linux --class gnu --class os {
++	load_video
++	insmod gzio
++	insmod part_msdos
++	insmod part_msdos
++	insmod btrfs
++	set root='hd0,msdos1'
++	if [ x$feature_platform_search_hint = xy ]; then
++	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  --hint='hd1,msdos3'  54c6abc2-b1e7-4987-aa73-c79927be69eb
++	else
++	  search --no-floppy --fs-uuid --set=root 54c6abc2-b1e7-4987-aa73-c79927be69eb
++	fi
++	linux16 /root4/boot/vmlinuz-0-rescue-20e7024f4e9c4b70b1042b91acd434c6 root=UUID=54c6abc2-b1e7-4987-aa73-c79927be69eb ro rootflags=subvol=root4 rhgb quiet
++	initrd16 /root4/boot/initramfs-0-rescue-20e7024f4e9c4b70b1042b91acd434c6.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 ###
++###
++
++### 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.17.1
+
diff --git a/SOURCES/0005-Use-system-LDFLAGS.patch b/SOURCES/0005-Use-system-LDFLAGS.patch
new file mode 100644
index 0000000..17954c4
--- /dev/null
+++ b/SOURCES/0005-Use-system-LDFLAGS.patch
@@ -0,0 +1,25 @@
+From e08c858af4d2b09e62441560f3ccecc9e750c87a Mon Sep 17 00:00:00 2001
+From: Rafael dos Santos <rdossant@redhat.com>
+Date: Tue, 29 May 2018 15:15:24 +0200
+Subject: [PATCH 5/8] Use system LDFLAGS
+
+---
+ Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Makefile b/Makefile
+index ac144046133..f0d13720db5 100644
+--- a/Makefile
++++ b/Makefile
+@@ -25,7 +25,7 @@ OBJECTS = grubby.o log.o
+ 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 := 
++LDFLAGS := $(RPM_LD_FLAGS)
+ 
+ grubby_LIBS = -lblkid -lpopt
+ 
+-- 
+2.17.1
+
diff --git a/SOURCES/0006-Honor-sbindir.patch b/SOURCES/0006-Honor-sbindir.patch
new file mode 100644
index 0000000..0d947cc
--- /dev/null
+++ b/SOURCES/0006-Honor-sbindir.patch
@@ -0,0 +1,36 @@
+From db200499551e386e7616c621fcbd69e350081664 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 18 Jul 2018 13:41:02 -0400
+Subject: [PATCH 6/8] Honor sbindir
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ Makefile | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index f0d13720db5..cfa8e0d60ab 100644
+--- a/Makefile
++++ b/Makefile
+@@ -42,14 +42,14 @@ test: all
+ 	@./test.sh
+ 
+ install: all
+-	mkdir -p $(DESTDIR)$(PREFIX)/sbin
++	mkdir -p $(DESTDIR)$(PREFIX)$(sbindir)
+ 	mkdir -p $(DESTDIR)/$(mandir)/man8
+-	install -m 755 new-kernel-pkg $(DESTDIR)$(PREFIX)/sbin
++	install -m 755 new-kernel-pkg $(DESTDIR)$(PREFIX)$(sbindir)
+ 	install -m 644 new-kernel-pkg.8 $(DESTDIR)/$(mandir)/man8
+-	install -m 755 installkernel $(DESTDIR)$(PREFIX)/sbin
++	install -m 755 installkernel $(DESTDIR)$(PREFIX)$(sbindir)
+ 	install -m 644 installkernel.8 $(DESTDIR)/$(mandir)/man8
+ 	if [ -f grubby ]; then \
+-		install -m 755 grubby $(DESTDIR)$(PREFIX)/sbin ; \
++		install -m 755 grubby $(DESTDIR)$(PREFIX)$(sbindir) ; \
+ 		install -m 644 grubby.8 $(DESTDIR)/$(mandir)/man8 ; \
+ 	fi
+ 
+-- 
+2.17.1
+
diff --git a/SOURCES/0007-Make-installkernel-to-use-kernel-install-scripts-on-.patch b/SOURCES/0007-Make-installkernel-to-use-kernel-install-scripts-on-.patch
new file mode 100644
index 0000000..727cab6
--- /dev/null
+++ b/SOURCES/0007-Make-installkernel-to-use-kernel-install-scripts-on-.patch
@@ -0,0 +1,48 @@
+From fa1bf7b54cb71fa193da16ffc404f8535d7d16ac Mon Sep 17 00:00:00 2001
+From: Javier Martinez Canillas <javierm@redhat.com>
+Date: Tue, 31 Jul 2018 17:43:53 +0200
+Subject: [PATCH 7/8] Make installkernel to use kernel-install scripts on BLS
+ configuration
+
+The kernel make install target executes the arch/$ARCH/boot/install.sh
+that in turns executes the distro specific installkernel script. This
+script always uses new-kernel-pkg to install the kernel images.
+
+But on a BootLoaderSpec setup, the kernel-install scripts must be used
+instead. Check if the system uses a BLS setup, and call kernel-install
+add in that case instead of new-kernel-pkg.
+
+Reported-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+---
+ installkernel | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/installkernel b/installkernel
+index b887929c179..68dcfac16d2 100755
+--- a/installkernel
++++ b/installkernel
+@@ -20,6 +20,8 @@
+ # Author(s): tyson@rwii.com
+ #
+ 
++[[ -f /etc/default/grub ]] && . /etc/default/grub
++
+ usage() {
+     echo "Usage: `basename $0` <kernel_version> <bootimage> <mapfile>" >&2
+     exit 1
+@@ -77,6 +79,11 @@ cp $MAPFILE $INSTALL_PATH/System.map-$KERNEL_VERSION
+ ln -fs ${RELATIVE_PATH}$INSTALL_PATH/$KERNEL_NAME-$KERNEL_VERSION $LINK_PATH/$KERNEL_NAME
+ ln -fs ${RELATIVE_PATH}$INSTALL_PATH/System.map-$KERNEL_VERSION $LINK_PATH/System.map
+ 
++if [ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ] || [ ! -f /sbin/new-kernel-pkg ]; then
++	kernel-install add $KERNEL_VERSION $INSTALL_PATH/$KERNEL_NAME-$KERNEL_VERSION
++	exit $?
++fi
++
+ 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-name $KERNEL_NAME $KERNEL_VERSION
+-- 
+2.17.1
+
diff --git a/SOURCES/0008-Add-usr-libexec-rpm-sort.patch b/SOURCES/0008-Add-usr-libexec-rpm-sort.patch
new file mode 100644
index 0000000..b3e5faa
--- /dev/null
+++ b/SOURCES/0008-Add-usr-libexec-rpm-sort.patch
@@ -0,0 +1,418 @@
+From b8a581014170c6a9bb8ffb799090401a57a4bbe6 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Fri, 12 Oct 2018 16:39:37 -0400
+Subject: [PATCH 8/8] Add /usr/libexec/rpm-sort
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ rpm-sort.c | 355 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Makefile   |   9 +-
+ .gitignore |   1 +
+ 3 files changed, 363 insertions(+), 2 deletions(-)
+ create mode 100644 rpm-sort.c
+
+diff --git a/rpm-sort.c b/rpm-sort.c
+new file mode 100644
+index 00000000000..f19635645ba
+--- /dev/null
++++ b/rpm-sort.c
+@@ -0,0 +1,355 @@
++#define _GNU_SOURCE
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <errno.h>
++#include <assert.h>
++#include <argp.h>
++#include <rpm/rpmlib.h>
++#include <err.h>
++
++typedef enum {
++        RPMNVRCMP,
++        VERSNVRCMP,
++        RPMVERCMP,
++        STRVERSCMP,
++} comparitors;
++
++static comparitors comparitor = RPMNVRCMP;
++
++static inline void *xmalloc(size_t sz)
++{
++        void *ret = malloc(sz);
++
++        assert(sz == 0 || ret != NULL);
++        return ret;
++}
++
++static inline void *xrealloc(void *p, size_t sz)
++{
++        void *ret = realloc(p, sz);
++
++        assert(sz == 0 || ret != NULL);
++        return ret;
++}
++
++static inline char *xstrdup(const char * const s)
++{
++        void *ret = strdup(s);
++
++        assert(s == NULL || ret != NULL);
++        return ret;
++}
++
++static size_t
++read_file (const char *input, char **ret)
++{
++  FILE *in;
++  size_t s;
++  size_t sz = 2048;
++  size_t offset = 0;
++  char *text;
++
++  if (!strcmp(input, "-"))
++    in = stdin;
++  else
++    in = fopen(input, "r");
++
++  text = xmalloc (sz);
++
++  if (!in)
++    err(1, "cannot open `%s'", input);
++
++  while ((s = fread (text + offset, 1, sz - offset, in)) != 0)
++    {
++      offset += s;
++      if (sz - offset == 0)
++	{
++	  sz += 2048;
++	  text = xrealloc (text, sz);
++	}
++    }
++
++  text[offset] = '\0';
++  *ret = text;
++
++  if (in != stdin)
++    fclose(in);
++
++  return offset + 1;
++}
++
++/* returns name/version/release */
++/* NULL string pointer returned if nothing found */
++static void
++split_package_string (char *package_string, char **name,
++                     char **version, char **release)
++{
++  char *package_version, *package_release;
++
++  /* Release */
++  package_release = strrchr (package_string, '-');
++
++  if (package_release != NULL)
++      *package_release++ = '\0';
++
++  *release = package_release;
++
++  /* Version */
++  package_version = strrchr(package_string, '-');
++
++  if (package_version != NULL)
++      *package_version++ = '\0';
++
++  *version = package_version;
++  /* Name */
++  *name = package_string;
++
++  /* Bubble up non-null values from release to name */
++  if (*name == NULL)
++    {
++      *name = (*version == NULL ? *release : *version);
++      *version = *release;
++      *release = NULL;
++    }
++  if (*version == NULL)
++    {
++      *version = *release;
++      *release = NULL;
++    }
++}
++
++static int
++cmprpmversp(const void *p1, const void *p2)
++{
++        return rpmvercmp(*(char * const *)p1, *(char * const *)p2);
++}
++
++static int
++cmpstrversp(const void *p1, const void *p2)
++{
++        return strverscmp(*(char * const *)p1, *(char * const *)p2);
++}
++
++/*
++ * package name-version-release comparator for qsort
++ * expects p, q which are pointers to character strings (char *)
++ * which will not be altered in this function
++ */
++static int
++package_version_compare (const void *p, const void *q)
++{
++  char *local_p, *local_q;
++  char *lhs_name, *lhs_version, *lhs_release;
++  char *rhs_name, *rhs_version, *rhs_release;
++  int vercmpflag = 0;
++  int (*cmp)(const char *s1, const char *s2);
++
++  switch(comparitor)
++    {
++    default: /* just to shut up -Werror=maybe-uninitialized */
++    case RPMNVRCMP:
++      cmp = rpmvercmp;
++      break;
++    case VERSNVRCMP:
++      cmp = strverscmp;
++      break;
++    case RPMVERCMP:
++      return cmprpmversp(p, q);
++      break;
++    case STRVERSCMP:
++      return cmpstrversp(p, q);
++      break;
++    }
++
++  local_p = alloca (strlen (*(char * const *)p) + 1);
++  local_q = alloca (strlen (*(char * const *)q) + 1);
++
++  /* make sure these allocated */
++  assert (local_p);
++  assert (local_q);
++
++  strcpy (local_p, *(char * const *)p);
++  strcpy (local_q, *(char * const *)q);
++
++  split_package_string (local_p, &lhs_name, &lhs_version, &lhs_release);
++  split_package_string (local_q, &rhs_name, &rhs_version, &rhs_release);
++
++  /* Check Name and return if unequal */
++  vercmpflag = cmp ((lhs_name == NULL ? "" : lhs_name),
++                    (rhs_name == NULL ? "" : rhs_name));
++  if (vercmpflag != 0)
++    return vercmpflag;
++
++  /* Check version and return if unequal */
++  vercmpflag = cmp ((lhs_version == NULL ? "" : lhs_version),
++                    (rhs_version == NULL ? "" : rhs_version));
++  if (vercmpflag != 0)
++    return vercmpflag;
++
++  /* Check release and return the version compare value */
++  vercmpflag = cmp ((lhs_release == NULL ? "" : lhs_release),
++                    (rhs_release == NULL ? "" : rhs_release));
++
++  return vercmpflag;
++}
++
++static void
++add_input (const char *filename, char ***package_names, size_t *n_package_names)
++{
++  char *orig_input_buffer = NULL;
++  char *input_buffer;
++  char *position_of_newline;
++  char **names = *package_names;
++  char **new_names = NULL;
++  size_t n_names = *n_package_names;
++
++  if (!*package_names)
++    new_names = names = xmalloc (sizeof (char *) * 2);
++
++  if (read_file (filename, &orig_input_buffer) < 2)
++    {
++      if (new_names)
++	free (new_names);
++      if (orig_input_buffer)
++	free (orig_input_buffer);
++      return;
++    }
++
++  input_buffer = orig_input_buffer;
++  while (input_buffer && *input_buffer &&
++	 (position_of_newline = strchrnul (input_buffer, '\n')))
++    {
++      size_t sz = position_of_newline - input_buffer;
++      char *new;
++
++      if (sz == 0)
++	{
++	  input_buffer = position_of_newline + 1;
++	  continue;
++	}
++
++      new = xmalloc (sz+1);
++      strncpy (new, input_buffer, sz);
++      new[sz] = '\0';
++
++      names = xrealloc (names, sizeof (char *) * (n_names + 1));
++      names[n_names] = new;
++      n_names++;
++
++      /* move buffer ahead to next line */
++      input_buffer = position_of_newline + 1;
++      if (*position_of_newline == '\0')
++	input_buffer = NULL;
++    }
++
++  free (orig_input_buffer);
++
++  *package_names = names;
++  *n_package_names = n_names;
++}
++
++static char *
++help_filter (int key, const char *text, void *input __attribute__ ((unused)))
++{
++  return (char *)text;
++}
++
++static struct argp_option options[] = {
++  { "comparitor", 'c', "COMPARITOR", 0, "[rpm-nvr-cmp|vers-nvr-cmp|rpmvercmp|strverscmp]", 0},
++  { 0, }
++};
++
++struct arguments
++{
++  size_t ninputs;
++  size_t input_max;
++  char **inputs;
++};
++
++static error_t
++argp_parser (int key, char *arg, struct argp_state *state)
++{
++  struct arguments *arguments = state->input;
++  switch (key)
++    {
++    case 'c':
++      if (!strcmp(arg, "rpm-nvr-cmp") || !strcmp(arg, "rpmnvrcmp"))
++        comparitor = RPMNVRCMP;
++      else if (!strcmp(arg, "vers-nvr-cmp") || !strcmp(arg, "versnvrcmp"))
++        comparitor = VERSNVRCMP;
++      else if (!strcmp(arg, "rpmvercmp"))
++        comparitor = RPMVERCMP;
++      else if (!strcmp(arg, "strverscmp"))
++        comparitor = STRVERSCMP;
++      else
++        err(1, "Invalid comparitor \"%s\"", arg);
++      break;
++    case ARGP_KEY_ARG:
++      assert (arguments->ninputs < arguments->input_max);
++      arguments->inputs[arguments->ninputs++] = xstrdup (arg);
++      break;
++    default:
++      return ARGP_ERR_UNKNOWN;
++    }
++  return 0;
++}
++
++static struct argp argp = {
++  options, argp_parser, "[INPUT_FILES]",
++  "Sort a list of strings in RPM version sort order.",
++  NULL, help_filter, NULL
++};
++
++int
++main (int argc, char *argv[])
++{
++  struct arguments arguments;
++  char **package_names = NULL;
++  size_t n_package_names = 0;
++  int i;
++
++  memset (&arguments, 0, sizeof (struct arguments));
++  arguments.input_max = argc+1;
++  arguments.inputs = xmalloc ((arguments.input_max + 1)
++			      * sizeof (arguments.inputs[0]));
++  memset (arguments.inputs, 0, (arguments.input_max + 1)
++	  * sizeof (arguments.inputs[0]));
++
++  /* Parse our arguments */
++  if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0)
++    errx(1, "%s", "Error in parsing command line arguments\n");
++
++  /* If there's no inputs in argv, add one for stdin */
++  if (!arguments.ninputs)
++    {
++      arguments.ninputs = 1;
++      arguments.inputs[0] = xmalloc (2);
++      strcpy(arguments.inputs[0], "-");
++    }
++
++  for (i = 0; i < arguments.ninputs; i++)
++    add_input(arguments.inputs[i], &package_names, &n_package_names);
++
++  if (package_names == NULL || n_package_names < 1)
++    errx(1, "Invalid input");
++
++  qsort (package_names, n_package_names, sizeof (char *),
++	 package_version_compare);
++
++  /* send sorted list to stdout */
++  for (i = 0; i < n_package_names; i++)
++    {
++      fprintf (stdout, "%s\n", package_names[i]);
++      free (package_names[i]);
++    }
++
++  free (package_names);
++  for (i = 0; i < arguments.ninputs; i++)
++    free (arguments.inputs[i]);
++
++  free (arguments.inputs);
++
++  return 0;
++}
+diff --git a/Makefile b/Makefile
+index cfa8e0d60ab..1ab58aeb039 100644
+--- a/Makefile
++++ b/Makefile
+@@ -29,7 +29,7 @@ LDFLAGS := $(RPM_LD_FLAGS)
+ 
+ grubby_LIBS = -lblkid -lpopt
+ 
+-all: grubby
++all: grubby rpm-sort
+ 
+ debug : clean
+ 	$(MAKE) CFLAGS="${CFLAGS} -DDEBUG=1" all
+@@ -52,12 +52,17 @@ install: all
+ 		install -m 755 grubby $(DESTDIR)$(PREFIX)$(sbindir) ; \
+ 		install -m 644 grubby.8 $(DESTDIR)/$(mandir)/man8 ; \
+ 	fi
++	install -m 755 -d $(DESTDIR)$(PREFIX)$(libexecdir)/grubby/
++	install -m 755 rpm-sort $(DESTDIR)$(PREFIX)$(libexecdir)/grubby/rpm-sort
+ 
+ grubby:: $(OBJECTS)
+ 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(grubby_LIBS)
+ 
++rpm-sort::rpm-sort.o
++	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -lrpm
++
+ clean:
+-	rm -f *.o grubby *~
++	rm -f *.o grubby rpm-sort *~
+ 
+ GITTAG = $(VERSION)-1
+ 
+diff --git a/.gitignore b/.gitignore
+index e64d3bc0986..1a5a546eee3 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -1,3 +1,4 @@
+ grubby
++rpm-sort
+ version.h
+ *.o
+-- 
+2.17.1
+
diff --git a/SOURCES/0009-Improve-man-page-for-info-option.patch b/SOURCES/0009-Improve-man-page-for-info-option.patch
new file mode 100644
index 0000000..742eb62
--- /dev/null
+++ b/SOURCES/0009-Improve-man-page-for-info-option.patch
@@ -0,0 +1,30 @@
+From 64f91f29b03639b0726f0c46f004a20f11379e22 Mon Sep 17 00:00:00 2001
+From: Jan Stodola <jstodola@redhat.com>
+Date: Sat, 1 Dec 2018 02:33:23 +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 355b6eb6908..9ffef895b0f 100644
+--- a/grubby.8
++++ b/grubby.8
+@@ -132,7 +132,10 @@ 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
++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-\-initrd\fR=\fIinitrd-path\fR
+-- 
+2.19.1
+
diff --git a/SOURCES/0010-Fix-GCC-warnings-about-possible-string-truncations-a.patch b/SOURCES/0010-Fix-GCC-warnings-about-possible-string-truncations-a.patch
new file mode 100644
index 0000000..c4de866
--- /dev/null
+++ b/SOURCES/0010-Fix-GCC-warnings-about-possible-string-truncations-a.patch
@@ -0,0 +1,104 @@
+From 00241c65a5c0b4bb32a847a6abb5a86d0c704a8f Mon Sep 17 00:00:00 2001
+From: Javier Martinez Canillas <javierm@redhat.com>
+Date: Tue, 5 Feb 2019 20:08:43 +0100
+Subject: [PATCH] Fix GCC warnings about possible string truncations and buffer
+ overflows
+
+Building with -Werror=stringop-truncation and -Werror=stringop-overflow
+leads to GCC complaining about possible string truncation and overflows.
+
+Fix this by using memcpy(), explicitly calculating the buffers lenghts
+and set a NUL byte terminator after copying the buffers.
+
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+---
+ grubby.c | 35 +++++++++++++++++++++++++++--------
+ 1 file changed, 27 insertions(+), 8 deletions(-)
+
+diff --git a/grubby.c b/grubby.c
+index 96d252a0a83..5ca689539cf 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -459,20 +459,26 @@ char *grub2ExtractTitle(struct singleLine * line) {
+     snprintf(result, resultMaxSize, "%s", ++current);
+     
+     i++;
++    int result_len = 0;
+     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);
++	memcpy(result + result_len, current_indent, current_indent_len);
++	result_len += current_indent_len;
++
+ 	if (!isquote(current[current_len-1])) {
+-	    strncat(result, current, current_len);
++	    memcpy(result + result_len, current_indent, current_indent_len);
++	    result_len += current_len;
+ 	} else {
+-	    strncat(result, current, current_len - 1);
++	    memcpy(result + result_len, current_indent, current_indent_len);
++	    result_len += (current_len - 1);
+ 	    break;
+ 	}
+     }
++    result[result_len] = '\0';
+     return result;
+ }
+ 
+@@ -1281,6 +1287,7 @@ static struct grubConfig * readConfig(const char * inName,
+ 	    extras = malloc(len + 1);
+ 	    *extras = '\0';
+ 
++	    int buf_len = 0;
+ 	    /* get title. */
+ 	    for (int i = 0; i < line->numElements; i++) {
+ 		if (!strcmp(line->elements[i].item, "menuentry"))
+@@ -1292,13 +1299,18 @@ static struct grubConfig * readConfig(const char * inName,
+ 
+ 		len = strlen(title);
+ 	        if (isquote(title[len-1])) {
+-		    strncat(buf, title,len-1);
++		    memcpy(buf + buf_len, title, len - 1);
++		    buf_len += (len - 1);
+ 		    break;
+ 		} else {
+-		    strcat(buf, title);
+-		    strcat(buf, line->elements[i].indent);
++		    memcpy(buf + buf_len, title, len);
++		    buf_len += len;
++		    len = strlen(line->elements[i].indent);
++		    memcpy(buf + buf_len, line->elements[i].indent, len);
++		    buf_len += len;
+ 		}
+ 	    }
++	    buf[buf_len] = '\0';
+ 
+ 	    /* get extras */
+ 	    int count = 0;
+@@ -4494,10 +4506,17 @@ int main(int argc, const char ** argv) {
+ 	exit(1);
+     }
+     saved_command_line[0] = '\0';
++    int cmdline_len = 0, arg_len;
+     for (int j = 1; j < argc; j++) {
+-	strcat(saved_command_line, argv[j]);
+-	strncat(saved_command_line, j == argc -1 ? "" : " ", 1);
++	arg_len = strlen(argv[j]);
++	memcpy(saved_command_line + cmdline_len, argv[j], arg_len);
++	cmdline_len += arg_len;
++	if (j != argc - 1) {
++	    memcpy(saved_command_line + cmdline_len, " ", 1);
++	    cmdline_len++;
++	}
+     }
++    saved_command_line[cmdline_len] = '\0';
+ 
+     optCon = poptGetContext("grubby", argc, argv, options, 0);
+     poptReadDefaultConfig(optCon, 1);
+-- 
+2.20.1
+
diff --git a/SOURCES/0011-Fix-stringop-overflow-warning.patch b/SOURCES/0011-Fix-stringop-overflow-warning.patch
new file mode 100644
index 0000000..0fc4734
--- /dev/null
+++ b/SOURCES/0011-Fix-stringop-overflow-warning.patch
@@ -0,0 +1,72 @@
+From ed5e255c023c9b78120d9ff2246d6516f652d4b7 Mon Sep 17 00:00:00 2001
+From: Javier Martinez Canillas <javierm@redhat.com>
+Date: Mon, 10 Feb 2020 19:32:39 +0100
+Subject: [PATCH] Fix stringop-overflow warning
+
+GCC gives the following compile warning:
+
+grubby.c: In function 'main':
+grubby.c:4508:27: error: writing 1 byte into a region of size 0 [-Werror=stringop-overflow=]
+ 4508 |     saved_command_line[0] = '\0';
+      |     ~~~~~~~~~~~~~~~~~~~~~~^~~~~~
+grubby.c:4503:26: note: at offset 0 to an object with size 0 allocated by 'malloc' here
+ 4503 |     saved_command_line = malloc(i);
+          |                          ^~~~~~~~~
+cc1: all warnings being treated as errors
+make: *** [Makefile:38: grubby.o] Error 1
+
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+---
+ grubby.c | 35 +++++++++++++++++++----------------
+ 1 file changed, 19 insertions(+), 16 deletions(-)
+
+diff --git a/grubby.c b/grubby.c
+index 5ca689539cf..0c0f67a0ae5 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -4500,23 +4500,26 @@ int main(int argc, const char ** argv) {
+     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';
+-    int cmdline_len = 0, arg_len;
+-    for (int j = 1; j < argc; j++) {
+-	arg_len = strlen(argv[j]);
+-	memcpy(saved_command_line + cmdline_len, argv[j], arg_len);
+-	cmdline_len += arg_len;
+-	if (j != argc - 1) {
+-	    memcpy(saved_command_line + cmdline_len, " ", 1);
+-	    cmdline_len++;
+-	}
++
++    if (i > 0) {
++	    saved_command_line = malloc(i);
++	    if (!saved_command_line) {
++		    fprintf(stderr, "grubby: %m\n");
++		    exit(1);
++	    }
++	    saved_command_line[0] = '\0';
++	    int cmdline_len = 0, arg_len;
++	    for (int j = 1; j < argc; j++) {
++		    arg_len = strlen(argv[j]);
++		    memcpy(saved_command_line + cmdline_len, argv[j], arg_len);
++		    cmdline_len += arg_len;
++		    if (j != argc - 1) {
++			    memcpy(saved_command_line + cmdline_len, " ", 1);
++			    cmdline_len++;
++		    }
++	    }
++	    saved_command_line[cmdline_len] = '\0';
+     }
+-    saved_command_line[cmdline_len] = '\0';
+ 
+     optCon = poptGetContext("grubby", argc, argv, options, 0);
+     poptReadDefaultConfig(optCon, 1);
+-- 
+2.24.1
+
diff --git a/SOURCES/0012-Fix-maybe-uninitialized-warning.patch b/SOURCES/0012-Fix-maybe-uninitialized-warning.patch
new file mode 100644
index 0000000..bcaa145
--- /dev/null
+++ b/SOURCES/0012-Fix-maybe-uninitialized-warning.patch
@@ -0,0 +1,35 @@
+From ee9f80190d4c458a09309fbd9a88d2756dc2d3fa Mon Sep 17 00:00:00 2001
+From: Javier Martinez Canillas <javierm@redhat.com>
+Date: Mon, 10 Feb 2020 20:13:13 +0100
+Subject: [PATCH] Fix maybe-uninitialized warning
+
+GCC gives the following compile warning:
+
+grubby.c: In function 'suseGrubConfGetBoot':
+grubby.c:2770:5: error: 'grubDevice' may be used uninitialized in this function [-Werror=maybe-uninitialized]
+ 2770 |     free(grubDevice);
+      |     ^~~~~~~~~~~~~~~~
+cc1: all warnings being treated as errors
+make: *** [Makefile:38: grubby.o] Error 1
+
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+---
+ grubby.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grubby.c b/grubby.c
+index 0c0f67a0ae5..779c25a2bf9 100644
+--- a/grubby.c
++++ b/grubby.c
+@@ -2755,7 +2755,7 @@ int grubGetBootFromDeviceMap(const char * device,
+ }
+ 
+ int suseGrubConfGetBoot(const char * path, char ** bootPtr) {
+-    char * grubDevice;
++    char * grubDevice = NULL;
+ 
+     if (suseGrubConfGetInstallDevice(path, &grubDevice))
+ 	dbgPrintf("error looking for grub installation device\n");
+-- 
+2.24.1
+
diff --git a/SOURCES/0013-Fix-build-with-rpm-4.16.patch b/SOURCES/0013-Fix-build-with-rpm-4.16.patch
new file mode 100644
index 0000000..9c122b7
--- /dev/null
+++ b/SOURCES/0013-Fix-build-with-rpm-4.16.patch
@@ -0,0 +1,28 @@
+From 1afddd618629a97479560bedbdcfa11b2c492a0e Mon Sep 17 00:00:00 2001
+From: Javier Martinez Canillas <javierm@redhat.com>
+Date: Fri, 26 Jun 2020 10:02:51 +0200
+Subject: [PATCH] Fix build with rpm-4.16
+
+rpmvercmp() was moved to librpmio, so link against this library instead.
+
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+---
+ Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Makefile b/Makefile
+index 1ab58aeb039..a54b053a30b 100644
+--- a/Makefile
++++ b/Makefile
+@@ -59,7 +59,7 @@ grubby:: $(OBJECTS)
+ 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(grubby_LIBS)
+ 
+ rpm-sort::rpm-sort.o
+-	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -lrpm
++	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ -lrpmio
+ 
+ clean:
+ 	rm -f *.o grubby rpm-sort *~
+-- 
+2.26.2
+
diff --git a/SOURCES/10-devicetree.install b/SOURCES/10-devicetree.install
new file mode 100755
index 0000000..3345391
--- /dev/null
+++ b/SOURCES/10-devicetree.install
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+# set -x
+
+if [[ "$(uname -m)" == arm* || "$(uname -m)" == aarch64 ]]
+then
+COMMAND="$1"
+KERNEL_VERSION="$2"
+#BOOT_DIR_ABS="$3"
+#KERNEL_IMAGE="$4"
+
+[ -f /etc/u-boot.conf ] && source /etc/u-boot.conf || true
+[ -z "$FIRMWAREDT" ] || FirmwareDT=$FIRMWAREDT
+
+if [[ $FirmwareDT == "True" ]]
+then
+	# if we want to use firmware DT we remove symlink to current kernel DT
+        if [ -h /boot/dtb ]; then
+            rm -f /boot/dtb
+        fi
+	exit 0
+fi
+
+# Setup a /boot/dtb -> /boot/dtb-$newest_kernel_version symlink so that
+# u-boot can find the correct dtb to load.
+#
+# If invoked to 'add' a new kernel, find the newest based on `sort`ing
+# the kernel versions dtb.  If 'remove', then follow basically the same
+# procedure but exclude the version currently being removed.
+#
+# The theory of operation here is that, while newer kernels may add new
+# dtb nodes and fields, as upstreaming hw support for some particular
+# device progresses, it should never make backward incompatible changes.
+# So it should always be safe to use a newer dtb with an older kernel.
+
+    list_dtb_versions() {
+        excluded_version="$1"
+        for dtbdir in /boot/dtb-*; do
+            dtbver=${dtbdir#*-}
+            if [ "$dtbver" != "$excluded_version" ]; then
+                echo $dtbver
+            fi
+        done
+    }
+
+    setup_dtb_link() {
+        ver=`list_dtb_versions $1 | sort -r --sort=version | head -1`
+        if [ -h /boot/dtb ]; then
+            rm -f /boot/dtb
+        fi
+        ln -s dtb-$ver /boot/dtb
+    }
+
+    ret=0
+    case "$COMMAND" in
+        add)
+            # If we're adding a kernel we want that version
+            if [ -h /boot/dtb ]; then
+                rm -f /boot/dtb
+            fi
+            ln -s dtb-$KERNEL_VERSION /boot/dtb
+            ret=$?
+            ;;
+        remove)
+            setup_dtb_link $KERNEL_VERSION
+            ret=$?
+            ;;
+    esac
+    exit $ret
+else
+    # Just exit on non ARM
+    exit 0
+fi
diff --git a/SOURCES/95-kernel-hooks.install b/SOURCES/95-kernel-hooks.install
new file mode 100755
index 0000000..1313556
--- /dev/null
+++ b/SOURCES/95-kernel-hooks.install
@@ -0,0 +1,33 @@
+#!/usr/bin/bash
+
+if ! [[ $KERNEL_INSTALL_MACHINE_ID ]]; then
+    exit 0
+fi
+
+COMMAND="$1"
+KERNEL_VERSION="$2"
+BOOT_DIR_ABS="$3"
+
+# If $BOOT_DIR_ABS exists, some other boot loader is active.
+[[ -d "$BOOT_DIR_ABS" ]] && exit 0
+
+run_hooks()
+{
+    local f
+    local files="$1"
+    for f in $files ; do
+        [ -x "$f" ] || continue
+        "$f" "$KERNEL_VERSION" "/boot/vmlinuz-$KERNEL_VERSION"
+    done
+}
+
+case "$COMMAND" in
+    add)
+        run_hooks "/etc/kernel/postinst.d/*[^~] /etc/kernel/postinst.d/$KERNEL_VERSION/*[^~]"
+        ;;
+    remove)
+        run_hooks "/etc/kernel/prerm.d/*[^~] /etc/kernel/prerm.d/$KERNEL_VERSION/*[^~]"
+        ;;
+    *)
+        exit 0
+esac
diff --git a/SOURCES/grubby-bls b/SOURCES/grubby-bls
new file mode 100755
index 0000000..aa1f3a2
--- /dev/null
+++ b/SOURCES/grubby-bls
@@ -0,0 +1,841 @@
+#!/bin/bash
+#
+# grubby wrapper to manage BootLoaderSpec files
+#
+#
+# Copyright 2018 Red Hat, Inc.  All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+readonly SCRIPTNAME="${0##*/}"
+
+CMDLINE_LINUX_DEBUG=" systemd.log_level=debug systemd.log_target=kmsg"
+LINUX_DEBUG_VERSION_POSTFIX="_with_debugging"
+LINUX_DEBUG_TITLE_POSTFIX=" with debugging"
+
+declare -a bls_file
+declare -a bls_title
+declare -a bls_version
+declare -a bls_linux
+declare -a bls_initrd
+declare -a bls_options
+declare -a bls_id
+
+[[ -f /etc/sysconfig/kernel ]] && . /etc/sysconfig/kernel
+[[ -f /etc/os-release ]] && . /etc/os-release
+read MACHINE_ID < /etc/machine-id
+arch=$(uname -m)
+
+if [[ $arch = 's390' || $arch = 's390x' ]]; then
+    bootloader="zipl"
+else
+    bootloader="grub2"
+fi
+
+print_error() {
+    echo "$1" >&2
+    exit 1
+}
+
+print_info() {
+    echo "$1" >&2
+}
+
+if [[ ${#} = 0 ]]; then
+    print_error "no action specified"
+fi
+
+get_bls_value() {
+    local bls="$1" && shift
+    local key="$1" && shift
+
+    echo "$(grep "^${key}[ \t]" "${bls}" | sed -e "s!^${key}[ \t]*!!")"
+}
+
+set_bls_value() {
+    local bls="$1" && shift
+    local key="$1" && shift
+    local value="$1" && shift
+
+    value=$(echo $value | sed -e 's/\//\\\//g')
+    sed -i -e "s/^${key}.*/${key} ${value}/" "${bls}"
+}
+
+append_bls_value() {
+    local bls="$1" && shift
+    local key="$1" && shift
+    local value="$1" && shift
+
+    old_value="$(get_bls_value "${bls}" ${key})"
+    set_bls_value "${bls}" "${key}" "${old_value}${value}"
+}
+
+get_bls_values() {
+    count=0
+    local -a files
+    local IFS=$'\n'
+    files=($(for bls in ${blsdir}/*.conf ; do
+        if ! [[ -e "${bls}" ]] ; then
+            continue
+        fi
+        bls="${bls%.conf}"
+        bls="${bls##*/}"
+        echo "${bls}"
+    done | /usr/libexec/grubby/rpm-sort -c rpmnvrcmp 2>/dev/null | tac)) || :
+
+    for bls in "${files[@]}" ; do
+        blspath="${blsdir}/${bls}.conf"
+        bls_file[$count]="${blspath}"
+        bls_title[$count]="$(get_bls_value ${blspath} title)"
+        bls_version[$count]="$(get_bls_value ${blspath} version)"
+        bls_linux[$count]="$(get_bls_value ${blspath} linux)"
+        bls_initrd[$count]="$(get_bls_value ${blspath} initrd)"
+        bls_options[$count]="$(get_bls_value ${blspath} options)"
+        bls_id[$count]="${bls}"
+
+        count=$((count+1))
+    done
+}
+
+get_default_index() {
+    local default=""
+    local index="-1"
+    local title=""
+    local version=""
+    if [[ $bootloader = "grub2" ]]; then
+	default="$(grep '^saved_entry=' ${env} | sed -e 's/^saved_entry=//')"
+    else
+	default="$(grep '^default=' ${zipl_config} | sed -e 's/^default=//')"
+    fi
+
+    if [[ -z $default ]]; then
+	index=0
+    elif [[ $default =~ ^[0-9]+$ ]]; then
+	index="$default"
+    fi
+
+    for i in ${!bls_file[@]}; do
+        if [[ $i -eq $index ]]; then
+            echo $i
+            return
+        fi
+
+        if [[ $default = ${bls_id[$i]} || $default = ${bls_title[$i]} ]]; then
+            echo $i
+            return
+        fi
+    done
+}
+
+display_default_value() {
+    local prefix=$(get_prefix)
+
+    case "$display_default" in
+        kernel)
+            echo "${prefix}${bls_linux[$default_index]}"
+            exit 0
+            ;;
+        index)
+            echo "$default_index"
+            exit 0
+            ;;
+        title)
+            echo "${bls_title[$default_index]}"
+            exit 0
+            ;;
+    esac
+}
+
+param_to_indexes() {
+    local param="$1"
+    local indexes=""
+
+    if [[ $param = "ALL" ]]; then
+        for i in ${!bls_file[@]}; do
+            indexes="$indexes $i"
+        done
+        echo -n $indexes
+        return
+    fi
+
+    if [[ $param = "DEFAULT" ]]; then
+        echo -n $default_index
+        return
+    fi
+
+    for i in ${!bls_file[@]}; do
+        if [[ $param = "${bls_linux[$i]}" || "/${param##*/}" = "${bls_linux[$i]}" ]]; then
+            indexes="$indexes $i"
+        fi
+
+        if [[ $param = "TITLE=${bls_title[$i]}" ]]; then
+            indexes="$indexes $i"
+        fi
+
+	if [[ $param = $i ]]; then
+	    indexes="$indexes $i"
+	fi
+    done
+
+    if [[ -n $indexes ]]; then
+        echo -n $indexes
+        return
+    fi
+
+    echo -n "-1"
+}
+
+get_prefix() {
+    if [[ $bootloader = grub2 ]] && mountpoint -q /boot; then
+	echo "/boot"
+    else
+	echo ""
+    fi
+}
+
+expand_var() {
+    local var=$1
+
+    if [[ $bootloader == "grub2" ]]; then
+        local value="$(grub2-editenv "${env}" list | grep ${var##$} | sed -e "s/${var##$}=//")"
+        value="$(echo ${value} | sed -e 's/\//\\\//g')"
+        if [[ -n $value ]]; then
+            var="$value"
+        fi
+    fi
+
+    echo $var
+}
+
+has_kernelopts()
+{
+    local args=${bls_options[$1]}
+    local opts=(${args})
+
+    for opt in ${opts[*]}; do
+        [[ $opt = "\$kernelopts" ]] && echo "true"
+    done
+
+    echo "false"
+}
+
+get_bls_args() {
+    local args=${bls_options[$1]}
+    local opts=(${args})
+
+    for opt in ${opts[*]}; do
+        if [[ $opt =~ ^\$ ]]; then
+            value="$(expand_var $opt)"
+            args="$(echo ${args} | sed -e "s/${opt}/${value}/")"
+        fi
+    done
+
+    echo ${args}
+}
+
+display_info_values() {
+    local indexes=($(param_to_indexes "$1"))
+    local prefix=$(get_prefix)
+
+    if [[ $indexes = "-1" ]]; then
+        print_error "The param $1 is incorrect"
+    fi
+
+    for i in ${indexes[*]}; do
+        local root=""
+        local value=""
+        local args="$(get_bls_args "$i")"
+
+        local opts=(${args})
+
+        for opt in ${opts[*]}; do
+            if echo $opt | grep -q "^root="; then
+                root="$(echo $opt | sed -e 's/root=//')"
+                value="$(echo ${opt} | sed -e 's/\//\\\//g')"
+                args="$(echo ${args} | sed -e "s/${value}[ \t]*//")"
+                break
+            fi
+        done
+
+        echo "index=$i"
+        echo "kernel=\"${prefix}${bls_linux[$i]}\""
+        echo "args=\"${args}\""
+
+        if [[ -n $root ]]; then
+            echo "root=\"${root}\""
+        fi
+
+        echo "initrd=\"${prefix}${bls_initrd[$i]}\""
+        echo "title=\"${bls_title[$i]}\""
+        echo "id=\"${bls_id[$i]}\""
+    done
+    exit 0
+}
+
+mkbls() {
+    local kernel=$1 && shift
+    local kernelver=$1 && shift
+    local datetime=$1 && shift
+
+    local debugname=""
+    local flavor=""
+    local prefix=""
+
+    if [[ $(get_prefix) = "" ]]; then
+	prefix="/boot"
+    fi
+
+    if [[ $kernelver == *\+* ]] ; then
+        local flavor=-"${kernelver##*+}"
+        if [[ $flavor == "-debug" ]]; then
+            local debugname="with debugging"
+	    local debugid="-debug"
+        fi
+    fi
+
+    cat <<EOF
+title ${NAME} (${kernelver}) ${VERSION}${debugname}
+version ${kernelver}${debugid}
+linux ${kernel}
+initrd ${prefix}/initramfs-${kernelver}.img
+options \$kernelopts
+id ${ID}-${datetime}-${kernelver}${debugid}
+grub_users \$grub_users
+grub_arg --unrestricted
+grub_class kernel${flavor}
+EOF
+}
+
+unset_default_bls()
+{
+    if [[ $bootloader = grub2 ]]; then
+        grub2-editenv "${env}" unset saved_entry
+    else
+        sed -i -e "/^default=.*/d" "${zipl_config}"
+    fi
+}
+
+remove_bls_fragment() {
+    local indexes=($(param_to_indexes "$1"))
+
+    if [[ $indexes = "-1" ]]; then
+	print_error "The param $(get_prefix)$1 is incorrect"
+    fi
+
+    for i in "${indexes[@]}"; do
+        if [[ $default_index = $i ]]; then
+            unset_default_bls
+        fi
+        rm -f "${bls_file[$i]}"
+    done
+
+    get_bls_values
+
+    update_grubcfg
+}
+
+get_custom_bls_filename() {
+    local kernelver=$1
+    local bls_target="${blsdir}/${MACHINE_ID}-${kernelver}.conf"
+    count=0
+    local -a files
+    local IFS=$'\n'
+
+    prefix="${bls_target%%.conf}"
+    prefix="${bls_target%%${arch}}"
+    prefix="${prefix%.*}"
+
+    last=($(for bls in ${prefix}.*~custom*.conf ; do
+        if ! [[ -e "${bls}" ]] ; then
+            continue
+        fi
+        bls="${bls##${prefix}.}"
+        bls="${bls%%~custom*}"
+        echo "${bls}"
+    done | tail -n1)) || :
+
+    if [[ -z $last ]]; then
+        last="0"
+    else
+        last=$((last+1))
+    fi
+
+    echo "${bls_target}" | sed -e "s!${prefix}!${prefix}.${last}~custom!"
+}
+
+add_bls_fragment() {
+    local kernel="$1" && shift
+    local title="$1" && shift
+    local options="$1" && shift
+    local initrd="$1" && shift
+    local extra_initrd="$1" && shift
+
+    if [[ $kernel = *"vmlinuz-"* ]]; then
+	kernelver="${kernel##*/vmlinuz-}"
+	prefix="vmlinuz-"
+    else
+	kernelver="${kernel##*/}"
+    fi
+
+    if [[ ! -f "/boot/${prefix}${kernelver}" ]] &&
+       [[ $bad_image != "true" ]]; then
+        print_error "The ${kernelver} kernel isn't installed in the machine"
+    fi
+
+    if [[ -z $title ]]; then
+	print_error "The kernel title must be specified"
+    fi
+
+    if [[ ! -d $blsdir ]]; then
+        install -m 700 -d "${blsdir}"
+    fi
+
+    bls_target="${blsdir}/${MACHINE_ID}-${kernelver}.conf"
+
+    if [[ -e ${bls_target} ]]; then
+        bls_target="$(get_custom_bls_filename "${kernelver}")"
+        print_info "An entry for kernel ${kernelver} already exists, adding ${bls_target}"
+    fi
+
+    kernel_dir="/lib/modules/${kernelver}"
+    if [[ -d $kernel_dir ]]; then
+        datetime="$(date -u +%Y%m%d%H%M%S -d "$(stat -c '%y' "${kernel_dir}")")"
+    else
+        datetime=0
+    fi
+    mkbls "${kernel}" "${kernelver}" "${datetime}" > "${bls_target}"
+
+    if [[ -n $title ]]; then
+        set_bls_value "${bls_target}" "title" "${title}"
+    fi
+
+    if [[ -n $options ]]; then
+        set_bls_value "${bls_target}" "options" "${options}"
+    fi
+
+    if [[ -n $initrd ]]; then
+        set_bls_value "${bls_target}" "initrd" "${initrd}"
+    fi
+
+    if [[ -n $extra_initrd ]]; then
+        append_bls_value "${bls_target}" "initrd" " ${extra_initrd}"
+    fi
+
+    if [[ $MAKEDEBUG = "yes" ]]; then
+        bls_debug="$(echo ${bls_target} | sed -e "s/${kernelver}/${kernelver}~debug/")"
+        cp -aT  "${bls_target}" "${bls_debug}"
+        append_bls_value "${bls_debug}" "title" "${LINUX_DEBUG_TITLE_POSTFIX}"
+        append_bls_value "${bls_debug}" "version" "${LINUX_DEBUG_VERSION_POSTFIX}"
+        append_bls_value "${bls_debug}" "options" "${CMDLINE_LINUX_DEBUG}"
+        blsid="$(get_bls_value ${bls_debug} "id" | sed -e "s/${kernelver}/${kernelver}~debug/")"
+        set_bls_value "${bls_debug}" "id" "${blsid}"
+    fi
+
+    get_bls_values
+
+    if [[ $make_default = "true" ]]; then
+        set_default_bls "TITLE=${title}"
+    fi
+
+    update_grubcfg
+
+    exit 0
+}
+
+update_args() {
+    local args=$1 && shift
+    local remove_args=($1) && shift
+    local add_args=($1) && shift
+
+    for arg in ${remove_args[*]}; do
+        arg="$(echo $arg | sed -e 's/\//\\\//g')"
+        if [[ $arg = *"="* ]]; then
+            args="$(echo $args | sed -E "s/(^|[[:space:]])$arg([[:space:]]|$)/ /")"
+        else
+            args="$(echo $args | sed -E "s/(^|[[:space:]])$arg(([[:space:]]|$)|([=][^ ]*([$]*)))/ /g")"
+        fi
+    done
+
+    for arg in ${add_args[*]}; do
+        arg="${arg%%=*}"
+        arg="$(echo $arg | sed -e 's/\//\\\//g')"
+        args="$(echo $args | sed -E "s/(^|[[:space:]])$arg(([[:space:]]|$)|([=][^ ]*([$]*)))/ /g")"
+    done
+
+    for arg in ${add_args[*]}; do
+        args="$args $arg"
+    done
+
+    echo ${args}
+}
+
+update_bls_fragment() {
+    local param="$1"
+    local indexes=($(param_to_indexes "$1")) && shift
+    local remove_args=$1 && shift
+    local add_args=$1 && shift
+    local initrd=$1 && shift
+    local opts
+
+    if [[ $indexes = "-1" ]]; then
+        print_error "The param $(get_prefix)${param} is incorrect"
+    fi
+
+    if [[ $param = "ALL" && $bootloader = grub2 ]] && [[ -n $remove_args || -n $add_args ]]; then
+        local old_args=""
+
+        if [[ -z $no_etc_update ]] && [[ -e ${grub_etc_default} ]]; then
+            old_args="$(source ${grub_etc_default}; echo ${GRUB_CMDLINE_LINUX})"
+            if [[ -n $old_args ]]; then
+                opts="$(update_args "${old_args}" "${remove_args}" "${add_args}")"
+                opts="$(echo "$opts" | sed -e 's/\//\\\//g')"
+                sed -i -e "s/^GRUB_CMDLINE_LINUX.*/GRUB_CMDLINE_LINUX=\\\"${opts}\\\"/" "${grub_etc_default}"
+            fi
+        fi
+
+        old_args="$(grub2-editenv "${env}" list | grep kernelopts | sed -e "s/kernelopts=//")"
+        if [[ -n $old_args ]]; then
+            opts="$(update_args "${old_args}" "${remove_args}" "${add_args}")"
+            grub2-editenv "${env}" set kernelopts="${opts}"
+        fi
+    elif [[ $bootloader = grub2 ]]; then
+        opts="$(grub2-editenv "${env}" list | grep kernelopts | sed -e "s/kernelopts=//")"
+    fi
+
+    for i in ${indexes[*]}; do
+	if [[ -n $remove_args || -n $add_args ]]; then
+            local old_args="$(get_bls_args "$i")"
+            local new_args="$(update_args "${old_args}" "${remove_args}" "${add_args}")"
+
+            if [[ $param != "ALL" || "$(has_kernelopts "$i")" = "false" ]]; then
+                set_bls_value "${bls_file[$i]}" "options" "${new_args}"
+            fi
+	fi
+
+	if [[ -n $initrd ]]; then
+	    set_bls_value "${bls_file[$i]}" "initrd" "${initrd}"
+	fi
+    done
+
+    update_grubcfg
+}
+
+set_default_bls() {
+    local index=($(param_to_indexes "$1"))
+
+    if [[ $index = "-1" ]]; then
+        print_error "The param $1 is incorrect"
+    fi
+
+    if [[ $bootloader = grub2 ]]; then
+        grub2-editenv "${env}" set saved_entry="${bls_id[$index]}"
+    else
+        local default="${bls_title[$index]}"
+        local current="$(grep '^default=' ${zipl_config} | sed -e 's/^default=//')"
+        if [[ -n $current ]]; then
+            sed -i -e "s,^default=.*,default=${default}," "${zipl_config}"
+        else
+            echo "default=${default}" >> "${zipl_config}"
+        fi
+    fi
+
+    print_info "The default is ${bls_file[$index]} with index $index and kernel $(get_prefix)${bls_linux[$index]}"
+}
+
+remove_var_prefix() {
+    local prefix="$1"
+
+    [ -z "${prefix}" ] && return
+
+    if [[ -n $remove_kernel && $remove_kernel =~ ^/ ]]; then
+       remove_kernel="/${remove_kernel##${prefix}/}"
+    fi
+
+    if [[ -n $initrd ]]; then
+	initrd="/${initrd##${prefix}/}"
+    fi
+
+    if [[ -n $extra_initrd ]]; then
+	extra_initrd="/${extra_initrd##${prefix}/}"
+    fi
+
+    if [[ -n $kernel ]]; then
+	kernel="/${kernel##${prefix}/}"
+    fi
+
+    if [[ -n $update_kernel && $update_kernel =~ ^/ ]]; then
+	update_kernel="/${update_kernel##${prefix}/}"
+    fi
+}
+
+update_grubcfg()
+{
+    # Older ppc64le OPAL firmware (petitboot version < 1.8.0) don't have BLS support
+    # so grub2-mkconfig has to be run to generate a config with menuentry commands.
+    if [ "${arch}" = "ppc64le" ] && [ -d /sys/firmware/opal ]; then
+        RUN_MKCONFIG="true"
+        petitboot_path="/sys/firmware/devicetree/base/ibm,firmware-versions/petitboot"
+
+        if test -e ${petitboot_path}; then
+            read -r -d '' petitboot_version < ${petitboot_path}
+            petitboot_version="$(echo ${petitboot_version//v})"
+
+            if test -n ${petitboot_version}; then
+                major_version="$(echo ${petitboot_version} | cut -d . -f1)"
+                minor_version="$(echo ${petitboot_version} | cut -d . -f2)"
+
+                re='^[0-9]+$'
+                if [[ $major_version =~ $re ]] && [[ $minor_version =~ $re ]] &&
+                       ([[ ${major_version} -gt 1 ]] ||
+                            [[ ${major_version} -eq 1 &&
+                                 ${minor_version} -ge 8  ]]); then
+                    RUN_MKCONFIG="false"
+                fi
+            fi
+        fi
+    fi
+
+    if [[ $RUN_MKCONFIG = "true" ]]; then
+        grub2-mkconfig --no-grubenv-update -o "${grub_config}" >& /dev/null
+    fi
+}
+
+print_usage()
+{
+    cat <<EOF
+Usage: grubby [OPTION...]
+      --add-kernel=kernel-path            add an entry for the specified kernel
+      --args=args                         default arguments for the new kernel or new arguments for kernel being updated)
+      --bad-image-okay                    don't sanity check images in boot entries (for testing only)
+  -c, --config-file=path                  path to grub config file to update ("-" for stdin)
+      --copy-default                      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
+      --default-kernel                    display the path of the default kernel
+      --default-index                     display the index of the default kernel
+      --default-title                     display the title of the default kernel
+      --env=path                          path for environment data
+      --grub2                             configure grub2 bootloader
+      --info=kernel-path                  display boot information for specified kernel
+      --initrd=initrd-path                initrd image for the new kernel
+  -i, --extra-initrd=initrd-path          auxiliary initrd image for things other than the new kernel
+      --make-default                      make the newly added entry the default boot entry
+      --remove-args=STRING                remove kernel arguments
+      --remove-kernel=kernel-path         remove all entries for the specified kernel
+      --set-default=kernel-path           make the first entry referencing the specified kernel the default
+      --set-default-index=entry-index     make the given entry index the default entry
+      --title=entry-title                 title to use for the new kernel entry
+      --update-kernel=kernel-path         updated information for the specified kernel
+      --zipl                              configure zipl bootloader
+  -b, --bls-directory                     path to directory containing the BootLoaderSpec fragment files
+      --no-etc-grub-update                don't update the GRUB_CMDLINE_LINUX variable in /etc/default/grub
+
+Help options:
+  -?, --help                              Show this help message
+
+EOF
+}
+
+OPTS="$(getopt -o c:i:b:? --long help,add-kernel:,args:,bad-image-okay,\
+config-file:,copy-default,default-kernel,default-index,default-title,env:,\
+grub2,info:,initrd:,extra-initrd:,make-default,remove-args:,\
+remove-kernel:,set-default:,set-default-index:,title:,update-kernel:,zipl,\
+bls-directory:,no-etc-grub-update,add-multiboot:,mbargs:,mounts:,boot-filesystem:,\
+bootloader-probe,debug,devtree,devtreedir:,elilo,efi,extlinux,grub,lilo,\
+output-file:,remove-mbargs:,remove-multiboot:,silo,yaboot -n ${SCRIPTNAME} -- "$@")"
+
+[[ $? = 0 ]] || exit 1
+
+eval set -- "$OPTS"
+
+while [ ${#} -gt 0 ]; do
+    case "$1" in
+        --help|-h)
+            print_usage
+            exit 0
+            ;;
+        --add-kernel)
+            kernel="${2}"
+            shift
+            ;;
+        --args)
+            args="${2}"
+            shift
+            ;;
+        --bad-image-okay)
+            bad_image=true
+            ;;
+        --config-file|-c)
+            grub_config="${2}"
+            zipl_config="${2}"
+            shift
+            ;;
+        --copy-default)
+            copy_default=true
+            ;;
+        --default-kernel)
+            display_default="kernel"
+            ;;
+        --default-index)
+            display_default="index"
+            ;;
+        --default-title)
+            display_default="title"
+            ;;
+        --env)
+            env="${2}"
+            shift
+            ;;
+        --grub2)
+            bootloader="grub2"
+            ;;
+        --info)
+            display_info="${2}"
+            shift
+            ;;
+        --initrd)
+            initrd="${2}"
+            shift
+            ;;
+        --extra-initrd|-i)
+            extra_initrd="${2}"
+            shift
+            ;;
+        --make-default)
+            make_default=true
+            ;;
+        --remove-args)
+            remove_args="${2}"
+            shift
+            ;;
+        --remove-kernel)
+            remove_kernel="${2}"
+            shift
+            ;;
+        --set-default)
+            set_default="${2}"
+            shift
+            ;;
+        --set-default-index)
+            set_default="${2}"
+            shift
+            ;;
+        --title)
+            title="${2}"
+            shift
+            ;;
+        --update-kernel)
+            update_kernel="${2}"
+            shift
+            ;;
+        --zipl)
+            bootloader="zipl"
+            ;;
+        --bls-directory|-b)
+            blsdir="${2}"
+	    shift
+	    ;;
+        --no-etc-grub-update)
+            no_etc_update=true
+            shift
+            ;;
+        --add-multiboot|--mbargs|--mounts|--boot-filesystem|\
+        --bootloader-probe|--debug|--devtree|--devtreedir|--elilo|--efi|\
+        --extlinux|--grub|--lilo|--output-file|--remove-mbargs|--silo|\
+        --remove-multiboot|--slilo|--yaboot)
+            echo
+            echo "${SCRIPTNAME}: the option \"${1}\" was deprecated" >&2
+            echo "Try '${SCRIPTNAME} --help' to list supported options" >&2
+            echo
+	    exit 1
+	    ;;
+        --)
+            shift
+            break
+            ;;
+        *)
+            echo
+            echo "${SCRIPTNAME}: invalid option \"${1}\"" >&2
+            echo "Try '${SCRIPTNAME} --help' for more information" >&2
+            echo
+            exit 1
+            ;;
+    esac
+    shift
+done
+
+if [[ -z $update_kernel && -z $kernel ]] && [[ -n $args || -n $remove_args ]]; then
+    print_error "no action specified"
+fi
+
+if [[ -z $blsdir ]]; then
+    blsdir="/boot/loader/entries"
+fi
+
+if [[ -z $env ]]; then
+    env="/boot/grub2/grubenv"
+fi
+
+if [[ -z $zipl_config ]]; then
+    zipl_config="/etc/zipl.conf"
+fi
+
+if [[ -z $grub_config ]]; then
+    grub_config="/boot/grub2/grub.cfg"
+fi
+
+if [[ -z $grub_etc_default ]]; then
+    grub_etc_default="/etc/default/grub"
+fi
+
+get_bls_values
+
+default_index="$(get_default_index)"
+
+if [[ -n $display_default ]]; then
+    display_default_value
+fi
+
+if [[ -n $display_info ]]; then
+    display_info_values "${display_info}"
+fi
+
+remove_var_prefix "$(get_prefix)"
+
+if [[ -n $kernel ]]; then
+    if [[ $copy_default = "true" ]]; then
+	opts="${bls_options[$default_index]}"
+	if [[ -n $args ]]; then
+	    opts="${opts} ${args}"
+	fi
+    else
+	opts="${args}"
+    fi
+
+    add_bls_fragment "${kernel}" "${title}" "${opts}" "${initrd}" \
+                     "${extra_initrd}"
+fi
+
+if [[ -n $remove_kernel ]]; then
+    remove_bls_fragment "${remove_kernel}"
+fi
+
+if [[ -n $update_kernel ]]; then
+    update_bls_fragment "${update_kernel}" "${remove_args}" "${args}" "${initrd}"
+fi
+
+if [[ -n $set_default ]]; then
+    set_default_bls "${set_default}"
+fi
+
+exit 0
diff --git a/SOURCES/grubby.8 b/SOURCES/grubby.8
new file mode 100644
index 0000000..9bcd247
--- /dev/null
+++ b/SOURCES/grubby.8
@@ -0,0 +1,179 @@
+.TH GRUBBY 8 "Wed Apr 29 2020"
+.SH NAME
+grubby \- command line tool for configuring grub and zipl
+
+.SH SYNOPSIS
+\fBgrubby\fR [--add-kernel=\fIkernel-path\fR] [--args=\fIargs\fR]
+       [--bad-image-okay] [--config-file=\fIpath\fR] [--copy-default]
+       [--default-kernel] [--default-index] [--default-title]
+       [--env=\fIpath\fR] [--grub2] [--info=\fIkernel-path\fR]
+       [--initrd=\fIinitrd-path\fR] [--extra-initrd=\fIinitrd-path\fR]
+       [--make-default] [--remove-args=\fIargs\fR]
+       [--remove-kernel=\fIkernel-path\fR] [--set-default=\fIkernel-path\fR]
+       [--set-default-index=\fientry-index\fR] [--title=\fentry-title\fR]
+       [--update-kernel=\fIkernel-path\fR] [--zipl] [--bls-directory=\fIpath\fR]
+
+.SH DESCRIPTION
+\fBgrubby\fR is a command line tool for updating and displaying information
+about the configuration files for the \fBgrub2\fR and \fBzipl\fR 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 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 PowerPC platforms, systems
+based on Power8 and Power9 support \fBgrub2\fR as a bootloader and use a
+configuration stored in \fB/boot/grub2/grub.cfg\fR. On s390x platforms the
+\fBzipl\fR bootloader use a default configuration in \fB/etc/zipl.conf\fR.
+
+All bootloaders define the boot entries as individual configuration fragments
+that are stored by default in \fB/boot/loader/entries\fR. The format for the
+config files is specified at \fBhttps://systemd.io/BOOT_LOADER_SPECIFICATION\fR.
+The \fBgrubby\fR tool is used to update and display the configuration defined
+in the BootLoaderSpec fragment files.
+
+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.
+Also, the title of a boot entry may be specified by using \fBTITLE=\fItitle\fR
+as the argument; all entries with that title are used.
+
+.SH OPTIONS
+.TP
+\fB-\-add-kernel\fR=\fIkernel-path\fR
+Add a new boot entry for the kernel located at \fIkernel-path\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
+with the arguments of the default entry if \fB-\-copy-default\fR is used).
+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. The
+\fBroot=\fR kernel argument gets special handling if the configuration
+file has special handling for specifying the root filesystem.
+
+.TP
+\fB-\-bad-image-okay\fR
+When \fBgrubby\fR is looking for an entry to use for something (such
+as 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-\-config-file\fR=\fIpath\fR
+Use \fIpath\fR as the configuration file rather then the default.
+
+.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.
+
+.TP
+\fB-\-default-kernel\fR
+Display the full path to the current default kernel and exit.
+
+.TP
+\fB-\-default-index\fR
+Display the numeric index of the current default boot entry and exit.
+
+.TP
+\fB-\-default-title\fR
+Display the title of the current default boot entry and exit.
+
+.TP
+\fB-\-env\fR=\fIpath\fR
+Use \fIpath\fR as the grub2 environment block file rather then the default path.
+
+.TP
+\fB-\-grub2\fR
+Configure \fBgrub2\fR bootloader.
+
+.TP
+\fB-\-info\fR=\fIkernel-path\fR
+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-\-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-\-extrainitrd\fR=\fIinitrd-path\fR
+Use \fIinitrd-path\fR as the path to an auxiliary init ram disk image to be
+added to the boot entry.
+
+.TP
+\fB-\-make-default\fR
+Make the new kernel entry being added the default entry.
+
+.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.
+
+.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.
+
+.TP
+\fB-\-set-default\fR=\fIkernel-path\fR
+The first entry which boots the specified kernel is made the default
+boot entry.
+
+.TP
+\fB-\-set-default-index\fR=\fIentry-index\fR
+Makes the given entry number the default boot entry.
+
+.TP
+\fB-\-title\fR=\fIentry-title\fR
+When a new kernel entry is added \fIentry-title\fR is used as the title
+for the entry.
+
+.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. If the
+\fBALL\fR argument is used the variable \fB GRUB_CMDLINE_LINUX\fR in
+\fB/etc/default/grub\fR is updated with the latest kernel argument list,
+unless the \fB-\-no-etc-grub-update\fR option is used.
+
+.TP
+\fB-\-zipl\fR
+Configure \fBzipl\fR bootloader.
+
+.TP
+\fB-\-bls-directory\fR=\fIpath\fR
+Use \fIpath\fR as the directory for the BootLoaderSpec config files rather
+than the default \fB/boot/loader/entries\fR.
+
+.TP
+\fB-\-no-etc-grub-update\fR
+Makes grubby to not update the \fBGRUB_CMDLINE_LINUX\fR variable in
+\fB/etc/default/grub\fR when the \fB-\-update-kernel\fR option is
+used with the \fBALL\fR argument.
+
+.SH "SEE ALSO"
+.BR zipl (8),
+.BR mkinitrd (8),
+.BR kernel-install (8)
+
+.SH AUTHORS
+.nf
+Erik Troan
+Jeremy Katz
+Peter Jones
+Javier Martinez
+.fi
diff --git a/SOURCES/grubby.in b/SOURCES/grubby.in
new file mode 100644
index 0000000..023e595
--- /dev/null
+++ b/SOURCES/grubby.in
@@ -0,0 +1,8 @@
+#!/bin/bash
+if [[ -x @@LIBEXECDIR@@/grubby ]] ; then
+	exec @@LIBEXECDIR@@/grubby "${@}"
+elif [[ -x @@LIBEXECDIR@@/grubby-bls ]] ; then
+	exec @@LIBEXECDIR@@/grubby-bls "${@}"
+fi
+echo "Grubby is not installed correctly." >>/dev/stderr
+exit 1
diff --git a/SOURCES/installkernel-bls b/SOURCES/installkernel-bls
new file mode 100755
index 0000000..f2f607e
--- /dev/null
+++ b/SOURCES/installkernel-bls
@@ -0,0 +1,83 @@
+#! /bin/sh
+#
+# /sbin/installkernel
+#
+# Copyright 2007-2008 Red Hat, Inc.  All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): tyson@rwii.com
+#
+
+usage() {
+    echo "Usage: `basename $0` <kernel_version> <bootimage> <mapfile>" >&2
+    exit 1
+}
+
+cfgLoader=
+
+if [ -z "$INSTALL_PATH" -o "$INSTALL_PATH" == "/boot" ]; then
+    INSTALL_PATH=/boot
+    cfgLoader=1
+fi
+
+LINK_PATH=/boot
+RELATIVE_PATH=`echo "$INSTALL_PATH/" | sed "s|^$LINK_PATH/||"`
+KERNEL_VERSION=$1
+BOOTIMAGE=$2
+MAPFILE=$3
+ARCH=$(uname -m)
+if [ $ARCH = 'ppc64' -o $ARCH = 'ppc' ]; then
+    KERNEL_NAME=vmlinux
+else
+    KERNEL_NAME=vmlinuz
+fi
+
+if [ -z "$KERNEL_VERSION" -o -z "$BOOTIMAGE" -o -z "$MAPFILE" ]; then
+    usage
+fi
+
+if [ -f $INSTALL_PATH/$KERNEL_NAME-$KERNEL_VERSION ]; then
+      mv $INSTALL_PATH/$KERNEL_NAME-$KERNEL_VERSION \
+              $INSTALL_PATH/$KERNEL_NAME-$KERNEL_VERSION.old;
+fi
+
+if [ ! -L $INSTALL_PATH/$KERNEL_NAME ]; then
+    if [ -e $INSTALLPATH/$KERNEL_NAME ]; then
+	mv $INSTALL_PATH/$KERNEL_NAME $INSTALL_PATH/$KERNEL_NAME.old
+    fi
+fi
+
+if [ -f $INSTALL_PATH/System.map-$KERNEL_VERSION ]; then
+      mv $INSTALL_PATH/System.map-$KERNEL_VERSION \
+              $INSTALL_PATH/System.map-$KERNEL_VERSION.old;
+fi
+
+if [ ! -L $INSTALL_PATH/System.map ]; then
+    if [ -e $INSTALLPATH/System.map ]; then
+	mv $INSTALL_PATH/System.map $INSTALL_PATH/System.map.old
+    fi
+fi
+ln -sf ${RELATIVE_PATH}$INSTALL_PATH/System.map-$KERNEL_VERSION $LINK_PATH/System.map
+
+cat $BOOTIMAGE > $INSTALL_PATH/$KERNEL_NAME-$KERNEL_VERSION
+cp $MAPFILE $INSTALL_PATH/System.map-$KERNEL_VERSION
+
+ln -fs ${RELATIVE_PATH}$INSTALL_PATH/$KERNEL_NAME-$KERNEL_VERSION $LINK_PATH/$KERNEL_NAME
+ln -fs ${RELATIVE_PATH}$INSTALL_PATH/System.map-$KERNEL_VERSION $LINK_PATH/System.map
+
+if [ -n "$cfgLoader" ]; then
+	kernel-install add $KERNEL_VERSION $INSTALL_PATH/$KERNEL_NAME-$KERNEL_VERSION
+	exit $?
+fi
diff --git a/SOURCES/installkernel.in b/SOURCES/installkernel.in
new file mode 100644
index 0000000..87b81ee
--- /dev/null
+++ b/SOURCES/installkernel.in
@@ -0,0 +1,8 @@
+#!/bin/bash
+if [[ -x @@LIBEXECDIR@@/installkernel ]] ; then
+	exec @@LIBEXECDIR@@/installkernel "${@}"
+elif [[ -x @@LIBEXECDIR@@/installkernel-bls ]] ; then
+	exec @@LIBEXECDIR@@/installkernel-bls "${@}"
+fi
+echo "installkernel is not installed correctly." >>/dev/stderr
+exit 1
diff --git a/SPECS/grubby.spec b/SPECS/grubby.spec
new file mode 100644
index 0000000..70b69ad
--- /dev/null
+++ b/SPECS/grubby.spec
@@ -0,0 +1,717 @@
+Name: grubby
+Version: 8.40
+Release: 54%{?dist}
+Summary: Command line tool for updating bootloader configs
+License: GPLv2+
+URL: https://github.com/rhinstaller/grubby
+# we only pull git snaps at the moment
+# git clone git@github.com:rhinstaller/grubby.git
+# git archive --format=tar --prefix=grubby-%%{version}/ HEAD |bzip2 > grubby-%%{version}.tar.bz2
+# Source0: %%{name}-%%{version}.tar.bz2
+Source0: https://github.com/rhboot/grubby/archive/%{version}-1.tar.gz
+Source1: grubby-bls
+Source2: grubby.in
+Source3: installkernel.in
+Source4: installkernel-bls
+Source5: 95-kernel-hooks.install
+Source6: 10-devicetree.install
+Source7: grubby.8
+
+Patch0001: 0001-remove-the-old-crufty-u-boot-support.patch
+Patch0002: 0002-Change-return-type-in-getRootSpecifier.patch
+Patch0003: 0003-Add-btrfs-subvolume-support-for-grub2.patch
+Patch0004: 0004-Add-tests-for-btrfs-support.patch
+Patch0005: 0005-Use-system-LDFLAGS.patch
+Patch0006: 0006-Honor-sbindir.patch
+Patch0007: 0007-Make-installkernel-to-use-kernel-install-scripts-on-.patch
+Patch0008: 0008-Add-usr-libexec-rpm-sort.patch
+Patch0009: 0009-Improve-man-page-for-info-option.patch
+Patch0010: 0010-Fix-GCC-warnings-about-possible-string-truncations-a.patch
+Patch0011: 0011-Fix-stringop-overflow-warning.patch
+Patch0012: 0012-Fix-maybe-uninitialized-warning.patch
+Patch0013: 0013-Fix-build-with-rpm-4.16.patch
+
+BuildRequires: gcc
+BuildRequires: pkgconfig glib2-devel popt-devel 
+BuildRequires: libblkid-devel sed make
+# for make test / getopt:
+BuildRequires: util-linux-ng
+BuildRequires: rpm-devel
+%ifarch aarch64 i686 x86_64 %{power64}
+BuildRequires: grub2-tools-minimal
+Requires: grub2-tools-minimal
+Requires: grub2-tools
+%endif
+%ifarch s390 s390x
+Requires: s390utils-core
+%endif
+Requires: findutils
+Requires: util-linux
+
+Conflicts:	uboot-tools < 2021.01-0.1.rc2
+Obsoletes:	%{name}-bls < %{version}-%{release}
+
+%description
+This package provides a grubby compatibility script that manages
+BootLoaderSpec files and is meant to only be used for legacy compatibility
+users with existing grubby users.
+
+%prep
+%autosetup -p1 -n grubby-%{version}-1
+
+%build
+%set_build_flags
+%make_build LDFLAGS="${LDFLAGS}"
+
+%ifnarch aarch64 %{arm}
+%check
+make test
+%endif
+
+%install
+make install DESTDIR=$RPM_BUILD_ROOT mandir=%{_mandir} sbindir=%{_sbindir} libexecdir=%{_libexecdir}
+
+mkdir -p %{buildroot}%{_libexecdir}/{grubby,installkernel}/ %{buildroot}%{_sbindir}/
+mv -v %{buildroot}%{_sbindir}/grubby %{buildroot}%{_libexecdir}/grubby/grubby
+mv -v %{buildroot}%{_sbindir}/installkernel %{buildroot}%{_libexecdir}/installkernel/installkernel
+install -m 0755 %{SOURCE1} %{buildroot}%{_libexecdir}/grubby/
+install -m 0755 %{SOURCE4} %{buildroot}%{_libexecdir}/installkernel/
+sed -e "s,@@LIBEXECDIR@@,%{_libexecdir}/grubby,g" %{SOURCE2} \
+	> %{buildroot}%{_sbindir}/grubby
+sed -e "s,@@LIBEXECDIR@@,%{_libexecdir}/installkernel,g" %{SOURCE3} \
+	> %{buildroot}%{_sbindir}/installkernel
+install -D -m 0755 -t %{buildroot}%{_prefix}/lib/kernel/install.d/ %{SOURCE5}
+install -D -m 0755 -t %{buildroot}%{_prefix}/lib/kernel/install.d/ %{SOURCE6}
+rm %{buildroot}%{_mandir}/man8/grubby.8*
+install -m 0644 %{SOURCE7} %{buildroot}%{_mandir}/man8/
+
+%post
+if [ "$1" = 2 ]; then
+    arch=$(uname -m)
+    [[ $arch == "s390x" ]] && \
+    zipl-switch-to-blscfg --backup-suffix=.rpmsave &>/dev/null || :
+fi
+
+%package deprecated
+Summary:	Legacy command line tool for updating bootloader configs
+Conflicts:	%{name} <= 8.40-18
+
+%description deprecated
+This package provides deprecated, legacy grubby.  This is for temporary
+compatibility only.
+
+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.
+
+%files
+%license COPYING
+%dir %{_libexecdir}/grubby
+%dir %{_libexecdir}/installkernel
+%attr(0755,root,root) %{_libexecdir}/grubby/grubby-bls
+%attr(0755,root,root) %{_libexecdir}/grubby/rpm-sort
+%attr(0755,root,root) %{_sbindir}/grubby
+%attr(0755,root,root) %{_libexecdir}/installkernel/installkernel-bls
+%attr(0755,root,root) %{_sbindir}/installkernel
+%attr(0755,root,root) %{_prefix}/lib/kernel/install.d/10-devicetree.install
+%attr(0755,root,root) %{_prefix}/lib/kernel/install.d/95-kernel-hooks.install
+%{_mandir}/man8/[gi]*.8*
+
+%files deprecated
+%license COPYING
+%dir %{_libexecdir}/grubby
+%dir %{_libexecdir}/installkernel
+%attr(0755,root,root) %{_libexecdir}/grubby/grubby
+%attr(0755,root,root) %{_libexecdir}/installkernel/installkernel
+%attr(0755,root,root) %{_sbindir}/grubby
+%attr(0755,root,root) %{_sbindir}/installkernel
+%attr(0755,root,root) %{_sbindir}/new-kernel-pkg
+ %{_mandir}/man8/*.8*
+
+%changelog
+* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 8.40-54
+- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
+  Related: rhbz#1991688
+
+* Tue Apr 27 2021 Javier Martinez Canillas <javierm@redhat.com> - 8.40-53
+- grubby-bs: Fix changing kernel cmdline params not working on ppc64le
+  Resolves: rhbz#1896222
+
+* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 8.40-52
+- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
+
+* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 8.40-51
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
+
+* Wed Dec 30 2020 Tom Stellard <tstellar@redhat.com> - 8.40-50
+- Use make_build macro instead of plain make
+- https://docs.fedoraproject.org/en-US/packaging-guidelines/#_parallel_make
+
+* Fri Nov 20 2020 Peter Robinson <pbrobinson@fedoraproject.org> - 8.40-49
+- Add device tree kernel install option
+
+* Mon Oct 26 2020 Josh Boyer <jwb@redhat.com> - 8.40-48
+- Only require s390utils-core, not s390utils-base
+
+* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 8.40-47
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
+
+* Fri Jun 26 2020 Javier Martinez Canillas <javierm@redhat.com> - 8.40-46
+- fix build with rpm-4.16
+- grubby-bls: fix --extra-initrd option not adding the correct path
+
+* Wed May 13 2020 Javier Martinez Canillas <javierm@redhat.com> - 8.40-45
+- grubby-bls: don't replace options with kernelopts if values are the same
+
+* Wed May 06 2020 Javier Martinez Canillas <javierm@redhat.com> - 8.40-44
+- Fix installed man page file mode bits
+
+* Tue May 05 2020 Javier Martinez Canillas <javierm@redhat.com> - 8.40-43
+- grubby-bls: always escape the delimiter character used in sed commands
+- grubby-bls: add a --no-etc-grub-update option
+
+* Wed Apr 29 2020 Javier Martinez Canillas <javierm@redhat.com> - 8.40-42
+- grubby-bls: fix corner case when a kernel param value contains a '='
+- grubby-bls: update man page to match options in current wrapper script
+
+* Mon Mar 30 2020 Javier Martinez Canillas <javierm@redhat.com> - 8.40-41
+- Make grubby to also update GRUB_CMDLINE_LINUX in /etc/default/grub
+  Related: rhbz#1287854
+
+* Mon Feb 10 2020 Javier Martinez Canillas <javierm@redhat.com> - 8.40-40
+- Fix FTBFS
+  Resolves: rhbz#1799496
+- Fix wrong S-o-B tag in patch
+- Fix warning about using unversioned Obsoletes
+
+* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 8.40-39
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
+
+* Fri Nov 29 2019 Javier Martinez Canillas <javierm@redhat.com> - 8.40-38
+- grubby-bls: don't update grubenv when generating grub.cfg for ppc64le
+  Related: rhbz#1726514
+
+* Thu Nov 28 2019 Javier Martinez Canillas <javierm@redhat.com> - 8.40-37
+- grubby-bls: don't print rpm-sort error messages
+  Resolves: rhbz#1731924
+- grubby-bls: remove -o option and support -c for ppc64le grub config
+  Resolves: rhbz#1758598
+- grubby-bls: fix logic to check if the kernelopts var is defined in a BLS
+  Resolves: rhbz#1726514
+
+* Tue Aug 06 2019 Yuval Turgeman <yturgema@redhat.com> - 8.40-36
+- grubby-bls: strip only /boot from paths
+
+* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 8.40-35
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
+
+* Mon Jun 17 2019 Javier Martinez Canillas <javierm@redhat.com> - 8.40-34
+- Add a kernel-install plugin to execute hook scripts in /etc/kernel/
+  Resolves: rhbz#1696202
+
+* Mon Jun 10 22:13:19 CET 2019 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 8.40-33
+- Rebuild for RPM 4.15
+
+* Mon Jun 10 15:42:02 CET 2019 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 8.40-32
+- Rebuild for RPM 4.15
+
+* Fri May 03 2019 Javier Martinez Canillas <javierm@redhat.com> - 8.40-31
+- Use mountpoint command to check whether /boot is a mount point
+  Resolves: rhbz#1706091
+
+* Thu Mar 21 2019 Javier Martinez Canillas <javierm@redhat.com> - 8.40-30
+- grubby-bls: fix --add-kernel not working when using the --args option
+  Resolves: rhbz#1691004
+
+* Mon Mar 11 2019 Javier Martinez Canillas <javierm@redhat.com> - 8.40-29
+- Only switch to BLS config for s390x / zipl
+  Related: rhbz#1652806
+
+* Fri Mar 01 2019 Javier Martinez Canillas <javierm@redhat.com> - 8.40-28
+- grubby-bls: make --update-kernel ALL to update kernelopts var in grubenv
+
+* Thu Feb 14 2019 Javier Martinez Canillas <javierm@redhat.com> - 8.40-27
+- grubby-bls: error if args or remove-args is used without update-kernel
+
+* Tue Feb 05 2019 Javier Martinez Canillas <javierm@redhat.com> - 8.40-26
+- Fix GCC warnings about possible string truncations and buffer overflows
+- grubby-bls: unset default entry if is the one being removed
+- grubby-bls: show absolute path when printing error about incorrect param
+
+* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 8.40-25
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
+
+* Mon Jan 14 2019 Javier Martinez Canillas <javierm@redhat.com> - 8.40-24
+- Correctly set LDFLAGS to include hardened flags (pjones)
+  Related: rhbz#1654936
+- grubby-bls: expand all variables in options field when updating it
+  Resolves: rhbz#1660700
+
+* Tue Dec 11 2018 Javier Martinez Canillas <javierm@redhat.com> - 8.40-23
+- grubby-bls: lookup default entry by either id or title on grub2
+  Related: rhbz#1654936
+
+* Fri Nov 30 2018 Javier Martinez Canillas <javierm@redhat.com> - 8.40-22
+- grubby-bls: also print the absolute path in the --default-kernel option
+  Resolves: rhbz#1649778
+- grubby-bls: allow to specify the same kernel param multiple times
+  Resolves: rhbz#1652486
+- grubby-bls: expand kernel options if these are environment variables
+  Resolves: rhbz#1649785
+- grubby-bls: always generate the BLS snippets when adding new entries
+  Resolves: rhbz#1653365
+- Improve man page for --info option (jstodola)
+  Resolves: rhbz#1651672
+- Make the old grubby take precedence over grubby-bls if is installed
+  Related: rhbz#165484
+
+* Wed Nov 21 2018 Javier Martinez Canillas <javierm@redhat.com> - 8.40-21
+- installkernel-bls: remove unnecessary check for GRUB_ENABLE_BLSCFG=true
+  Resolves: rhbz#1647721
+- grubby-bls: use title field instead of version for zipl default entry
+  Related: rhbz#1645200
+- grubby-bls: print the absolute kernel and initramfs images paths
+  Resolves: rhbz#1649778
+- grubby-bls: make info print the root parameter if is present in cmdline
+  Resolves: rhbz#1649791
+
+* Tue Nov 13 2018 Javier Martinez Canillas <javierm@redhat.com> - 8.40-20
+- Switch to a BLS configuration on %%post
+
+* Tue Nov 06 2018 Javier Martinez Canillas <javierm@redhat.com> - 8.40-19
+- Make the temporary config wrapper be what "grubby" contains, and put
+  traditional grubby in grubby-deprecated (pjones)
+- Re-enable debuginfo generation (pjones)
+  Related: rhbz#1619344
+- Install installkernel-bls here as well, not just in the grub2 package,
+  since s390x doesn't have grubby packages (pjones)
+  Related: rhbz#1619344
+- Make grubby-bls execute grub2-mkconfig on ppc64
+  Resolves: rhbz#1636039
+- grubby-bls should only check if kernel exists and not if was installed
+  Resolves: rhbz#1634740
+- Use ! instead of , as sed delimiter in grubby-bls script
+  Resolves: rhbz#1634744
+- Print information about the entry set as default
+  Resolves: rhbz#1636180
+- grubby-bls: make "id" be the filename, and include it in --info=ALL (pjones)
+  Related: rhbz#1638103
+- grubby-bls: Make grubby-bls sort everything the same way grub2 does (pjones)
+  Resolves: rhbz#1638103
+- grubby-bls: Consistently use the filename as the bls id
+  Related: rhbz#1638103
+- grubby-bls: check if entry exists before attempting to print its info
+  Resolves: rhbz#1634712
+- grubby-bls: make a copy of the cmdline if is modified for an entry
+  Resolves: rhbz#1629054
+- grubby-bls: escape delimiter character before replacing the options field
+  Resolves: rhbz#1640017
+- grubby-bls: grubby-bls: use id instead of title to get the default entry
+  Resolves: rhbz#1638103
+- grubby-bls: use ~debug instead of -debug as suffix to sort correctly
+  Related: rhbz#1638103
+- grubby-bls: allow to add many BLS entries for the same kernel image
+  Resolves: rhbz#1634752
+- grubby-bls: fix --default-* options for s390x
+  Resolves: rhbz#1644608
+- grubby-bls: only compare using relative paths if /boot is a mount point
+  Resolves: rhbz#1642078
+
+* Fri Aug 10 2018 Javier Martinez Canillas <javierm@redhat.com> - 8.40-18
+- Make installkernel to use kernel-install scripts on BLS configuration
+
+* Tue Jul 24 2018 Javier Martinez Canillas <javierm@redhat.com> - 8.40-17
+- Fix grubby wrapper paths
+  Resolves: rhbz#1607981
+
+* Tue Jul 24 2018 Peter Jones <pjones@redhat.com> - 8.40-16
+- Fix permissions on /usr/sbin/grubby
+
+* Fri Jul 13 2018 Javier Martinez Canillas <javierm@redhat.com> - 8.40-15
+- Add a grubby-bls package that conflicts with grubby
+
+* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 8.40-14
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
+
+* Thu Jun 14 2018 Peter Jones <pjones@redhat.com> - 8.40-13
+- Use standard Fedora linker flags (rhbz#1543502) (rdossant)
+- Switch zipl config to BLS configuration on %%postun for s390x (javierm)
+
+* Tue Apr 10 2018 Javier Martinez Canillas <javierm@redhat.com> - 8.40-12
+- Use .rpmsave as backup suffix when switching to BLS configuration
+
+* Fri Apr 06 2018 Javier Martinez Canillas <javierm@redhat.com> - 8.40-11
+- Switch grub2 config to BLS configuration on %%postun
+
+* Sat Mar 03 2018 Nathaniel McCallum <npmccallum@redhat.com> - 8.40-10
+- Add support for /boot on btrfs subvolumes
+
+* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 8.40-9
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
+
+* Wed Jan 24 2018 Peter Robinson <pbrobinson@fedoraproject.org> 8.40-8
+- Drop u-boot uImage generation on ARMv7
+- Minor cleanups
+
+* Tue Sep 12 2017 Peter Jones <pjones@redhat.com> - 8.40-7
+- Explicitly require grub2-tools on platforms that need grub2-editenv
+- Minor packaging cleanups
+
+* Wed Aug 02 2017 Fedora Release Engineering <releng@fedoraproject.org> - 8.40-6
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
+
+* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 8.40-5
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
+
+* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 8.40-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
+
+* Wed Feb 03 2016 Fedora Release Engineering <releng@fedoraproject.org> - 8.40-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
+
+* Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 8.40-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
+
+* Wed Apr 15 2015 Peter Jones <pjones@redhat.com> - 8.40-1
+- Update to 8.40
+- More work on the thing that went to testing in 8.39
+  Resolves: rhbz#1211887
+
+* Tue Apr 14 2015 Peter Jones <pjones@redhat.com> - 8.39-1
+- Update to 8.39
+- Fix title extraction with some config file types
+  Resolves: rhbz#1204353
+  Resolves: rhbz#1204888
+  Resolves: rhbz#1206943
+
+* Tue Apr 14 2015 Peter Jones <pjones@redhat.com> - 8.38-1
+- Update to 8.38
+- Fix title extraction with some config file types
+  Resolves: rhbz#1204353
+  Resolves: rhbz#1204888
+  Resolves: rhbz#1206943
+
+* Tue Mar 17 2015 Peter Jones <pjones@redhat.com> - 8.37-1
+- Update to 8.37
+- Fix test case from 8.35 on ppc64
+  Resolves: rhbz#1202876
+
+* Thu Nov 13 2014 Peter Jones <pjones@redhat.com> - 8.35-9
+- Disable "make check" on arm builds; right now the test suite is broken
+  there and raises false positives constantly.
+
+* Mon Oct 27 2014 Peter Jones <pjones@redhat.com> - 8.35-8
+- Treat kernel and kernel-core as identical in terms of --make-default
+  Resolves: rhbz#1141414
+
+* Thu Oct 16 2014 Peter Jones <pjones@redhat.com> - 8.35-7
+- Revert "debug" image creation for now
+  Resolves: rhbz#1153410
+- Fix minor quoting errors in dtbdir code
+  Resolves: rhbz#1088933
+
+* Wed Oct 15 2014 Peter Jones <pjones@redhat.com> - 8.35-6
+- Update grubby to support device tree options for arm.  Again.
+  Resolves: rhbz#1088933
+
+* Fri Sep 26 2014 Peter Jones <pjones@redhat.com> - 8.35-5
+- See if what people are seeing in 1141414 is actually 957681
+  Related: rhbz#957681
+  Related: rhbz#1141414
+
+* Sat Aug 16 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 8.35-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
+
+* Sat Jul 12 2014 Tom Callaway <spot@fedoraproject.org> - 8.35-3
+- fix license handling
+
+* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 8.35-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
+
+* Wed May 21 2014 Peter Jones <pjones@redhat.com> - 8.35-1
+- Fix a minor test case error that causes koji builds to fail.
+  Related: rhbz#1096358
+
+* Wed May 21 2014 Peter Jones <pjones@redhat.com> - 8.34-1
+- Make grub2 "--copy-default --add-kernel=foo --initrd=bar" work when default
+  has no initrd line.
+  Resolves: rhbz#1099627
+  Related: rhbz#1096358
+
+* Tue Apr 01 2014 Peter Jones <pjones@redhat.com> - 8.33-1
+- Fix --devtree test in new-kernel-pkg even harder (#1082318)
+
+* Mon Mar 31 2014 Peter Jones <pjones@redhat.com> - 8.32-1
+- Fix --devtree test in new-kernel-pkg (#1082318)
+- Fix aarch64 #define test.
+
+* Fri Mar 28 2014 Peter Jones <pjones@redhat.com> - 8.31-1
+- Update to 8.31
+- Fold in patches from Fedora and RHEL 7 trees
+
+* Mon Jan 20 2014 Lubomir Rintel <lkundrak@v3.sk> - 8.28-2
+- Fix extlinux default
+
+* Fri Aug 02 2013 Peter Jones <pjones@redhat.com> - 8.28-1
+- More work on grub's "saved_entry" system. 
+  Resolves: rhbz#768106
+  Resolves: rhbz#736188
+
+* Tue Jul 30 2013 Peter Jones <pjones@redhat.com> - 8.27-1
+- Make grubby understand grub's "saved_entry" system
+  Resolves: rhbz#768106
+  Resolves: rhbz#736188
+- BuildRequire grub2 on appropriate platforms, for the test suite.
+
+* 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
+