diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8173666
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+SOURCES/grub-2.02~beta2.tar.xz
+SOURCES/unifont-5.1.20080820.pcf.gz
diff --git a/.grub2.metadata b/.grub2.metadata
new file mode 100644
index 0000000..a7bf121
--- /dev/null
+++ b/.grub2.metadata
@@ -0,0 +1,2 @@
+1bf580f1e8bce4909a7ac7ca485cee02b00ed383 SOURCES/grub-2.02~beta2.tar.xz
+87f8600ba24e521b5d20bdf6c4b71af8ae861e3a SOURCES/unifont-5.1.20080820.pcf.gz
diff --git a/SOURCES/0001-fix-EFI-detection-on-Windows.patch b/SOURCES/0001-fix-EFI-detection-on-Windows.patch
new file mode 100644
index 0000000..e2f5d18
--- /dev/null
+++ b/SOURCES/0001-fix-EFI-detection-on-Windows.patch
@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Wed, 25 Dec 2013 22:36:28 +0400
+Subject: [PATCH] fix EFI detection on Windows
+
+We are on legacy BIOS if GetFirmwareEnvironmentVariable fails (returns
+zero) *and* extended error information is ERROR_INVALID_FUNCTION.
+
+Cf. http://msdn.microsoft.com/en-us/library/windows/desktop/ms724325%28v=vs.85%29.aspx
+---
+ grub-core/osdep/windows/platform.c | 2 +-
+ ChangeLog                          | 5 +++++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/osdep/windows/platform.c b/grub-core/osdep/windows/platform.c
+index f2b9d714329..d217efe1704 100644
+--- a/grub-core/osdep/windows/platform.c
++++ b/grub-core/osdep/windows/platform.c
+@@ -100,7 +100,7 @@ get_platform (void)
+ 
+   if (!func_GetFirmwareEnvironmentVariableW (L"BootOrder", GRUB_EFI_GLOBAL_VARIABLE_GUID_WINDOWS_STR,
+ 					     buffer, sizeof (buffer))
+-      && GetLastError () != ERROR_INVALID_FUNCTION)
++      && GetLastError () == ERROR_INVALID_FUNCTION)
+     {
+       platform = PLAT_BIOS;
+       return;
+diff --git a/ChangeLog b/ChangeLog
+index 41bcebfb321..21ec1c77c57 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2013-12-25  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* grub-core/osdep/windows/platform.c (get_platform): Fix EFI
++	detection.
++
+ 2013-12-24  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* configure.ac: Set version to 2.02~beta2.
diff --git a/SOURCES/0002-grub-core-kern-arm-cache_armv6.S-Remove-.arch-direct.patch b/SOURCES/0002-grub-core-kern-arm-cache_armv6.S-Remove-.arch-direct.patch
new file mode 100644
index 0000000..bb7a145
--- /dev/null
+++ b/SOURCES/0002-grub-core-kern-arm-cache_armv6.S-Remove-.arch-direct.patch
@@ -0,0 +1,39 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Wed, 25 Dec 2013 23:31:42 +0100
+Subject: [PATCH] * grub-core/kern/arm/cache_armv6.S: Remove .arch directive.
+
+	As these functions are used on pre-ARMv6 CPUs as well we don't want
+	to make assembler assume that architecture is higher than default one.
+---
+ grub-core/kern/arm/cache_armv6.S | 1 -
+ ChangeLog                        | 7 +++++++
+ 2 files changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/arm/cache_armv6.S b/grub-core/kern/arm/cache_armv6.S
+index 39da1dfc606..dfaded0eb30 100644
+--- a/grub-core/kern/arm/cache_armv6.S
++++ b/grub-core/kern/arm/cache_armv6.S
+@@ -22,7 +22,6 @@
+ 	.text
+ 	.syntax	unified
+ 	.arm
+-	.arch	armv6
+ 
+ # define DMB	mcr	p15, 0, r0, c7, c10, 5
+ # define DSB	mcr	p15, 0, r0, c7, c10, 4
+diff --git a/ChangeLog b/ChangeLog
+index 21ec1c77c57..153bc43c1c5 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,10 @@
++2013-12-25  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/kern/arm/cache_armv6.S: Remove .arch directive.
++
++	As these functions are used on pre-ARMv6 CPUs as well we don't want
++	to make assembler assume that architecture is higher than default one.
++
+ 2013-12-25  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* grub-core/osdep/windows/platform.c (get_platform): Fix EFI
diff --git a/SOURCES/0003-INSTALL-Cross-compiling-the-GRUB-Fix-some-spelling-m.patch b/SOURCES/0003-INSTALL-Cross-compiling-the-GRUB-Fix-some-spelling-m.patch
new file mode 100644
index 0000000..e4d3972
--- /dev/null
+++ b/SOURCES/0003-INSTALL-Cross-compiling-the-GRUB-Fix-some-spelling-m.patch
@@ -0,0 +1,85 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Fri, 27 Dec 2013 03:03:32 +0000
+Subject: [PATCH] * INSTALL (Cross-compiling the GRUB): Fix some spelling
+ mistakes. * docs/grub.texi (Getting the source code): Likewise.
+
+---
+ ChangeLog          |  5 +++++
+ INSTALL            | 10 +++++-----
+ docs/grub-dev.texi |  8 ++++----
+ 3 files changed, 14 insertions(+), 9 deletions(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index 153bc43c1c5..bbb0f31532d 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2013-12-27  Colin Watson  <cjwatson@ubuntu.com>
++
++	* INSTALL (Cross-compiling the GRUB): Fix some spelling mistakes.
++	* docs/grub.texi (Getting the source code): Likewise.
++
+ 2013-12-25  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/kern/arm/cache_armv6.S: Remove .arch directive.
+diff --git a/INSTALL b/INSTALL
+index afc957ca997..db12530dff3 100644
+--- a/INSTALL
++++ b/INSTALL
+@@ -140,7 +140,7 @@ If build and host are different make check isn't available.
+ If build and host are different man pages are not generated.
+ 
+ As an example imagine you have a build system running on FreeBSD on sparc
+-which prepares packages for developpers running amd64 GNU/Linux laptop and
++which prepares packages for developers running amd64 GNU/Linux laptop and
+ they need to make images for ARM board running U-boot. In this case:
+ 
+ build=sparc64-freebsd
+@@ -149,7 +149,7 @@ target=arm-uboot
+ 
+ For this example the configure line might look like (more details below)
+ (some options are optional and included here for completeness but some rarely
+-used options are omited):
++used options are omitted):
+ 
+ ./configure BUILD_CC=gcc BUILD_FREETYPE=freetype-config --host=amd64-linux-gnu
+ CC=amd64-linux-gnu-gcc CFLAGS="-g -O2" FREETYPE=amd64-linux-gnu-freetype-config
+@@ -196,9 +196,9 @@ corresponding platform are not needed for the platform in question.
+     11. TARGET_RANLIB= for ranlib for target.
+ 
+   - Additionally for emu, for host and target.
+-    1. SDL is looked for in stadard linker directories (-lSDL) (optional)
+-    2. libpciaccess is looked for in stadard linker directories (-lpciaccess) (optional)
+-    3. libusb is looked for in stadard linker directories (-lusb) (optional)
++    1. SDL is looked for in standard linker directories (-lSDL) (optional)
++    2. libpciaccess is looked for in standard linker directories (-lpciaccess) (optional)
++    3. libusb is looked for in standard linker directories (-lusb) (optional)
+ 
+   - Platform-agnostic tools and data.
+     1. make is the tool you execute after ./configure.
+diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi
+index c796850522a..7c6244cdb71 100644
+--- a/docs/grub-dev.texi
++++ b/docs/grub-dev.texi
+@@ -108,16 +108,16 @@ The branches available are:
+ 
+ @table @samp
+ @item master
+-      Main developpement branch.
++      Main development branch.
+ @item grub-legacy
+       GRUB 0.97 codebase. Kept for reference and legal reasons
+ @item multiboot
+       Multiboot specfication
+ @item multiboot2
+       Multiboot2 specfication
+-@item developper branches
+-      Prefixed with developper name. Every developper of a team manages his own branches.
+-      Developper branches do not need changelog entries.
++@item developer branches
++      Prefixed with developer name. Every developer of a team manages his own branches.
++      Developer branches do not need changelog entries.
+ @end table
+ 
+ Once you have used @kbd{git clone} to fetch an initial copy of a branch, you
diff --git a/SOURCES/0004-NEWS-First-draft-of-2.02-entry.patch b/SOURCES/0004-NEWS-First-draft-of-2.02-entry.patch
new file mode 100644
index 0000000..1141167
--- /dev/null
+++ b/SOURCES/0004-NEWS-First-draft-of-2.02-entry.patch
@@ -0,0 +1,149 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Fri, 27 Dec 2013 03:05:38 +0000
+Subject: [PATCH] * NEWS: First draft of 2.02 entry.
+
+---
+ ChangeLog |   4 +++
+ NEWS      | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 123 insertions(+)
+
+diff --git a/ChangeLog b/ChangeLog
+index bbb0f31532d..82dc61d24c9 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2013-12-27  Colin Watson  <cjwatson@ubuntu.com>
++
++	* NEWS: First draft of 2.02 entry.
++
+ 2013-12-27  Colin Watson  <cjwatson@ubuntu.com>
+ 
+ 	* INSTALL (Cross-compiling the GRUB): Fix some spelling mistakes.
+diff --git a/NEWS b/NEWS
+index 4bb5f98010d..577d9fd7323 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,3 +1,122 @@
++New in 2.02:
++
++* New/improved filesystem and disk support:
++  * Big-endian UFS1.
++  * Experimental 64-bit ext2 support.
++  * Various fixes for non-512-byte sector devices.
++  * New `proc' filesystem framework, used by LUKS disks.
++  * Fix DM-RAID partition handling.
++  * New `nativedisk' command to switch from firmware to native disk drivers.
++  * Compressed HFS+.
++  * DragonFly BSD labels.
++  * CBFS (coreboot).
++  * Handle partitioned LVM properly.
++  * Use LVM UUIDs whenever possible.
++  * GPT PReP.
++  * New `progress' module that shows progress information while reading
++    files.
++
++* New/improved terminal and video support:
++  * Monochrome text (matching `hercules' in GRUB Legacy).
++  * Morse code output using system speaker.
++  * `spkmodem' output (simple data protocol using system speaker).
++  * Handle Japanese special keys.
++  * coreboot framebuffer.
++  * Serial on ARC.
++  * Native vt100 handling for grub-emu, replacing the use of the curses
++    library.
++  * New gfxmenu options for terminal window positioning, theme background
++    image handling, and scrollbar padding, plus `item_pixmap_style' and
++    `highlight_overlay'.
++  * Support several more image types (paletted and greyscale).
++
++* Boot protocol improvements:
++  * Support Apple FAT binaries on non-Apple platforms.
++  * Improve FreeDOS direct loading support compatibility.
++  * Enable `linux16' on all x86 platforms, not just BIOS.
++  * New TrueCrypt ISO loader.
++
++* New/improved network support:
++  * New variables `net_default_*' containing properties of the default
++    interface.
++  * Autoload `http' and `tftp' modules if necessary.
++  * Improve TFTP robustness.
++  * Parse `nd' disk names in GRUB Legacy configuration files.
++  * Issue separate DNS queries for IPv4 and IPv6.
++
++* New/improved platform support:
++  * New `efifwsetup' and `lsefi' commands on EFI platforms.
++  * New `cmosclean', `cmosdump', and `cmosset' commands on platforms with
++    CMOS support.
++  * New `cbmemc', `coreboot_boottime', and `lscoreboot' commands on
++    coreboot.
++  * Improve opcode parsing in ACPI halt implementation.
++  * Use the TSC as a possible time source on i386-ieee1275.
++  * Merge PowerPC grub-mkrescue implementation with the common one.
++  * Support grub-mkrescue on i386-ieee1275, sparc64, bootinfo machines such
++    as pSeries, and mips-arc.
++  * Make grub-mkrescue better support Apple Intel Macs on CD.
++  * Enable GRUB Legacy configuration file parsing on EFI.
++  * Support halt for Loongson 2E.
++  * ARM U-Boot and EFI ports.
++  * Reorganise platform-dependent code in utilities to avoid #ifdef mess.
++  * AROS and Haiku support for userspace utilities.
++  * Xen PV port.
++  * Fix EFI stack alignment.
++  * ARM64 EFI port.
++  * On Linux, read partition start offsets from sysfs if possible.
++  * New grub-macbless utility, and better integration with Mac firmware in
++    grub-install.
++  * Support Yeeloong 3A.
++  * Add `cpuid --pae' option to detect Physical Address Extension on x86.
++
++* Security:
++  * Add optional facility to enforce that all files read by the core image
++    from disk have a valid detached digital signature.
++
++* Performance:
++  * Avoid costly division operations in many places.
++  * New boot time analysis framework (`./configure --enable-boot-time').
++  * Initialise USB ports in parallel.
++  * New `testspeed' command to test file read speed.
++
++* Scripting:
++  * New `eval' and `tr' commands.
++  * grub-script-check fails on scripts containing no commands.
++
++* Installation and other utility improvements:
++  * Add option to compress files on installation or image creation.
++  * Using grub-reboot no longer requires setting `GRUB_DEFAULT=saved'.
++  * Support probing EFI System Partition (requires os-prober >= 1.58).
++  * Fix inconsistent use of `GRUB_CRYPTODISK_ENABLE' and
++    `GRUB_ENABLE_CRYPTODISK'; the latter is now used consistently.
++  * grub-mount handles symbolic links to directories.
++  * Support disabling submenus with `GRUB_DISABLE_SUBMENU' configuration key
++    for grub-mkconfig.
++  * grub-install, grub-mknetdir, grub-mkrescue, and grub-mkstandalone
++    rewritten in C.  They should now work in supported non-Unix-like
++    environments.
++  * Reorganise timeout handling using new `timeout_style' environment
++    variable and `GRUB_TIMEOUT_STYLE' configuration key for grub-mkconfig.
++    Menu hotkeys pressed during a hidden timeout now boot the corresponding
++    menu entry immediately.
++  * New `file' command and grub-file utility to check file types.
++  * New syslinux configuration file parser.
++
++* Build system:
++  * Remove all uses of nested functions; GRUB no longer requires an
++    executable stack.
++  * Fix documentation build with Texinfo >= 5.1.
++  * More robust and documented cross-compiling support.
++  * Partial clang support for some platforms.
++  * Eliminate the use of AutoGen.  This allowed some performance
++    improvements to the build system.
++  * Fix build with FreeType >= 2.5.1.
++  * Make gentpl.py compatible with Python 3.  It now requires at least
++    Python 2.6.
++
++* Revision control moved to git.
++
+ New in 2.00:
+ 
+ * Appearance:
diff --git a/SOURCES/0005-Merge-branch-master-of-git.sv.gnu.org-srv-git-grub.patch b/SOURCES/0005-Merge-branch-master-of-git.sv.gnu.org-srv-git-grub.patch
new file mode 100644
index 0000000..6fd2f6f
--- /dev/null
+++ b/SOURCES/0005-Merge-branch-master-of-git.sv.gnu.org-srv-git-grub.patch
@@ -0,0 +1,45 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 27 Dec 2013 11:20:37 +0100
+Subject: [PATCH] Merge branch 'master' of git.sv.gnu.org:/srv/git/grub
+
+Conflicts:
+    ChangeLog
+---
+ ChangeLog | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index 82dc61d24c9..da3c2dfdf0a 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,19 +1,19 @@
+-2013-12-27  Colin Watson  <cjwatson@ubuntu.com>
+-
+-	* NEWS: First draft of 2.02 entry.
+-
+-2013-12-27  Colin Watson  <cjwatson@ubuntu.com>
+-
+-	* INSTALL (Cross-compiling the GRUB): Fix some spelling mistakes.
+-	* docs/grub.texi (Getting the source code): Likewise.
+-
+-2013-12-25  Vladimir Serbinenko  <phcoder@gmail.com>
++2013-12-27  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/kern/arm/cache_armv6.S: Remove .arch directive.
+ 
+ 	As these functions are used on pre-ARMv6 CPUs as well we don't want
+ 	to make assembler assume that architecture is higher than default one.
+ 
++2013-12-27  Colin Watson  <cjwatson@ubuntu.com>
++
++	* NEWS: First draft of 2.02 entry.
++
++2013-12-27  Colin Watson  <cjwatson@ubuntu.com>
++
++	* INSTALL (Cross-compiling the GRUB): Fix some spelling mistakes.
++	* docs/grub.texi (Getting the source code): Likewise.
++
+ 2013-12-25  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* grub-core/osdep/windows/platform.c (get_platform): Fix EFI
diff --git a/SOURCES/0006-NEWS-The-cmosclean-command-in-fact-dates-back-to-1.9.patch b/SOURCES/0006-NEWS-The-cmosclean-command-in-fact-dates-back-to-1.9.patch
new file mode 100644
index 0000000..01dc202
--- /dev/null
+++ b/SOURCES/0006-NEWS-The-cmosclean-command-in-fact-dates-back-to-1.9.patch
@@ -0,0 +1,38 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Sat, 28 Dec 2013 02:20:27 +0000
+Subject: [PATCH] * NEWS: The cmosclean command in fact dates back to 1.99.
+ Remove mention of it from 2.02.
+
+---
+ ChangeLog | 5 +++++
+ NEWS      | 3 +--
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index da3c2dfdf0a..c33856eab8d 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2013-12-28  Colin Watson  <cjwatson@ubuntu.com>
++
++	* NEWS: The cmosclean command in fact dates back to 1.99.  Remove
++	mention of it from 2.02.
++
+ 2013-12-27  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/kern/arm/cache_armv6.S: Remove .arch directive.
+diff --git a/NEWS b/NEWS
+index 577d9fd7323..b74c05f637f 100644
+--- a/NEWS
++++ b/NEWS
+@@ -46,8 +46,7 @@ New in 2.02:
+ 
+ * New/improved platform support:
+   * New `efifwsetup' and `lsefi' commands on EFI platforms.
+-  * New `cmosclean', `cmosdump', and `cmosset' commands on platforms with
+-    CMOS support.
++  * New `cmosdump' and `cmosset' commands on platforms with CMOS support.
+   * New `cbmemc', `coreboot_boottime', and `lscoreboot' commands on
+     coreboot.
+   * Improve opcode parsing in ACPI halt implementation.
diff --git a/SOURCES/0007-remove-unused-error.h-from-kern-emu-misc.c.patch b/SOURCES/0007-remove-unused-error.h-from-kern-emu-misc.c.patch
new file mode 100644
index 0000000..36b2004
--- /dev/null
+++ b/SOURCES/0007-remove-unused-error.h-from-kern-emu-misc.c.patch
@@ -0,0 +1,36 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Sat, 28 Dec 2013 09:01:20 +0400
+Subject: [PATCH] remove unused error.h from kern/emu/misc.c
+
+Fixes compilation on mingw32, where include is apparently missing.
+---
+ grub-core/kern/emu/misc.c | 1 -
+ ChangeLog                 | 5 +++++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c
+index 43471b4efe9..bb606da2803 100644
+--- a/grub-core/kern/emu/misc.c
++++ b/grub-core/kern/emu/misc.c
+@@ -20,7 +20,6 @@
+ #include <config.h>
+ 
+ #include <errno.h>
+-#include <error.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <stdint.h>
+diff --git a/ChangeLog b/ChangeLog
+index c33856eab8d..0401f6154f8 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2013-12-28  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* grub-core/kern/emu/misc.c: Remove unused error.h; fixes compilation
++	on mingw.
++
+ 2013-12-28  Colin Watson  <cjwatson@ubuntu.com>
+ 
+ 	* NEWS: The cmosclean command in fact dates back to 1.99.  Remove
diff --git a/SOURCES/0008-Don-t-abort-on-unavailable-coreboot-tables-if-not-ru.patch b/SOURCES/0008-Don-t-abort-on-unavailable-coreboot-tables-if-not-ru.patch
new file mode 100644
index 0000000..c900a62
--- /dev/null
+++ b/SOURCES/0008-Don-t-abort-on-unavailable-coreboot-tables-if-not-ru.patch
@@ -0,0 +1,67 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Sat, 28 Dec 2013 17:25:14 +0100
+Subject: [PATCH] Don't abort() on unavailable coreboot tables if not running
+ on coreboot.
+
+---
+ grub-core/kern/i386/coreboot/cbtable.c | 2 +-
+ grub-core/kern/i386/coreboot/init.c    | 5 +++++
+ ChangeLog                              | 4 ++++
+ 3 files changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/i386/coreboot/cbtable.c b/grub-core/kern/i386/coreboot/cbtable.c
+index e3bb7b2e09d..1669bc0ca23 100644
+--- a/grub-core/kern/i386/coreboot/cbtable.c
++++ b/grub-core/kern/i386/coreboot/cbtable.c
+@@ -55,7 +55,7 @@ grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t,
+     if (check_signature (table_header))
+       goto signature_found;
+ 
+-  grub_fatal ("Could not find coreboot table\n");
++  return 0;
+ 
+ signature_found:
+ 
+diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c
+index 6b150b47d88..3314f027fec 100644
+--- a/grub-core/kern/i386/coreboot/init.c
++++ b/grub-core/kern/i386/coreboot/init.c
+@@ -51,6 +51,7 @@ grub_exit (void)
+ 
+ grub_addr_t grub_modbase = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR;
+ static grub_uint64_t modend;
++static int have_memory = 0;
+ 
+ /* Helper for grub_machine_init.  */
+ static int
+@@ -82,6 +83,8 @@ heap_init (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
+ 
+   grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) (end - begin));
+ 
++  have_memory = 1;
++
+   return 0;
+ }
+ 
+@@ -97,6 +100,8 @@ grub_machine_init (void)
+   grub_vga_text_init ();
+ 
+   grub_machine_mmap_iterate (heap_init, NULL);
++  if (!have_memory)
++    grub_fatal ("No memory found");
+ 
+   grub_video_coreboot_fb_late_init ();
+ 
+diff --git a/ChangeLog b/ChangeLog
+index 0401f6154f8..ed6d77cc8ea 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2013-12-28  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	Don't abort() on unavailable coreboot tables if not running on coreboot.
++
+ 2013-12-28  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* grub-core/kern/emu/misc.c: Remove unused error.h; fixes compilation
diff --git a/SOURCES/0009-NEWS-Add-few-missing-entries.-Correct-existing-ones.patch b/SOURCES/0009-NEWS-Add-few-missing-entries.-Correct-existing-ones.patch
new file mode 100644
index 0000000..6d567b4
--- /dev/null
+++ b/SOURCES/0009-NEWS-Add-few-missing-entries.-Correct-existing-ones.patch
@@ -0,0 +1,117 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Mon, 30 Dec 2013 06:49:15 +0100
+Subject: [PATCH] * NEWS: Add few missing entries. Correct existing ones.
+
+---
+ ChangeLog |  4 ++++
+ NEWS      | 27 ++++++++++++++++++++++-----
+ 2 files changed, 26 insertions(+), 5 deletions(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index ed6d77cc8ea..db843006df9 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2013-12-30  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* NEWS: Add few missing entries. Correct existing ones.
++
+ 2013-12-28  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	Don't abort() on unavailable coreboot tables if not running on coreboot.
+diff --git a/NEWS b/NEWS
+index b74c05f637f..49a2459b6a0 100644
+--- a/NEWS
++++ b/NEWS
+@@ -35,6 +35,8 @@ New in 2.02:
+   * Improve FreeDOS direct loading support compatibility.
+   * Enable `linux16' on all x86 platforms, not just BIOS.
+   * New TrueCrypt ISO loader.
++  * multiboot2 boot-services EFI specification.
++  * multiboot2 full-file specfication.
+ 
+ * New/improved network support:
+   * New variables `net_default_*' containing properties of the default
+@@ -44,11 +46,17 @@ New in 2.02:
+   * Parse `nd' disk names in GRUB Legacy configuration files.
+   * Issue separate DNS queries for IPv4 and IPv6.
+ 
++* Coreboot improvements:
++  * CBFS support both in on-disk images (loopback) and flash.
++  * Ability to launch another payload from flash or disk
++  * Coreboot framebuffer
++  * CBMEMC support (both logging and inspecting logs)
++  * Inspecting coreboot timestamps.
++  * Inspecting coreboot tables.
++
+ * New/improved platform support:
+   * New `efifwsetup' and `lsefi' commands on EFI platforms.
+   * New `cmosdump' and `cmosset' commands on platforms with CMOS support.
+-  * New `cbmemc', `coreboot_boottime', and `lscoreboot' commands on
+-    coreboot.
+   * Improve opcode parsing in ACPI halt implementation.
+   * Use the TSC as a possible time source on i386-ieee1275.
+   * Merge PowerPC grub-mkrescue implementation with the common one.
+@@ -68,6 +76,7 @@ New in 2.02:
+     grub-install.
+   * Support Yeeloong 3A.
+   * Add `cpuid --pae' option to detect Physical Address Extension on x86.
++  * Support for USB debug dongles.
+ 
+ * Security:
+   * Add optional facility to enforce that all files read by the core image
+@@ -78,6 +87,7 @@ New in 2.02:
+   * New boot time analysis framework (`./configure --enable-boot-time').
+   * Initialise USB ports in parallel.
+   * New `testspeed' command to test file read speed.
++  * Speed-up gfxterm by storing intermediate results in more compact format.
+ 
+ * Scripting:
+   * New `eval' and `tr' commands.
+@@ -95,6 +105,7 @@ New in 2.02:
+   * grub-install, grub-mknetdir, grub-mkrescue, and grub-mkstandalone
+     rewritten in C.  They should now work in supported non-Unix-like
+     environments.
++  * Native mingw support, including ability to install on EFI under windows.
+   * Reorganise timeout handling using new `timeout_style' environment
+     variable and `GRUB_TIMEOUT_STYLE' configuration key for grub-mkconfig.
+     Menu hotkeys pressed during a hidden timeout now boot the corresponding
+@@ -107,12 +118,19 @@ New in 2.02:
+     executable stack.
+   * Fix documentation build with Texinfo >= 5.1.
+   * More robust and documented cross-compiling support.
+-  * Partial clang support for some platforms.
++  * Partial clang support for some platforms (experimental).
++  * Partial mingw64 x86_64-efi compile support (highly experimental).
++  * Partial mingw32 i386-* (other than already present i386-pc)
++    compile support (highly experimental).
+   * Eliminate the use of AutoGen.  This allowed some performance
+     improvements to the build system.
++  * Remove variable length arrays.
++  * OpenBSD compile and tools support (NetBSD and FreeBSD were already supported).
+   * Fix build with FreeType >= 2.5.1.
+   * Make gentpl.py compatible with Python 3.  It now requires at least
+     Python 2.6.
++  * modinfo.sh contains build information now.
++  * Added many new tests to improve robustness.
+ 
+ * Revision control moved to git.
+ 
+@@ -142,7 +160,6 @@ New in 2.00:
+   * IEEE1275 serial.
+   * EFI serial.
+   * Network stack for BIOS, IEEE1275, EMU and EFI, including TFTP, HTTP and DNS.
+-  * VBE on coreboot support.
+ 
+ * New filesystem, filters and disks formats:
+   * DVH partition map.
+@@ -166,7 +183,7 @@ New in 2.00:
+   * multidevice, mirrored and raidz(2,3) ZFS support.
+   * RAID LVM (internal RAIDing) support.
+   * ZFS crypto support.
+-  * ZLE and GZIP on ZFS support.
++  * ZLE, LZ4 and GZIP on ZFS support.
+   * Support ZFS up to 33.
+   * HFS string is now treated like mac-roman and not UTF-8
+   * HFS mtime support.
diff --git a/SOURCES/0010-strip-.eh_frame-section-from-arm64-efi-kernel.patch b/SOURCES/0010-strip-.eh_frame-section-from-arm64-efi-kernel.patch
new file mode 100644
index 0000000..39b57e0
--- /dev/null
+++ b/SOURCES/0010-strip-.eh_frame-section-from-arm64-efi-kernel.patch
@@ -0,0 +1,36 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Mon, 30 Dec 2013 12:56:19 +0000
+Subject: [PATCH] strip .eh_frame section from arm64-efi kernel
+
+Fixes grub-mkimage error "relocation 0x105 is not implemented yet."
+---
+ grub-core/Makefile.core.def | 2 +-
+ ChangeLog                   | 4 ++++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index c916246de27..42443bc00b9 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -66,7 +66,7 @@ kernel = {
+   arm_efi_stripflags       = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
+ 
+   arm64_efi_ldflags          = '-Wl,-r,-d';
+-  arm64_efi_stripflags       = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
++  arm64_efi_stripflags       = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame';
+ 
+   i386_pc_ldflags          = '$(TARGET_IMG_LDFLAGS)';
+   i386_pc_ldflags          = '$(TARGET_IMG_BASE_LDOPT),0x9000';
+diff --git a/ChangeLog b/ChangeLog
+index db843006df9..8c1ececa1ed 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2013-12-30  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* grub-core/Makefile.core.def: strip .eh_frame section for arm64-efi.
++
+ 2013-12-30  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* NEWS: Add few missing entries. Correct existing ones.
diff --git a/SOURCES/0011-use-grub-boot-aa64.efi-for-boot-images-on-AArch64.patch b/SOURCES/0011-use-grub-boot-aa64.efi-for-boot-images-on-AArch64.patch
new file mode 100644
index 0000000..ba4a9c9
--- /dev/null
+++ b/SOURCES/0011-use-grub-boot-aa64.efi-for-boot-images-on-AArch64.patch
@@ -0,0 +1,34 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Tue, 7 Jan 2014 10:38:54 +0400
+Subject: [PATCH] use {grub,boot}aa64.efi for boot images on AArch64
+
+According to UEFI 2.4 specification, default boot file name on AArch64
+is BOOTAA64.EFI (3.4.1.1 Removable Media Boot Behavior). Also set default
+GRUB image name to grubaa64.efi to match it.
+---
+ util/grub-install.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/util/grub-install.c b/util/grub-install.c
+index 8cfe0eaa2ef..4608b80fe05 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -1091,7 +1091,7 @@ main (int argc, char *argv[])
+ 	      efi_file = "BOOTARM.EFI";
+ 	      break;
+ 	    case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+-	      efi_file = "BOOTAARCH64.EFI";
++	      efi_file = "BOOTAA64.EFI";
+ 	      break;
+ 	    default:
+ 	      grub_util_error ("%s", _("You've found a bug"));
+@@ -1118,7 +1118,7 @@ main (int argc, char *argv[])
+ 	      efi_file = "grubarm.efi";
+ 	      break;
+ 	    case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+-	      efi_file = "grubarm64.efi";
++	      efi_file = "grubaa64.efi";
+ 	      break;
+ 	    default:
+ 	      efi_file = "grub.efi";
diff --git a/SOURCES/0012-fix-32-bit-compilation-on-MinGW-w64.patch b/SOURCES/0012-fix-32-bit-compilation-on-MinGW-w64.patch
new file mode 100644
index 0000000..56f0178
--- /dev/null
+++ b/SOURCES/0012-fix-32-bit-compilation-on-MinGW-w64.patch
@@ -0,0 +1,42 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Tue, 7 Jan 2014 18:43:02 +0400
+Subject: [PATCH] fix 32 bit compilation on MinGW-w64
+
+Use _FILE_OFFSET_BITS macro to distinguish between native MinGW and
+32 bit under MinGW-64. The latter does not require fseeko/ftello
+redefinition which it already does in case of _FILE_OFFSET_BITS=64.
+---
+ include/grub/osdep/hostfile_windows.h | 3 +++
+ ChangeLog                             | 5 +++++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/include/grub/osdep/hostfile_windows.h b/include/grub/osdep/hostfile_windows.h
+index 36615b2c451..79efcfa5084 100644
+--- a/include/grub/osdep/hostfile_windows.h
++++ b/include/grub/osdep/hostfile_windows.h
+@@ -69,8 +69,11 @@ enum grub_util_fd_open_flags_t
+ 
+ #if defined (__MINGW32__) && !defined (__MINGW64__)
+ 
++/* 32 bit on MinGW-64 already redefines them if _FILE_OFFSET_BITS=64 */
++#if !defined(_FILE_OFFSET_BITS)
+ #define fseeko fseeko64
+ #define ftello ftello64
++#endif
+ 
+ #endif
+ 
+diff --git a/ChangeLog b/ChangeLog
+index 8c1ececa1ed..e87f0a7a4a4 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-01-07  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* include/grub/osdep/hostfile_windows.h: Do not redefine fseeko/ftello
++	on MinGW-64 when compiling for 32 bits.
++
+ 2013-12-30  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* grub-core/Makefile.core.def: strip .eh_frame section for arm64-efi.
diff --git a/SOURCES/0013-Change-grub-mkrescue-to-use-bootaa64.efi-too.patch b/SOURCES/0013-Change-grub-mkrescue-to-use-bootaa64.efi-too.patch
new file mode 100644
index 0000000..53589b5
--- /dev/null
+++ b/SOURCES/0013-Change-grub-mkrescue-to-use-bootaa64.efi-too.patch
@@ -0,0 +1,39 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Tue, 7 Jan 2014 20:34:25 +0400
+Subject: [PATCH] Change grub-mkrescue to use bootaa64.efi too
+
+Also add ChangeLog entry for previous change.
+---
+ util/grub-mkrescue.c | 2 +-
+ ChangeLog            | 7 +++++++
+ 2 files changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c
+index 317879d0b50..0d03e55d20c 100644
+--- a/util/grub-mkrescue.c
++++ b/util/grub-mkrescue.c
+@@ -663,7 +663,7 @@ main (int argc, char *argv[])
+       make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_ARM_EFI, "arm-efi", imgname);
+       free (imgname);
+ 
+-      imgname = grub_util_path_concat (2, efidir_efi_boot, "bootaarch64.efi");
++      imgname = grub_util_path_concat (2, efidir_efi_boot, "bootaa64.efi");
+       make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_ARM64_EFI, "arm64-efi",
+ 			     imgname);
+       free (imgname);
+diff --git a/ChangeLog b/ChangeLog
+index e87f0a7a4a4..0b9fa05b2a0 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,10 @@
++2014-01-07  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* util/grub-install.c: Use bootaa64.efi instead of bootaarch64.efi on
++	arm64 to comply with EFI specification. Also use grubaa64.efi for
++	consistency.
++	* util/grub-mkrescue.c: Change to use bootaa64.efi too.
++
+ 2014-01-07  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* include/grub/osdep/hostfile_windows.h: Do not redefine fseeko/ftello
diff --git a/SOURCES/0014-arm64-set-correct-length-of-device-path-end-entry.patch b/SOURCES/0014-arm64-set-correct-length-of-device-path-end-entry.patch
new file mode 100644
index 0000000..39ed674
--- /dev/null
+++ b/SOURCES/0014-arm64-set-correct-length-of-device-path-end-entry.patch
@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Leif Lindholm <leif.lindholm@linaro.org>
+Date: Tue, 7 Jan 2014 17:52:50 +0000
+Subject: [PATCH] arm64: set correct length of device path end entry
+
+The length of the Device Path End entry in the grub_linux_boot()
+function was incorrectly set to 0. This triggers an assert failure
+in debug builds of Tianocore.
+
+Set it to sizeof (grub_efi_device_path_t).
+---
+ grub-core/loader/arm64/linux.c | 2 +-
+ ChangeLog                      | 4 ++++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
+index 9d15aad625e..75ad871a81c 100644
+--- a/grub-core/loader/arm64/linux.c
++++ b/grub-core/loader/arm64/linux.c
+@@ -268,7 +268,7 @@ grub_linux_boot (void)
+ 
+   mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+   mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+-  mempath[1].header.length = 0;
++  mempath[1].header.length = sizeof (grub_efi_device_path_t);
+ 
+   b = grub_efi_system_table->boot_services;
+   status = b->load_image (0, grub_efi_image_handle,
+diff --git a/ChangeLog b/ChangeLog
+index 0b9fa05b2a0..4ec5517bded 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-01-07  Leif Lindholm <leif.lindholm@linaro.org>
++
++	* grub-core/loader/arm64/linux.c: correctly set device path end length.
++
+ 2014-01-07  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* util/grub-install.c: Use bootaa64.efi instead of bootaarch64.efi on
diff --git a/SOURCES/0015-Makefile.util.def-grub-macbless-Change-mansection-to.patch b/SOURCES/0015-Makefile.util.def-grub-macbless-Change-mansection-to.patch
new file mode 100644
index 0000000..90ad43c
--- /dev/null
+++ b/SOURCES/0015-Makefile.util.def-grub-macbless-Change-mansection-to.patch
@@ -0,0 +1,35 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Wed, 8 Jan 2014 11:05:20 +0000
+Subject: [PATCH] * Makefile.util.def (grub-macbless): Change mansection to 8.
+
+---
+ Makefile.util.def | 2 +-
+ ChangeLog         | 4 ++++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/Makefile.util.def b/Makefile.util.def
+index 985e76ca4e5..3c99be2b0ca 100644
+--- a/Makefile.util.def
++++ b/Makefile.util.def
+@@ -405,7 +405,7 @@ program = {
+ program = {
+   name = grub-macbless;
+   installdir = sbin;
+-  mansection = 1;
++  mansection = 8;
+   common = util/grub-macbless.c;
+   common = grub-core/osdep/init.c;
+   common = grub-core/kern/emu/argp_common.c;
+diff --git a/ChangeLog b/ChangeLog
+index 4ec5517bded..b445f121586 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-01-08  Colin Watson  <cjwatson@ubuntu.com>
++
++	* Makefile.util.def (grub-macbless): Change mansection to 8.
++
+ 2014-01-07  Leif Lindholm <leif.lindholm@linaro.org>
+ 
+ 	* grub-core/loader/arm64/linux.c: correctly set device path end length.
diff --git a/SOURCES/0016-add-part_apple-to-EFI-rescue-image-to-fix-missing-pr.patch b/SOURCES/0016-add-part_apple-to-EFI-rescue-image-to-fix-missing-pr.patch
new file mode 100644
index 0000000..863584c
--- /dev/null
+++ b/SOURCES/0016-add-part_apple-to-EFI-rescue-image-to-fix-missing-pr.patch
@@ -0,0 +1,44 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Sun, 12 Jan 2014 15:29:21 +0400
+Subject: [PATCH] add part_apple to EFI rescue image to fix missing prefix
+
+On Mac rescue image is booted from HFS+ partition, so bootpath looks like
+/ACPI(a0341d0,0)/PCI(1,1f)/ATAPI(0,0,0)/HD(3,5d1,ca3,0000000000000000,20,0)/EndEntire
+
+grub fails to find device for this path because it cannot scan partition
+table. The simplest fix is to add part_apple by default.
+---
+ util/grub-mkrescue.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c
+index 0d03e55d20c..34e0b7affb1 100644
+--- a/util/grub-mkrescue.c
++++ b/util/grub-mkrescue.c
+@@ -653,11 +653,15 @@ main (int argc, char *argv[])
+       make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_IA64_EFI, "ia64-efi", imgname);
+       free (imgname);
+ 
++      grub_install_push_module ("part_apple");
+       img64 = grub_util_path_concat (2, efidir_efi_boot, "bootx64.efi");
+       make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_X86_64_EFI, "x86_64-efi", img64);
++      grub_install_pop_module ();
+ 
++      grub_install_push_module ("part_apple");
+       img32 = grub_util_path_concat (2, efidir_efi_boot, "bootia32.efi");
+       make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_I386_EFI, "i386-efi", img32);
++      grub_install_pop_module ();
+ 
+       imgname = grub_util_path_concat (2, efidir_efi_boot, "bootarm.efi");
+       make_image_fwdisk_abs (GRUB_INSTALL_PLATFORM_ARM_EFI, "arm-efi", imgname);
+@@ -707,7 +711,9 @@ main (int argc, char *argv[])
+       free (efidir);
+     }
+ 
++  grub_install_push_module ("part_apple");
+   make_image_fwdisk (GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275, "powerpc-ieee1275", "powerpc-ieee1275/core.elf");
++  grub_install_pop_module ();
+ 
+   if (source_dirs[GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275])
+     {
diff --git a/SOURCES/0017-freebsd-hostdisk.c-is-only-ever-compiled-on-FreeBSD.patch b/SOURCES/0017-freebsd-hostdisk.c-is-only-ever-compiled-on-FreeBSD.patch
new file mode 100644
index 0000000..3f346cf
--- /dev/null
+++ b/SOURCES/0017-freebsd-hostdisk.c-is-only-ever-compiled-on-FreeBSD.patch
@@ -0,0 +1,45 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Fri, 17 Jan 2014 02:30:52 +0000
+Subject: [PATCH] freebsd/hostdisk.c is only ever compiled on FreeBSD
+
+* grub-core/osdep/freebsd/hostdisk.c (grub_util_fd_open): Remove
+redundant preprocessor conditional.
+---
+ grub-core/osdep/freebsd/hostdisk.c | 2 --
+ ChangeLog                          | 5 +++++
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/osdep/freebsd/hostdisk.c b/grub-core/osdep/freebsd/hostdisk.c
+index bd5fddb9150..eb202dcc831 100644
+--- a/grub-core/osdep/freebsd/hostdisk.c
++++ b/grub-core/osdep/freebsd/hostdisk.c
+@@ -108,7 +108,6 @@ grub_util_fd_open (const char *os_dev, int flags)
+ 
+   ret = open (os_dev, flags, S_IROTH | S_IRGRP | S_IRUSR | S_IWUSR);
+ 
+-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+   if (! (sysctl_oldflags & 0x10)
+       && sysctlbyname ("kern.geom.debugflags", NULL , 0, &sysctl_oldflags, sysctl_size))
+     {
+@@ -116,7 +115,6 @@ grub_util_fd_open (const char *os_dev, int flags)
+       close (ret);
+       return GRUB_UTIL_FD_INVALID;
+     }
+-#endif
+ 
+   return ret;
+ }
+diff --git a/ChangeLog b/ChangeLog
+index b445f121586..6613b4ee52b 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-01-17  Colin Watson  <cjwatson@debian.org>
++
++	* grub-core/osdep/freebsd/hostdisk.c (grub_util_fd_open): Remove
++	redundant preprocessor conditional.
++
+ 2014-01-08  Colin Watson  <cjwatson@ubuntu.com>
+ 
+ 	* Makefile.util.def (grub-macbless): Change mansection to 8.
diff --git a/SOURCES/0018-Prefer-more-portable-test-1-constructs.patch b/SOURCES/0018-Prefer-more-portable-test-1-constructs.patch
new file mode 100644
index 0000000..0fa41cd
--- /dev/null
+++ b/SOURCES/0018-Prefer-more-portable-test-1-constructs.patch
@@ -0,0 +1,106 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Fri, 17 Jan 2014 15:24:50 +0000
+Subject: [PATCH] Prefer more portable test(1) constructs
+
+* util/grub.d/00_header.in (make_timeout): Use && rather than test
+-a.
+* util/grub.d/10_windows.in: Likewise.
+* util/grub.d/10_netbsd.in (netbsd_load_fs_module): Use || rather
+than test -o.
+* util/grub.d/30_os-prober.in: Use && rather than test -a, and ||
+rather than test -o.
+---
+ ChangeLog                   | 12 +++++++++++-
+ util/grub.d/00_header.in    |  2 +-
+ util/grub.d/10_netbsd.in    |  2 +-
+ util/grub.d/10_windows.in   |  4 ++--
+ util/grub.d/30_os-prober.in |  4 ++--
+ 5 files changed, 17 insertions(+), 7 deletions(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index 6613b4ee52b..c8e95a6b98d 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,4 +1,14 @@
+-2014-01-17  Colin Watson  <cjwatson@debian.org>
++2014-01-17  Colin Watson  <cjwatson@ubuntu.com>
++
++	* util/grub.d/00_header.in (make_timeout): Use && rather than test
++	-a.
++	* util/grub.d/10_windows.in: Likewise.
++	* util/grub.d/10_netbsd.in (netbsd_load_fs_module): Use || rather
++	than test -o.
++	* util/grub.d/30_os-prober.in: Use && rather than test -a, and ||
++	rather than test -o.
++
++2014-01-17  Colin Watson  <cjwatson@ubuntu.com>
+ 
+ 	* grub-core/osdep/freebsd/hostdisk.c (grub_util_fd_open): Remove
+ 	redundant preprocessor conditional.
+diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
+index 0c82f231574..ce2ec819d8c 100644
+--- a/util/grub.d/00_header.in
++++ b/util/grub.d/00_header.in
+@@ -285,7 +285,7 @@ make_timeout ()
+     if [ "x${3}" != "x" ] ; then
+ 	timeout="${2}"
+ 	style="${3}"
+-    elif [ "x${1}" != "x" -a "x${1}" != "x0" ] ; then
++    elif [ "x${1}" != "x" ] && [ "x${1}" != "x0" ] ; then
+ 	# Handle the deprecated GRUB_HIDDEN_TIMEOUT scheme.
+ 	timeout="${1}"
+ 	if [ "x${2}" != "x0" ] ; then
+diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in
+index 29a0e41a9a5..9988a42bc50 100644
+--- a/util/grub.d/10_netbsd.in
++++ b/util/grub.d/10_netbsd.in
+@@ -69,7 +69,7 @@ netbsd_load_fs_module ()
+   kversion=$(zcat -f "${kernel}" | strings | sed -n -e '/^@(#)NetBSD/ { s/^@(#)NetBSD \([0-9\.]*\) .*$/\1/g ; p ; q ; }')
+   kmodule="/stand/${karch}/${kversion}/modules/${kmod}/${kmod}.kmod"
+ 
+-  if test -z "$karch" -o -z "$kversion" -o ! -f "${kmodule}"; then
++  if test -z "$karch" || test -z "$kversion" || test ! -f "${kmodule}"; then
+     return
+   fi
+ 
+diff --git a/util/grub.d/10_windows.in b/util/grub.d/10_windows.in
+index 9025914f6cf..48bd955464b 100644
+--- a/util/grub.d/10_windows.in
++++ b/util/grub.d/10_windows.in
+@@ -66,11 +66,11 @@ for drv in $drives ; do
+   osid=
+ 
+   # Check for Vista bootmgr.
+-  if [ -f "$dir"/bootmgr -a -f "$dir"/boot/bcd ] ; then
++  if [ -f "$dir"/bootmgr ] && [ -f "$dir"/boot/bcd ] ; then
+     OS="$(gettext "Windows Vista/7 (loader)")"
+     osid=bootmgr
+   # Check for NTLDR.
+-  elif [ -f "$dir"/ntldr -a -f "$dir"/ntdetect.com -a -f "$dir"/boot.ini ] ; then
++  elif [ -f "$dir"/ntldr ] && [ -f "$dir"/ntdetect.com ] && [ -f "$dir"/boot.ini ] ; then
+     OS=`get_os_name_from_boot_ini "$dir"/boot.ini` || OS="$(gettext "Windows NT/2000/XP (loader)")"
+     osid=ntldr
+     needmap=t
+diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
+index 0470e66853d..7cf8487d63a 100644
+--- a/util/grub.d/30_os-prober.in
++++ b/util/grub.d/30_os-prober.in
+@@ -30,7 +30,7 @@ if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
+   exit 0
+ fi
+ 
+-if [ -z "`which os-prober 2> /dev/null`" -o -z "`which linux-boot-prober 2> /dev/null`" ] ; then
++if [ -z "`which os-prober 2> /dev/null`" ] || [ -z "`which linux-boot-prober 2> /dev/null`" ] ; then
+   # missing os-prober and/or linux-boot-prober
+   exit 0
+ fi
+@@ -119,7 +119,7 @@ for OS in ${OSPROBED} ; do
+       EXPUUID="${EXPUUID}@${DEVICE#*@}"
+   fi
+ 
+-  if [ "x${GRUB_OS_PROBER_SKIP_LIST}" != "x" -a "x`echo ${GRUB_OS_PROBER_SKIP_LIST} | grep -i -e '\b'${EXPUUID}'\b'`" != "x" ] ; then
++  if [ "x${GRUB_OS_PROBER_SKIP_LIST}" != "x" ] && [ "x`echo ${GRUB_OS_PROBER_SKIP_LIST} | grep -i -e '\b'${EXPUUID}'\b'`" != "x" ] ; then
+     echo "Skipped ${LONGNAME} on ${DEVICE} by user request." >&2
+     continue
+   fi
diff --git a/SOURCES/0019-NEWS-Add-few-missing-entries.patch b/SOURCES/0019-NEWS-Add-few-missing-entries.patch
new file mode 100644
index 0000000..53226a5
--- /dev/null
+++ b/SOURCES/0019-NEWS-Add-few-missing-entries.patch
@@ -0,0 +1,97 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Sat, 18 Jan 2014 16:31:10 +0100
+Subject: [PATCH] * NEWS: Add few missing entries.
+
+---
+ ChangeLog |  4 ++++
+ NEWS      | 18 +++++++++++++++---
+ 2 files changed, 19 insertions(+), 3 deletions(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index c8e95a6b98d..6a19f850448 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* NEWS: Add few missing entries.
++
+ 2014-01-17  Colin Watson  <cjwatson@ubuntu.com>
+ 
+ 	* util/grub.d/00_header.in (make_timeout): Use && rather than test
+diff --git a/NEWS b/NEWS
+index 49a2459b6a0..a61df942a35 100644
+--- a/NEWS
++++ b/NEWS
+@@ -15,6 +15,8 @@ New in 2.02:
+   * GPT PReP.
+   * New `progress' module that shows progress information while reading
+     files.
++  * ZFS features support.
++  * ZFS LZ4 support.
+ 
+ * New/improved terminal and video support:
+   * Monochrome text (matching `hercules' in GRUB Legacy).
+@@ -36,6 +38,7 @@ New in 2.02:
+   * Enable `linux16' on all x86 platforms, not just BIOS.
+   * New TrueCrypt ISO loader.
+   * multiboot2 boot-services EFI specification.
++  * multiboot2 EFI memory map specification.
+   * multiboot2 full-file specfication.
+ 
+ * New/improved network support:
+@@ -51,12 +54,15 @@ New in 2.02:
+   * Ability to launch another payload from flash or disk
+   * Coreboot framebuffer
+   * CBMEMC support (both logging and inspecting logs)
+-  * Inspecting coreboot timestamps.
+-  * Inspecting coreboot tables.
++  * Command for inspecting coreboot timestamps (`coreboot_boottime').
++  * Command for inspecting coreboot tables (`lscoreboot').
++  * New target default_payload.elf.
++  * Increased maximal core size.
+ 
+ * New/improved platform support:
+   * New `efifwsetup' and `lsefi' commands on EFI platforms.
+   * New `cmosdump' and `cmosset' commands on platforms with CMOS support.
++  * New command `pcidump' for PCI platforms.
+   * Improve opcode parsing in ACPI halt implementation.
+   * Use the TSC as a possible time source on i386-ieee1275.
+   * Merge PowerPC grub-mkrescue implementation with the common one.
+@@ -77,6 +83,8 @@ New in 2.02:
+   * Support Yeeloong 3A.
+   * Add `cpuid --pae' option to detect Physical Address Extension on x86.
+   * Support for USB debug dongles.
++  * Support for *-emu on all platforms (previously only i386/x86_64 worked).
++  * Support *-emu on Windows.
+ 
+ * Security:
+   * Add optional facility to enforce that all files read by the core image
+@@ -88,6 +96,8 @@ New in 2.02:
+   * Initialise USB ports in parallel.
+   * New `testspeed' command to test file read speed.
+   * Speed-up gfxterm by storing intermediate results in more compact format.
++  * Lazy LVM/mdraid scan.
++  * Disk hints.
+ 
+ * Scripting:
+   * New `eval' and `tr' commands.
+@@ -105,7 +115,8 @@ New in 2.02:
+   * grub-install, grub-mknetdir, grub-mkrescue, and grub-mkstandalone
+     rewritten in C.  They should now work in supported non-Unix-like
+     environments.
+-  * Native mingw support, including ability to install on EFI under windows.
++  * Native mingw support.
++  * Ability to install on EFI under windows.
+   * Reorganise timeout handling using new `timeout_style' environment
+     variable and `GRUB_TIMEOUT_STYLE' configuration key for grub-mkconfig.
+     Menu hotkeys pressed during a hidden timeout now boot the corresponding
+@@ -122,6 +133,7 @@ New in 2.02:
+   * Partial mingw64 x86_64-efi compile support (highly experimental).
+   * Partial mingw32 i386-* (other than already present i386-pc)
+     compile support (highly experimental).
++  * Support for grub-mkpasswd on Windows.
+   * Eliminate the use of AutoGen.  This allowed some performance
+     improvements to the build system.
+   * Remove variable length arrays.
diff --git a/SOURCES/0020-grub-core-kern-efi-efi.c-Ensure-that-the-result-star.patch b/SOURCES/0020-grub-core-kern-efi-efi.c-Ensure-that-the-result-star.patch
new file mode 100644
index 0000000..0c964a6
--- /dev/null
+++ b/SOURCES/0020-grub-core-kern-efi-efi.c-Ensure-that-the-result-star.patch
@@ -0,0 +1,85 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Sat, 18 Jan 2014 16:41:47 +0100
+Subject: [PATCH] * grub-core/kern/efi/efi.c: Ensure that the result starts
+ with / and has no //.
+
+---
+ grub-core/kern/efi/efi.c | 25 +++++++++++++++++--------
+ ChangeLog                |  5 +++++
+ 2 files changed, 22 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index b253141f26e..b9eb1ab1e33 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -309,7 +309,7 @@ grub_efi_modules_addr (void)
+ char *
+ grub_efi_get_filename (grub_efi_device_path_t *dp0)
+ {
+-  char *name = 0, *p;
++  char *name = 0, *p, *pi;
+   grub_size_t filesize = 0;
+   grub_efi_device_path_t *dp;
+ 
+@@ -328,7 +328,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
+ 	  grub_efi_uint16_t len;
+ 	  len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
+ 		 / sizeof (grub_efi_char16_t));
+-	  filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 1;
++	  filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 2;
+ 	}
+ 
+       dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
+@@ -356,12 +356,12 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
+ 	  grub_efi_file_path_device_path_t *fp;
+ 	  grub_efi_uint16_t len;
+ 
+-	  if (p != name)
+-	    *p++ = '/';
++	  *p++ = '/';
+ 
+ 	  len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
+ 		 / sizeof (grub_efi_char16_t));
+ 	  fp = (grub_efi_file_path_device_path_t *) dp;
++
+ 	  p = (char *) grub_utf16_to_utf8 ((unsigned char *) p, fp->path_name, len);
+ 	}
+ 
+@@ -370,10 +370,19 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
+ 
+   *p = '\0';
+ 
+-  /* EFI breaks paths with backslashes.  */
+-  for (p = name; *p; p++)
+-    if (*p == '\\')
+-      *p = '/';
++  for (pi = name, p = name; *pi;)
++    {
++      /* EFI breaks paths with backslashes.  */
++      if (*pi == '\\' || *pi == '/')
++	{
++	  *p++ = '/';
++	  while (*pi == '\\' || *pi == '/')
++	    pi++;
++	  continue;
++	}
++      *p++ = *pi++;
++    }
++  *p = '\0';
+ 
+   return name;
+ }
+diff --git a/ChangeLog b/ChangeLog
+index 6a19f850448..b04a4ef70b9 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/kern/efi/efi.c: Ensure that the result starts with /
++	and has no //.
++
+ 2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* NEWS: Add few missing entries.
diff --git a/SOURCES/0021-util-grub-mount.c-Extend-GCC-warning-workaround-to-g.patch b/SOURCES/0021-util-grub-mount.c-Extend-GCC-warning-workaround-to-g.patch
new file mode 100644
index 0000000..c406ede
--- /dev/null
+++ b/SOURCES/0021-util-grub-mount.c-Extend-GCC-warning-workaround-to-g.patch
@@ -0,0 +1,42 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Sat, 18 Jan 2014 16:43:29 +0100
+Subject: [PATCH] * util/grub-mount.c: Extend GCC warning workaround to
+ grub-mount.
+
+---
+ util/grub-mount.c | 7 ++++++-
+ ChangeLog         | 4 ++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/util/grub-mount.c b/util/grub-mount.c
+index 118881e0d9d..19de2e62057 100644
+--- a/util/grub-mount.c
++++ b/util/grub-mount.c
+@@ -41,8 +41,13 @@
+ #include <string.h>
+ #include <stdlib.h>
+ 
++#pragma GCC diagnostic ignored "-Wmissing-prototypes"
++#pragma GCC diagnostic ignored "-Wmissing-declarations"
++#include <argp.h>
++#pragma GCC diagnostic error "-Wmissing-prototypes"
++#pragma GCC diagnostic error "-Wmissing-declarations"
++
+ #include "progname.h"
+-#include "argp.h"
+ 
+ static const char *root = NULL;
+ grub_device_t dev = NULL;
+diff --git a/ChangeLog b/ChangeLog
+index b04a4ef70b9..8534158b6c0 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* util/grub-mount.c: Extend GCC warning workaround to grub-mount.
++
+ 2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/kern/efi/efi.c: Ensure that the result starts with /
diff --git a/SOURCES/0022-reintroduce-BUILD_LDFLAGS-for-the-cross-compile-case.patch b/SOURCES/0022-reintroduce-BUILD_LDFLAGS-for-the-cross-compile-case.patch
new file mode 100644
index 0000000..aff34c5
--- /dev/null
+++ b/SOURCES/0022-reintroduce-BUILD_LDFLAGS-for-the-cross-compile-case.patch
@@ -0,0 +1,150 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Sat, 18 Jan 2014 19:50:54 +0400
+Subject: [PATCH] reintroduce BUILD_LDFLAGS for the cross-compile case
+
+This allows providing separate LDFLAGS for build and host environments, which
+are not necessary the same for cross-compile case. In particular, it allows
+building host programs statically to not depend on presence of libraries at
+run-time (e.g. MinGW DLLs on Windows) while continue to use default dynamic
+linking at build time.
+
+Also fix obsolete comments in confgure.ac - we do use different environment
+for build and host now.
+---
+ configure.ac          | 13 ++++++++-----
+ Makefile.am           |  8 ++++----
+ ChangeLog             |  7 +++++++
+ INSTALL               |  3 ++-
+ grub-core/Makefile.am |  6 +++---
+ 5 files changed, 24 insertions(+), 13 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 7c5d080b8a2..2e4cf3c2e22 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -26,11 +26,10 @@ dnl This is necessary because the target type in autoconf does not
+ dnl describe such a system very well.
+ dnl
+ dnl The current strategy is to use variables with no prefix (such as
+-dnl CC, CFLAGS, etc.) for the host type as well as the build type,
+-dnl because GRUB does not need to use those variables for the build
+-dnl type, so there is no conflict. Variables with the prefix "TARGET_"
+-dnl (such as TARGET_CC, TARGET_CFLAGS, etc.) are used for the target
+-dnl type.
++dnl CC, CFLAGS, etc.) for the host type, variables with prefix "BUILD_"
++dnl (such as BUILD_CC, BUILD_CFLAGS, etc.) for the build type and variables
++dnl with the prefix "TARGET_" (such as TARGET_CC, TARGET_CFLAGS, etc.) are
++dnl used for the target type. See INSTALL for full list of variables.
+ 
+ AC_INIT([GRUB],[2.02~beta2],[bug-grub@gnu.org])
+ 
+@@ -477,6 +476,7 @@ AC_SUBST(HOST_CC)
+ AC_SUBST(BUILD_CC)
+ AC_SUBST(BUILD_CFLAGS)
+ AC_SUBST(BUILD_CPPFLAGS)
++AC_SUBST(BUILD_LDFLAGS)
+ AC_SUBST(TARGET_CC)
+ AC_SUBST(TARGET_NM)
+ AC_SUBST(TARGET_RANLIB)
+@@ -1290,10 +1290,12 @@ SAVED_CC="$CC"
+ SAVED_CPP="$CPP"
+ SAVED_CFLAGS="$CFLAGS"
+ SAVED_CPPFLAGS="$CPPFLAGS"
++SAVED_LDFLAGS="$LDFLAGS"
+ CC="$BUILD_CC"
+ CPP="$BUILD_CPP"
+ CFLAGS="$BUILD_CFLAGS"
+ CPPFLAGS="$BUILD_CPPFLAGS"
++LDFLAGS="$BUILD_LDFAGS"
+ 
+ unset ac_cv_c_bigendian
+ unset ac_cv_header_ft2build_h
+@@ -1356,6 +1358,7 @@ CC="$SAVED_CC"
+ CPP="$SAVED_CPP"
+ CFLAGS="$SAVED_CFLAGS"
+ CPPFLAGS="$SAVED_CPPFLAGS"
++LDFLAGS="$SAVED_LDFLAGS"
+ 
+ 
+ DJVU_FONT_SOURCE=
+diff --git a/Makefile.am b/Makefile.am
+index 320e86f8f55..1bbec0e79d3 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -67,20 +67,20 @@ endif
+ starfield_theme_files = $(srcdir)/themes/starfield/blob_w.png $(srcdir)/themes/starfield/boot_menu_c.png $(srcdir)/themes/starfield/boot_menu_e.png $(srcdir)/themes/starfield/boot_menu_ne.png $(srcdir)/themes/starfield/boot_menu_n.png $(srcdir)/themes/starfield/boot_menu_nw.png $(srcdir)/themes/starfield/boot_menu_se.png $(srcdir)/themes/starfield/boot_menu_s.png $(srcdir)/themes/starfield/boot_menu_sw.png $(srcdir)/themes/starfield/boot_menu_w.png $(srcdir)/themes/starfield/slider_c.png $(srcdir)/themes/starfield/slider_n.png $(srcdir)/themes/starfield/slider_s.png $(srcdir)/themes/starfield/starfield.png $(srcdir)/themes/starfield/terminal_box_c.png $(srcdir)/themes/starfield/terminal_box_e.png $(srcdir)/themes/starfield/terminal_box_ne.png $(srcdir)/themes/starfield/terminal_box_n.png $(srcdir)/themes/starfield/terminal_box_nw.png $(srcdir)/themes/starfield/terminal_box_se.png $(srcdir)/themes/starfield/terminal_box_s.png $(srcdir)/themes/starfield/terminal_box_sw.png $(srcdir)/themes/starfield/terminal_box_w.png $(srcdir)/themes/starfield/theme.txt $(srcdir)/themes/starfield/README $(srcdir)/themes/starfield/COPYING.CC-BY-SA-3.0
+ 
+ build-grub-mkfont: util/grub-mkfont.c grub-core/unidata.c grub-core/kern/emu/misc.c util/misc.c
+-	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-mkfont\" $^ $(build_freetype_cflags) $(build_freetype_libs)
++	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-mkfont\" $^ $(build_freetype_cflags) $(build_freetype_libs)
+ CLEANFILES += build-grub-mkfont
+ 
+ garbage-gen: util/garbage-gen.c
+-	$(BUILD_CC) -o $@ $(BUILD_CFLAGS) $(BUILD_CPPFLAGS)  $^
++	$(BUILD_CC) -o $@ $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS)  $^
+ CLEANFILES += garbage-gen
+ EXTRA_DIST += util/garbage-gen.c
+ 
+ build-grub-gen-asciih: util/grub-gen-asciih.c
+-	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror
++	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror
+ CLEANFILES += build-grub-gen-asciih
+ 
+ build-grub-gen-widthspec: util/grub-gen-widthspec.c
+-	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror
++	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror
+ CLEANFILES += build-grub-gen-widthspec
+ 
+ if COND_STARFIELD
+diff --git a/ChangeLog b/ChangeLog
+index 8534158b6c0..9c3ef2e2150 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,10 @@
++2014-01-07  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* configure.ac: Add support for BUILD_LDFLAGS.
++	* Makefile.am: Use BUILD_LDFLAGS for build time programs here ...
++	* grub-core/Makefile.am: ... and here.
++	* INSTALL: Mention BUILD_LDFLAGS.
++
+ 2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* util/grub-mount.c: Extend GCC warning workaround to grub-mount.
+diff --git a/INSTALL b/INSTALL
+index db12530dff3..b67cd7f3476 100644
+--- a/INSTALL
++++ b/INSTALL
+@@ -168,7 +168,8 @@ corresponding platform are not needed for the platform in question.
+        generate sin and cos tables.
+     2. BUILD_CFLAGS= for C options for build.
+     3. BUILD_CPPFLAGS= for C preprocessor options for build.
+-    4. BUILD_FREETYPE= for freetype-config for build (optional).
++    4. BUILD_LDFLAGS= for linker options for build.
++    5. BUILD_FREETYPE= for freetype-config for build (optional).
+ 
+   - For host
+     1. --host= to autoconf name of host.
+diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
+index 1b3142d2160..13b7979106f 100644
+--- a/grub-core/Makefile.am
++++ b/grub-core/Makefile.am
+@@ -27,14 +27,14 @@ CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM)
+ CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM)
+ 
+ build-grub-pep2elf: $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
+-	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=64 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pep2elf\" $^
++	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=64 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pep2elf\" $^
+ 
+ build-grub-pe2elf: $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
+-	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=32 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pe2elf\" $^
++	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=32 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pe2elf\" $^
+ 
+ # gentrigtables
+ gentrigtables: gentrigtables.c
+-	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $< $(BUILD_LIBM)
++	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $< $(BUILD_LIBM)
+ CLEANFILES += gentrigtables
+ 
+ # trigtables.c
diff --git a/SOURCES/0023-grub-core-term-terminfo.c-Recognize-keys-F1-F12.patch b/SOURCES/0023-grub-core-term-terminfo.c-Recognize-keys-F1-F12.patch
new file mode 100644
index 0000000..64ecaea
--- /dev/null
+++ b/SOURCES/0023-grub-core-term-terminfo.c-Recognize-keys-F1-F12.patch
@@ -0,0 +1,151 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Sat, 18 Jan 2014 16:57:35 +0100
+Subject: [PATCH] * grub-core/term/terminfo.c: Recognize keys F1-F12.
+
+---
+ grub-core/term/terminfo.c | 86 +++++++++++++++++++++++++++--------------------
+ ChangeLog                 |  4 +++
+ 2 files changed, 54 insertions(+), 36 deletions(-)
+
+diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c
+index 3d48b198fbd..f0d3e3debc6 100644
+--- a/grub-core/term/terminfo.c
++++ b/grub-core/term/terminfo.c
+@@ -460,28 +460,31 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
+ 	{'@', GRUB_TERM_KEY_INSERT},
+       };
+ 
+-    static struct
+-    {
+-      char key;
+-      unsigned ascii;
+-    }
+-    four_code_table[] =
++    static unsigned four_code_table[] =
+       {
+-	{'1', GRUB_TERM_KEY_HOME},
+-	{'3', GRUB_TERM_KEY_DC},
+-	{'5', GRUB_TERM_KEY_PPAGE},
+-	{'6', GRUB_TERM_KEY_NPAGE},
+-	{'7', GRUB_TERM_KEY_HOME},
+-	{'8', GRUB_TERM_KEY_END}
++	[1] = GRUB_TERM_KEY_HOME,
++	[3] = GRUB_TERM_KEY_DC,
++	[5] = GRUB_TERM_KEY_PPAGE,
++	[6] = GRUB_TERM_KEY_NPAGE,
++	[7] = GRUB_TERM_KEY_HOME,
++	[8] = GRUB_TERM_KEY_END,
++	[17] = GRUB_TERM_KEY_F6,
++	[18] = GRUB_TERM_KEY_F7,
++	[19] = GRUB_TERM_KEY_F8,
++	[20] = GRUB_TERM_KEY_F9,
++	[21] = GRUB_TERM_KEY_F10,
++	[23] = GRUB_TERM_KEY_F11,
++	[24] = GRUB_TERM_KEY_F12,
+       };
+     char fx_key[] = 
+       { 'P', 'Q', 'w', 'x', 't', 'u',
+-        'q', 'r', 'p', 'M', 'A', 'B' };
++        'q', 'r', 'p', 'M', 'A', 'B', 'H', 'F' };
+     unsigned fx_code[] = 
+ 	{ GRUB_TERM_KEY_F1, GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3,
+ 	  GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, GRUB_TERM_KEY_F6,
+ 	  GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9,
+-	  GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12 };
++	  GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12,
++	  GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_END };
+     unsigned i;
+ 
+     if (c == '\e')
+@@ -492,19 +495,13 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
+ 	  {
+ 	    CONTINUE_READ;
+ 
+-	    switch (c)
+-	      {
+-	      case 'H':
+-		keys[0] = GRUB_TERM_KEY_HOME;
+-		*len = 1;
+-		return;
+-	      case 'F':
+-		keys[0] = GRUB_TERM_KEY_END;
+-		*len = 1;
+-		return;
+-	      default:
+-		return;
+-	      }
++	    for (i = 0; i < ARRAY_SIZE (fx_key); i++)
++	      if (fx_key[i] == c)
++		{
++		  keys[0] = fx_code[i];
++		  *len = 1;
++		  return;
++		}
+ 	  }
+ 
+ 	if (c != '[')
+@@ -523,6 +520,15 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
+ 
+     switch (c)
+       {
++      case '[':
++	CONTINUE_READ;
++	if (c >= 'A' && c <= 'E')
++	  {
++	    keys[0] = GRUB_TERM_KEY_F1 + c - 'A';
++	    *len = 1;
++	    return;
++	  }
++	return;
+       case 'O':
+ 	CONTINUE_READ;
+ 	for (i = 0; i < ARRAY_SIZE (fx_key); i++)
+@@ -555,18 +561,26 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
+ 	  return;
+ 	}	  
+ 
+-      default:
+-	for (i = 0; i < ARRAY_SIZE (four_code_table); i++)
+-	  if (four_code_table[i].key == c)
++      case '1' ... '9':
++	{
++	  unsigned val = c - '0';
++	  CONTINUE_READ;
++	  if (c >= '0' && c <= '9')
+ 	    {
++	      val = val * 10 + (c - '0');
+ 	      CONTINUE_READ;
+-	      if (c != '~')
+-		return;
+-	      keys[0] = four_code_table[i].ascii;
+-	      *len = 1;
+-	      return;
+ 	    }
+-	return;
++	  if (c != '~')
++	    return;
++	  if (val >= ARRAY_SIZE (four_code_table)
++	      || four_code_table[val] == 0)
++	    return;
++	  keys[0] = four_code_table[val];
++	  *len = 1;
++	  return;
++	}
++	default:
++	  return;
+       }
+   }
+ #undef CONTINUE_READ
+diff --git a/ChangeLog b/ChangeLog
+index 9c3ef2e2150..bdfbf44da88 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/term/terminfo.c: Recognize keys F1-F12.
++
+ 2014-01-07  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* configure.ac: Add support for BUILD_LDFLAGS.
diff --git a/SOURCES/0024-Fix-ChangeLog-date.patch b/SOURCES/0024-Fix-ChangeLog-date.patch
new file mode 100644
index 0000000..56dbb01
--- /dev/null
+++ b/SOURCES/0024-Fix-ChangeLog-date.patch
@@ -0,0 +1,22 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Sat, 18 Jan 2014 20:01:16 +0400
+Subject: [PATCH] Fix ChangeLog date
+
+---
+ ChangeLog | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index bdfbf44da88..fcbf2207b32 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -2,7 +2,7 @@
+ 
+ 	* grub-core/term/terminfo.c: Recognize keys F1-F12.
+ 
+-2014-01-07  Andrey Borzenkov <arvidjaar@gmail.com>
++2014-01-18  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* configure.ac: Add support for BUILD_LDFLAGS.
+ 	* Makefile.am: Use BUILD_LDFLAGS for build time programs here ...
diff --git a/SOURCES/0025-Use-_W64-to-detect-MinGW-W64-32-instead-of-_FILE_OFF.patch b/SOURCES/0025-Use-_W64-to-detect-MinGW-W64-32-instead-of-_FILE_OFF.patch
new file mode 100644
index 0000000..fdec621
--- /dev/null
+++ b/SOURCES/0025-Use-_W64-to-detect-MinGW-W64-32-instead-of-_FILE_OFF.patch
@@ -0,0 +1,43 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Sat, 18 Jan 2014 20:04:11 +0400
+Subject: [PATCH] Use _W64 to detect MinGW W64-32 instead of _FILE_OFFSET_BITS
+
+In 94cee4a4c201bb506377b2c26e072eee8cb19d6f I overlooked that config.h
+unconditionally sets _FILE_OFFSET_BITS, so it cannot be used to detect
+MinGW W64 environment. It looks like Emacs folks already found
+solution; instead of _FILE_OFFSET_BITS use _W64 as suggested in
+http://lists.gnu.org/archive/html/emacs-devel/2013-03/msg00723.html
+---
+ include/grub/osdep/hostfile_windows.h | 4 ++--
+ ChangeLog                             | 5 +++++
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/include/grub/osdep/hostfile_windows.h b/include/grub/osdep/hostfile_windows.h
+index 79efcfa5084..bf6451b6db4 100644
+--- a/include/grub/osdep/hostfile_windows.h
++++ b/include/grub/osdep/hostfile_windows.h
+@@ -69,8 +69,8 @@ enum grub_util_fd_open_flags_t
+ 
+ #if defined (__MINGW32__) && !defined (__MINGW64__)
+ 
+-/* 32 bit on MinGW-64 already redefines them if _FILE_OFFSET_BITS=64 */
+-#if !defined(_FILE_OFFSET_BITS)
++/* 32 bit on Mingw-w64 already redefines them if _FILE_OFFSET_BITS=64 */
++#ifndef _W64
+ #define fseeko fseeko64
+ #define ftello ftello64
+ #endif
+diff --git a/ChangeLog b/ChangeLog
+index fcbf2207b32..5aac7c1d854 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-01-18  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* include/grub/osdep/hostfile_windows.h: Use _W64 instead of
++	FILE_OFFSET_BITS to differentiate between native MinGW and Mingw W64.
++
+ 2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/term/terminfo.c: Recognize keys F1-F12.
diff --git a/SOURCES/0026-add-BUILD_EXEEXT-support-to-fix-make-clean-on-Window.patch b/SOURCES/0026-add-BUILD_EXEEXT-support-to-fix-make-clean-on-Window.patch
new file mode 100644
index 0000000..63738d5
--- /dev/null
+++ b/SOURCES/0026-add-BUILD_EXEEXT-support-to-fix-make-clean-on-Window.patch
@@ -0,0 +1,169 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Sat, 18 Jan 2014 20:41:24 +0400
+Subject: [PATCH] add BUILD_EXEEXT support to fix make clean on Windows
+
+Add $(BUILD_EXEEXT) to ensure files are removed. Also add CLEANFILES where
+appropriate.
+---
+ configure.ac          | 21 ++++++++++++++++-----
+ Makefile.util.def     |  2 +-
+ Makefile.am           | 16 ++++++++--------
+ ChangeLog             |  7 +++++++
+ grub-core/Makefile.am | 14 ++++++++------
+ 5 files changed, 40 insertions(+), 20 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 2e4cf3c2e22..cf3de3be1fc 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -38,7 +38,8 @@ AC_CONFIG_AUX_DIR([build-aux])
+ # We don't want -g -O2 by default in CFLAGS
+ : ${CFLAGS=""}
+ 
+-# Checks for host and target systems.
++# Checks for build, host and target systems.
++AC_CANONICAL_BUILD
+ AC_CANONICAL_HOST
+ save_program_prefix="${program_prefix}"
+ AC_CANONICAL_TARGET
+@@ -422,6 +423,16 @@ case "$build_os" in
+   haiku*)				BUILD_LIBM= ;;
+   *) 					BUILD_LIBM=-lm ;;
+ esac
++
++dnl FIXME proper test seems to require too deep dive into Autoconf internals.
++dnl For now just list known platforms that we support.
++
++case "$build_os" in
++  cygwin*|mingw32*|mingw64*)		BUILD_EXEEXT=.exe ;;
++  *)					BUILD_EXEEXT= ;;
++esac
++AC_SUBST(BUILD_EXEEXT)
++
+ # For gnulib.
+ gl_INIT
+ 
+@@ -765,11 +776,11 @@ if test x"$platform" = xemu ; then
+     *windows* | *cygwin* | *mingw*)
+       if test x${target_cpu} = xi386 ; then
+         grub_cv_target_cc_link_format=-mi386pe;
+-	TARGET_OBJ2ELF='./build-grub-pe2elf';
++	TARGET_OBJ2ELF='./build-grub-pe2elf$(BUILD_EXEEXT)';
+       fi
+       if test x${target_cpu} = xx86_64 ; then
+         grub_cv_target_cc_link_format=-mi386pep;
+-	TARGET_OBJ2ELF='./build-grub-pep2elf';
++	TARGET_OBJ2ELF='./build-grub-pep2elf$(BUILD_EXEEXT)';
+       fi
+       TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,$grub_cv_target_cc_link_format"
+       ;;
+@@ -803,10 +814,10 @@ elif test x"$target_cpu" = xi386 || test x"$target_cpu" = xx86_64; then
+   fi
+   TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,$grub_cv_target_cc_link_format"
+   if test x"$grub_cv_target_cc_link_format" = x-mi386pe ; then
+-    TARGET_OBJ2ELF='./build-grub-pe2elf';
++    TARGET_OBJ2ELF='./build-grub-pe2elf$(BUILD_EXEEXT)';
+   fi
+   if test x"$grub_cv_target_cc_link_format" = x-mi386pep ; then
+-    TARGET_OBJ2ELF='./build-grub-pep2elf';
++    TARGET_OBJ2ELF='./build-grub-pep2elf$(BUILD_EXEEXT)';
+   fi
+ fi
+ 
+diff --git a/Makefile.util.def b/Makefile.util.def
+index 3c99be2b0ca..83df212f412 100644
+--- a/Makefile.util.def
++++ b/Makefile.util.def
+@@ -708,7 +708,7 @@ script = {
+   name = grub-fs-tester;
+   common = tests/util/grub-fs-tester.in;
+   installdir = noinst;
+-  dependencies = garbage-gen;
++  dependencies = 'garbage-gen$(BUILD_EXEEXT)';
+ };
+ 
+ script = {
+diff --git a/Makefile.am b/Makefile.am
+index 1bbec0e79d3..aa526f573c3 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -66,22 +66,22 @@ endif
+ 
+ starfield_theme_files = $(srcdir)/themes/starfield/blob_w.png $(srcdir)/themes/starfield/boot_menu_c.png $(srcdir)/themes/starfield/boot_menu_e.png $(srcdir)/themes/starfield/boot_menu_ne.png $(srcdir)/themes/starfield/boot_menu_n.png $(srcdir)/themes/starfield/boot_menu_nw.png $(srcdir)/themes/starfield/boot_menu_se.png $(srcdir)/themes/starfield/boot_menu_s.png $(srcdir)/themes/starfield/boot_menu_sw.png $(srcdir)/themes/starfield/boot_menu_w.png $(srcdir)/themes/starfield/slider_c.png $(srcdir)/themes/starfield/slider_n.png $(srcdir)/themes/starfield/slider_s.png $(srcdir)/themes/starfield/starfield.png $(srcdir)/themes/starfield/terminal_box_c.png $(srcdir)/themes/starfield/terminal_box_e.png $(srcdir)/themes/starfield/terminal_box_ne.png $(srcdir)/themes/starfield/terminal_box_n.png $(srcdir)/themes/starfield/terminal_box_nw.png $(srcdir)/themes/starfield/terminal_box_se.png $(srcdir)/themes/starfield/terminal_box_s.png $(srcdir)/themes/starfield/terminal_box_sw.png $(srcdir)/themes/starfield/terminal_box_w.png $(srcdir)/themes/starfield/theme.txt $(srcdir)/themes/starfield/README $(srcdir)/themes/starfield/COPYING.CC-BY-SA-3.0
+ 
+-build-grub-mkfont: util/grub-mkfont.c grub-core/unidata.c grub-core/kern/emu/misc.c util/misc.c
++build-grub-mkfont$(BUILD_EXEEXT): util/grub-mkfont.c grub-core/unidata.c grub-core/kern/emu/misc.c util/misc.c
+ 	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-mkfont\" $^ $(build_freetype_cflags) $(build_freetype_libs)
+-CLEANFILES += build-grub-mkfont
++CLEANFILES += build-grub-mkfont$(BUILD_EXEEXT)
+ 
+-garbage-gen: util/garbage-gen.c
++garbage-gen$(BUILD_EXEEXT): util/garbage-gen.c
+ 	$(BUILD_CC) -o $@ $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS)  $^
+-CLEANFILES += garbage-gen
++CLEANFILES += garbage-gen$(BUILD_EXEEXT)
+ EXTRA_DIST += util/garbage-gen.c
+ 
+-build-grub-gen-asciih: util/grub-gen-asciih.c
++build-grub-gen-asciih$(BUILD_EXEEXT): util/grub-gen-asciih.c
+ 	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror
+-CLEANFILES += build-grub-gen-asciih
++CLEANFILES += build-grub-gen-asciih$(BUILD_EXEEXT)
+ 
+-build-grub-gen-widthspec: util/grub-gen-widthspec.c
++build-grub-gen-widthspec$(BUILD_EXEEXT): util/grub-gen-widthspec.c
+ 	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror
+-CLEANFILES += build-grub-gen-widthspec
++CLEANFILES += build-grub-gen-widthspec$(BUILD_EXEEXT)
+ 
+ if COND_STARFIELD
+ starfield_DATA = dejavu_10.pf2 dejavu_12.pf2 dejavu_bold_14.pf2 dejavu_14.pf2 dejavu_16.pf2 $(starfield_theme_files)
+diff --git a/ChangeLog b/ChangeLog
+index 5aac7c1d854..dad2da2faef 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,10 @@
++2014-01-18  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* configure.ac: Add support for BUILD_EXEEXT and use it ...
++	* Makefile.am: ... here.
++	* Makefile.util.def: ... and here.
++	* grub-core/Makefile.am: ... and here.
++
+ 2014-01-18  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* include/grub/osdep/hostfile_windows.h: Use _W64 instead of
+diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
+index 13b7979106f..826b3dd7c1a 100644
+--- a/grub-core/Makefile.am
++++ b/grub-core/Makefile.am
+@@ -26,20 +26,22 @@ CFLAGS_LIBRARY += $(CFLAGS_PLATFORM) -fno-builtin
+ CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM)
+ CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM)
+ 
+-build-grub-pep2elf: $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
++build-grub-pep2elf$(BUILD_EXEEXT): $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
+ 	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=64 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pep2elf\" $^
++CLEANFILES += build-grub-pep2elf$(BUILD_EXEEXT)
+ 
+-build-grub-pe2elf: $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
++build-grub-pe2elf$(BUILD_EXEEXT): $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
+ 	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=32 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pe2elf\" $^
++CLEANFILES += build-grub-pe2elf$(BUILD_EXEEXT)
+ 
+ # gentrigtables
+-gentrigtables: gentrigtables.c
++gentrigtables$(BUILD_EXEEXT): gentrigtables.c
+ 	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $< $(BUILD_LIBM)
+-CLEANFILES += gentrigtables
++CLEANFILES += gentrigtables$(BUILD_EXEEXT)
+ 
+ # trigtables.c
+-trigtables.c: gentrigtables gentrigtables.c $(top_srcdir)/configure.ac
+-	./gentrigtables > $@
++trigtables.c: gentrigtables$(BUILD_EXEEXT) gentrigtables.c $(top_srcdir)/configure.ac
++	./gentrigtables$(BUILD_EXEEXT) > $@
+ CLEANFILES += trigtables.c
+ 
+ # XXX Use Automake's LEX & YACC support
diff --git a/SOURCES/0027-fix-include-loop-on-MinGW-due-to-libintl.h-pulling-s.patch b/SOURCES/0027-fix-include-loop-on-MinGW-due-to-libintl.h-pulling-s.patch
new file mode 100644
index 0000000..796a9b9
--- /dev/null
+++ b/SOURCES/0027-fix-include-loop-on-MinGW-due-to-libintl.h-pulling-s.patch
@@ -0,0 +1,275 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Sat, 18 Jan 2014 21:22:57 +0400
+Subject: [PATCH] fix include loop on MinGW due to libintl.h pulling stdio.h
+
+In file included from ./include/grub/dl.h:23:0,
+                 from grub-core/lib/libgcrypt-grub/cipher/rfc2268.c:3:
+./include/grub/list.h:34:18: warning: conflicting types for 'grub_list_push' [en
+abled by default]
+ void EXPORT_FUNC(grub_list_push) (grub_list_t *head, grub_list_t item);
+                  ^
+./include/grub/symbol.h:68:25: note: in definition of macro 'EXPORT_FUNC'
+ # define EXPORT_FUNC(x) x
+                         ^
+In file included from ./include/grub/fs.h:30:0,
+                 from ./include/grub/file.h:25,
+                 from ./grub-core/lib/posix_wrap/stdio.h:23,
+                 from c:\mingw\include\libintl.h:314,
+                 from ./include/grub/i18n.h:33,
+                 from ./include/grub/misc.h:27,
+                 from ./include/grub/list.h:25,
+                 from ./include/grub/dl.h:28,
+                 from grub-core/lib/libgcrypt-grub/cipher/rfc2268.c:3:
+./include/grub/partition.h:106:3: note: previous implicit declaration of 'grub_l
+ist_push' was here
+   grub_list_push (GRUB_AS_LIST_P (&grub_partition_map_list),
+   ^
+list.h needs just ATTRIBUTE_ERROR from misc.h; split compiler features
+into separate file grub/compiler.h and include it instead.
+---
+ grub-core/commands/fileXX.c        |  1 +
+ grub-core/efiemu/prepare.c         |  1 +
+ grub-core/loader/i386/xen_file.c   |  1 +
+ grub-core/loader/i386/xen_fileXX.c |  1 +
+ grub-core/video/capture.c          |  1 +
+ include/grub/command.h             |  1 +
+ include/grub/compiler.h            | 51 ++++++++++++++++++++++++++++++++++++++
+ include/grub/dl.h                  |  1 +
+ include/grub/list.h                |  4 +--
+ include/grub/misc.h                | 29 +---------------------
+ include/grub/procfs.h              |  1 +
+ ChangeLog                          | 14 +++++++++++
+ 12 files changed, 76 insertions(+), 30 deletions(-)
+ create mode 100644 include/grub/compiler.h
+
+diff --git a/grub-core/commands/fileXX.c b/grub-core/commands/fileXX.c
+index c9857ff67b1..58e1094c68b 100644
+--- a/grub-core/commands/fileXX.c
++++ b/grub-core/commands/fileXX.c
+@@ -18,6 +18,7 @@
+ 
+ #include <grub/fileid.h>
+ #include <grub/elfload.h>
++#include <grub/misc.h>
+ 
+ #pragma GCC diagnostic ignored "-Wcast-align"
+ 
+diff --git a/grub-core/efiemu/prepare.c b/grub-core/efiemu/prepare.c
+index fb1b25d17f2..84c3368a82c 100644
+--- a/grub-core/efiemu/prepare.c
++++ b/grub-core/efiemu/prepare.c
+@@ -21,6 +21,7 @@
+ #include <grub/err.h>
+ #include <grub/mm.h>
+ #include <grub/types.h>
++#include <grub/misc.h>
+ #include <grub/efiemu/efiemu.h>
+ #include <grub/crypto.h>
+ 
+diff --git a/grub-core/loader/i386/xen_file.c b/grub-core/loader/i386/xen_file.c
+index ebbf6aa11ba..ff23235f064 100644
+--- a/grub-core/loader/i386/xen_file.c
++++ b/grub-core/loader/i386/xen_file.c
+@@ -18,6 +18,7 @@
+ 
+ #include <grub/xen_file.h>
+ #include <grub/i386/linux.h>
++#include <grub/misc.h>
+ 
+ grub_elf_t
+ grub_xen_file (grub_file_t file)
+diff --git a/grub-core/loader/i386/xen_fileXX.c b/grub-core/loader/i386/xen_fileXX.c
+index 6df00157629..73a5f90fdb9 100644
+--- a/grub-core/loader/i386/xen_fileXX.c
++++ b/grub-core/loader/i386/xen_fileXX.c
+@@ -17,6 +17,7 @@
+  */
+ 
+ #include <grub/xen_file.h>
++#include <grub/misc.h>
+ 
+ static grub_err_t
+ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
+diff --git a/grub-core/video/capture.c b/grub-core/video/capture.c
+index 67c8edde824..4f83c744116 100644
+--- a/grub-core/video/capture.c
++++ b/grub-core/video/capture.c
+@@ -4,6 +4,7 @@
+ #include <grub/video.h>
+ #include <grub/video_fb.h>
+ #include <grub/mm.h>
++#include <grub/misc.h>
+ 
+ static struct
+ {
+diff --git a/include/grub/command.h b/include/grub/command.h
+index 8705a635519..eee4e847ee4 100644
+--- a/include/grub/command.h
++++ b/include/grub/command.h
+@@ -22,6 +22,7 @@
+ #include <grub/symbol.h>
+ #include <grub/err.h>
+ #include <grub/list.h>
++#include <grub/misc.h>
+ 
+ typedef enum grub_command_flags
+   {
+diff --git a/include/grub/compiler.h b/include/grub/compiler.h
+new file mode 100644
+index 00000000000..c9e1d7a73dc
+--- /dev/null
++++ b/include/grub/compiler.h
+@@ -0,0 +1,51 @@
++/* compiler.h - macros for various compiler features */
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010,2014  Free Software Foundation, Inc.
++ *
++ *  GRUB 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 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef GRUB_COMPILER_HEADER
++#define GRUB_COMPILER_HEADER	1
++
++/* GCC version checking borrowed from glibc. */
++#if defined(__GNUC__) && defined(__GNUC_MINOR__)
++#  define GNUC_PREREQ(maj,min) \
++	((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
++#else
++#  define GNUC_PREREQ(maj,min) 0
++#endif
++
++/* Does this compiler support compile-time error attributes? */
++#if GNUC_PREREQ(4,3)
++#  define ATTRIBUTE_ERROR(msg) \
++	__attribute__ ((__error__ (msg)))
++#else
++#  define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn))
++#endif
++
++#if GNUC_PREREQ(4,4)
++#  define GNU_PRINTF gnu_printf
++#else
++#  define GNU_PRINTF printf
++#endif
++
++#if GNUC_PREREQ(3,4)
++#  define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
++#else
++#  define WARN_UNUSED_RESULT
++#endif
++
++#endif /* ! GRUB_COMPILER_HEADER */
+diff --git a/include/grub/dl.h b/include/grub/dl.h
+index d29a899f52c..9562fa6634c 100644
+--- a/include/grub/dl.h
++++ b/include/grub/dl.h
+@@ -26,6 +26,7 @@
+ #include <grub/types.h>
+ #include <grub/elf.h>
+ #include <grub/list.h>
++#include <grub/misc.h>
+ #endif
+ 
+ /*
+diff --git a/include/grub/list.h b/include/grub/list.h
+index edd20adfdb2..d170ff6da02 100644
+--- a/include/grub/list.h
++++ b/include/grub/list.h
+@@ -21,8 +21,8 @@
+ #define GRUB_LIST_HEADER 1
+ 
+ #include <grub/symbol.h>
+-#include <grub/types.h>
+-#include <grub/misc.h>
++#include <grub/err.h>
++#include <grub/compiler.h>
+ 
+ struct grub_list
+ {
+diff --git a/include/grub/misc.h b/include/grub/misc.h
+index 2cf74b55006..c6cd4564d86 100644
+--- a/include/grub/misc.h
++++ b/include/grub/misc.h
+@@ -25,34 +25,7 @@
+ #include <grub/symbol.h>
+ #include <grub/err.h>
+ #include <grub/i18n.h>
+-
+-/* GCC version checking borrowed from glibc. */
+-#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+-#  define GNUC_PREREQ(maj,min) \
+-	((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+-#else
+-#  define GNUC_PREREQ(maj,min) 0
+-#endif
+-
+-/* Does this compiler support compile-time error attributes? */
+-#if GNUC_PREREQ(4,3)
+-#  define ATTRIBUTE_ERROR(msg) \
+-	__attribute__ ((__error__ (msg)))
+-#else
+-#  define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn))
+-#endif
+-
+-#if GNUC_PREREQ(4,4)
+-#  define GNU_PRINTF gnu_printf
+-#else
+-#  define GNU_PRINTF printf
+-#endif
+-
+-#if GNUC_PREREQ(3,4)
+-#  define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
+-#else
+-#  define WARN_UNUSED_RESULT
+-#endif
++#include <grub/compiler.h>
+ 
+ #define ALIGN_UP(addr, align) \
+ 	((addr + (typeof (addr)) align - 1) & ~((typeof (addr)) align - 1))
+diff --git a/include/grub/procfs.h b/include/grub/procfs.h
+index d393da77f91..8cc331d946f 100644
+--- a/include/grub/procfs.h
++++ b/include/grub/procfs.h
+@@ -20,6 +20,7 @@
+ #define GRUB_PROCFS_HEADER	1
+ 
+ #include <grub/list.h>
++#include <grub/types.h>
+ 
+ struct grub_procfs_entry
+ {
+diff --git a/ChangeLog b/ChangeLog
+index dad2da2faef..dad469b43b1 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,17 @@
++2014-01-18  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* include/grub/misc.h: Move macros for compiler features to ...
++	* include/grub/compiler.h: ... new file.
++	* include/grub/list.h: Include <grub/compiler.h> instead of <grub/misc.h>.
++	* grub-core/commands/fileXX.c: Include <grub/misc.h>.
++	* grub-core/efiemu/prepare.c: Include <grub/misc.h>.
++	* grub-core/loader/i386/xen_file.c: Include <grub/misc.h>.
++	* grub-core/loader/i386/xen_fileXX.c: Include <grub/misc.h>.
++	* grub-core/video/capture.c: Include <grub/misc.h>.
++	* include/grub/command.h: Include <grub/misc.h>.
++	* include/grub/dl.h: Include <grub/misc.h>.
++	* include/grub/procfs.h: Include <grub/misc.h>.
++
+ 2014-01-18  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* configure.ac: Add support for BUILD_EXEEXT and use it ...
diff --git a/SOURCES/0028-grub-core-commands-macbless.c-Rename-FILE-and-DIR-to.patch b/SOURCES/0028-grub-core-commands-macbless.c-Rename-FILE-and-DIR-to.patch
new file mode 100644
index 0000000..88122a7
--- /dev/null
+++ b/SOURCES/0028-grub-core-commands-macbless.c-Rename-FILE-and-DIR-to.patch
@@ -0,0 +1,58 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Sat, 18 Jan 2014 19:26:40 +0100
+Subject: [PATCH] * grub-core/commands/macbless.c: Rename FILE and DIR to avoid
+ conflicts.
+
+	Reported by: Andrey Borzenkov.
+---
+ grub-core/commands/macbless.c | 6 +++---
+ ChangeLog                     | 7 +++++++
+ 2 files changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/commands/macbless.c b/grub-core/commands/macbless.c
+index c5210833ed0..4724edd7709 100644
+--- a/grub-core/commands/macbless.c
++++ b/grub-core/commands/macbless.c
+@@ -37,7 +37,7 @@ struct find_node_context
+   grub_uint64_t inode_found;
+   char *dirname;
+   enum
+-  { NONE, FILE, DIR } found;
++  { FOUND_NONE, FOUND_FILE, FOUND_DIR } found;
+ };
+ 
+ static int
+@@ -53,7 +53,7 @@ find_inode (const char *filename,
+ 	   && grub_strcasecmp (ctx->dirname, filename) == 0)))
+     {
+       ctx->inode_found = info->inode;
+-      ctx->found = info->dir ? DIR : FILE;
++      ctx->found = info->dir ? FOUND_DIR : FOUND_FILE;
+     }
+   return 0;
+ }
+@@ -175,7 +175,7 @@ grub_mac_bless_file (grub_device_t dev, const char *path_in, int intel)
+   grub_free (path);
+ 
+   return grub_mac_bless_inode (dev, (grub_uint32_t) ctx.inode_found,
+-			       (ctx.found == DIR), intel);
++			       (ctx.found == FOUND_DIR), intel);
+ }
+ 
+ static grub_err_t
+diff --git a/ChangeLog b/ChangeLog
+index dad469b43b1..9d1a3f051c1 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,10 @@
++2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/commands/macbless.c: Rename FILE and DIR to avoid
++	conflicts.
++
++	Reported by: Andrey Borzenkov.
++
+ 2014-01-18  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* include/grub/misc.h: Move macros for compiler features to ...
diff --git a/SOURCES/0029-Makefile.util.def-Link-grub-ofpathname-with-zfs-libs.patch b/SOURCES/0029-Makefile.util.def-Link-grub-ofpathname-with-zfs-libs.patch
new file mode 100644
index 0000000..4bf38f3
--- /dev/null
+++ b/SOURCES/0029-Makefile.util.def-Link-grub-ofpathname-with-zfs-libs.patch
@@ -0,0 +1,35 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Mike Gilbert <floppym@gentoo.org>
+Date: Sat, 18 Jan 2014 19:41:15 +0100
+Subject: [PATCH] * Makefile.util.def: Link grub-ofpathname with zfs libs.
+
+---
+ Makefile.util.def | 2 +-
+ ChangeLog         | 4 ++++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/Makefile.util.def b/Makefile.util.def
+index 83df212f412..a286a89cd8d 100644
+--- a/Makefile.util.def
++++ b/Makefile.util.def
+@@ -384,7 +384,7 @@ program = {
+   ldadd = libgrubgcry.a;
+   ldadd = libgrubkern.a;
+   ldadd = grub-core/gnulib/libgnu.a;
+-  ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBGEOM)';
++  ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
+ };
+ 
+ program = {
+diff --git a/ChangeLog b/ChangeLog
+index 9d1a3f051c1..edceb66dbcc 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-01-01  Mike Gilbert <floppym@gentoo.org>
++
++	* Makefile.util.def: Link grub-ofpathname with zfs libs.
++
+ 2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/commands/macbless.c: Rename FILE and DIR to avoid
diff --git a/SOURCES/0030-Makefile.am-default_payload.elf-Add-modules-multiboo.patch b/SOURCES/0030-Makefile.am-default_payload.elf-Add-modules-multiboo.patch
new file mode 100644
index 0000000..b5781c4
--- /dev/null
+++ b/SOURCES/0030-Makefile.am-default_payload.elf-Add-modules-multiboo.patch
@@ -0,0 +1,39 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Sat, 18 Jan 2014 19:43:19 +0100
+Subject: [PATCH] * Makefile.am (default_payload.elf): Add modules multiboot
+ cbmemc linux16 gzio echo help.
+
+---
+ Makefile.am | 2 +-
+ ChangeLog   | 7 ++++++-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index aa526f573c3..97c062d7d35 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -399,7 +399,7 @@ bootcheck: $(BOOTCHECKS)
+ 
+ if COND_i386_coreboot
+ default_payload.elf: grub-mkstandalone grub-mkimage
+-	pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata ehci uhci ohci usb_keyboard usbms part_msdos xfs ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg
++	pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata ehci uhci ohci usb_keyboard usbms part_msdos xfs ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial multiboot cbmemc linux16 gzio echo help' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg
+ endif
+ 
+ windowsdir=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows
+diff --git a/ChangeLog b/ChangeLog
+index edceb66dbcc..cff9386d3d2 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,4 +1,9 @@
+-2014-01-01  Mike Gilbert <floppym@gentoo.org>
++2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* Makefile.am (default_payload.elf): Add modules
++	multiboot cbmemc linux16 gzio echo help.
++
++2014-01-18  Mike Gilbert <floppym@gentoo.org>
+ 
+ 	* Makefile.util.def: Link grub-ofpathname with zfs libs.
+ 
diff --git a/SOURCES/0031-fix-removal-of-cpu-machine-links-on-mingw-msys.patch b/SOURCES/0031-fix-removal-of-cpu-machine-links-on-mingw-msys.patch
new file mode 100644
index 0000000..ae23226
--- /dev/null
+++ b/SOURCES/0031-fix-removal-of-cpu-machine-links-on-mingw-msys.patch
@@ -0,0 +1,52 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Sat, 18 Jan 2014 22:48:04 +0400
+Subject: [PATCH] fix removal of {cpu,machine} links on mingw/msys
+
+At least on Windows 2003 using "ln -s dir1 dir2" in msys shell succeeds,
+but results in what looks like hard link. Subsequent "rm -f dir2" (e.g.
+during second config.status invocation) fails. Check that we also can
+remove link to directory.
+
+Make it more clear in message that we are checking "ln -s".
+---
+ ChangeLog    | 5 +++++
+ acinclude.m4 | 6 +++---
+ 2 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index cff9386d3d2..c3bfa9fcb1b 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-01-18  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* acinclude.m4 (grub_CHECK_LINK_DIR): Check that we can also remove
++	symbolic link to directory. It fails in Msys shell on Windows 2003.
++
+ 2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* Makefile.am (default_payload.elf): Add modules
+diff --git a/acinclude.m4 b/acinclude.m4
+index 32d5477d100..b2bb88d838e 100644
+--- a/acinclude.m4
++++ b/acinclude.m4
+@@ -418,15 +418,15 @@ else
+ [fi]
+ ])
+ 
+-dnl Check if ln can handle directories properly (mingw).
++dnl Check if ln -s can handle directories properly (mingw).
+ AC_DEFUN([grub_CHECK_LINK_DIR],[
+-AC_MSG_CHECKING([whether ln can handle directories properly])
++AC_MSG_CHECKING([whether ln -s can handle directories properly])
+ [mkdir testdir 2>/dev/null
+ case $srcdir in
+ [\\/$]* | ?:[\\/]* ) reldir=$srcdir/include/grub/util ;;
+     *) reldir=../$srcdir/include/grub/util ;;
+ esac
+-if ln -s $reldir testdir/util 2>/dev/null ; then]
++if ln -s $reldir testdir/util 2>/dev/null && rm -f testdir/util 2>/dev/null ; then]
+   AC_MSG_RESULT([yes])
+   [link_dir=yes
+ else
diff --git a/SOURCES/0032-grub-core-normal-main.c-read_config_file-Buffer-conf.patch b/SOURCES/0032-grub-core-normal-main.c-read_config_file-Buffer-conf.patch
new file mode 100644
index 0000000..c019a8e
--- /dev/null
+++ b/SOURCES/0032-grub-core-normal-main.c-read_config_file-Buffer-conf.patch
@@ -0,0 +1,65 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Sat, 18 Jan 2014 19:54:09 +0100
+Subject: [PATCH] * grub-core/normal/main.c (read_config_file): Buffer config
+ file. Reduces boot time.
+
+---
+ grub-core/normal/main.c | 14 +++++++++++---
+ ChangeLog               |  5 +++++
+ 2 files changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
+index c36663f738c..3a926fc5fa9 100644
+--- a/grub-core/normal/main.c
++++ b/grub-core/normal/main.c
+@@ -32,6 +32,7 @@
+ #include <grub/i18n.h>
+ #include <grub/charset.h>
+ #include <grub/script_sh.h>
++#include <grub/bufio.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -104,7 +105,7 @@ read_config_file_getline (char **line, int cont __attribute__ ((unused)),
+ static grub_menu_t
+ read_config_file (const char *config)
+ {
+-  grub_file_t file;
++  grub_file_t rawfile, file;
+   char *old_file = 0, *old_dir = 0;
+   char *config_dir, *ptr = 0;
+   const char *ctmp;
+@@ -122,10 +123,17 @@ read_config_file (const char *config)
+     }
+ 
+   /* Try to open the config file.  */
+-  file = grub_file_open (config);
+-  if (! file)
++  rawfile = grub_file_open (config);
++  if (! rawfile)
+     return 0;
+ 
++  file = grub_bufio_open (rawfile, 0);
++  if (! file)
++    {
++      grub_file_close (file);
++      return 0;
++    }
++
+   ctmp = grub_env_get ("config_file");
+   if (ctmp)
+     old_file = grub_strdup (ctmp);
+diff --git a/ChangeLog b/ChangeLog
+index c3bfa9fcb1b..c84f7e7cc00 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/normal/main.c (read_config_file): Buffer config file.
++	Reduces boot time.
++
+ 2014-01-18  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* acinclude.m4 (grub_CHECK_LINK_DIR): Check that we can also remove
diff --git a/SOURCES/0033-util-grub-install.c-Fix-a-typo.patch b/SOURCES/0033-util-grub-install.c-Fix-a-typo.patch
new file mode 100644
index 0000000..f4eb803
--- /dev/null
+++ b/SOURCES/0033-util-grub-install.c-Fix-a-typo.patch
@@ -0,0 +1,35 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Sat, 18 Jan 2014 20:02:51 +0100
+Subject: [PATCH] * util/grub-install.c: Fix a typo.
+
+---
+ util/grub-install.c | 2 +-
+ ChangeLog           | 4 ++++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/util/grub-install.c b/util/grub-install.c
+index 4608b80fe05..5903f340a61 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -1259,7 +1259,7 @@ main (int argc, char *argv[])
+ 
+   if (!config.is_cryptodisk_enabled && have_cryptodisk)
+     grub_util_error (_("attempt to install to encrypted disk without cryptodisk enabled. "
+-		       "Set `%s' in file `%s'."), "GRUB_ENABLE_CRYPTODISK=1",
++		       "Set `%s' in file `%s'."), "GRUB_ENABLE_CRYPTODISK=y",
+ 		     grub_util_get_config_filename ());
+ 
+   if (disk_module && grub_strcmp (disk_module, "ata") == 0)
+diff --git a/ChangeLog b/ChangeLog
+index c84f7e7cc00..9360345efc2 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* util/grub-install.c: Fix a typo.
++
+ 2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/normal/main.c (read_config_file): Buffer config file.
diff --git a/SOURCES/0034-use-MODULE_FILES-for-genemuinit-instead-of-MOD_FILES.patch b/SOURCES/0034-use-MODULE_FILES-for-genemuinit-instead-of-MOD_FILES.patch
new file mode 100644
index 0000000..b4fd228
--- /dev/null
+++ b/SOURCES/0034-use-MODULE_FILES-for-genemuinit-instead-of-MOD_FILES.patch
@@ -0,0 +1,88 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Sat, 18 Jan 2014 23:15:40 +0400
+Subject: [PATCH] use MODULE_FILES for genemuinit* instead of MOD_FILES
+
+MinGW native nm does not support ELF binaries.
+---
+ ChangeLog                     | 8 ++++++++
+ grub-core/Makefile.am         | 8 ++++----
+ grub-core/genemuinit.sh       | 4 ++--
+ grub-core/genemuinitheader.sh | 4 ++--
+ 4 files changed, 16 insertions(+), 8 deletions(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index 9360345efc2..4688ff4e6d3 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,11 @@
++2014-01-18  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* grub-core/Makefile.am: Build grub_emu_init.[ch] from MODULE_FILES
++	instead of MOD_FILES.
++	* grub-core/genemuinit.sh: Simplify stripping of suffix so it works
++	both with and without .exe.
++	* grub-core/genemuinitheader.sh: Same.
++
+ 2014-01-18  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* util/grub-install.c: Fix a typo.
+diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
+index 826b3dd7c1a..5c087c83b8f 100644
+--- a/grub-core/Makefile.am
++++ b/grub-core/Makefile.am
+@@ -294,12 +294,12 @@ grub_emu-grub_emu_init.$(OBJEXT):grub_emu_init.h
+ kern/emu/grub_emu_dyn-main.$(OBJEXT):grub_emu_init.h
+ grub_emu_dyn-grub_emu_init.$(OBJEXT):grub_emu_init.h
+ 
+-grub_emu_init.h: genemuinitheader.sh $(MOD_FILES)
+-	rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinitheader.sh $(TARGET_NM) > $@
++grub_emu_init.h: genemuinitheader.sh $(MODULE_FILES)
++	rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinitheader.sh $(TARGET_NM) > $@
+ CLEANFILES += grub_emu_init.h
+ 
+-grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MOD_FILES)
+-	rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinit.sh $(TARGET_NM) > $@
++grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MODULE_FILES)
++	rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinit.sh $(TARGET_NM) > $@
+ CLEANFILES += grub_emu_init.c
+ endif
+ 
+diff --git a/grub-core/genemuinit.sh b/grub-core/genemuinit.sh
+index 45c15ecb9f4..8c6bb1c18ff 100644
+--- a/grub-core/genemuinit.sh
++++ b/grub-core/genemuinit.sh
+@@ -47,7 +47,7 @@ EOF
+ read mods
+ for line in $mods; do
+   if ${nm} --defined-only -P -p ${line} | grep grub_mod_init > /dev/null; then
+-      echo "grub_${line}_init ();" | sed 's,\.mod,,g;'
++      echo "grub_${line%%.*}_init ();"
+   fi
+ done
+ 
+@@ -63,7 +63,7 @@ EOF
+ 
+ for line in $mods; do
+   if ${nm} --defined-only -P -p ${line} | grep grub_mod_fini > /dev/null; then
+-      echo "grub_${line}_fini ();" | sed 's,\.mod,,g;'
++      echo "grub_${line%%.*}_fini ();"
+   fi
+ done
+ 
+diff --git a/grub-core/genemuinitheader.sh b/grub-core/genemuinitheader.sh
+index 6b83f599317..a99a15d06f1 100644
+--- a/grub-core/genemuinitheader.sh
++++ b/grub-core/genemuinitheader.sh
+@@ -44,9 +44,9 @@ EOF
+ read mods
+ for line in $mods; do
+   if ${nm} --defined-only -P -p ${line} | grep grub_mod_init > /dev/null; then
+-      echo "void grub_${line}_init (void);" | sed 's,\.mod,,g;'
++      echo "void grub_${line%%.*}_init (void);"
+   fi
+   if ${nm} --defined-only -P -p ${line} | grep grub_mod_fini > /dev/null; then
+-      echo "void grub_${line}_fini (void);" | sed 's,\.mod,,g;'
++      echo "void grub_${line%%.*}_fini (void);"
+   fi
+ done
diff --git a/SOURCES/0035-Ignore-EPERM-when-modifying-kern.geom.debugflags.patch b/SOURCES/0035-Ignore-EPERM-when-modifying-kern.geom.debugflags.patch
new file mode 100644
index 0000000..0c2043c
--- /dev/null
+++ b/SOURCES/0035-Ignore-EPERM-when-modifying-kern.geom.debugflags.patch
@@ -0,0 +1,55 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Fri, 17 Jan 2014 02:28:46 +0000
+Subject: [PATCH] Ignore EPERM when modifying kern.geom.debugflags
+
+Many tests fail when run as a non-root user on FreeBSD.  The failures
+all amount to an inability to open files using grub_util_fd_open,
+because we cannot set the kern.geom.debugflags sysctl.  This sysctl is
+indeed important to allow us to do such things as installing GRUB to the
+MBR, but if we need to do that and can't then we will get an error
+later.  Enforcing it here is unnecessary and prevents otherwise
+perfectly reasonable operations.
+---
+ grub-core/osdep/freebsd/hostdisk.c | 12 ++++++++++--
+ ChangeLog                          |  7 +++++++
+ 2 files changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/osdep/freebsd/hostdisk.c b/grub-core/osdep/freebsd/hostdisk.c
+index eb202dcc831..6145d073555 100644
+--- a/grub-core/osdep/freebsd/hostdisk.c
++++ b/grub-core/osdep/freebsd/hostdisk.c
+@@ -102,8 +102,16 @@ grub_util_fd_open (const char *os_dev, int flags)
+   if (! (sysctl_oldflags & 0x10)
+       && sysctlbyname ("kern.geom.debugflags", NULL , 0, &sysctl_flags, sysctl_size))
+     {
+-      grub_error (GRUB_ERR_BAD_DEVICE, "cannot set flags of sysctl kern.geom.debugflags");
+-      return GRUB_UTIL_FD_INVALID;
++      if (errno == EPERM)
++	/* Running as an unprivileged user; don't worry about restoring
++	   flags, although if we try to write to anything interesting such
++	   as the MBR then we may fail later.  */
++	sysctl_oldflags = 0x10;
++      else
++	{
++	  grub_error (GRUB_ERR_BAD_DEVICE, "cannot set flags of sysctl kern.geom.debugflags");
++	  return GRUB_UTIL_FD_INVALID;
++	}
+     }
+ 
+   ret = open (os_dev, flags, S_IROTH | S_IRGRP | S_IRUSR | S_IWUSR);
+diff --git a/ChangeLog b/ChangeLog
+index 4688ff4e6d3..10abfe28f20 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,10 @@
++2014-01-19  Colin Watson  <cjwatson@ubuntu.com>
++
++	* grub-core/osdep/freebsd/hostdisk.c (grub_util_fd_open): Ignore
++	EPERM when modifying kern.geom.debugflags.  It is only a problem for
++	such things as installing GRUB to the MBR, in which case there'll be
++	an error later anyway, not for opening files during tests.
++
+ 2014-01-18  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* grub-core/Makefile.am: Build grub_emu_init.[ch] from MODULE_FILES
diff --git a/SOURCES/0036-change-stop-condition-to-avoid-infinite-loops.patch b/SOURCES/0036-change-stop-condition-to-avoid-infinite-loops.patch
new file mode 100644
index 0000000..e16c2d1
--- /dev/null
+++ b/SOURCES/0036-change-stop-condition-to-avoid-infinite-loops.patch
@@ -0,0 +1,49 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
+Date: Tue, 21 Jan 2014 10:49:39 -0200
+Subject: [PATCH] change stop condition to avoid infinite loops
+
+In net/net.c there is a while (1) that only exits if there is a stop
+condition and more then 10 packages or if there is no package received.
+
+If GRUB is idle and enter in this loop, the only condition to leave is
+if it doesn't have incoming packages. In a network with heavy traffic
+this never happens.
+---
+ grub-core/net/net.c |  2 +-
+ ChangeLog           | 12 ++++++++++++
+ 2 files changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index 0e57e93e821..56355f3c98c 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -1453,7 +1453,7 @@ receive_packets (struct grub_net_card *card, int *stop_condition)
+ 	}
+       card->opened = 1;
+     }
+-  while (1)
++  while (received < 100)
+     {
+       /* Maybe should be better have a fixed number of packets for each card
+ 	 and just mark them as used and not used.  */ 
+diff --git a/ChangeLog b/ChangeLog
+index 10abfe28f20..f69d8c7e042 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,15 @@
++2014-01-21  Paulo Flabiano Smorigo  <pfsmorigo@br.ibm.com>
++
++	* grub-core/net/net.c (receive_packets): Change stop condition to avoid
++	infinite loops.
++
++	In net/net.c there is a while (1) that only exits if there is a stop
++	condition and more then 10 packages or if there is no package received.
++
++	If GRUB is idle and enter in this loop, the only condition to leave is
++	if it doesn't have incoming packages. In a network with heavy traffic
++	this never happens.
++
+ 2014-01-19  Colin Watson  <cjwatson@ubuntu.com>
+ 
+ 	* grub-core/osdep/freebsd/hostdisk.c (grub_util_fd_open): Ignore
diff --git a/SOURCES/0037-increase-network-try-interval-gradually.patch b/SOURCES/0037-increase-network-try-interval-gradually.patch
new file mode 100644
index 0000000..f3ddc4c
--- /dev/null
+++ b/SOURCES/0037-increase-network-try-interval-gradually.patch
@@ -0,0 +1,106 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
+Date: Tue, 21 Jan 2014 11:03:51 -0200
+Subject: [PATCH] increase network try interval gradually
+
+* grub-core/net/arp.c (grub_net_arp_send_request): Increase network try
+interval gradually.
+* grub-core/net/icmp6.c (grub_net_icmp6_send_request): Likewise.
+* grub-core/net/net.c (grub_net_fs_read_real): Likewise.
+* grub-core/net/tftp.c (tftp_open): Likewise.
+* include/grub/net.h (GRUB_NET_INTERVAL_ADDITION): New define.
+---
+ grub-core/net/arp.c   | 3 ++-
+ grub-core/net/icmp6.c | 3 ++-
+ grub-core/net/net.c   | 5 +++--
+ grub-core/net/tftp.c  | 3 ++-
+ include/grub/net.h    | 1 +
+ ChangeLog             | 9 +++++++++
+ 6 files changed, 19 insertions(+), 5 deletions(-)
+
+diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c
+index e92c7e7daec..d62d0cc1e01 100644
+--- a/grub-core/net/arp.c
++++ b/grub-core/net/arp.c
+@@ -110,7 +110,8 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
+ 	return GRUB_ERR_NONE;
+       pending_req = proto_addr->ipv4;
+       have_pending = 0;
+-      grub_net_poll_cards (GRUB_NET_INTERVAL, &have_pending);
++      grub_net_poll_cards (GRUB_NET_INTERVAL + (i * GRUB_NET_INTERVAL_ADDITION),
++                           &have_pending);
+       if (grub_net_link_layer_resolve_check (inf, proto_addr))
+ 	return GRUB_ERR_NONE;
+       nb.data = nbd;
+diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c
+index 2741e6f11fb..bbc902014fe 100644
+--- a/grub-core/net/icmp6.c
++++ b/grub-core/net/icmp6.c
+@@ -518,7 +518,8 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf,
+     {
+       if (grub_net_link_layer_resolve_check (inf, proto_addr))
+ 	break;
+-      grub_net_poll_cards (GRUB_NET_INTERVAL, 0);
++      grub_net_poll_cards (GRUB_NET_INTERVAL + (i * GRUB_NET_INTERVAL_ADDITION),
++                           0);
+       if (grub_net_link_layer_resolve_check (inf, proto_addr))
+ 	break;
+       nb->data = nbd;
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index 56355f3c98c..1521d8d2c87 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -1558,8 +1558,9 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len)
+       if (!net->eof)
+ 	{
+ 	  try++;
+-	  grub_net_poll_cards (GRUB_NET_INTERVAL, &net->stall);
+-	}
++	  grub_net_poll_cards (GRUB_NET_INTERVAL +
++                               (try * GRUB_NET_INTERVAL_ADDITION), &net->stall);
++        }
+       else
+ 	return total;
+     }
+diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
+index 9c489f1fc94..51736142764 100644
+--- a/grub-core/net/tftp.c
++++ b/grub-core/net/tftp.c
+@@ -398,7 +398,8 @@ tftp_open (struct grub_file *file, const char *filename)
+ 	  destroy_pq (data);
+ 	  return err;
+ 	}
+-      grub_net_poll_cards (GRUB_NET_INTERVAL, &data->have_oack);
++      grub_net_poll_cards (GRUB_NET_INTERVAL + (i * GRUB_NET_INTERVAL_ADDITION),
++                           &data->have_oack);
+       if (data->have_oack)
+ 	break;
+     }
+diff --git a/include/grub/net.h b/include/grub/net.h
+index de6259ee1a0..0e0a605c5a6 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -532,5 +532,6 @@ extern char *grub_net_default_server;
+ 
+ #define GRUB_NET_TRIES 40
+ #define GRUB_NET_INTERVAL 400
++#define GRUB_NET_INTERVAL_ADDITION 20
+ 
+ #endif /* ! GRUB_NET_HEADER */
+diff --git a/ChangeLog b/ChangeLog
+index f69d8c7e042..f5618a6eb70 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,12 @@
++2014-01-21  Paulo Flabiano Smorigo  <pfsmorigo@br.ibm.com>
++
++	* grub-core/net/arp.c (grub_net_arp_send_request): Increase network try
++	interval gradually.
++	* grub-core/net/icmp6.c (grub_net_icmp6_send_request): Likewise.
++	* grub-core/net/net.c (grub_net_fs_read_real): Likewise.
++	* grub-core/net/tftp.c (tftp_open): Likewise.
++	* include/grub/net.h (GRUB_NET_INTERVAL_ADDITION): New define.
++
+ 2014-01-21  Paulo Flabiano Smorigo  <pfsmorigo@br.ibm.com>
+ 
+ 	* grub-core/net/net.c (receive_packets): Change stop condition to avoid
diff --git a/SOURCES/0038-look-for-DejaVu-also-in-usr-share-fonts-truetype.patch b/SOURCES/0038-look-for-DejaVu-also-in-usr-share-fonts-truetype.patch
new file mode 100644
index 0000000..72a51a0
--- /dev/null
+++ b/SOURCES/0038-look-for-DejaVu-also-in-usr-share-fonts-truetype.patch
@@ -0,0 +1,36 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Tue, 21 Jan 2014 19:29:33 +0400
+Subject: [PATCH] look for DejaVu also in /usr/share/fonts/truetype
+
+It is installed in this path on openSUSE.
+---
+ configure.ac | 2 +-
+ ChangeLog    | 4 ++++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/configure.ac b/configure.ac
+index cf3de3be1fc..120263e9c58 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1389,7 +1389,7 @@ fi
+ 
+ if test x"$starfield_excuse" = x; then
+    for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do
+-     for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu; do
++     for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype; do
+         if test -f "$dir/DejaVuSans.$ext"; then
+           DJVU_FONT_SOURCE="$dir/DejaVuSans.$ext"
+           break 2
+diff --git a/ChangeLog b/ChangeLog
+index f5618a6eb70..9f5d81dfbac 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-01-21  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* configure.ac: Look for DejaVuSans also in /usr/share/fonts/truetype.
++
+ 2014-01-21  Paulo Flabiano Smorigo  <pfsmorigo@br.ibm.com>
+ 
+ 	* grub-core/net/arp.c (grub_net_arp_send_request): Increase network try
diff --git a/SOURCES/0039-Show-detected-path-to-DejaVuSans-in-configure-summar.patch b/SOURCES/0039-Show-detected-path-to-DejaVuSans-in-configure-summar.patch
new file mode 100644
index 0000000..9162ce2
--- /dev/null
+++ b/SOURCES/0039-Show-detected-path-to-DejaVuSans-in-configure-summar.patch
@@ -0,0 +1,34 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Tue, 21 Jan 2014 19:41:11 +0400
+Subject: [PATCH] Show detected path to DejaVuSans in configure summary
+
+---
+ configure.ac | 1 +
+ ChangeLog    | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/configure.ac b/configure.ac
+index 120263e9c58..8888c2ff29c 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1816,6 +1816,7 @@ echo grub-mount: No "($grub_mount_excuse)"
+ fi
+ if [ x"$starfield_excuse" = x ]; then
+ echo starfield theme: Yes
++echo With DejaVuSans font from $DJVU_FONT_SOURCE
+ else
+ echo starfield theme: No "($starfield_excuse)"
+ fi
+diff --git a/ChangeLog b/ChangeLog
+index 9f5d81dfbac..3ba57aed842 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,6 +1,7 @@
+ 2014-01-21  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* configure.ac: Look for DejaVuSans also in /usr/share/fonts/truetype.
++	Show detected font path in summary.
+ 
+ 2014-01-21  Paulo Flabiano Smorigo  <pfsmorigo@br.ibm.com>
+ 
diff --git a/SOURCES/0040-add-GRUB_WINDOWS_EXTRA_DIST-to-allow-shipping-runtim.patch b/SOURCES/0040-add-GRUB_WINDOWS_EXTRA_DIST-to-allow-shipping-runtim.patch
new file mode 100644
index 0000000..832f2f1
--- /dev/null
+++ b/SOURCES/0040-add-GRUB_WINDOWS_EXTRA_DIST-to-allow-shipping-runtim.patch
@@ -0,0 +1,56 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Tue, 21 Jan 2014 20:54:09 +0400
+Subject: [PATCH] add GRUB_WINDOWS_EXTRA_DIST to allow shipping runtime files
+
+Not all toolkits provide static libraries. This patch enables creation of self
+contained distribution that does not require pre-existing runtime libraries.
+Intended usage is
+
+export GRUB_WINDOWS_EXTRA_DIST="/path/to/liblzma.dll /path/to/libintl.dll"
+make
+make windowszip
+
+As those libraries and locations are dependent on toolchain in use, trying
+to autodetect them is likely impossible. So just provide a simple way to
+package everything in one step.
+
+Also remove $(windowsdir) after ZIP was created same as other "make dist"
+targets.
+---
+ Makefile.am | 4 ++++
+ ChangeLog   | 5 +++++
+ 2 files changed, 9 insertions(+)
+
+diff --git a/Makefile.am b/Makefile.am
+index 97c062d7d35..f02ae0a393c 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -420,10 +420,14 @@ windowsdir: $(PROGRAMS) $(starfield_DATA) $(platform_DATA)
+ 	for x in $(starfield_DATA); do \
+ 		cp -fp $$x $(windowsdir)/themes/starfield/$$(basename $$x); \
+ 	done
++	for x in $(GRUB_WINDOWS_EXTRA_DIST); do \
++		cp -fp $$x $(windowsdir); \
++	done
+ 
+ windowszip=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows.zip
+ windowszip: windowsdir
+ 	test -f $(windowszip) && rm $(windowszip) || true
+ 	zip -r $(windowszip) $(windowsdir)
++	rm -rf $(windowsdir)
+ 
+ EXTRA_DIST += linguas.sh
+diff --git a/ChangeLog b/ChangeLog
+index 3ba57aed842..1ede3709165 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-01-21  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* Makefile.am: Allow adding extra files to generated Windows ZIP
++	archive by setting GRUB_WINDOWS_EXTRA_DIST.
++
+ 2014-01-21  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* configure.ac: Look for DejaVuSans also in /usr/share/fonts/truetype.
diff --git a/SOURCES/0041-util-grub-install.c-write_to_disk-Add-an-info-messag.patch b/SOURCES/0041-util-grub-install.c-write_to_disk-Add-an-info-messag.patch
new file mode 100644
index 0000000..003b15f
--- /dev/null
+++ b/SOURCES/0041-util-grub-install.c-write_to_disk-Add-an-info-messag.patch
@@ -0,0 +1,34 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Thu, 23 Jan 2014 12:05:36 +0000
+Subject: [PATCH] * util/grub-install.c (write_to_disk): Add an info message.
+
+---
+ util/grub-install.c | 1 +
+ ChangeLog           | 4 ++++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/util/grub-install.c b/util/grub-install.c
+index 5903f340a61..787dc90fce5 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -675,6 +675,7 @@ write_to_disk (grub_device_t dev, const char *fn)
+ 
+   core_img = grub_util_read_image (fn);    
+ 
++  grub_util_info ("writing `%s' to `%s'", fn, dev->disk->name);
+   err = grub_disk_write (dev->disk, 0, 0,
+ 			 core_size, core_img);
+   free (core_img);
+diff --git a/ChangeLog b/ChangeLog
+index 1ede3709165..eee8e78a726 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-01-23  Colin Watson  <cjwatson@ubuntu.com>
++
++	* util/grub-install.c (write_to_disk): Add an info message.
++
+ 2014-01-21  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* Makefile.am: Allow adding extra files to generated Windows ZIP
diff --git a/SOURCES/0042-util-grub-install.c-List-available-targets.patch b/SOURCES/0042-util-grub-install.c-List-available-targets.patch
new file mode 100644
index 0000000..364f5af
--- /dev/null
+++ b/SOURCES/0042-util-grub-install.c-List-available-targets.patch
@@ -0,0 +1,106 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 24 Jan 2014 18:09:25 +0100
+Subject: [PATCH] * util/grub-install.c: List available targets.
+
+---
+ util/grub-install-common.c  | 30 ++++++++++++++++++++++++++++++
+ util/grub-install.c         | 10 ++++++++--
+ include/grub/util/install.h |  2 ++
+ ChangeLog                   |  4 ++++
+ 4 files changed, 44 insertions(+), 2 deletions(-)
+
+diff --git a/util/grub-install-common.c b/util/grub-install-common.c
+index 6ea0a8e1795..c8bedcb2e59 100644
+--- a/util/grub-install-common.c
++++ b/util/grub-install-common.c
+@@ -667,6 +667,36 @@ static struct
+     [GRUB_INSTALL_PLATFORM_ARM_UBOOT] =        { "arm",     "uboot"     },
+   }; 
+ 
++char *
++grub_install_get_platforms_string (void)
++{
++  char **arr = xmalloc (sizeof (char *) * ARRAY_SIZE (platforms));
++  int platform_strins_len = 0;
++  char *platforms_string;
++  char *ptr;
++  unsigned i;
++  for (i = 0; i < ARRAY_SIZE (platforms); i++)
++    {
++      arr[i] = xasprintf ("%s-%s", platforms[i].cpu,
++			  platforms[i].platform);
++      platform_strins_len += strlen (arr[i]) + 2;
++    }
++  ptr = platforms_string = xmalloc (platform_strins_len);
++  qsort (arr, ARRAY_SIZE (platforms), sizeof (char *), grub_qsort_strcmp);
++  for (i = 0; i < ARRAY_SIZE (platforms); i++)
++    {
++      strcpy (ptr, arr[i]);
++      ptr += strlen (arr[i]);
++      *ptr++ = ',';
++      *ptr++ = ' ';
++      free (arr[i]);
++    }
++  ptr[-2] = 0;
++  free (arr);
++ 
++  return platforms_string;
++}
++
+ char *
+ grub_install_get_platform_name (enum grub_install_plat platid)
+ {
+diff --git a/util/grub-install.c b/util/grub-install.c
+index 787dc90fce5..2e6226a3716 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -256,7 +256,7 @@ static struct argp_option options[] = {
+    OPTION_HIDDEN, 0, 2},
+   {"target", OPTION_TARGET, N_("TARGET"),
+    /* TRANSLATORS: "TARGET" as in "target platform".  */
+-   0, N_("install GRUB for TARGET platform [default=%s]"), 2},
++   0, N_("install GRUB for TARGET platform [default=%s]; available targets: %s"), 2},
+   {"grub-setup", OPTION_SETUP, "FILE", OPTION_HIDDEN, 0, 2},
+   {"grub-mkrelpath", OPTION_MKRELPATH, "FILE", OPTION_HIDDEN, 0, 2},
+   {"grub-mkdevicemap", OPTION_MKDEVICEMAP, "FILE", OPTION_HIDDEN, 0, 2},
+@@ -340,7 +340,13 @@ help_filter (int key, const char *text, void *input __attribute__ ((unused)))
+     case OPTION_BOOT_DIRECTORY:
+       return xasprintf (text, GRUB_DIR_NAME, GRUB_BOOT_DIR_NAME "/" GRUB_DIR_NAME);
+     case OPTION_TARGET:
+-      return xasprintf (text, get_default_platform ());
++      {
++	char *plats = grub_install_get_platforms_string ();
++	char *ret;
++	ret = xasprintf (text, get_default_platform (), plats);
++	free (plats);
++	return ret;
++      }
+     case ARGP_KEY_HELP_POST_DOC:
+       return xasprintf (text, program_name, GRUB_BOOT_DIR_NAME "/" GRUB_DIR_NAME);
+     default:
+diff --git a/include/grub/util/install.h b/include/grub/util/install.h
+index bc987aadc16..aedcd29f905 100644
+--- a/include/grub/util/install.h
++++ b/include/grub/util/install.h
+@@ -138,6 +138,8 @@ grub_install_get_platform_cpu (enum grub_install_plat platid);
+ const char *
+ grub_install_get_platform_platform (enum grub_install_plat platid);
+ 
++char *
++grub_install_get_platforms_string (void);
+ 
+ typedef enum {
+   GRUB_COMPRESSION_AUTO,
+diff --git a/ChangeLog b/ChangeLog
+index eee8e78a726..20e8baaa23e 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-01-24  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* util/grub-install.c: List available targets.
++
+ 2014-01-23  Colin Watson  <cjwatson@ubuntu.com>
+ 
+ 	* util/grub-install.c (write_to_disk): Add an info message.
diff --git a/SOURCES/0043-Fix-several-translatable-strings.patch b/SOURCES/0043-Fix-several-translatable-strings.patch
new file mode 100644
index 0000000..7cbc73f
--- /dev/null
+++ b/SOURCES/0043-Fix-several-translatable-strings.patch
@@ -0,0 +1,73 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 24 Jan 2014 18:20:27 +0100
+Subject: [PATCH] Fix several translatable strings.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+	Suggested by: D. Prévot.
+---
+ grub-core/commands/syslinuxcfg.c | 2 +-
+ grub-core/loader/arm64/linux.c   | 2 +-
+ util/grub-syslinux2cfg.c         | 4 ++--
+ ChangeLog                        | 6 ++++++
+ 4 files changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/commands/syslinuxcfg.c b/grub-core/commands/syslinuxcfg.c
+index a4bfc40b6d2..00ae113c5a7 100644
+--- a/grub-core/commands/syslinuxcfg.c
++++ b/grub-core/commands/syslinuxcfg.c
+@@ -50,7 +50,7 @@ static const struct grub_arg_option options[] =
+      N_("root directory of the syslinux disk [default=/]."),
+      N_("DIR"), ARG_TYPE_STRING},
+     {"cwd",  'c', 0,
+-     N_("current directory of the syslinux [default is parent directory of input file]."),
++     N_("current directory of syslinux [default is parent directory of input file]."),
+      N_("DIR"), ARG_TYPE_STRING},
+     {"isolinux",     'i',  0, N_("assume input is an isolinux configuration file."), 0, 0},
+     {"pxelinux",     'p',  0, N_("assume input is a pxelinux configuration file."), 0, 0},
+diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
+index 75ad871a81c..65129c21a8d 100644
+--- a/grub-core/loader/arm64/linux.c
++++ b/grub-core/loader/arm64/linux.c
+@@ -120,7 +120,7 @@ check_kernel (struct grub_arm64_linux_kernel_header *lh)
+ 
+   if ((lh->code0 & 0xffff) != GRUB_EFI_PE_MAGIC)
+     return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+-		       N_("plain Image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
++		       N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
+ 
+   grub_dprintf ("linux", "UEFI stub kernel:\n");
+   grub_dprintf ("linux", "text_offset = 0x%012llx\n",
+diff --git a/util/grub-syslinux2cfg.c b/util/grub-syslinux2cfg.c
+index 5e944c20a83..f4fda6db9bb 100644
+--- a/util/grub-syslinux2cfg.c
++++ b/util/grub-syslinux2cfg.c
+@@ -66,10 +66,10 @@ static struct argp_option options[] = {
+    N_("root directory of the syslinux disk [default=/]."), 0},
+   {"target-cwd",  'T', N_("DIR"), 0,
+    N_(
+-      "current directory of the syslinux as it will be seen on runtime  [default is parent directory of input file]."
++      "current directory of syslinux as it will be seen on runtime  [default is parent directory of input file]."
+ ), 0},
+   {"cwd",  'c', N_("DIR"), 0,
+-   N_("current directory of the syslinux [default is parent directory of input file]."), 0},
++   N_("current directory of syslinux [default is parent directory of input file]."), 0},
+ 
+   {"output",  'o', N_("FILE"), 0, N_("write output to FILE [default=stdout]."), 0},
+   {"isolinux",     'i', 0,      0, N_("assume input is an isolinux configuration file."), 0},
+diff --git a/ChangeLog b/ChangeLog
+index 20e8baaa23e..e149d8ef33d 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,9 @@
++2014-01-24  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	Fix several translatable strings.
++
++	Suggested by: D. Prévot.
++
+ 2014-01-24  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* util/grub-install.c: List available targets.
diff --git a/SOURCES/0044-do-not-set-default-prefix-in-grub-mkimage.patch b/SOURCES/0044-do-not-set-default-prefix-in-grub-mkimage.patch
new file mode 100644
index 0000000..3a6d430
--- /dev/null
+++ b/SOURCES/0044-do-not-set-default-prefix-in-grub-mkimage.patch
@@ -0,0 +1,72 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Sat, 25 Jan 2014 19:54:51 +0400
+Subject: [PATCH] do not set default prefix in grub-mkimage
+
+Default prefix is likely wrong on Unix and completely wrong on Windows.
+Let caller set it explicitly to avoid any ambiguity.
+---
+ util/grub-mkimage.c | 16 +++++++++++-----
+ ChangeLog           |  4 ++++
+ 2 files changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
+index a2bd4c196e5..1e0bcf1bf4f 100644
+--- a/util/grub-mkimage.c
++++ b/util/grub-mkimage.c
+@@ -64,7 +64,7 @@ static struct argp_option options[] = {
+   {"directory",  'd', N_("DIR"), 0,
+    /* TRANSLATORS: platform here isn't identifier. It can be translated.  */
+    N_("use images and modules under DIR [default=%s/<platform>]"), 0},
+-  {"prefix",  'p', N_("DIR"), 0, N_("set prefix directory [default=%s]"), 0},
++  {"prefix",  'p', N_("DIR"), 0, N_("set prefix directory"), 0},
+   {"memdisk",  'm', N_("FILE"), 0,
+    /* TRANSLATORS: "memdisk" here isn't an identifier, it can be translated.
+     "embed" is a verb (command description).  "*/
+@@ -93,8 +93,6 @@ help_filter (int key, const char *text, void *input __attribute__ ((unused)))
+     {
+     case 'd':
+       return xasprintf (text, grub_util_get_pkglibdir ());
+-    case 'p':
+-      return xasprintf (text, DEFAULT_DIRECTORY);
+     case 'O':
+       {
+ 	char *formats = grub_install_get_image_targets_string (), *ret;
+@@ -268,6 +266,15 @@ main (int argc, char *argv[])
+       exit(1);
+     }
+ 
++  if (!arguments.prefix)
++    {
++      char *program = xstrdup(program_name);
++      printf ("%s\n", _("Prefix not specified (use the -p option)."));
++      argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program);
++      free (program);
++      exit(1);
++    }
++
+   if (arguments.output)
+     {
+       fp = grub_util_fopen (arguments.output, "wb");
+@@ -287,8 +294,7 @@ main (int argc, char *argv[])
+       strcpy (ptr, dn);
+     }
+ 
+-  grub_install_generate_image (arguments.dir,
+-			       arguments.prefix ? : DEFAULT_DIRECTORY, fp,
++  grub_install_generate_image (arguments.dir, arguments.prefix, fp,
+ 			       arguments.output, arguments.modules,
+ 			       arguments.memdisk, arguments.pubkeys,
+ 			       arguments.npubkeys, arguments.config,
+diff --git a/ChangeLog b/ChangeLog
+index e149d8ef33d..b405b7ee5bd 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-01-25  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* util/grub-mkimage.c: Make prefix argument mandatory.
++
+ 2014-01-24  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	Fix several translatable strings.
diff --git a/SOURCES/0045-fix-Mingw-W64-32-cross-compile-failure-due-to-printf.patch b/SOURCES/0045-fix-Mingw-W64-32-cross-compile-failure-due-to-printf.patch
new file mode 100644
index 0000000..cbd9868
--- /dev/null
+++ b/SOURCES/0045-fix-Mingw-W64-32-cross-compile-failure-due-to-printf.patch
@@ -0,0 +1,105 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Sat, 25 Jan 2014 21:49:41 +0400
+Subject: [PATCH] fix Mingw W64-32 cross compile failure due to printf
+ redefinition in libintl.h
+
+In file included from util/misc.c:36:0:
+./include/grub/emu/misc.h:56:1: error: 'libintl_printf' is an unrecognized format function type [-Werror=format=]
+ char * EXPORT_FUNC(xasprintf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) WARN_UNUSED_RESULT;
+ ^
+./include/grub/emu/misc.h:58:1: error: 'libintl_printf' is an unrecognized format function type [-Werror=format=]
+
+The reason is libintl.h which redefines printf as libintl_printf. The problem
+is not present in native MinGW build which avoids redefinition.  Use
+(format (__printf__) instead which is valid replacement in GCC.
+
+v2: add grub-core/lib/libgcrypt/src/g10lib.h
+v3: modify g10lib.h during import
+---
+ include/grub/crypto.h   | 2 +-
+ include/grub/emu/misc.h | 8 ++++----
+ include/grub/err.h      | 2 +-
+ ChangeLog               | 9 +++++++++
+ util/import_gcry.py     | 6 ++++++
+ 5 files changed, 21 insertions(+), 6 deletions(-)
+
+diff --git a/include/grub/crypto.h b/include/grub/crypto.h
+index ec1b980d2ec..a24e89dd9cd 100644
+--- a/include/grub/crypto.h
++++ b/include/grub/crypto.h
+@@ -408,7 +408,7 @@ void _gcry_assert_failed (const char *expr, const char *file, int line,
+                           const char *func) __attribute__ ((noreturn));
+ 
+ void _gcry_burn_stack (int bytes);
+-void _gcry_log_error( const char *fmt, ... )  __attribute__ ((format (printf, 1, 2)));
++void _gcry_log_error( const char *fmt, ... )  __attribute__ ((format (__printf__, 1, 2)));
+ 
+ 
+ #ifdef GRUB_UTIL
+diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h
+index dde48c192d3..a588ba21da2 100644
+--- a/include/grub/emu/misc.h
++++ b/include/grub/emu/misc.h
+@@ -53,11 +53,11 @@ grub_util_device_is_mapped (const char *dev);
+ void * EXPORT_FUNC(xmalloc) (grub_size_t size) WARN_UNUSED_RESULT;
+ void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) WARN_UNUSED_RESULT;
+ char * EXPORT_FUNC(xstrdup) (const char *str) WARN_UNUSED_RESULT;
+-char * EXPORT_FUNC(xasprintf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) WARN_UNUSED_RESULT;
++char * EXPORT_FUNC(xasprintf) (const char *fmt, ...) __attribute__ ((format (__printf__, 1, 2))) WARN_UNUSED_RESULT;
+ 
+-void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+-void EXPORT_FUNC(grub_util_info) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+-void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2), noreturn));
++void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...) __attribute__ ((format (__printf__, 1, 2)));
++void EXPORT_FUNC(grub_util_info) (const char *fmt, ...) __attribute__ ((format (__printf__, 1, 2)));
++void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((format (__printf__, 1, 2), noreturn));
+ 
+ grub_uint64_t EXPORT_FUNC (grub_util_get_cpu_time_ms) (void);
+ 
+diff --git a/include/grub/err.h b/include/grub/err.h
+index 9896fccf98a..1590c688e1d 100644
+--- a/include/grub/err.h
++++ b/include/grub/err.h
+@@ -91,6 +91,6 @@ int EXPORT_FUNC(grub_error_pop) (void);
+ void EXPORT_FUNC(grub_print_error) (void);
+ extern int EXPORT_VAR(grub_err_printed_errors);
+ int grub_err_printf (const char *fmt, ...)
+-     __attribute__ ((format (printf, 1, 2)));
++     __attribute__ ((format (__printf__, 1, 2)));
+ 
+ #endif /* ! GRUB_ERR_HEADER */
+diff --git a/ChangeLog b/ChangeLog
+index b405b7ee5bd..c93f11fbb20 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,12 @@
++
++2014-01-25  Andrey Borzenkov <arvidjaar@gmail.com>
++
++	* include/grub/crypto.h: Replace __attribute__ ((format (printf)) with
++	__attribute__ ((format (__printf__)) to fix compilation under MinGW-w64.
++	* include/grub/emu/misc.h: ... and here.
++	* include/grub/err.h: ... and here.
++	* util/import_gcry.py: ... and here (in files g10lib.h).
++
+ 2014-01-25  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
+ 	* util/grub-mkimage.c: Make prefix argument mandatory.
+diff --git a/util/import_gcry.py b/util/import_gcry.py
+index 63ebb90f1fe..2b3322d3a12 100644
+--- a/util/import_gcry.py
++++ b/util/import_gcry.py
+@@ -534,6 +534,12 @@ for src in sorted (os.listdir (os.path.join (indir, "src"))):
+         fw.close ()
+         continue
+ 
++    if src == "g10lib.h":
++        fw.write (f.read ().replace ("(printf,f,a)", "(__printf__,f,a)"))
++        f.close ()
++        fw.close ()
++        continue
++
+     fw.write (f.read ())
+     f.close ()
+     fw.close ()
diff --git a/SOURCES/0046-grub-core-term-serial.c-grub_serial_register-Fix-inv.patch b/SOURCES/0046-grub-core-term-serial.c-grub_serial_register-Fix-inv.patch
new file mode 100644
index 0000000..2f0d133
--- /dev/null
+++ b/SOURCES/0046-grub-core-term-serial.c-grub_serial_register-Fix-inv.patch
@@ -0,0 +1,57 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Sun, 26 Jan 2014 02:36:05 +0100
+Subject: [PATCH] * grub-core/term/serial.c (grub_serial_register): Fix invalid
+ free. Ensure that pointers are inited to NULL and that pointers are not
+ accessed after free.
+
+---
+ grub-core/term/serial.c | 8 ++++----
+ ChangeLog               | 5 +++++
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c
+index b581a763ed0..c9b5574ae3c 100644
+--- a/grub-core/term/serial.c
++++ b/grub-core/term/serial.c
+@@ -338,23 +338,23 @@ grub_serial_register (struct grub_serial_port *port)
+       grub_free (indata);
+       return grub_errno;
+     }
+-  
+-  out = grub_malloc (sizeof (*out));
++
++  out = grub_zalloc (sizeof (*out));
+   if (!out)
+     {
+-      grub_free (in);
+       grub_free (indata);
+       grub_free ((char *) in->name);
++      grub_free (in);
+       return grub_errno;
+     }
+ 
+   outdata = grub_malloc (sizeof (*outdata));
+   if (!outdata)
+     {
+-      grub_free (in);
+       grub_free (indata);
+       grub_free ((char *) in->name);
+       grub_free (out);
++      grub_free (in);
+       return grub_errno;
+     }
+ 
+diff --git a/ChangeLog b/ChangeLog
+index c93f11fbb20..67b4d5c2add 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-01-26  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/term/serial.c (grub_serial_register): Fix invalid free.
++	Ensure that pointers are inited to NULL and that pointers are not
++	accessed after free.
+ 
+ 2014-01-25  Andrey Borzenkov <arvidjaar@gmail.com>
+ 
diff --git a/SOURCES/0047-grub-install-support-for-partitioned-partx-loop-devi.patch b/SOURCES/0047-grub-install-support-for-partitioned-partx-loop-devi.patch
new file mode 100644
index 0000000..76f1a8e
--- /dev/null
+++ b/SOURCES/0047-grub-install-support-for-partitioned-partx-loop-devi.patch
@@ -0,0 +1,51 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Mike Gilbert <floppym@gentoo.org>
+Date: Sun, 26 Jan 2014 02:56:04 +0100
+Subject: [PATCH] grub-install: support for partitioned partx loop devices.
+
+	* grub-core/osdep/linux/getroot.c (grub_util_part_to_disk): Detect
+	/dev/loopX as being the parent of /dev/loopXpY.
+---
+ grub-core/osdep/linux/getroot.c | 13 +++++++++++++
+ ChangeLog                       |  7 +++++++
+ 2 files changed, 20 insertions(+)
+
+diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
+index 772de0a9bc4..19581d32997 100644
+--- a/grub-core/osdep/linux/getroot.c
++++ b/grub-core/osdep/linux/getroot.c
+@@ -883,6 +883,19 @@ grub_util_part_to_disk (const char *os_dev, struct stat *st,
+ 	  *pp = '\0';
+ 	  return path;
+ 	}
++
++      /* If this is a loop device */
++      if ((strncmp ("loop", p, 4) == 0) && p[4] >= '0' && p[4] <= '9')
++	{
++	  char *pp = p + 4;
++	  while (*pp >= '0' && *pp <= '9')
++	    pp++;
++	  if (*pp == 'p')
++	    *is_part = 1;
++	  /* /dev/loop[0-9]+p[0-9]* */
++	  *pp = '\0';
++	  return path;
++	}
+     }
+ 
+   return path;
+diff --git a/ChangeLog b/ChangeLog
+index 67b4d5c2add..bbec1e70bbd 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,10 @@
++2014-01-26  Mike Gilbert <floppym@gentoo.org>
++
++	grub-install: support for partitioned partx loop devices.
++
++	* grub-core/osdep/linux/getroot.c (grub_util_part_to_disk): Detect
++	/dev/loopX as being the parent of /dev/loopXpY.
++
+ 2014-01-26  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/term/serial.c (grub_serial_register): Fix invalid free.
diff --git a/SOURCES/0048-grub-core-term-at_keyboard.c-Tolerate-missing-keyboa.patch b/SOURCES/0048-grub-core-term-at_keyboard.c-Tolerate-missing-keyboa.patch
new file mode 100644
index 0000000..cf332c0
--- /dev/null
+++ b/SOURCES/0048-grub-core-term-at_keyboard.c-Tolerate-missing-keyboa.patch
@@ -0,0 +1,36 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Sun, 26 Jan 2014 03:31:10 +0100
+Subject: [PATCH] * grub-core/term/at_keyboard.c: Tolerate missing keyboard.
+
+---
+ grub-core/term/at_keyboard.c | 3 +++
+ ChangeLog                    | 4 ++++
+ 2 files changed, 7 insertions(+)
+
+diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c
+index f5071ce69e8..b4257e84a04 100644
+--- a/grub-core/term/at_keyboard.c
++++ b/grub-core/term/at_keyboard.c
+@@ -396,6 +396,9 @@ fetch_key (int *is_break)
+   if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
+     return -1;
+   at_key = grub_inb (KEYBOARD_REG_DATA);
++  /* May happen if no keyboard is connected. Just ignore this.  */
++  if (at_key == 0xff)
++    return -1;
+   if (at_key == 0xe0)
+     {
+       e0_received = 1;
+diff --git a/ChangeLog b/ChangeLog
+index bbec1e70bbd..d37d4a6fc16 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-01-26  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/term/at_keyboard.c: Tolerate missing keyboard.
++
+ 2014-01-26  Mike Gilbert <floppym@gentoo.org>
+ 
+ 	grub-install: support for partitioned partx loop devices.
diff --git a/SOURCES/0049-.gitignore-add-missing-files-and-.exe-variants.patch b/SOURCES/0049-.gitignore-add-missing-files-and-.exe-variants.patch
new file mode 100644
index 0000000..267ab1e
--- /dev/null
+++ b/SOURCES/0049-.gitignore-add-missing-files-and-.exe-variants.patch
@@ -0,0 +1,70 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
+Date: Wed, 29 Jan 2014 13:26:00 -0200
+Subject: [PATCH] .gitignore: add missing files and .exe variants.
+
+---
+ .gitignore | 7 +++++++
+ ChangeLog  | 6 +++++-
+ 2 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/.gitignore b/.gitignore
+index 2b0156acd7c..18ab8e81278 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -58,6 +58,8 @@ grub-emu.exe
+ grub-emu-lite.exe
+ grub_emu_init.c
+ grub_emu_init.h
++/grub-file
++/grub-file.exe
+ grub-fstest
+ grub-fstest.exe
+ grub_fstest_init.c
+@@ -66,6 +68,8 @@ grub_func_test
+ grub-install
+ grub-install.exe
+ grub-kbdcomp
++/grub-macbless
++/grub-macbless.exe
+ grub-macho2img
+ /grub-menulst2cfg
+ /grub-menulst2cfg.exe
+@@ -120,6 +124,8 @@ grub-shell
+ grub-shell-tester
+ grub-sparc64-setup
+ grub-sparc64-setup.exe
++/grub-syslinux2cfg
++/grub-syslinux2cfg.exe
+ gzcompress_test
+ hddboot_test
+ help_test
+@@ -194,6 +200,7 @@ grub-core/modinfo.sh
+ grub-core/*.module
+ grub-core/*.module.exe
+ grub-core/*.pp
++grub-core/kernel.img.bin
+ util/bash-completion.d/grub
+ grub-core/gnulib/alloca.h
+ grub-core/gnulib/arg-nonnull.h
+diff --git a/ChangeLog b/ChangeLog
+index d37d4a6fc16..a49f5f1f48f 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-01-29  Paulo Flabiano Smorigo  <pfsmorigo@br.ibm.com>
++
++	* .gitignore: add missing files and .exe variants.
++
+ 2014-01-26  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/term/at_keyboard.c: Tolerate missing keyboard.
+@@ -1113,7 +1117,7 @@
+ 
+ 2013-12-14  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+-	* .gitignore: Add .exe variants. Add missing files. Remove few outdated
++	* .gitignore: add .exe variants. add missing files. remove few outdated
+ 	entries.
+ 
+ 2013-12-14  Vladimir Serbinenko  <phcoder@gmail.com>
diff --git a/SOURCES/0050-util-grub-mkfont.c-Downgrade-warnings-about-unhandle.patch b/SOURCES/0050-util-grub-mkfont.c-Downgrade-warnings-about-unhandle.patch
new file mode 100644
index 0000000..83a6b08
--- /dev/null
+++ b/SOURCES/0050-util-grub-mkfont.c-Downgrade-warnings-about-unhandle.patch
@@ -0,0 +1,74 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Wed, 29 Jan 2014 23:41:48 +0100
+Subject: [PATCH] * util/grub-mkfont.c: Downgrade warnings about unhandled
+ features to debug.
+
+---
+ util/grub-mkfont.c | 14 ++++++++------
+ ChangeLog          |  9 +++++++++
+ 2 files changed, 17 insertions(+), 6 deletions(-)
+
+diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c
+index 3cb02ad5c45..3de07ee9c06 100644
+--- a/util/grub-mkfont.c
++++ b/util/grub-mkfont.c
+@@ -516,8 +516,8 @@ process_cursive (struct gsub_feature *feature,
+ 	}		      
+       if (grub_be_to_cpu16 (lookup->flag) & ~GSUB_RTL_CHAR)
+ 	{
+-	  printf (_("Unsupported substitution flag: 0x%x\n"),
+-		  grub_be_to_cpu16 (lookup->flag));
++	  grub_util_info ("unsupported substitution flag: 0x%x",
++			  grub_be_to_cpu16 (lookup->flag));
+ 	}
+       switch (feattag)
+ 	{
+@@ -577,7 +577,8 @@ process_cursive (struct gsub_feature *feature,
+ 	       There are 2 coverage specifications: list and range.
+ 	       This warning is thrown when another coverage specification
+ 	       is detected.  */
+-	    printf (_("Unsupported coverage specification: %d\n"), covertype);
++	    fprintf (stderr,
++		     _("Unsupported coverage specification: %d\n"), covertype);
+ 	}
+     }
+ }
+@@ -616,7 +617,8 @@ add_font (struct grub_font_info *font_info, FT_Face face, int nocut)
+ 	  grub_uint32_t feattag
+ 	    = grub_be_to_cpu32 (features->features[i].feature_tag);
+ 	  if (feature->params)
+-	    printf (_("WARNING: unsupported font feature parameters: %x\n"),
++	    fprintf (stderr,
++		     _("WARNING: unsupported font feature parameters: %x\n"),
+ 		    grub_be_to_cpu16 (feature->params));
+ 	  switch (feattag)
+ 	    {
+@@ -647,8 +649,8 @@ add_font (struct grub_font_info *font_info, FT_Face face, int nocut)
+ 		  if (!grub_isgraph (str[j]))
+ 		    str[j] = '?';
+ 		/* TRANSLATORS: It's gsub feature, not gsub font.  */
+-		printf (_("Unknown gsub font feature 0x%x (%s)\n"),
+-			feattag, str);
++		grub_util_info ("Unknown gsub font feature 0x%x (%s)",
++				feattag, str);
+ 	      }
+ 	    }
+ 	}
+diff --git a/ChangeLog b/ChangeLog
+index a49f5f1f48f..9837c7f8d38 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,12 @@
++2014-01-29  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* util/grub-mkfont.c: Downgrade warnings about unhandled features
++	to debug.
++
++2014-01-29  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/term/at_keyboard.c: Tolerate missing keyboard.
++
+ 2014-01-29  Paulo Flabiano Smorigo  <pfsmorigo@br.ibm.com>
+ 
+ 	* .gitignore: add missing files and .exe variants.
diff --git a/SOURCES/0051-grub-core-disk-ahci.c-Do-not-enable-I-O-decoding-and.patch b/SOURCES/0051-grub-core-disk-ahci.c-Do-not-enable-I-O-decoding-and.patch
new file mode 100644
index 0000000..1d852b3
--- /dev/null
+++ b/SOURCES/0051-grub-core-disk-ahci.c-Do-not-enable-I-O-decoding-and.patch
@@ -0,0 +1,52 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Wed, 29 Jan 2014 23:43:25 +0100
+Subject: [PATCH] * grub-core/disk/ahci.c: Do not enable I/O decoding and keep
+ enabling busmaster for the end.
+
+---
+ grub-core/disk/ahci.c | 10 ++++++----
+ ChangeLog             |  5 +++++
+ 2 files changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c
+index 0b13fb8ebed..18c13270c65 100644
+--- a/grub-core/disk/ahci.c
++++ b/grub-core/disk/ahci.c
+@@ -194,10 +194,8 @@ grub_ahci_pciinit (grub_pci_device_t dev,
+     return 0;
+ 
+   addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
+-  grub_pci_write_word (addr, grub_pci_read_word (addr) | 
+-		    GRUB_PCI_COMMAND_IO_ENABLED
+-		    | GRUB_PCI_COMMAND_MEM_ENABLED
+-		    | GRUB_PCI_COMMAND_BUS_MASTER);
++  grub_pci_write_word (addr, grub_pci_read_word (addr)
++		    | GRUB_PCI_COMMAND_MEM_ENABLED);
+ 
+   hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK,
+ 				   sizeof (hba));
+@@ -621,6 +619,10 @@ grub_ahci_pciinit (grub_pci_device_t dev,
+     if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].sig >> 16) == 0xeb14)
+       adevs[i]->atapi = 1;
+ 
++  addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
++  grub_pci_write_word (addr, grub_pci_read_word (addr)
++		    | GRUB_PCI_COMMAND_BUS_MASTER);
++
+   for (i = 0; i < nports; i++)
+     if (adevs[i])
+       {
+diff --git a/ChangeLog b/ChangeLog
+index 9837c7f8d38..51eba95f36f 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-01-29  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/disk/ahci.c: Do not enable I/O decoding and keep
++	enabling busmaster for the end.
++
+ 2014-01-29  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* util/grub-mkfont.c: Downgrade warnings about unhandled features
diff --git a/SOURCES/0052-grub-core-disk-ahci.c-Allocate-and-clean-space-for-a.patch b/SOURCES/0052-grub-core-disk-ahci.c-Allocate-and-clean-space-for-a.patch
new file mode 100644
index 0000000..d1a4ef9
--- /dev/null
+++ b/SOURCES/0052-grub-core-disk-ahci.c-Allocate-and-clean-space-for-a.patch
@@ -0,0 +1,50 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Wed, 29 Jan 2014 23:45:18 +0100
+Subject: [PATCH] * grub-core/disk/ahci.c: Allocate and clean space for all
+ possible 32 slots to avoid pointing to uninited area.
+
+---
+ grub-core/disk/ahci.c | 8 +++++++-
+ ChangeLog             | 5 +++++
+ 2 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c
+index 18c13270c65..d63fd09fdc6 100644
+--- a/grub-core/disk/ahci.c
++++ b/grub-core/disk/ahci.c
+@@ -358,7 +358,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
+ 	grub_dprintf ("ahci", "err: %x\n",
+ 		      adevs[i]->hba->ports[adevs[i]->port].sata_error);
+ 
+-	adevs[i]->command_list_chunk = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head));
++	adevs[i]->command_list_chunk = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head) * 32);
+ 	if (!adevs[i]->command_list_chunk)
+ 	  {
+ 	    adevs[i] = 0;
+@@ -376,6 +376,12 @@ grub_ahci_pciinit (grub_pci_device_t dev,
+ 
+ 	adevs[i]->command_list = grub_dma_get_virt (adevs[i]->command_list_chunk);
+ 	adevs[i]->command_table = grub_dma_get_virt (adevs[i]->command_table_chunk);
++
++	grub_memset ((void *) adevs[i]->command_list, 0,
++		     sizeof (struct grub_ahci_cmd_table));
++	grub_memset ((void *) adevs[i]->command_table, 0,
++		     sizeof (struct grub_ahci_cmd_head) * 32);
++
+ 	adevs[i]->command_list->command_table_base
+ 	  = grub_dma_get_phys (adevs[i]->command_table_chunk);
+ 
+diff --git a/ChangeLog b/ChangeLog
+index 51eba95f36f..9bb18177793 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-01-29  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/disk/ahci.c: Allocate and clean space for all possible 32
++	slots to avoid pointing to uninited area.
++
+ 2014-01-29  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/disk/ahci.c: Do not enable I/O decoding and keep
diff --git a/SOURCES/0053-grub-core-disk-ahci.c-Add-safety-cleanups.patch b/SOURCES/0053-grub-core-disk-ahci.c-Add-safety-cleanups.patch
new file mode 100644
index 0000000..7a1172a
--- /dev/null
+++ b/SOURCES/0053-grub-core-disk-ahci.c-Add-safety-cleanups.patch
@@ -0,0 +1,57 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Wed, 29 Jan 2014 23:46:17 +0100
+Subject: [PATCH] * grub-core/disk/ahci.c: Add safety cleanups.
+
+---
+ grub-core/disk/ahci.c | 10 ++++++++++
+ ChangeLog             |  4 ++++
+ 2 files changed, 14 insertions(+)
+
+diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c
+index d63fd09fdc6..643e691ef80 100644
+--- a/grub-core/disk/ahci.c
++++ b/grub-core/disk/ahci.c
+@@ -454,6 +454,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
+ 	adevs[i]->hba->ports[adevs[i]->port].fis_base = grub_dma_get_phys (adevs[i]->rfis);
+ 	adevs[i]->hba->ports[adevs[i]->port].command_list_base
+ 	  = grub_dma_get_phys (adevs[i]->command_list_chunk);
++	adevs[i]->hba->ports[adevs[i]->port].command_issue = 0;
+ 	adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_FRE;
+       }
+ 
+@@ -600,6 +601,9 @@ grub_ahci_pciinit (grub_pci_device_t dev,
+ 	failed_adevs[i] = adevs[i];
+ 	adevs[i] = 0;
+       }
++
++  grub_dprintf ("ahci", "cleaning up failed devs\n");
++
+   for (i = 0; i < nports; i++)
+     if (failed_adevs[i] && (fr_running & (1 << i)))
+       failed_adevs[i]->hba->ports[failed_adevs[i]->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
+@@ -855,6 +859,12 @@ grub_ahci_reset_port (struct grub_ahci_device *dev, int force)
+     {
+       struct grub_disk_ata_pass_through_parms parms2;
+       dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST;
++      dev->hba->ports[dev->port].command_issue = 0;
++      dev->command_list[0].config = 0;
++      dev->command_table[0].prdt[0].unused = 0;
++      dev->command_table[0].prdt[0].size = 0;
++      dev->command_table[0].prdt[0].data_base = 0;
++
+       endtime = grub_get_time_ms () + 1000;
+       while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
+ 	if (grub_get_time_ms () > endtime)
+diff --git a/ChangeLog b/ChangeLog
+index 9bb18177793..15300b020c6 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-01-29  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/disk/ahci.c: Add safety cleanups.
++
+ 2014-01-29  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/disk/ahci.c: Allocate and clean space for all possible 32
diff --git a/SOURCES/0054-grub-core-disk-ahci.c-Properly-handle-transactions-w.patch b/SOURCES/0054-grub-core-disk-ahci.c-Properly-handle-transactions-w.patch
new file mode 100644
index 0000000..11a7c59
--- /dev/null
+++ b/SOURCES/0054-grub-core-disk-ahci.c-Properly-handle-transactions-w.patch
@@ -0,0 +1,49 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Wed, 29 Jan 2014 23:49:51 +0100
+Subject: [PATCH] * grub-core/disk/ahci.c: Properly handle transactions with no
+ transferred data.
+
+---
+ grub-core/disk/ahci.c | 7 +++++--
+ ChangeLog             | 5 +++++
+ 2 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c
+index 643e691ef80..fdd40c64dd9 100644
+--- a/grub-core/disk/ahci.c
++++ b/grub-core/disk/ahci.c
+@@ -932,7 +932,10 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
+   if (parms->size > GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH)
+     return grub_error (GRUB_ERR_BUG, "too big data buffer");
+ 
+-  bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1));
++  if (parms->size)
++    bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1));
++  else
++    bufc = grub_memalign_dma32 (1024, 512);
+ 
+   grub_dprintf ("ahci", "AHCI tfd = %x, CL=%p\n",
+ 		dev->hba->ports[dev->port].task_file_data,
+@@ -942,7 +945,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
+     = (5 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT)
+     //    | GRUB_AHCI_CONFIG_CLEAR_R_OK
+     | (0 << GRUB_AHCI_CONFIG_PMP_SHIFT)
+-    | (1 << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT)
++    | ((parms->size ? 1 : 0) << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT)
+     | (parms->cmdsize ? GRUB_AHCI_CONFIG_ATAPI : 0)
+     | (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ)
+     | (parms->taskfile.cmd == 8 ? (1 << 8) : 0);
+diff --git a/ChangeLog b/ChangeLog
+index 15300b020c6..bc1ab231b02 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-01-29  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/disk/ahci.c: Properly handle transactions with no
++	transferred data.
++
+ 2014-01-29  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/disk/ahci.c: Add safety cleanups.
diff --git a/SOURCES/0055-grub-core-disk-ahci.c-Increase-timeout.-Some-SSDs-ta.patch b/SOURCES/0055-grub-core-disk-ahci.c-Increase-timeout.-Some-SSDs-ta.patch
new file mode 100644
index 0000000..3430836
--- /dev/null
+++ b/SOURCES/0055-grub-core-disk-ahci.c-Increase-timeout.-Some-SSDs-ta.patch
@@ -0,0 +1,37 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Wed, 29 Jan 2014 23:50:49 +0100
+Subject: [PATCH] * grub-core/disk/ahci.c: Increase timeout. Some SSDs take up
+ to 7 seconds to recover if last poweroff was bad.
+
+---
+ grub-core/disk/ahci.c | 2 +-
+ ChangeLog             | 5 +++++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c
+index fdd40c64dd9..5e4a6397a49 100644
+--- a/grub-core/disk/ahci.c
++++ b/grub-core/disk/ahci.c
+@@ -1022,7 +1022,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
+   grub_dprintf ("ahci", "AHCI tfd = %x\n",
+ 		dev->hba->ports[dev->port].task_file_data);
+ 
+-  endtime = grub_get_time_ms () + (spinup ? 10000 : 5000);
++  endtime = grub_get_time_ms () + (spinup ? 20000 : 20000);
+   while ((dev->hba->ports[dev->port].command_issue & 1))
+     if (grub_get_time_ms () > endtime)
+       {
+diff --git a/ChangeLog b/ChangeLog
+index bc1ab231b02..1a822f3d2f2 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-01-29  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/disk/ahci.c: Increase timeout. Some SSDs take up to
++	7 seconds to recover if last poweroff was bad.
++
+ 2014-01-29  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/disk/ahci.c: Properly handle transactions with no
diff --git a/SOURCES/0056-util-grub-mkfont.c-Build-fix-for-argp.h-with-older-g.patch b/SOURCES/0056-util-grub-mkfont.c-Build-fix-for-argp.h-with-older-g.patch
new file mode 100644
index 0000000..bfdec61
--- /dev/null
+++ b/SOURCES/0056-util-grub-mkfont.c-Build-fix-for-argp.h-with-older-g.patch
@@ -0,0 +1,38 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Mon, 3 Feb 2014 14:34:27 +0100
+Subject: [PATCH] * util/grub-mkfont.c: Build fix for argp.h with older gcc.
+
+---
+ util/grub-mkfont.c | 4 ++++
+ ChangeLog          | 4 ++++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c
+index 3de07ee9c06..e6485b40f28 100644
+--- a/util/grub-mkfont.c
++++ b/util/grub-mkfont.c
+@@ -33,7 +33,11 @@
+ 
+ #ifndef GRUB_BUILD
+ #define _GNU_SOURCE	1
++#pragma GCC diagnostic ignored "-Wmissing-prototypes"
++#pragma GCC diagnostic ignored "-Wmissing-declarations"
+ #include <argp.h>
++#pragma GCC diagnostic error "-Wmissing-prototypes"
++#pragma GCC diagnostic error "-Wmissing-declarations"
+ #endif
+ #include <assert.h>
+ 
+diff --git a/ChangeLog b/ChangeLog
+index 1a822f3d2f2..f2bba8402c5 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-02-03  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* util/grub-mkfont.c: Build fix for argp.h with older gcc.
++
+ 2014-01-29  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/disk/ahci.c: Increase timeout. Some SSDs take up to
diff --git a/SOURCES/0057-util-grub-mkrescue.c-Build-fix-for-argp.h-with-older.patch b/SOURCES/0057-util-grub-mkrescue.c-Build-fix-for-argp.h-with-older.patch
new file mode 100644
index 0000000..441b0e4
--- /dev/null
+++ b/SOURCES/0057-util-grub-mkrescue.c-Build-fix-for-argp.h-with-older.patch
@@ -0,0 +1,38 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Mon, 3 Feb 2014 14:35:51 +0100
+Subject: [PATCH] * util/grub-mkrescue.c: Build fix for argp.h with older gcc.
+
+---
+ util/grub-mkrescue.c | 4 ++++
+ ChangeLog            | 4 ++++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c
+index 34e0b7affb1..e719839820b 100644
+--- a/util/grub-mkrescue.c
++++ b/util/grub-mkrescue.c
+@@ -25,7 +25,11 @@
+ #include <grub/emu/exec.h>
+ #include <grub/emu/config.h>
+ #include <grub/emu/hostdisk.h>
++#pragma GCC diagnostic ignored "-Wmissing-prototypes"
++#pragma GCC diagnostic ignored "-Wmissing-declarations"
+ #include <argp.h>
++#pragma GCC diagnostic error "-Wmissing-prototypes"
++#pragma GCC diagnostic error "-Wmissing-declarations"
+ 
+ #include <sys/types.h>
+ #include <sys/wait.h>
+diff --git a/ChangeLog b/ChangeLog
+index f2bba8402c5..f4a472144b1 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-02-03  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* util/grub-mkrescue.c: Build fix for argp.h with older gcc.
++
+ 2014-02-03  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* util/grub-mkfont.c: Build fix for argp.h with older gcc.
diff --git a/SOURCES/0058-add-grub_env_set_net_property-function.patch b/SOURCES/0058-add-grub_env_set_net_property-function.patch
new file mode 100644
index 0000000..10e37d0
--- /dev/null
+++ b/SOURCES/0058-add-grub_env_set_net_property-function.patch
@@ -0,0 +1,196 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
+Date: Tue, 4 Feb 2014 18:41:38 -0200
+Subject: [PATCH] add grub_env_set_net_property function
+
+* grub-core/net/bootp.c: Remove set_env_limn_ro.
+* grub-core/net/net.c: Add grub_env_set_net_property.
+* include/grub/net.h: Likewise.
+---
+ grub-core/net/bootp.c | 63 +++++++++++++--------------------------------------
+ grub-core/net/net.c   | 38 +++++++++++++++++++++++++++++++
+ include/grub/net.h    |  4 ++++
+ ChangeLog             |  8 +++++++
+ 4 files changed, 66 insertions(+), 47 deletions(-)
+
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index c14e9de57a4..6310ed447e8 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -25,41 +25,6 @@
+ #include <grub/net/udp.h>
+ #include <grub/datetime.h>
+ 
+-static char *
+-grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
+-			 const char *val __attribute__ ((unused)))
+-{
+-  return NULL;
+-}
+-
+-static void
+-set_env_limn_ro (const char *intername, const char *suffix,
+-		 const char *value, grub_size_t len)
+-{
+-  char *varname, *varvalue;
+-  char *ptr;
+-  varname = grub_xasprintf ("net_%s_%s", intername, suffix);
+-  if (!varname)
+-    return;
+-  for (ptr = varname; *ptr; ptr++)
+-    if (*ptr == ':')
+-      *ptr = '_';
+-  varvalue = grub_malloc (len + 1);
+-  if (!varvalue)
+-    {
+-      grub_free (varname);
+-      return;
+-    }
+-
+-  grub_memcpy (varvalue, value, len);
+-  varvalue[len] = 0;
+-  grub_env_set (varname, varvalue);
+-  grub_register_variable_hook (varname, 0, grub_env_write_readonly);
+-  grub_env_export (varname);
+-  grub_free (varname);
+-  grub_free (varvalue);
+-}
+-
+ static void
+ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
+ {
+@@ -136,20 +101,24 @@ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
+ 	  }
+ 	  continue;
+ 	case GRUB_NET_BOOTP_HOSTNAME:
+-	  set_env_limn_ro (name, "hostname", (const char *) ptr, taglength);
+-	  break;
++          grub_env_set_net_property (name, "hostname", (const char *) ptr,
++                                     taglength);
++          break;
+ 
+ 	case GRUB_NET_BOOTP_DOMAIN:
+-	  set_env_limn_ro (name, "domain", (const char *) ptr, taglength);
+-	  break;
++          grub_env_set_net_property (name, "domain", (const char *) ptr,
++                                     taglength);
++          break;
+ 
+ 	case GRUB_NET_BOOTP_ROOT_PATH:
+-	  set_env_limn_ro (name, "rootpath", (const char *) ptr, taglength);
+-	  break;
++          grub_env_set_net_property (name, "rootpath", (const char *) ptr,
++                                     taglength);
++          break;
+ 
+ 	case GRUB_NET_BOOTP_EXTENSIONS_PATH:
+-	  set_env_limn_ro (name, "extensionspath", (const char *) ptr, taglength);
+-	  break;
++          grub_env_set_net_property (name, "extensionspath", (const char *) ptr,
++                                     taglength);
++          break;
+ 
+ 	  /* If you need any other options please contact GRUB
+ 	     development team.  */
+@@ -211,8 +180,8 @@ grub_net_configure_by_dhcp_ack (const char *name,
+     }
+ 
+   if (size > OFFSET_OF (boot_file, bp))
+-    set_env_limn_ro (name, "boot_file", (char *) bp->boot_file,
+-		     sizeof (bp->boot_file));
++    grub_env_set_net_property (name, "boot_file", bp->boot_file,
++                               sizeof (bp->boot_file));
+   if (is_def)
+     grub_net_default_server = 0;
+   if (is_def && !grub_net_default_server && bp->server_ip)
+@@ -243,8 +212,8 @@ grub_net_configure_by_dhcp_ack (const char *name,
+   if (size > OFFSET_OF (server_name, bp)
+       && bp->server_name[0])
+     {
+-      set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name,
+-		       sizeof (bp->server_name));
++      grub_env_set_net_property (name, "dhcp_server_name", bp->server_name,
++                                 sizeof (bp->server_name));
+       if (is_def && !grub_net_default_server)
+ 	{
+ 	  grub_net_default_server = grub_strdup (bp->server_name);
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index 1521d8d2c87..f2e723bd409 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -1480,6 +1480,44 @@ receive_packets (struct grub_net_card *card, int *stop_condition)
+   grub_print_error ();
+ }
+ 
++static char *
++grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
++			 const char *val __attribute__ ((unused)))
++{
++  return NULL;
++}
++
++grub_err_t
++grub_env_set_net_property (const char *intername, const char *suffix,
++                           const char *value, grub_size_t len)
++{
++  char *varname, *varvalue;
++  char *ptr;
++
++  varname = grub_xasprintf ("net_%s_%s", intername, suffix);
++  if (!varname)
++    return grub_errno;
++  for (ptr = varname; *ptr; ptr++)
++    if (*ptr == ':')
++      *ptr = '_';
++  varvalue = grub_malloc (len + 1);
++  if (!varvalue)
++    {
++      grub_free (varname);
++      return grub_errno;
++    }
++
++  grub_memcpy (varvalue, value, len);
++  varvalue[len] = 0;
++  grub_err_t ret = grub_env_set (varname, varvalue);
++  grub_register_variable_hook (varname, 0, grub_env_write_readonly);
++  grub_env_export (varname);
++  grub_free (varname);
++  grub_free (varvalue);
++
++  return ret;
++}
++
+ void
+ grub_net_poll_cards (unsigned time, int *stop_condition)
+ {
+diff --git a/include/grub/net.h b/include/grub/net.h
+index 0e0a605c5a6..538baa33eca 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -480,6 +480,10 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target,
+ void
+ grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str);
+ 
++grub_err_t
++grub_env_set_net_property (const char *intername, const char *suffix,
++                           const char *value, grub_size_t len);
++
+ void
+ grub_net_poll_cards (unsigned time, int *stop_condition);
+ 
+diff --git a/ChangeLog b/ChangeLog
+index f4a472144b1..63f5aa322c3 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,11 @@
++2014-02-04  Paulo Flabiano Smorigo  <pfsmorigo@br.ibm.com>
++
++	Add grub_env_set_net_property function.
++
++	* grub-core/net/bootp.c: Remove set_env_limn_ro.
++	* grub-core/net/net.c: Add grub_env_set_net_property.
++	* include/grub/net.h: Likewise.
++
+ 2014-02-03  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* util/grub-mkrescue.c: Build fix for argp.h with older gcc.
diff --git a/SOURCES/0059-add-bootpath-parser-for-open-firmware.patch b/SOURCES/0059-add-bootpath-parser-for-open-firmware.patch
new file mode 100644
index 0000000..51e6cf7
--- /dev/null
+++ b/SOURCES/0059-add-bootpath-parser-for-open-firmware.patch
@@ -0,0 +1,206 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
+Date: Tue, 4 Feb 2014 19:00:55 -0200
+Subject: [PATCH] add bootpath parser for open firmware
+
+It enables net boot even when there is no bootp/dhcp server.
+
+* grub-core/net/drivers/ieee1275/ofnet.c: Add grub_ieee1275_parse_bootpath and
+call it at grub_ieee1275_net_config_real.
+* grub-core/kern/ieee1275/init.c: Add bootpath to grub_ieee1275_net_config.
+* include/grub/ieee1275/ieee1275.h: Likewise.
+---
+ grub-core/kern/ieee1275/init.c         |   7 +--
+ grub-core/net/drivers/ieee1275/ofnet.c | 107 ++++++++++++++++++++++++++++++++-
+ include/grub/ieee1275/ieee1275.h       |   5 +-
+ ChangeLog                              |  13 ++++
+ 4 files changed, 125 insertions(+), 7 deletions(-)
+
+diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
+index 89b2822e14d..d5bd74d3552 100644
+--- a/grub-core/kern/ieee1275/init.c
++++ b/grub-core/kern/ieee1275/init.c
+@@ -80,9 +80,8 @@ grub_translate_ieee1275_path (char *filepath)
+     }
+ }
+ 
+-void (*grub_ieee1275_net_config) (const char *dev,
+-				  char **device,
+-				  char **path);
++void (*grub_ieee1275_net_config) (const char *dev, char **device, char **path,
++                                  char *bootpath);
+ void
+ grub_machine_get_bootlocation (char **device, char **path)
+ {
+@@ -126,7 +125,7 @@ grub_machine_get_bootlocation (char **device, char **path)
+       *ptr = 0;
+ 
+       if (grub_ieee1275_net_config)
+-	grub_ieee1275_net_config (canon, device, path);
++	grub_ieee1275_net_config (canon, device, path, bootpath);
+       grub_free (dev);
+       grub_free (canon);
+     }
+diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c
+index 4483c9122f7..eea8e71d300 100644
+--- a/grub-core/net/drivers/ieee1275/ofnet.c
++++ b/grub-core/net/drivers/ieee1275/ofnet.c
+@@ -127,8 +127,111 @@ bootp_response_properties[] =
+     { .name = "bootpreply-packet", .offset = 0x2a},
+   };
+ 
++enum
++{
++  BOOTARGS_SERVER_ADDR,
++  BOOTARGS_FILENAME,
++  BOOTARGS_CLIENT_ADDR,
++  BOOTARGS_GATEWAY_ADDR,
++  BOOTARGS_BOOTP_RETRIES,
++  BOOTARGS_TFTP_RETRIES,
++  BOOTARGS_SUBNET_MASK,
++  BOOTARGS_BLOCKSIZE
++};
++
++static int
++grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
++                              char **device, struct grub_net_card **card)
++{
++  char *args;
++  char *comma_char = 0;
++  char *equal_char = 0;
++  grub_size_t field_counter = 0;
++
++  grub_net_network_level_address_t client_addr, gateway_addr, subnet_mask;
++  grub_net_link_level_address_t hw_addr;
++  grub_net_interface_flags_t flags = 0;
++  struct grub_net_network_level_interface *inter;
++
++  hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
++
++  args = bootpath + grub_strlen (devpath) + 1;
++  do
++    {
++      comma_char = grub_strchr (args, ',');
++      if (comma_char != 0)
++        *comma_char = 0;
++
++      /* Check if it's an option (like speed=auto) and not a default parameter */
++      equal_char = grub_strchr (args, '=');
++      if (equal_char != 0)
++        {
++          *equal_char = 0;
++          grub_env_set_net_property ((*card)->name, args, equal_char + 1,
++                                     grub_strlen(equal_char + 1));
++          *equal_char = '=';
++        }
++      else
++        {
++          switch (field_counter++)
++            {
++            case BOOTARGS_SERVER_ADDR:
++              *device = grub_xasprintf ("tftp,%s", args);
++              if (!*device)
++                return grub_errno;
++              break;
++
++            case BOOTARGS_CLIENT_ADDR:
++              grub_net_resolve_address (args, &client_addr);
++              break;
++
++            case BOOTARGS_GATEWAY_ADDR:
++              grub_net_resolve_address (args, &gateway_addr);
++              break;
++
++            case BOOTARGS_SUBNET_MASK:
++              grub_net_resolve_address (args, &subnet_mask);
++              break;
++            }
++        }
++      args = comma_char + 1;
++      if (comma_char != 0)
++        *comma_char = ',';
++    } while (comma_char != 0);
++
++  if ((client_addr.ipv4 != 0) && (subnet_mask.ipv4 != 0))
++    {
++      grub_ieee1275_phandle_t devhandle;
++      grub_ieee1275_finddevice (devpath, &devhandle);
++      grub_ieee1275_get_property (devhandle, "mac-address",
++                                  hw_addr.mac, sizeof(hw_addr.mac), 0);
++      inter = grub_net_add_addr ((*card)->name, *card, &client_addr, &hw_addr,
++                                 flags);
++      grub_net_add_ipv4_local (inter,
++                          __builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4)));
++    }
++
++  if (gateway_addr.ipv4 != 0)
++    {
++      grub_net_network_level_netaddress_t target;
++      char *rname;
++
++      target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
++      target.ipv4.base = 0;
++      target.ipv4.masksize = 0;
++      rname = grub_xasprintf ("%s:default", ((*card)->name));
++      if (rname)
++        grub_net_add_route_gw (rname, target, gateway_addr);
++      else
++        return grub_errno;
++    }
++
++  return 0;
++}
++
+ static void
+-grub_ieee1275_net_config_real (const char *devpath, char **device, char **path)
++grub_ieee1275_net_config_real (const char *devpath, char **device, char **path,
++                               char *bootpath)
+ {
+   struct grub_net_card *card;
+ 
+@@ -158,6 +261,8 @@ grub_ieee1275_net_config_real (const char *devpath, char **device, char **path)
+       }
+     grub_free (canon);
+ 
++    grub_ieee1275_parse_bootpath (devpath, bootpath, device, &card);
++
+     for (i = 0; i < ARRAY_SIZE (bootp_response_properties); i++)
+       if (grub_ieee1275_get_property_length (grub_ieee1275_chosen,
+ 					     bootp_response_properties[i].name,
+diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
+index dc54beabb4b..8e425130327 100644
+--- a/include/grub/ieee1275/ieee1275.h
++++ b/include/grub/ieee1275/ieee1275.h
+@@ -70,8 +70,9 @@ struct grub_ieee1275_devalias
+ };
+ 
+ extern void (*EXPORT_VAR(grub_ieee1275_net_config)) (const char *dev,
+-						     char **device,
+-						     char **path);
++                                                     char **device,
++                                                     char **path,
++                                                     char *bootargs);
+ 
+ /* Maps a device alias to a pathname.  */
+ extern grub_ieee1275_phandle_t EXPORT_VAR(grub_ieee1275_chosen);
+diff --git a/ChangeLog b/ChangeLog
+index 63f5aa322c3..5237631583a 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,16 @@
++2014-02-04  Paulo Flabiano Smorigo  <pfsmorigo@br.ibm.com>
++
++	Add bootpath parser for open firmware.
++
++	It enables net boot even when there is no bootp/dhcp server.
++
++	* grub-core/net/drivers/ieee1275/ofnet.c: Add grub_ieee1275_parse_bootpath
++	and call it at grub_ieee1275_net_config_real.
++	* grub-core/kern/ieee1275/init.c: Add bootpath to
++	grub_ieee1275_net_config.
++	* include/grub/ieee1275/ieee1275.h: Likewise.
++
++
+ 2014-02-04  Paulo Flabiano Smorigo  <pfsmorigo@br.ibm.com>
+ 
+ 	Add grub_env_set_net_property function.
diff --git a/SOURCES/0060-grub-core-disk-ahci.c-Ignore-NPORTS-field-and-rely-o.patch b/SOURCES/0060-grub-core-disk-ahci.c-Ignore-NPORTS-field-and-rely-o.patch
new file mode 100644
index 0000000..6875b14
--- /dev/null
+++ b/SOURCES/0060-grub-core-disk-ahci.c-Ignore-NPORTS-field-and-rely-o.patch
@@ -0,0 +1,37 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Thu, 20 Feb 2014 10:11:43 +0100
+Subject: [PATCH] * grub-core/disk/ahci.c: Ignore NPORTS field and rely on PI
+ exclusively.
+
+---
+ grub-core/disk/ahci.c | 2 +-
+ ChangeLog             | 5 +++++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c
+index 5e4a6397a49..89365cd0925 100644
+--- a/grub-core/disk/ahci.c
++++ b/grub-core/disk/ahci.c
+@@ -322,7 +322,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
+ 
+   grub_dprintf ("ahci", "GLC:%x\n", hba->global_control);
+ 
+-  nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1;
++  nports = (GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1;
+ 
+   grub_dprintf ("ahci", "%d AHCI ports, PI = 0x%x\n", nports,
+ 		hba->ports_implemented);
+diff --git a/ChangeLog b/ChangeLog
+index 5237631583a..be41aa51f65 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-02-20  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/disk/ahci.c: Ignore NPORTS field and rely on PI
++	exclusively.
++
+ 2014-02-04  Paulo Flabiano Smorigo  <pfsmorigo@br.ibm.com>
+ 
+ 	Add bootpath parser for open firmware.
diff --git a/SOURCES/0061-grub-core-kern-i386-coreboot-mmap.c-Filter-out-0xa00.patch b/SOURCES/0061-grub-core-kern-i386-coreboot-mmap.c-Filter-out-0xa00.patch
new file mode 100644
index 0000000..e3839f4
--- /dev/null
+++ b/SOURCES/0061-grub-core-kern-i386-coreboot-mmap.c-Filter-out-0xa00.patch
@@ -0,0 +1,79 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 28 Feb 2014 09:47:57 +0100
+Subject: [PATCH] * grub-core/kern/i386/coreboot/mmap.c: Filter out
+ 0xa0000-0x100000 region.
+
+---
+ grub-core/kern/i386/coreboot/mmap.c | 38 +++++++++++++++++++++++++++++++------
+ ChangeLog                           |  5 +++++
+ 2 files changed, 37 insertions(+), 6 deletions(-)
+
+diff --git a/grub-core/kern/i386/coreboot/mmap.c b/grub-core/kern/i386/coreboot/mmap.c
+index 11979755144..4d29f6b7d90 100644
+--- a/grub-core/kern/i386/coreboot/mmap.c
++++ b/grub-core/kern/i386/coreboot/mmap.c
+@@ -44,18 +44,44 @@ iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, void *data)
+   mem_region =
+     (mem_region_t) ((long) table_item +
+ 			       sizeof (struct grub_linuxbios_table_item));
+-  while ((long) mem_region < (long) table_item + (long) table_item->size)
++  for (; (long) mem_region < (long) table_item + (long) table_item->size;
++       mem_region++)
+     {
+-      if (ctx->hook (mem_region->addr, mem_region->size,
++      grub_uint64_t start = mem_region->addr;
++      grub_uint64_t end = mem_region->addr + mem_region->size;
++      /* Mark region 0xa0000 - 0x100000 as reserved.  */
++      if (start < 0x100000 && end >= 0xa0000
++	  && mem_region->type == GRUB_MACHINE_MEMORY_AVAILABLE)
++	{
++	  if (start < 0xa0000
++	      && ctx->hook (start, 0xa0000 - start,
++			    /* Multiboot mmaps match with the coreboot mmap
++			       definition.  Therefore, we can just pass type
++			       through.  */
++			    mem_region->type,
++			    ctx->hook_data))
++	    return 1;
++	  if (start < 0xa0000)
++	    start = 0xa0000;
++	  if (start >= end)
++	    continue;
++
++	  if (ctx->hook (start, (end > 0x100000 ? 0x100000 : end) - start,
++			 GRUB_MEMORY_RESERVED,
++			 ctx->hook_data))
++	    return 1;
++	  start = 0x100000;
++
++	  if (end <= start)
++	    continue;
++	}
++      if (ctx->hook (start, end - start,
+ 		     /* Multiboot mmaps match with the coreboot mmap
+ 		        definition.  Therefore, we can just pass type
+ 		        through.  */
+-		     (((mem_region->type <= GRUB_MACHINE_MEMORY_BADRAM) && (mem_region->type >= GRUB_MACHINE_MEMORY_AVAILABLE))
+-		      || mem_region->type == GRUB_MEMORY_COREBOOT_TABLES) ? mem_region->type : GRUB_MEMORY_RESERVED,
++		     mem_region->type,
+ 		     ctx->hook_data))
+ 	return 1;
+-
+-      mem_region++;
+     }
+ 
+   return 0;
+diff --git a/ChangeLog b/ChangeLog
+index be41aa51f65..4f6f6d6d35a 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-02-28  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/kern/i386/coreboot/mmap.c: Filter out 0xa0000-0x100000
++	region.
++
+ 2014-02-20  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/disk/ahci.c: Ignore NPORTS field and rely on PI
diff --git a/SOURCES/0062-grub-core-loader-i386-multiboot_mbi.c-grub_multiboot.patch b/SOURCES/0062-grub-core-loader-i386-multiboot_mbi.c-grub_multiboot.patch
new file mode 100644
index 0000000..3319170
--- /dev/null
+++ b/SOURCES/0062-grub-core-loader-i386-multiboot_mbi.c-grub_multiboot.patch
@@ -0,0 +1,37 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 28 Feb 2014 09:48:57 +0100
+Subject: [PATCH] * grub-core/loader/i386/multiboot_mbi.c
+ (grub_multiboot_make_mbi): Limit location to 640K.
+
+---
+ grub-core/loader/i386/multiboot_mbi.c | 2 +-
+ ChangeLog                             | 5 +++++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c
+index 7431aa49bbe..f10c087f724 100644
+--- a/grub-core/loader/i386/multiboot_mbi.c
++++ b/grub-core/loader/i386/multiboot_mbi.c
+@@ -446,7 +446,7 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
+   bufsize = grub_multiboot_get_mbi_size ();
+ 
+   err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
+-					  0x10000, 0x100000 - bufsize,
++					  0x10000, 0xa0000 - bufsize,
+ 					  bufsize, 4,
+ 					  GRUB_RELOCATOR_PREFERENCE_NONE, 0);
+   if (err)
+diff --git a/ChangeLog b/ChangeLog
+index 4f6f6d6d35a..bbaed2691c7 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-02-28  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_make_mbi): Limit
++	location to 640K.
++
+ 2014-02-28  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/kern/i386/coreboot/mmap.c: Filter out 0xa0000-0x100000
diff --git a/SOURCES/0063-grub-core-mmap-i386-uppermem.c-lower_hook-COREBOOT-I.patch b/SOURCES/0063-grub-core-mmap-i386-uppermem.c-lower_hook-COREBOOT-I.patch
new file mode 100644
index 0000000..78c780e
--- /dev/null
+++ b/SOURCES/0063-grub-core-mmap-i386-uppermem.c-lower_hook-COREBOOT-I.patch
@@ -0,0 +1,42 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 28 Feb 2014 09:50:47 +0100
+Subject: [PATCH] * grub-core/mmap/i386/uppermem.c (lower_hook) [COREBOOT]:
+ Ignore low tables for low memory calculations.
+
+---
+ grub-core/mmap/i386/uppermem.c | 6 +++++-
+ ChangeLog                      | 5 +++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/mmap/i386/uppermem.c b/grub-core/mmap/i386/uppermem.c
+index bd8b429c4be..a6be9896d82 100644
+--- a/grub-core/mmap/i386/uppermem.c
++++ b/grub-core/mmap/i386/uppermem.c
+@@ -31,8 +31,12 @@ lower_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
+ 
+   if (type != GRUB_MEMORY_AVAILABLE)
+     return 0;
++#ifdef GRUB_MACHINE_COREBOOT
++  if (addr <= 0x1000)
++#else
+   if (addr == 0)
+-    *lower = size;
++#endif
++    *lower = size + addr;
+   return 0;
+ }
+ 
+diff --git a/ChangeLog b/ChangeLog
+index bbaed2691c7..6ed6cf4ec2b 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-02-28  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/mmap/i386/uppermem.c (lower_hook) [COREBOOT]: Ignore low
++	tables for low memory calculations.
++
+ 2014-02-28  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_make_mbi): Limit
diff --git a/SOURCES/0064-grub-core-kern-i386-pc-mmap.c-Fallback-to-EISA-memor.patch b/SOURCES/0064-grub-core-kern-i386-pc-mmap.c-Fallback-to-EISA-memor.patch
new file mode 100644
index 0000000..933e08c
--- /dev/null
+++ b/SOURCES/0064-grub-core-kern-i386-pc-mmap.c-Fallback-to-EISA-memor.patch
@@ -0,0 +1,83 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 28 Feb 2014 10:07:11 +0100
+Subject: [PATCH] * grub-core/kern/i386/pc/mmap.c: Fallback to EISA memory map
+ if E820 failed to return any regions.
+
+---
+ grub-core/kern/i386/pc/mmap.c | 40 +++++++++++++++++++++-------------------
+ ChangeLog                     |  5 +++++
+ 2 files changed, 26 insertions(+), 19 deletions(-)
+
+diff --git a/grub-core/kern/i386/pc/mmap.c b/grub-core/kern/i386/pc/mmap.c
+index 8009e833c1a..f1375f3e12d 100644
+--- a/grub-core/kern/i386/pc/mmap.c
++++ b/grub-core/kern/i386/pc/mmap.c
+@@ -141,33 +141,35 @@ grub_get_mmap_entry (struct grub_machine_mmap_entry *entry,
+ grub_err_t
+ grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
+ {
+-  grub_uint32_t cont;
++  grub_uint32_t cont = 0;
+   struct grub_machine_mmap_entry *entry
+     = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
++  int e820_works = 0;
+ 
+-  grub_memset (entry, 0, sizeof (entry));
++  while (1)
++    {
++      grub_memset (entry, 0, sizeof (entry));
+ 
+-  /* Check if grub_get_mmap_entry works.  */
+-  cont = grub_get_mmap_entry (entry, 0);
++      cont = grub_get_mmap_entry (entry, cont);
+ 
+-  if (entry->size)
+-    do
+-      {
+-	if (hook (entry->addr, entry->len,
+-		  /* GRUB mmaps have been defined to match with the E820 definition.
+-		     Therefore, we can just pass type through.  */
+-		  entry->type, hook_data))
+-	  break;
++      if (!entry->size)
++	break;
+ 
+-	if (! cont)
+-	  break;
++      if (entry->len)
++	e820_works = 1;
++      if (entry->len
++	  && hook (entry->addr, entry->len,
++		   /* GRUB mmaps have been defined to match with
++		      the E820 definition.
++		      Therefore, we can just pass type through.  */
++		   entry->type, hook_data))
++	break;
+ 
+-	grub_memset (entry, 0, sizeof (entry));
++      if (! cont)
++	break;
++    }
+ 
+-	cont = grub_get_mmap_entry (entry, cont);
+-      }
+-    while (entry->size);
+-  else
++  if (!e820_works)
+     {
+       grub_uint32_t eisa_mmap = grub_get_eisa_mmap ();
+ 
+diff --git a/ChangeLog b/ChangeLog
+index 6ed6cf4ec2b..97cf57e253d 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-02-28  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/kern/i386/pc/mmap.c: Fallback to EISA memory map
++	if E820 failed to return any regions.
++
+ 2014-02-28  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/mmap/i386/uppermem.c (lower_hook) [COREBOOT]: Ignore low
diff --git a/SOURCES/0065-include-grub-i386-openbsd_bootarg.h-Add-addr-and-fre.patch b/SOURCES/0065-include-grub-i386-openbsd_bootarg.h-Add-addr-and-fre.patch
new file mode 100644
index 0000000..f6b2546
--- /dev/null
+++ b/SOURCES/0065-include-grub-i386-openbsd_bootarg.h-Add-addr-and-fre.patch
@@ -0,0 +1,64 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 28 Feb 2014 10:50:05 +0100
+Subject: [PATCH] * include/grub/i386/openbsd_bootarg.h: Add addr and frequency
+ fields. * grub-core/loader/i386/bsd.c (grub_cmd_openbsd): Fill addr field.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+	Suggested by: Markus Müller.
+---
+ grub-core/loader/i386/bsd.c         | 2 ++
+ include/grub/i386/openbsd_bootarg.h | 2 ++
+ ChangeLog                           | 7 +++++++
+ 3 files changed, 11 insertions(+)
+
+diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c
+index ea0edfafe57..19985f03e65 100644
+--- a/grub-core/loader/i386/bsd.c
++++ b/grub-core/loader/i386/bsd.c
+@@ -1646,6 +1646,7 @@ grub_cmd_openbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
+ 
+       serial.device = (GRUB_OPENBSD_COM_MAJOR << 8) | port;
+       serial.speed = speed;
++      serial.addr = grub_ns8250_hw_get_port (port);
+ 	  
+       grub_bsd_add_meta (OPENBSD_BOOTARG_CONSOLE, &serial, sizeof (serial));
+       bootflags |= OPENBSD_RB_SERCONS;
+@@ -1656,6 +1657,7 @@ grub_cmd_openbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
+ 
+       grub_memset (&serial, 0, sizeof (serial));
+       serial.device = (GRUB_OPENBSD_VGA_MAJOR << 8);
++      serial.addr = 0xffffffff;
+       grub_bsd_add_meta (OPENBSD_BOOTARG_CONSOLE, &serial, sizeof (serial));
+       bootflags &= ~OPENBSD_RB_SERCONS;
+     }
+diff --git a/include/grub/i386/openbsd_bootarg.h b/include/grub/i386/openbsd_bootarg.h
+index 01ca4868b25..9ebe6b4e4b1 100644
+--- a/include/grub/i386/openbsd_bootarg.h
++++ b/include/grub/i386/openbsd_bootarg.h
+@@ -75,6 +75,8 @@ struct grub_openbsd_bootarg_console
+ {
+   grub_uint32_t device;
+   grub_uint32_t speed;
++  grub_uint32_t addr;
++  grub_uint32_t frequency;
+ };
+ 
+ struct grub_openbsd_bootarg_pcibios
+diff --git a/ChangeLog b/ChangeLog
+index 97cf57e253d..f571f66533b 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,10 @@
++2014-02-28  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* include/grub/i386/openbsd_bootarg.h: Add addr and frequency fields.
++	* grub-core/loader/i386/bsd.c (grub_cmd_openbsd): Fill addr field.
++
++	Suggested by: Markus Müller.
++
+ 2014-02-28  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/kern/i386/pc/mmap.c: Fallback to EISA memory map
diff --git a/SOURCES/0066-ieee1275-check-for-IBM-pseries-emulated-machine.patch b/SOURCES/0066-ieee1275-check-for-IBM-pseries-emulated-machine.patch
new file mode 100644
index 0000000..2952449
--- /dev/null
+++ b/SOURCES/0066-ieee1275-check-for-IBM-pseries-emulated-machine.patch
@@ -0,0 +1,30 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
+Date: Thu, 20 Mar 2014 16:57:12 +0530
+Subject: [PATCH] ieee1275: check for IBM pseries emulated machine
+
+is_qemu is not being set lead to disabling of feature like
+GRUB_IEEE1275_FLAG_HAS_CURSORONOFF. This resulted in cursor not being
+displayed during the grub-menu edit.
+
+Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
+---
+ grub-core/kern/ieee1275/cmain.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c
+index d92ae14f53e..3e12e6b24e1 100644
+--- a/grub-core/kern/ieee1275/cmain.c
++++ b/grub-core/kern/ieee1275/cmain.c
+@@ -84,8 +84,10 @@ grub_ieee1275_find_options (void)
+ 
+   rc = grub_ieee1275_get_property (root, "model",
+ 				   tmp,	sizeof (tmp), 0);
+-  if (rc >= 0 && !grub_strcmp (tmp, "Emulated PC"))
++  if (rc >= 0 && (!grub_strcmp (tmp, "Emulated PC")
++		  || !grub_strcmp (tmp, "IBM pSeries (emulated by qemu)"))) {
+     is_qemu = 1;
++  }
+ 
+   if (rc >= 0 && grub_strncmp (tmp, "IBM", 3) == 0)
+     grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS);
diff --git a/SOURCES/0067-grub-core-loader-arm64-linux.c-Remove-redundant-0x.patch b/SOURCES/0067-grub-core-loader-arm64-linux.c-Remove-redundant-0x.patch
new file mode 100644
index 0000000..1188a42
--- /dev/null
+++ b/SOURCES/0067-grub-core-loader-arm64-linux.c-Remove-redundant-0x.patch
@@ -0,0 +1,35 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Fu Wei <fu.wei@linaro.org>
+Date: Wed, 26 Mar 2014 08:13:07 +0100
+Subject: [PATCH] * grub-core/loader/arm64/linux.c: Remove redundant "0x".
+
+---
+ grub-core/loader/arm64/linux.c | 2 +-
+ ChangeLog                      | 4 ++++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
+index 65129c21a8d..f1d10a16492 100644
+--- a/grub-core/loader/arm64/linux.c
++++ b/grub-core/loader/arm64/linux.c
+@@ -68,7 +68,7 @@ get_firmware_fdt (void)
+     if (grub_memcmp (&tables[i].vendor_guid, &fdt_guid, sizeof (fdt_guid)) == 0)
+       {
+ 	firmware_fdt = tables[i].vendor_table;
+-	grub_dprintf ("linux", "found registered FDT @ 0x%p\n", firmware_fdt);
++	grub_dprintf ("linux", "found registered FDT @ %p\n", firmware_fdt);
+ 	break;
+       }
+ 
+diff --git a/ChangeLog b/ChangeLog
+index f571f66533b..091535beb5c 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-03-26  Fu Wei <fu.wei@linaro.org>
++
++	* grub-core/loader/arm64/linux.c: Remove redundant "0x".
++
+ 2014-02-28  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* include/grub/i386/openbsd_bootarg.h: Add addr and frequency fields.
diff --git a/SOURCES/0068-grub-core-lib-relocator.c-Fix-the-case-when-end-of-l.patch b/SOURCES/0068-grub-core-lib-relocator.c-Fix-the-case-when-end-of-l.patch
new file mode 100644
index 0000000..9f0d9c3
--- /dev/null
+++ b/SOURCES/0068-grub-core-lib-relocator.c-Fix-the-case-when-end-of-l.patch
@@ -0,0 +1,36 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Wed, 26 Mar 2014 08:48:30 +0100
+Subject: [PATCH] * grub-core/lib/relocator.c: Fix the case when end of
+ leftover is used.
+
+---
+ grub-core/lib/relocator.c | 2 ++
+ ChangeLog                 | 4 ++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c
+index 9f9770bc48d..cb11ea5fa27 100644
+--- a/grub-core/lib/relocator.c
++++ b/grub-core/lib/relocator.c
+@@ -865,6 +865,8 @@ malloc_in_range (struct grub_relocator *rel,
+ 			% GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT;
+ 		      struct grub_relocator_fw_leftover *lo
+ 			= events[last_lo].leftover;
++		      if (offend == 0 && alloc_end != alloc_start)
++			offend = GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT;
+ 		      lo->freebytes[offstart / 8]
+ 			&= ((1 << (8 - (start % 8))) - 1);
+ 		      grub_memset (lo->freebytes + (offstart + 7) / 8, 0,
+diff --git a/ChangeLog b/ChangeLog
+index 091535beb5c..9404edab8e1 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-03-26  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/lib/relocator.c: Fix the case when end of leftover is used.
++
+ 2014-03-26  Fu Wei <fu.wei@linaro.org>
+ 
+ 	* grub-core/loader/arm64/linux.c: Remove redundant "0x".
diff --git a/SOURCES/0069-Fix-grub-probe-0-option.patch b/SOURCES/0069-Fix-grub-probe-0-option.patch
new file mode 100644
index 0000000..6727c9d
--- /dev/null
+++ b/SOURCES/0069-Fix-grub-probe-0-option.patch
@@ -0,0 +1,52 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 31 Mar 2014 13:51:17 +0100
+Subject: [PATCH] Fix grub-probe -0 option
+
+* util/grub-probe,c (options): Make -0 work again (broken by
+conversion to argp).
+(main): Simplify logic.
+---
+ util/grub-probe.c | 7 ++-----
+ ChangeLog         | 6 ++++++
+ 2 files changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/util/grub-probe.c b/util/grub-probe.c
+index 1f3b59f05b9..80509be8aa7 100644
+--- a/util/grub-probe.c
++++ b/util/grub-probe.c
+@@ -711,6 +711,7 @@ static struct argp_option options[] = {
+    N_("use FILE as the device map [default=%s]"), 0},
+   {"target",  't', N_("TARGET"), 0, 0, 0},
+   {"verbose",     'v', 0,      0, N_("print verbose messages."), 0},
++  {0, '0', 0, 0, N_("separate items in output using ASCII NUL characters"), 0},
+   { 0, 0, 0, 0, 0, 0 }
+ };
+ 
+@@ -884,11 +885,7 @@ main (int argc, char *argv[])
+   else
+     probe (arguments.devices[0], NULL, delim);
+ 
+-  if (!arguments.zero_delim && (print == PRINT_BIOS_HINT
+-				|| print == PRINT_IEEE1275_HINT
+-				|| print == PRINT_BAREMETAL_HINT
+-				|| print == PRINT_EFI_HINT
+-				|| print == PRINT_ARC_HINT))
++  if (delim == ' ')
+     putchar ('\n');
+ 
+   /* Free resources.  */
+diff --git a/ChangeLog b/ChangeLog
+index 9404edab8e1..efbed8ccbf6 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,9 @@
++2014-03-31  Colin Watson  <cjwatson@ubuntu.com>
++
++	* util/grub-probe,c (options): Make -0 work again (broken by
++	conversion to argp).
++	(main): Simplify logic.
++
+ 2014-03-26  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/lib/relocator.c: Fix the case when end of leftover is used.
diff --git a/SOURCES/0070-Fix-partmap-cryptodisk-and-abstraction-handling-in-g.patch b/SOURCES/0070-Fix-partmap-cryptodisk-and-abstraction-handling-in-g.patch
new file mode 100644
index 0000000..55939c1
--- /dev/null
+++ b/SOURCES/0070-Fix-partmap-cryptodisk-and-abstraction-handling-in-g.patch
@@ -0,0 +1,361 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 31 Mar 2014 14:48:33 +0100
+Subject: [PATCH] Fix partmap, cryptodisk, and abstraction handling in
+ grub-mkconfig.
+
+Commit 588744d0dc655177d5883bdcb8f72ff5160109ed caused grub-mkconfig
+no longer to be forgiving of trailing spaces on grub-probe output
+lines, which among other things means that util/grub.d/10_linux.in
+no longer detects LVM.  To fix this, make grub-probe's output
+delimiting more consistent.  As a bonus, this improves the coverage
+of the -0 option.
+
+Fixes Debian bug #735935.
+
+* grub-core/disk/cryptodisk.c
+(grub_util_cryptodisk_get_abstraction): Add a user-data argument.
+* grub-core/disk/diskfilter.c (grub_diskfilter_get_partmap):
+Likewise.
+* include/grub/cryptodisk.h (grub_util_cryptodisk_get_abstraction):
+Update prototype.
+* include/grub/diskfilter.h (grub_diskfilter_get_partmap): Likewise.
+* util/grub-install.c (push_partmap_module, push_cryptodisk_module,
+probe_mods): Adjust for extra user-data arguments.
+* util/grub-probe.c (do_print, probe_partmap, probe_cryptodisk_uuid,
+probe_abstraction): Use configured delimiter.  Update callers.
+---
+ grub-core/disk/cryptodisk.c | 19 ++++++++++---------
+ grub-core/disk/diskfilter.c |  5 +++--
+ util/grub-install.c         | 14 ++++++++++----
+ util/grub-probe.c           | 46 ++++++++++++++++++++++-----------------------
+ include/grub/cryptodisk.h   |  3 ++-
+ include/grub/diskfilter.h   |  3 ++-
+ ChangeLog                   | 25 ++++++++++++++++++++++++
+ 7 files changed, 74 insertions(+), 41 deletions(-)
+
+diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
+index 75c6e1f91ac..f0e3a900ae3 100644
+--- a/grub-core/disk/cryptodisk.c
++++ b/grub-core/disk/cryptodisk.c
+@@ -762,25 +762,26 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name,
+ 
+ void
+ grub_util_cryptodisk_get_abstraction (grub_disk_t disk,
+-				      void (*cb) (const char *val))
++				      void (*cb) (const char *val, void *data),
++				      void *data)
+ {
+   grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
+ 
+-  cb ("cryptodisk");
+-  cb (dev->modname);
++  cb ("cryptodisk", data);
++  cb (dev->modname, data);
+ 
+   if (dev->cipher)
+-    cb (dev->cipher->cipher->modname);
++    cb (dev->cipher->cipher->modname, data);
+   if (dev->secondary_cipher)
+-    cb (dev->secondary_cipher->cipher->modname);
++    cb (dev->secondary_cipher->cipher->modname, data);
+   if (dev->essiv_cipher)
+-    cb (dev->essiv_cipher->cipher->modname);
++    cb (dev->essiv_cipher->cipher->modname, data);
+   if (dev->hash)
+-    cb (dev->hash->modname);
++    cb (dev->hash->modname, data);
+   if (dev->essiv_hash)
+-    cb (dev->essiv_hash->modname);
++    cb (dev->essiv_hash->modname, data);
+   if (dev->iv_hash)
+-    cb (dev->iv_hash->modname);
++    cb (dev->iv_hash->modname, data);
+ }
+ 
+ const char *
+diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
+index 28b70c666d4..e8a3bcbd138 100644
+--- a/grub-core/disk/diskfilter.c
++++ b/grub-core/disk/diskfilter.c
+@@ -354,7 +354,8 @@ grub_diskfilter_memberlist (grub_disk_t disk)
+ 
+ void
+ grub_diskfilter_get_partmap (grub_disk_t disk,
+-			     void (*cb) (const char *pm))
++			     void (*cb) (const char *pm, void *data),
++			     void *data)
+ {
+   struct grub_diskfilter_lv *lv = disk->data;
+   struct grub_diskfilter_pv *pv;
+@@ -376,7 +377,7 @@ grub_diskfilter_get_partmap (grub_disk_t disk,
+ 	    continue;
+ 	  }
+ 	for (s = 0; pv->partmaps[s]; s++)
+-	  cb (pv->partmaps[s]);
++	  cb (pv->partmaps[s], data);
+       }
+ }
+ 
+diff --git a/util/grub-install.c b/util/grub-install.c
+index 2e6226a3716..e9c6a4656ef 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -387,7 +387,7 @@ probe_raid_level (grub_disk_t disk)
+ }
+ 
+ static void
+-push_partmap_module (const char *map)
++push_partmap_module (const char *map, void *data __attribute__ ((unused)))
+ {
+   char buf[50];
+ 
+@@ -401,6 +401,12 @@ push_partmap_module (const char *map)
+   grub_install_push_module (buf);
+ }
+ 
++static void
++push_cryptodisk_module (const char *mod, void *data __attribute__ ((unused)))
++{
++  grub_install_push_module (mod);
++}
++
+ static void
+ probe_mods (grub_disk_t disk)
+ {
+@@ -412,11 +418,11 @@ probe_mods (grub_disk_t disk)
+     grub_util_info ("no partition map found for %s", disk->name);
+ 
+   for (part = disk->partition; part; part = part->parent)
+-    push_partmap_module (part->partmap->name);
++    push_partmap_module (part->partmap->name, NULL);
+ 
+   if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID)
+     {
+-      grub_diskfilter_get_partmap (disk, push_partmap_module);
++      grub_diskfilter_get_partmap (disk, push_partmap_module, NULL);
+       have_abstractions = 1;
+     }
+ 
+@@ -432,7 +438,7 @@ probe_mods (grub_disk_t disk)
+   if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+     {
+       grub_util_cryptodisk_get_abstraction (disk,
+-					    grub_install_push_module);
++					    push_cryptodisk_module, NULL);
+       have_abstractions = 1;
+       have_cryptodisk = 1;
+     }
+diff --git a/util/grub-probe.c b/util/grub-probe.c
+index 80509be8aa7..ecb7b6bbdf2 100644
+--- a/util/grub-probe.c
++++ b/util/grub-probe.c
+@@ -130,13 +130,14 @@ get_targets_string (void)
+ }
+ 
+ static void
+-do_print (const char *x)
++do_print (const char *x, void *data)
+ {
+-  grub_printf ("%s ", x);
++  char delim = *(const char *) data;
++  grub_printf ("%s%c", x, delim);
+ }
+ 
+ static void
+-probe_partmap (grub_disk_t disk)
++probe_partmap (grub_disk_t disk, char delim)
+ {
+   grub_partition_t part;
+   grub_disk_memberlist_t list = NULL, tmp;
+@@ -147,10 +148,10 @@ probe_partmap (grub_disk_t disk)
+     }
+ 
+   for (part = disk->partition; part; part = part->parent)
+-    printf ("%s ", part->partmap->name);
++    printf ("%s%c", part->partmap->name, delim);
+ 
+   if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID)
+-    grub_diskfilter_get_partmap (disk, do_print);
++    grub_diskfilter_get_partmap (disk, do_print, &delim);
+ 
+   /* In case of LVM/RAID, check the member devices as well.  */
+   if (disk->dev->memberlist)
+@@ -159,7 +160,7 @@ probe_partmap (grub_disk_t disk)
+     }
+   while (list)
+     {
+-      probe_partmap (list->disk);
++      probe_partmap (list->disk, delim);
+       tmp = list->next;
+       free (list);
+       list = tmp;
+@@ -167,7 +168,7 @@ probe_partmap (grub_disk_t disk)
+ }
+ 
+ static void
+-probe_cryptodisk_uuid (grub_disk_t disk)
++probe_cryptodisk_uuid (grub_disk_t disk, char delim)
+ {
+   grub_disk_memberlist_t list = NULL, tmp;
+ 
+@@ -178,7 +179,7 @@ probe_cryptodisk_uuid (grub_disk_t disk)
+     }
+   while (list)
+     {
+-      probe_cryptodisk_uuid (list->disk);
++      probe_cryptodisk_uuid (list->disk, delim);
+       tmp = list->next;
+       free (list);
+       list = tmp;
+@@ -186,7 +187,7 @@ probe_cryptodisk_uuid (grub_disk_t disk)
+   if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+     {
+       const char *uu = grub_util_cryptodisk_get_uuid (disk);
+-      grub_printf ("%s ", uu);
++      grub_printf ("%s%c", uu, delim);
+     }
+ }
+ 
+@@ -210,7 +211,7 @@ probe_raid_level (grub_disk_t disk)
+ }
+ 
+ static void
+-probe_abstraction (grub_disk_t disk)
++probe_abstraction (grub_disk_t disk, char delim)
+ {
+   grub_disk_memberlist_t list = NULL, tmp;
+   int raid_level;
+@@ -219,7 +220,7 @@ probe_abstraction (grub_disk_t disk)
+     list = disk->dev->memberlist (disk);
+   while (list)
+     {
+-      probe_abstraction (list->disk);
++      probe_abstraction (list->disk, delim);
+ 
+       tmp = list->next;
+       free (list);
+@@ -229,26 +230,26 @@ probe_abstraction (grub_disk_t disk)
+   if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID
+       && (grub_memcmp (disk->name, "lvm/", sizeof ("lvm/") - 1) == 0 ||
+ 	  grub_memcmp (disk->name, "lvmid/", sizeof ("lvmid/") - 1) == 0))
+-    printf ("lvm ");
++    printf ("lvm%c", delim);
+ 
+   if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID
+       && grub_memcmp (disk->name, "ldm/", sizeof ("ldm/") - 1) == 0)
+-    printf ("ldm ");
++    printf ("ldm%c", delim);
+ 
+   if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+-    grub_util_cryptodisk_get_abstraction (disk, do_print);
++    grub_util_cryptodisk_get_abstraction (disk, do_print, &delim);
+ 
+   raid_level = probe_raid_level (disk);
+   if (raid_level >= 0)
+     {
+-      printf ("diskfilter ");
++      printf ("diskfilter%c", delim);
+       if (disk->dev->raidname)
+-	printf ("%s ", disk->dev->raidname (disk));
++	printf ("%s%c", disk->dev->raidname (disk), delim);
+     }
+   if (raid_level == 5)
+-    printf ("raid5rec ");
++    printf ("raid5rec%c", delim);
+   if (raid_level == 6)
+-    printf ("raid6rec ");
++    printf ("raid6rec%c", delim);
+ }
+ 
+ static void
+@@ -630,16 +631,14 @@ probe (const char *path, char **device_names, char delim)
+ 
+       if (print == PRINT_ABSTRACTION)
+ 	{
+-	  probe_abstraction (dev->disk);
+-	  putchar (delim);
++	  probe_abstraction (dev->disk, delim);
+ 	  grub_device_close (dev);
+ 	  continue;
+ 	}
+ 
+       if (print == PRINT_CRYPTODISK_UUID)
+ 	{
+-	  probe_cryptodisk_uuid (dev->disk);
+-	  putchar (delim);
++	  probe_cryptodisk_uuid (dev->disk, delim);
+ 	  grub_device_close (dev);
+ 	  continue;
+ 	}
+@@ -647,8 +646,7 @@ probe (const char *path, char **device_names, char delim)
+       if (print == PRINT_PARTMAP)
+ 	{
+ 	  /* Check if dev->disk itself is contained in a partmap.  */
+-	  probe_partmap (dev->disk);
+-	  putchar (delim);
++	  probe_partmap (dev->disk, delim);
+ 	  grub_device_close (dev);
+ 	  continue;
+ 	}
+diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
+index 66f3e1e221b..f2ad2a79ab2 100644
+--- a/include/grub/cryptodisk.h
++++ b/include/grub/cryptodisk.h
+@@ -145,7 +145,8 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name,
+ 			      grub_disk_t source, const char *cheat);
+ void
+ grub_util_cryptodisk_get_abstraction (grub_disk_t disk,
+-				      void (*cb) (const char *val));
++				      void (*cb) (const char *val, void *data),
++				      void *data);
+ 
+ char *
+ grub_util_get_geli_uuid (const char *dev);
+diff --git a/include/grub/diskfilter.h b/include/grub/diskfilter.h
+index 042fe04a5a4..1aedcd3dffb 100644
+--- a/include/grub/diskfilter.h
++++ b/include/grub/diskfilter.h
+@@ -202,7 +202,8 @@ grub_diskfilter_get_pv_from_disk (grub_disk_t disk,
+ 				  struct grub_diskfilter_vg **vg);
+ void
+ grub_diskfilter_get_partmap (grub_disk_t disk,
+-			     void (*cb) (const char *val));
++			     void (*cb) (const char *val, void *data),
++			     void *data);
+ #endif
+ 
+ #endif /* ! GRUB_RAID_H */
+diff --git a/ChangeLog b/ChangeLog
+index efbed8ccbf6..1cb3b683fcf 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,28 @@
++2014-03-31  Colin Watson  <cjwatson@ubuntu.com>
++
++	Fix partmap, cryptodisk, and abstraction handling in grub-mkconfig.
++
++	Commit 588744d0dc655177d5883bdcb8f72ff5160109ed caused grub-mkconfig
++	no longer to be forgiving of trailing spaces on grub-probe output
++	lines, which among other things means that util/grub.d/10_linux.in
++	no longer detects LVM.  To fix this, make grub-probe's output
++	delimiting more consistent.  As a bonus, this improves the coverage
++	of the -0 option.
++
++	Fixes Debian bug #735935.
++
++	* grub-core/disk/cryptodisk.c
++	(grub_util_cryptodisk_get_abstraction): Add a user-data argument.
++	* grub-core/disk/diskfilter.c (grub_diskfilter_get_partmap):
++	Likewise.
++	* include/grub/cryptodisk.h (grub_util_cryptodisk_get_abstraction):
++	Update prototype.
++	* include/grub/diskfilter.h (grub_diskfilter_get_partmap): Likewise.
++	* util/grub-install.c (push_partmap_module, push_cryptodisk_module,
++	probe_mods): Adjust for extra user-data arguments.
++	* util/grub-probe.c (do_print, probe_partmap, probe_cryptodisk_uuid,
++	probe_abstraction): Use configured delimiter.  Update callers.
++
+ 2014-03-31  Colin Watson  <cjwatson@ubuntu.com>
+ 
+ 	* util/grub-probe,c (options): Make -0 work again (broken by
diff --git a/SOURCES/0071-btrfs-fix-get_root-key-comparison-failures-due-to-en.patch b/SOURCES/0071-btrfs-fix-get_root-key-comparison-failures-due-to-en.patch
new file mode 100644
index 0000000..9d091a0
--- /dev/null
+++ b/SOURCES/0071-btrfs-fix-get_root-key-comparison-failures-due-to-en.patch
@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
+Date: Mon, 31 Mar 2014 15:32:30 +0100
+Subject: [PATCH] btrfs: fix get_root key comparison failures due to endianness
+
+* grub-core/fs/btrfs.c (get_root): Convert
+GRUB_BTRFS_ROOT_VOL_OBJECTID to little-endian.
+---
+ grub-core/fs/btrfs.c | 2 +-
+ ChangeLog            | 7 +++++++
+ 2 files changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
+index 89666b6fd59..f7b6c152037 100644
+--- a/grub-core/fs/btrfs.c
++++ b/grub-core/fs/btrfs.c
+@@ -1201,7 +1201,7 @@ get_root (struct grub_btrfs_data *data, struct grub_btrfs_key *key,
+   struct grub_btrfs_key key_out, key_in;
+   struct grub_btrfs_root_item ri;
+ 
+-  key_in.object_id = GRUB_BTRFS_ROOT_VOL_OBJECTID;
++  key_in.object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_ROOT_VOL_OBJECTID);
+   key_in.offset = 0;
+   key_in.type = GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM;
+   err = lower_bound (data, &key_in, &key_out,
+diff --git a/ChangeLog b/ChangeLog
+index 1cb3b683fcf..accffade86b 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,10 @@
++2014-03-31  Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
++
++	btrfs: fix get_root key comparison failures due to endianness
++
++	* grub-core/fs/btrfs.c (get_root): Convert
++	GRUB_BTRFS_ROOT_VOL_OBJECTID to little-endian.
++
+ 2014-03-31  Colin Watson  <cjwatson@ubuntu.com>
+ 
+ 	Fix partmap, cryptodisk, and abstraction handling in grub-mkconfig.
diff --git a/SOURCES/0072-grub-core-osdep-linux-getroot.c-grub_util_part_to_di.patch b/SOURCES/0072-grub-core-osdep-linux-getroot.c-grub_util_part_to_di.patch
new file mode 100644
index 0000000..c98e586
--- /dev/null
+++ b/SOURCES/0072-grub-core-osdep-linux-getroot.c-grub_util_part_to_di.patch
@@ -0,0 +1,52 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Thu, 3 Apr 2014 21:31:12 +0200
+Subject: [PATCH] * grub-core/osdep/linux/getroot.c (grub_util_part_to_disk):
+ Support NVMe device names.
+
+---
+ grub-core/osdep/linux/getroot.c | 17 +++++++++++++++++
+ ChangeLog                       |  5 +++++
+ 2 files changed, 22 insertions(+)
+
+diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
+index 19581d32997..7007193d9c7 100644
+--- a/grub-core/osdep/linux/getroot.c
++++ b/grub-core/osdep/linux/getroot.c
+@@ -896,6 +896,23 @@ grub_util_part_to_disk (const char *os_dev, struct stat *st,
+ 	  *pp = '\0';
+ 	  return path;
+ 	}
++
++      /* If this is a NVMe device */
++      if ((strncmp ("nvme", p, 4) == 0) && p[4] >= '0' && p[4] <= '9')
++	{
++	  char *pp = p + 4;
++	  while (*pp >= '0' && *pp <= '9')
++	    pp++;
++	  if (*pp == 'n')
++	    pp++;
++	  while (*pp >= '0' && *pp <= '9')
++	    pp++;
++	  if (*pp == 'p')
++	    *is_part = 1;
++	  /* /dev/nvme[0-9]+n[0-9]+p[0-9]* */
++	  *pp = '\0';
++	  return path;
++	}
+     }
+ 
+   return path;
+diff --git a/ChangeLog b/ChangeLog
+index accffade86b..4a484092a6f 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-04-03  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/osdep/linux/getroot.c (grub_util_part_to_disk): Support NVMe
++	device names.
++
+ 2014-03-31  Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
+ 
+ 	btrfs: fix get_root key comparison failures due to endianness
diff --git a/SOURCES/0073-Replace-few-instances-of-memcmp-memcpy-in-the-code-t.patch b/SOURCES/0073-Replace-few-instances-of-memcmp-memcpy-in-the-code-t.patch
new file mode 100644
index 0000000..3627cff
--- /dev/null
+++ b/SOURCES/0073-Replace-few-instances-of-memcmp-memcpy-in-the-code-t.patch
@@ -0,0 +1,99 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 4 Apr 2014 07:58:42 +0200
+Subject: [PATCH] Replace few instances of memcmp/memcpy in the code that
+ should be grub_memcmp/grub_memcpy.
+
+---
+ grub-core/commands/acpihalt.c  | 4 ++--
+ grub-core/commands/legacycfg.c | 4 ++--
+ grub-core/lib/relocator.c      | 2 +-
+ grub-core/loader/i386/bsd.c    | 4 ++--
+ ChangeLog                      | 5 +++++
+ 5 files changed, 12 insertions(+), 7 deletions(-)
+
+diff --git a/grub-core/commands/acpihalt.c b/grub-core/commands/acpihalt.c
+index 09421a6c69d..83bdfe1f23c 100644
+--- a/grub-core/commands/acpihalt.c
++++ b/grub-core/commands/acpihalt.c
+@@ -214,8 +214,8 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end,
+ 	  }
+ 	case GRUB_ACPI_OPCODE_NAME:
+ 	  ptr++;
+-	  if ((!scope || memcmp (scope, "\\", scope_len) == 0) &&
+-	      (memcmp (ptr, "_S5_", 4) == 0 || memcmp (ptr, "\\_S5_", 4) == 0))
++	  if ((!scope || grub_memcmp (scope, "\\", scope_len) == 0) &&
++	      (grub_memcmp (ptr, "_S5_", 4) == 0 || grub_memcmp (ptr, "\\_S5_", 4) == 0))
+ 	    {
+ 	      int ll;
+ 	      grub_uint8_t *ptr2 = ptr;
+diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c
+index e42a9d83ebb..2c09fb7dd78 100644
+--- a/grub-core/commands/legacycfg.c
++++ b/grub-core/commands/legacycfg.c
+@@ -580,7 +580,7 @@ check_password_md5_real (const char *entered,
+   GRUB_MD_MD5->write (ctx, entered, enteredlen);
+   digest = GRUB_MD_MD5->read (ctx);
+   GRUB_MD_MD5->final (ctx);
+-  memcpy (alt_result, digest, MD5_HASHLEN);
++  grub_memcpy (alt_result, digest, MD5_HASHLEN);
+   
+   GRUB_MD_MD5->init (ctx);
+   GRUB_MD_MD5->write (ctx, entered, enteredlen);
+@@ -596,7 +596,7 @@ check_password_md5_real (const char *entered,
+ 
+   for (i = 0; i < 1000; i++)
+     {
+-      memcpy (alt_result, digest, 16);
++      grub_memcpy (alt_result, digest, 16);
+ 
+       GRUB_MD_MD5->init (ctx);
+       if ((i & 1) != 0)
+diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c
+index cb11ea5fa27..f759c7f41f4 100644
+--- a/grub-core/lib/relocator.c
++++ b/grub-core/lib/relocator.c
+@@ -652,7 +652,7 @@ malloc_in_range (struct grub_relocator *rel,
+     for (i = 0; i < (BITS_IN_BYTE * sizeof (grub_addr_t) / DIGITSORT_BITS);
+ 	 i++)
+       {
+-	memset (counter, 0, (1 + (1 << DIGITSORT_BITS)) * sizeof (counter[0]));
++	grub_memset (counter, 0, (1 + (1 << DIGITSORT_BITS)) * sizeof (counter[0]));
+ 	for (j = 0; j < N; j++)
+ 	  counter[((events[j].pos >> (DIGITSORT_BITS * i)) 
+ 		   & DIGITSORT_MASK) + 1]++;
+diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c
+index 19985f03e65..41ef9109ee1 100644
+--- a/grub-core/loader/i386/bsd.c
++++ b/grub-core/loader/i386/bsd.c
+@@ -1082,7 +1082,7 @@ grub_netbsd_add_boot_disk_and_wedge (void)
+ 
+     grub_crypto_hash (GRUB_MD_MD5, hash,
+ 		      buf.raw, GRUB_DISK_SECTOR_SIZE);
+-    memcpy (biw.matchhash, hash, 16);
++    grub_memcpy (biw.matchhash, hash, 16);
+ 
+     grub_bsd_add_meta (NETBSD_BTINFO_BOOTWEDGE, &biw, sizeof (biw));
+   }
+@@ -1100,7 +1100,7 @@ grub_netbsd_add_boot_disk_and_wedge (void)
+ 	bid.labelsector = partmapsector;
+ 	bid.label.type = buf.label.type;
+ 	bid.label.checksum = buf.label.checksum;
+-	memcpy (bid.label.packname, buf.label.packname, 16);
++	grub_memcpy (bid.label.packname, buf.label.packname, 16);
+       }
+     else
+       {
+diff --git a/ChangeLog b/ChangeLog
+index 4a484092a6f..f18cdba90ce 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-04-04  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	Replace few instances of memcmp/memcpy in the code that should be
++	grub_memcmp/grub_memcpy.
++
+ 2014-04-03  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/osdep/linux/getroot.c (grub_util_part_to_disk): Support NVMe
diff --git a/SOURCES/0074-include-grub-libgcc.h-Remove-ctzsi2-and-ctzdi2.-They.patch b/SOURCES/0074-include-grub-libgcc.h-Remove-ctzsi2-and-ctzdi2.-They.patch
new file mode 100644
index 0000000..fce04da
--- /dev/null
+++ b/SOURCES/0074-include-grub-libgcc.h-Remove-ctzsi2-and-ctzdi2.-They.patch
@@ -0,0 +1,42 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 4 Apr 2014 08:02:38 +0200
+Subject: [PATCH] * include/grub/libgcc.h: Remove ctzsi2 and ctzdi2. They're no
+ longer pulled from libgcc.
+
+---
+ include/grub/libgcc.h | 7 -------
+ ChangeLog             | 5 +++++
+ 2 files changed, 5 insertions(+), 7 deletions(-)
+
+diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h
+index fdc6611a04c..97233d79e4c 100644
+--- a/include/grub/libgcc.h
++++ b/include/grub/libgcc.h
+@@ -42,13 +42,6 @@ void EXPORT_FUNC (__bswapsi2) (void);
+ # ifdef HAVE___BSWAPDI2
+ void EXPORT_FUNC (__bswapdi2) (void);
+ # endif
+-# ifdef HAVE___CTZDI2
+-void EXPORT_FUNC (__ctzdi2) (void);
+-# endif
+-# ifdef HAVE___CTZSI2
+-void EXPORT_FUNC (__ctzsi2) (void);
+-# endif
+-#endif
+ 
+ #ifdef HAVE__RESTGPR_14_X
+ void EXPORT_FUNC (_restgpr_14_x) (void);
+diff --git a/ChangeLog b/ChangeLog
+index f18cdba90ce..90e41bdadb3 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-04-04  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* include/grub/libgcc.h: Remove ctzsi2 and ctzdi2. They're no longer
++	pulled from libgcc.
++
+ 2014-04-04  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	Replace few instances of memcmp/memcpy in the code that should be
diff --git a/SOURCES/0075-Add-missing-endif.patch b/SOURCES/0075-Add-missing-endif.patch
new file mode 100644
index 0000000..f2a1037
--- /dev/null
+++ b/SOURCES/0075-Add-missing-endif.patch
@@ -0,0 +1,21 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 4 Apr 2014 08:11:15 +0200
+Subject: [PATCH] Add missing #endif
+
+---
+ include/grub/libgcc.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h
+index 97233d79e4c..8e93b6792d9 100644
+--- a/include/grub/libgcc.h
++++ b/include/grub/libgcc.h
+@@ -42,6 +42,7 @@ void EXPORT_FUNC (__bswapsi2) (void);
+ # ifdef HAVE___BSWAPDI2
+ void EXPORT_FUNC (__bswapdi2) (void);
+ # endif
++#endif
+ 
+ #ifdef HAVE__RESTGPR_14_X
+ void EXPORT_FUNC (_restgpr_14_x) (void);
diff --git a/SOURCES/0076-grub-core-lib-syslinux_parse.c-Fix-timeout-quoting.patch b/SOURCES/0076-grub-core-lib-syslinux_parse.c-Fix-timeout-quoting.patch
new file mode 100644
index 0000000..b738f38
--- /dev/null
+++ b/SOURCES/0076-grub-core-lib-syslinux_parse.c-Fix-timeout-quoting.patch
@@ -0,0 +1,35 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Sun, 6 Apr 2014 00:44:44 +0200
+Subject: [PATCH] * grub-core/lib/syslinux_parse.c: Fix timeout quoting.
+
+---
+ grub-core/lib/syslinux_parse.c | 2 +-
+ ChangeLog                      | 4 ++++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/lib/syslinux_parse.c b/grub-core/lib/syslinux_parse.c
+index 21fa17504aa..6bc504b7c58 100644
+--- a/grub-core/lib/syslinux_parse.c
++++ b/grub-core/lib/syslinux_parse.c
+@@ -1432,7 +1432,7 @@ config_file (struct output_buffer *outbuf,
+       for (curentry = menu.entries; curentry->next; curentry = curentry->next);
+       lentry = curentry;
+ 
+-      print_string ("set timeout='");
++      print_string ("set timeout=");
+       err = print_num (outbuf, (menu.timeout + 9) / 10);
+       if (err)
+ 	return err;
+diff --git a/ChangeLog b/ChangeLog
+index 90e41bdadb3..50d9291624a 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-04-06  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/lib/syslinux_parse.c: Fix timeout quoting.
++
+ 2014-04-04  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* include/grub/libgcc.h: Remove ctzsi2 and ctzdi2. They're no longer
diff --git a/SOURCES/0077-Improve-LVM-logical_volumes-string-matching.patch b/SOURCES/0077-Improve-LVM-logical_volumes-string-matching.patch
new file mode 100644
index 0000000..c5c603d
--- /dev/null
+++ b/SOURCES/0077-Improve-LVM-logical_volumes-string-matching.patch
@@ -0,0 +1,42 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Thu, 10 Apr 2014 14:42:41 +0100
+Subject: [PATCH] Improve LVM "logical_volumes" string matching
+
+* grub-core/disk/lvm.c (grub_lvm_detect): Search for
+"logical_volumes" block a little more accurately.
+---
+ grub-core/disk/lvm.c | 4 ++--
+ ChangeLog            | 5 +++++
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
+index 483c17eb5f6..862a9664f2c 100644
+--- a/grub-core/disk/lvm.c
++++ b/grub-core/disk/lvm.c
+@@ -333,10 +333,10 @@ grub_lvm_detect (grub_disk_t disk,
+ 	    }
+ 	}
+ 
+-      p = grub_strstr (p, "logical_volumes");
++      p = grub_strstr (p, "logical_volumes {");
+       if (p)
+ 	{
+-	  p += sizeof ("logical_volumes = ") - 1;
++	  p += sizeof ("logical_volumes {") - 1;
+ 
+ 	  /* And add all the lvs to the volume group. */
+ 	  while (1)
+diff --git a/ChangeLog b/ChangeLog
+index 50d9291624a..7f0c57dc0ae 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-04-10  Colin Watson  <cjwatson@ubuntu.com>
++
++	* grub-core/disk/lvm.c (grub_lvm_detect): Search for
++	"logical_volumes" block a little more accurately.
++
+ 2014-04-06  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/lib/syslinux_parse.c: Fix timeout quoting.
diff --git a/SOURCES/0078-Tolerate-devices-with-no-filesystem-UUID-returned-by.patch b/SOURCES/0078-Tolerate-devices-with-no-filesystem-UUID-returned-by.patch
new file mode 100644
index 0000000..1633534
--- /dev/null
+++ b/SOURCES/0078-Tolerate-devices-with-no-filesystem-UUID-returned-by.patch
@@ -0,0 +1,78 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Thu, 10 Apr 2014 16:54:33 +0100
+Subject: [PATCH] Tolerate devices with no filesystem UUID returned by
+ os-prober
+
+* util/grub.d/30_os-prober.in: Tolerate devices with no filesystem
+UUID.  Other parts of grub-mkconfig tolerate these, they were
+previously allowed here up to commit
+55e706c918922def17f5012c23cfe88c4c645208, and they can arise in
+practice when the system has active LVM snapshots.
+Fixes Ubuntu bug #1287436.
+---
+ ChangeLog                   |  9 +++++++++
+ util/grub.d/30_os-prober.in | 23 +++++++++++++----------
+ 2 files changed, 22 insertions(+), 10 deletions(-)
+
+diff --git a/ChangeLog b/ChangeLog
+index 7f0c57dc0ae..35564681a4d 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,12 @@
++2014-04-10  Colin Watson  <cjwatson@ubuntu.com>
++
++	* util/grub.d/30_os-prober.in: Tolerate devices with no filesystem
++	UUID.  Other parts of grub-mkconfig tolerate these, they were
++	previously allowed here up to commit
++	55e706c918922def17f5012c23cfe88c4c645208, and they can arise in
++	practice when the system has active LVM snapshots.
++	Fixes Ubuntu bug #1287436.
++
+ 2014-04-10  Colin Watson  <cjwatson@ubuntu.com>
+ 
+ 	* grub-core/disk/lvm.c (grub_lvm_detect): Search for
+diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
+index 7cf8487d63a..6f38c82a554 100644
+--- a/util/grub.d/30_os-prober.in
++++ b/util/grub.d/30_os-prober.in
+@@ -112,16 +112,17 @@ for OS in ${OSPROBED} ; do
+   LONGNAME="`echo ${OS} | cut -d ':' -f 2 | tr '^' ' '`"
+   LABEL="`echo ${OS} | cut -d ':' -f 3 | tr '^' ' '`"
+   BOOT="`echo ${OS} | cut -d ':' -f 4`"
+-  UUID="`${grub_probe} --target=fs_uuid --device ${DEVICE%@*}`"
+-  EXPUUID="$UUID"
++  if UUID="`${grub_probe} --target=fs_uuid --device ${DEVICE%@*}`"; then
++    EXPUUID="$UUID"
+ 
+-  if [ x"${DEVICE#*@}" != x ] ; then
++    if [ x"${DEVICE#*@}" != x ] ; then
+       EXPUUID="${EXPUUID}@${DEVICE#*@}"
+-  fi
++    fi
+ 
+-  if [ "x${GRUB_OS_PROBER_SKIP_LIST}" != "x" ] && [ "x`echo ${GRUB_OS_PROBER_SKIP_LIST} | grep -i -e '\b'${EXPUUID}'\b'`" != "x" ] ; then
+-    echo "Skipped ${LONGNAME} on ${DEVICE} by user request." >&2
+-    continue
++    if [ "x${GRUB_OS_PROBER_SKIP_LIST}" != "x" ] && [ "x`echo ${GRUB_OS_PROBER_SKIP_LIST} | grep -i -e '\b'${EXPUUID}'\b'`" != "x" ] ; then
++      echo "Skipped ${LONGNAME} on ${DEVICE} by user request." >&2
++      continue
++    fi
+   fi
+ 
+   BTRFS="`echo ${OS} | cut -d ':' -f 5`"
+@@ -277,9 +278,11 @@ EOF
+       echo "$title_correction_code"
+     ;;
+     macosx)
+-      OSXUUID="${UUID}"
+-      osx_entry xnu_kernel 32
+-      osx_entry xnu_kernel64 64
++      if [ "${UUID}" ]; then
++	OSXUUID="${UUID}"
++	osx_entry xnu_kernel 32
++	osx_entry xnu_kernel64 64
++      fi
+     ;;
+     hurd)
+       onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
diff --git a/SOURCES/0079-Allow-loading-old-kernels-by-placing-GDT-in-conventi.patch b/SOURCES/0079-Allow-loading-old-kernels-by-placing-GDT-in-conventi.patch
new file mode 100644
index 0000000..bb34f1c
--- /dev/null
+++ b/SOURCES/0079-Allow-loading-old-kernels-by-placing-GDT-in-conventi.patch
@@ -0,0 +1,46 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Piotr Krysiuk <piotras@gmail.com>
+Date: Sun, 20 Apr 2014 15:58:45 +0200
+Subject: [PATCH] Allow loading old kernels by placing GDT in conventional
+ memory.
+
+---
+ grub-core/lib/i386/relocator.c | 11 +++++++----
+ ChangeLog                      |  5 +++++
+ 2 files changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c
+index d2a1b27ae0e..ffaf25f088d 100644
+--- a/grub-core/lib/i386/relocator.c
++++ b/grub-core/lib/i386/relocator.c
+@@ -81,10 +81,13 @@ grub_relocator32_boot (struct grub_relocator *rel,
+   void *relst;
+   grub_relocator_chunk_t ch;
+ 
+-  err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
+-					  (0xffffffff - RELOCATOR_SIZEOF (32))
+-					  + 1, RELOCATOR_SIZEOF (32), 16,
+-					  GRUB_RELOCATOR_PREFERENCE_NONE,
++  /* Specific memory range due to Global Descriptor Table for use by payload
++     that we will store in returned chunk.  The address range and preference
++     are based on "THE LINUX/x86 BOOT PROTOCOL" specification.  */
++  err = grub_relocator_alloc_chunk_align (rel, &ch, 0x1000,
++					  0x9a000 - RELOCATOR_SIZEOF (32),
++					  RELOCATOR_SIZEOF (32), 16,
++					  GRUB_RELOCATOR_PREFERENCE_LOW,
+ 					  avoid_efi_bootservices);
+   if (err)
+     return err;
+diff --git a/ChangeLog b/ChangeLog
+index 35564681a4d..73a89289945 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-04-20  Piotr Krysiuk  <piotras@gmail.com>
++
++	* grub-core/lib/i386/relocator.c: Allow loading old kernels by placing
++	GDT in conventional memory.
++
+ 2014-04-10  Colin Watson  <cjwatson@ubuntu.com>
+ 
+ 	* util/grub.d/30_os-prober.in: Tolerate devices with no filesystem
diff --git a/SOURCES/0080-grub-core-kern-misc.c-__bzero-Don-t-compile-in-GRUB_.patch b/SOURCES/0080-grub-core-kern-misc.c-__bzero-Don-t-compile-in-GRUB_.patch
new file mode 100644
index 0000000..3aeb75c
--- /dev/null
+++ b/SOURCES/0080-grub-core-kern-misc.c-__bzero-Don-t-compile-in-GRUB_.patch
@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Sun, 20 Apr 2014 16:12:41 +0200
+Subject: [PATCH] * grub-core/kern/misc.c (__bzero): Don't compile in
+ GRUB_UTIL.
+
+	Reported by: Yves Blusseau <blusseau@zetam.org>.
+---
+ grub-core/kern/misc.c | 3 +++
+ ChangeLog             | 6 ++++++
+ 2 files changed, 9 insertions(+)
+
+diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
+index 54db2e1254e..c5c815d8d13 100644
+--- a/grub-core/kern/misc.c
++++ b/grub-core/kern/misc.c
+@@ -542,6 +542,9 @@ memset (void *s, int c, grub_size_t n)
+   return grub_memset (s, c, n);
+ }
+ 
++#endif
++
++#if !defined(GRUB_UTIL) && defined(__APPLE__)
+ void GRUB_BUILTIN_ATTR
+ __bzero (void *s, grub_size_t n)
+ {
+diff --git a/ChangeLog b/ChangeLog
+index 73a89289945..3b61c0a996d 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,9 @@
++2014-04-20  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/kern/misc.c (__bzero): Don't compile in GRUB_UTIL.
++
++	Reported by: Yves Blusseau <blusseau@zetam.org>.
++
+ 2014-04-20  Piotr Krysiuk  <piotras@gmail.com>
+ 
+ 	* grub-core/lib/i386/relocator.c: Allow loading old kernels by placing
diff --git a/SOURCES/0081-grub-core-commands-verify.c-grub_pubkey_open-Fix-mem.patch b/SOURCES/0081-grub-core-commands-verify.c-grub_pubkey_open-Fix-mem.patch
new file mode 100644
index 0000000..f941491
--- /dev/null
+++ b/SOURCES/0081-grub-core-commands-verify.c-grub_pubkey_open-Fix-mem.patch
@@ -0,0 +1,37 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Mon, 12 May 2014 10:01:48 +0200
+Subject: [PATCH] * grub-core/commands/verify.c (grub_pubkey_open): Fix memdisk
+ check.
+
+---
+ grub-core/commands/verify.c | 2 +-
+ ChangeLog                   | 5 +++++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c
+index a9dfd885247..6349ccfbaea 100644
+--- a/grub-core/commands/verify.c
++++ b/grub-core/commands/verify.c
+@@ -835,7 +835,7 @@ grub_pubkey_open (grub_file_t io, const char *filename)
+ 
+   if (!sec)
+     return io;
+-  if (io->device->disk && io->device->disk->id == GRUB_DISK_DEVICE_MEMDISK_ID)
++  if (io->device->disk && io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID)
+     return io;
+   fsuf = grub_malloc (grub_strlen (filename) + sizeof (".sig"));
+   if (!fsuf)
+diff --git a/ChangeLog b/ChangeLog
+index 3b61c0a996d..d0896d89e53 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-06-21  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/commands/verify.c (grub_pubkey_open): Fix memdisk
++	check.
++
+ 2014-04-20  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/kern/misc.c (__bzero): Don't compile in GRUB_UTIL.
diff --git a/SOURCES/0082-grub-core-commands-verify.c-grub_pubkey_open-Trust-p.patch b/SOURCES/0082-grub-core-commands-verify.c-grub_pubkey_open-Trust-p.patch
new file mode 100644
index 0000000..c86aea0
--- /dev/null
+++ b/SOURCES/0082-grub-core-commands-verify.c-grub_pubkey_open-Trust-p.patch
@@ -0,0 +1,38 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Thu, 15 May 2014 14:36:48 +0200
+Subject: [PATCH] * grub-core/commands/verify.c (grub_pubkey_open): Trust
+ procfs.
+
+---
+ grub-core/commands/verify.c | 4 +++-
+ ChangeLog                   | 4 ++++
+ 2 files changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c
+index 6349ccfbaea..525bdd18737 100644
+--- a/grub-core/commands/verify.c
++++ b/grub-core/commands/verify.c
+@@ -835,7 +835,9 @@ grub_pubkey_open (grub_file_t io, const char *filename)
+ 
+   if (!sec)
+     return io;
+-  if (io->device->disk && io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID)
++  if (io->device->disk && 
++      (io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID
++       || io->device->disk->dev->id == GRUB_DISK_DEVICE_PROCFS_ID))
+     return io;
+   fsuf = grub_malloc (grub_strlen (filename) + sizeof (".sig"));
+   if (!fsuf)
+diff --git a/ChangeLog b/ChangeLog
+index d0896d89e53..2a94ad979b3 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-06-21  Vladimir Serbinenko  <phcoder@gmail.com>
++
++	* grub-core/commands/verify.c (grub_pubkey_open): Trust procfs.
++
+ 2014-06-21  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/commands/verify.c (grub_pubkey_open): Fix memdisk
diff --git a/SOURCES/0083-util-grub-gen-asciih.c-add_glyph-Fix-uninitialised-v.patch b/SOURCES/0083-util-grub-gen-asciih.c-add_glyph-Fix-uninitialised-v.patch
new file mode 100644
index 0000000..3933381
--- /dev/null
+++ b/SOURCES/0083-util-grub-gen-asciih.c-add_glyph-Fix-uninitialised-v.patch
@@ -0,0 +1,70 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Trevor Woerner <trevor.woerner@linaro.org>
+Date: Sat, 21 Jun 2014 20:26:47 +0200
+Subject: [PATCH] * util/grub-gen-asciih.c (add_glyph): Fix uninitialised
+ variable.
+
+---
+ util/grub-gen-asciih.c | 15 +++++++++------
+ ChangeLog              |  4 ++++
+ 2 files changed, 13 insertions(+), 6 deletions(-)
+
+diff --git a/util/grub-gen-asciih.c b/util/grub-gen-asciih.c
+index e01447ae94f..e35dcb78fe6 100644
+--- a/util/grub-gen-asciih.c
++++ b/util/grub-gen-asciih.c
+@@ -81,14 +81,14 @@ add_glyph (FT_UInt glyph_idx, FT_Face face,
+   err = FT_Load_Glyph (face, glyph_idx, flag);
+   if (err)
+     {
+-      printf ("Freetype Error %d loading glyph 0x%x for U+0x%x",
++      fprintf (stderr, "Freetype Error %d loading glyph 0x%x for U+0x%x",
+ 	      err, glyph_idx, char_code);
+ 
+       if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs))
+-	printf (": %s\n", ft_errmsgs[err]);
++	fprintf (stderr, ": %s\n", ft_errmsgs[err]);
+       else
+-	printf ("\n");
+-      return;
++	fprintf (stderr, "\n");
++      exit (1);
+     }
+ 
+   glyph = face->glyph;
+@@ -128,7 +128,6 @@ add_glyph (FT_UInt glyph_idx, FT_Face face,
+ static void
+ write_font_ascii_bitmap (FILE *file, FT_Face face)
+ {
+-  struct grub_glyph_info glyph;
+   int char_code;
+ 
+   fprintf (file, "/* THIS CHUNK OF BYTES IS AUTOMATICALLY GENERATED */\n");
+@@ -138,10 +137,14 @@ write_font_ascii_bitmap (FILE *file, FT_Face face)
+   for (char_code = 0; char_code <= 0x7f; char_code++)
+     {
+       FT_UInt glyph_idx;
+-      
++      struct grub_glyph_info glyph;
++
+       glyph_idx = FT_Get_Char_Index (face, char_code);
+       if (!glyph_idx)
+ 	return;
++
++      memset (&glyph, 0, sizeof(glyph));
++
+       add_glyph (glyph_idx, face, char_code, &glyph);
+ 
+       if (glyph.width == 8 && glyph.height == 16
+diff --git a/ChangeLog b/ChangeLog
+index 2a94ad979b3..b5521130874 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-06-21  Trevor Woerner <trevor.woerner@linaro.org>
++
++	* util/grub-gen-asciih.c (add_glyph): Fix uninitialised variable.
++
+ 2014-06-21  Vladimir Serbinenko  <phcoder@gmail.com>
+ 
+ 	* grub-core/commands/verify.c (grub_pubkey_open): Trust procfs.
diff --git a/SOURCES/0084-grub-core-commands-efi-lsefisystab.c-grub_cmd_lsefis.patch b/SOURCES/0084-grub-core-commands-efi-lsefisystab.c-grub_cmd_lsefis.patch
new file mode 100644
index 0000000..1a1d5f7
--- /dev/null
+++ b/SOURCES/0084-grub-core-commands-efi-lsefisystab.c-grub_cmd_lsefis.patch
@@ -0,0 +1,36 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Stephane Rochoy <sheda>
+Date: Sun, 22 Jun 2014 01:34:57 +0200
+Subject: [PATCH] * grub-core/commands/efi/lsefisystab.c
+ (grub_cmd_lsefisystab): Show EFI system table physical address.
+
+---
+ grub-core/commands/efi/lsefisystab.c | 1 +
+ ChangeLog                            | 5 +++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/grub-core/commands/efi/lsefisystab.c b/grub-core/commands/efi/lsefisystab.c
+index eda8c5ff3f3..8717db91ea2 100644
+--- a/grub-core/commands/efi/lsefisystab.c
++++ b/grub-core/commands/efi/lsefisystab.c
+@@ -52,6 +52,7 @@ grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)),
+   grub_efi_configuration_table_t *t;
+   unsigned int i;
+ 
++  grub_printf ("Address: %p\n", st);
+   grub_printf ("Signature: %016" PRIxGRUB_UINT64_T " revision: %08x\n",
+ 	       st->hdr.signature, st->hdr.revision);
+   {
+diff --git a/ChangeLog b/ChangeLog
+index b5521130874..abf8f4b2716 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-06-21  Stephane Rochoy <sheda>
++
++	* grub-core/commands/efi/lsefisystab.c (grub_cmd_lsefisystab): Show
++	EFI system table physical address.
++
+ 2014-06-21  Trevor Woerner <trevor.woerner@linaro.org>
+ 
+ 	* util/grub-gen-asciih.c (add_glyph): Fix uninitialised variable.
diff --git a/SOURCES/0085-grub-core-loader-i386-bsd.c-grub_netbsd_boot-Pass-po.patch b/SOURCES/0085-grub-core-loader-i386-bsd.c-grub_netbsd_boot-Pass-po.patch
new file mode 100644
index 0000000..bfb63cc
--- /dev/null
+++ b/SOURCES/0085-grub-core-loader-i386-bsd.c-grub_netbsd_boot-Pass-po.patch
@@ -0,0 +1,67 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Stephane Rochoy <sheda>
+Date: Sun, 22 Jun 2014 01:35:52 +0200
+Subject: [PATCH] * grub-core/loader/i386/bsd.c (grub_netbsd_boot): Pass
+ pointer to EFI system table.
+
+---
+ grub-core/loader/i386/bsd.c         | 8 ++++++++
+ include/grub/i386/netbsd_bootinfo.h | 7 +++++++
+ ChangeLog                           | 5 +++++
+ 3 files changed, 20 insertions(+)
+
+diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c
+index 41ef9109ee1..8f691e0e2d1 100644
+--- a/grub-core/loader/i386/bsd.c
++++ b/grub-core/loader/i386/bsd.c
+@@ -1145,6 +1145,14 @@ grub_netbsd_boot (void)
+   if (err)
+     return err;
+ 
++#ifdef GRUB_MACHINE_EFI
++  err = grub_bsd_add_meta (NETBSD_BTINFO_EFI,
++			   &grub_efi_system_table,
++			   sizeof (grub_efi_system_table));
++  if (err)
++    return err;
++#endif
++
+   {
+     struct bsd_tag *tag;
+     tag_buf_len = 0;
+diff --git a/include/grub/i386/netbsd_bootinfo.h b/include/grub/i386/netbsd_bootinfo.h
+index e48c19b4089..9b4f4604103 100644
+--- a/include/grub/i386/netbsd_bootinfo.h
++++ b/include/grub/i386/netbsd_bootinfo.h
+@@ -58,6 +58,8 @@
+ #define NETBSD_BTINFO_BOOTWEDGE		10
+ #define NETBSD_BTINFO_MODULES		11
+ #define NETBSD_BTINFO_FRAMEBUF		12
++#define NETBSD_BTINFO_USERCONFCOMMANDS  13
++#define NETBSD_BTINFO_EFI	        14
+ 
+ struct grub_netbsd_bootinfo
+ {
+@@ -146,4 +148,9 @@ struct grub_netbsd_btinfo_framebuf
+ 
+ #define GRUB_NETBSD_MAX_ROOTDEVICE_LEN 16
+ 
++struct grub_netbsd_btinfo_efi
++{
++  void *pa_systbl;  /* Physical address of the EFI System Table */
++};
++
+ #endif
+diff --git a/ChangeLog b/ChangeLog
+index abf8f4b2716..0cdd095a498 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,8 @@
++2014-06-21  Stephane Rochoy <sheda>
++
++	* grub-core/loader/i386/bsd.c (grub_netbsd_boot): Pass pointer to
++	EFI system table.
++
+ 2014-06-21  Stephane Rochoy <sheda>
+ 
+ 	* grub-core/commands/efi/lsefisystab.c (grub_cmd_lsefisystab): Show
diff --git a/SOURCES/0086-util-grub-install.c-Fix-handling-of-disk-module.patch b/SOURCES/0086-util-grub-install.c-Fix-handling-of-disk-module.patch
new file mode 100644
index 0000000..ab838fa
--- /dev/null
+++ b/SOURCES/0086-util-grub-install.c-Fix-handling-of-disk-module.patch
@@ -0,0 +1,43 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Glenn Washburn <development@efficientek.com>
+Date: Sun, 22 Jun 2014 01:45:11 +0200
+Subject: [PATCH] * util/grub-install.c: Fix handling of --disk-module.
+
+---
+ util/grub-install.c | 3 +--
+ ChangeLog           | 4 ++++
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/util/grub-install.c b/util/grub-install.c
+index e9c6a4656ef..7d61c32be2f 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -94,7 +94,6 @@ enum
+     OPTION_RECHECK, 
+     OPTION_FORCE,
+     OPTION_FORCE_FILE_ID,
+-    OPTION_MODULE, 
+     OPTION_NO_NVRAM, 
+     OPTION_REMOVABLE, 
+     OPTION_BOOTLOADER_ID, 
+@@ -273,7 +272,7 @@ static struct argp_option options[] = {
+    N_("install even if problems are detected"), 2},
+   {"force-file-id", OPTION_FORCE_FILE_ID, 0, 0,
+    N_("use identifier file even if UUID is available"), 2},
+-  {"disk-module", OPTION_MODULE, N_("MODULE"), 0,
++  {"disk-module", OPTION_DISK_MODULE, N_("MODULE"), 0,
+    N_("disk module to use (biosdisk or native). "
+       "This option is only available on BIOS target."), 2},
+   {"no-nvram", OPTION_NO_NVRAM, 0, 0,
+diff --git a/ChangeLog b/ChangeLog
+index 0cdd095a498..4ce664327f9 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-06-21  Glenn Washburn <development@efficientek.com>
++
++	* util/grub-install.c: Fix handling of --disk-module.
++
+ 2014-06-21  Stephane Rochoy <sheda>
+ 
+ 	* grub-core/loader/i386/bsd.c (grub_netbsd_boot): Pass pointer to
diff --git a/SOURCES/0087-grub-core-commands-loadenv.c-check_blocklists-Fix-ov.patch b/SOURCES/0087-grub-core-commands-loadenv.c-check_blocklists-Fix-ov.patch
new file mode 100644
index 0000000..994ad08
--- /dev/null
+++ b/SOURCES/0087-grub-core-commands-loadenv.c-check_blocklists-Fix-ov.patch
@@ -0,0 +1,55 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=D0=A0=D0=BE=D0=BC=D0=B0=D0=BD=20=D0=9F=D0=B5=D1=85=D0=BE?=
+ =?UTF-8?q?=D0=B2?= <roman_pekhov>
+Date: Sun, 22 Jun 2014 03:51:50 +0400
+Subject: [PATCH] * grub-core/commands/loadenv.c (check_blocklists): Fix
+ overlap check.
+
+---
+ grub-core/commands/loadenv.c | 13 ++-----------
+ ChangeLog                    |  4 ++++
+ 2 files changed, 6 insertions(+), 11 deletions(-)
+
+diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c
+index 6af81120745..acd93d123ed 100644
+--- a/grub-core/commands/loadenv.c
++++ b/grub-core/commands/loadenv.c
+@@ -263,7 +263,7 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
+       for (q = p->next; q; q = q->next)
+         {
+ 	  grub_disk_addr_t s1, s2;
+-	  grub_disk_addr_t e1, e2, t;
++	  grub_disk_addr_t e1, e2;
+ 
+ 	  s1 = p->sector;
+ 	  e1 = s1 + ((p->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
+@@ -271,16 +271,7 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
+ 	  s2 = q->sector;
+ 	  e2 = s2 + ((q->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
+ 
+-	  if (s2 > s1)
+-	    {
+-	      t = s2;
+-	      s2 = s1;
+-	      s1 = t;
+-	      t = e2;
+-	      e2 = e1;
+-	      e1 = t;
+-	    }
+-          if (e1 > s2)
++	  if (s1 < e2 && s2 < e1)
+             {
+               /* This might be actually valid, but it is unbelievable that
+                  any filesystem makes such a silly allocation.  */
+diff --git a/ChangeLog b/ChangeLog
+index 4ce664327f9..a2da9743231 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,7 @@
++2014-06-21  Роман Пехов <roman_pekhov>
++
++	* grub-core/commands/loadenv.c (check_blocklists): Fix overlap check.
++
+ 2014-06-21  Glenn Washburn <development@efficientek.com>
+ 
+ 	* util/grub-install.c: Fix handling of --disk-module.
diff --git a/SOURCES/0088-NEWS-The-cmosclean-command-in-fact-dates-back-to-1.9.patch b/SOURCES/0088-NEWS-The-cmosclean-command-in-fact-dates-back-to-1.9.patch
new file mode 100644
index 0000000..b3bde1e
--- /dev/null
+++ b/SOURCES/0088-NEWS-The-cmosclean-command-in-fact-dates-back-to-1.9.patch
@@ -0,0 +1,23 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Sat, 28 Dec 2013 02:20:27 +0000
+Subject: [PATCH] * NEWS: The cmosclean command in fact dates back to 1.99.
+ Remove mention of it from 2.02.
+
+---
+ NEWS | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index a61df942a35..f621c65de06 100644
+--- a/NEWS
++++ b/NEWS
+@@ -63,6 +63,8 @@ New in 2.02:
+   * New `efifwsetup' and `lsefi' commands on EFI platforms.
+   * New `cmosdump' and `cmosset' commands on platforms with CMOS support.
+   * New command `pcidump' for PCI platforms.
++  * New `cbmemc', `coreboot_boottime', and `lscoreboot' commands on
++    coreboot.
+   * Improve opcode parsing in ACPI halt implementation.
+   * Use the TSC as a possible time source on i386-ieee1275.
+   * Merge PowerPC grub-mkrescue implementation with the common one.
diff --git a/SOURCES/0089-Migrate-PPC-from-Yaboot-to-Grub2.patch b/SOURCES/0089-Migrate-PPC-from-Yaboot-to-Grub2.patch
new file mode 100644
index 0000000..68086cd
--- /dev/null
+++ b/SOURCES/0089-Migrate-PPC-from-Yaboot-to-Grub2.patch
@@ -0,0 +1,151 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Mark Hamzy <hamzy@us.ibm.com>
+Date: Wed, 28 Mar 2012 14:46:41 -0500
+Subject: [PATCH] Migrate PPC from Yaboot to Grub2
+
+Add configuration support for serial terminal consoles.  This will set the
+maximum screen size so that text is not overwritten.
+---
+ Makefile.util.def              |   7 +++
+ util/grub.d/20_ppc_terminfo.in | 114 +++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 121 insertions(+)
+ create mode 100644 util/grub.d/20_ppc_terminfo.in
+
+diff --git a/Makefile.util.def b/Makefile.util.def
+index a286a89cd8d..8f40e78332a 100644
+--- a/Makefile.util.def
++++ b/Makefile.util.def
+@@ -484,6 +484,13 @@ script = {
+   condition = COND_HOST_LINUX;
+ };
+ 
++script = {
++  name = '20_ppc_terminfo';
++  common = util/grub.d/20_ppc_terminfo.in;
++  installdir = grubconf;
++  condition = COND_HOST_LINUX;
++};
++
+ script = {
+   name = '30_os-prober';
+   common = util/grub.d/30_os-prober.in;
+diff --git a/util/grub.d/20_ppc_terminfo.in b/util/grub.d/20_ppc_terminfo.in
+new file mode 100644
+index 00000000000..10d66586820
+--- /dev/null
++++ b/util/grub.d/20_ppc_terminfo.in
+@@ -0,0 +1,114 @@
++#! /bin/sh
++set -e
++
++# grub-mkconfig helper script.
++# Copyright (C) 2006,2007,2008,2009,2010  Free Software Foundation, Inc.
++#
++# GRUB 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 3 of the License, or
++# (at your option) any later version.
++#
++# GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
++
++prefix=@prefix@
++exec_prefix=@exec_prefix@
++bindir=@bindir@
++libdir=@libdir@
++. "@datadir@/@PACKAGE@/grub-mkconfig_lib"
++
++export TEXTDOMAIN=@PACKAGE@
++export TEXTDOMAINDIR=@localedir@
++
++X=80
++Y=24
++TERMINAL=ofconsole
++
++argument () {
++  opt=$1
++  shift
++
++  if test $# -eq 0; then
++      echo "$0: option requires an argument -- '$opt'" 1>&2
++      exit 1
++  fi
++  echo $1
++}
++
++check_terminfo () {
++
++  while test $# -gt 0
++  do
++    option=$1
++    shift
++
++    case "$option" in
++    terminfo | TERMINFO)
++        ;;
++
++    -g)
++        NEWXY=`argument $option "$@"`
++        NEWX=`echo $NEWXY | cut -d x -f 1`
++        NEWY=`echo $NEWXY | cut -d x -f 2`
++
++        if [ ${NEWX} -ge 80 ] ; then
++          X=${NEWX}
++        else
++          echo "Warning: ${NEWX} is less than the minimum size of 80"
++        fi
++
++        if [ ${NEWY} -ge 24 ] ; then
++          Y=${NEWY}
++        else
++          echo "Warning: ${NEWY} is less than the minimum size of 24"
++        fi
++
++        shift
++        ;;
++
++    *)
++#       # accept console or ofconsole
++#       if [ "$option" != "console" -a "$option" != "ofconsole" ] ; then
++#         echo "Error: GRUB_TERMINFO unknown console: $option"
++#         exit 1
++#       fi
++#       # perfer console
++#       TERMINAL=console
++        # accept ofconsole
++        if [ "$option" != "ofconsole" ] ; then
++          echo "Error: GRUB_TERMINFO unknown console: $option"
++          exit 1
++        fi
++        # perfer console
++        TERMINAL=ofconsole
++        ;;
++    esac
++
++  done
++
++}
++
++if ! uname -m | grep -q ppc ; then
++  exit 0
++fi
++
++if [ "x${GRUB_TERMINFO}" != "x" ] ; then
++  F1=`echo ${GRUB_TERMINFO} | cut -d " " -f 1`
++
++  if [ "${F1}" != "terminfo" ] ; then
++    echo "Error: GRUB_TERMINFO is set to \"${GRUB_TERMINFO}\" The first word should be terminfo."
++    exit 1
++  fi
++
++  check_terminfo ${GRUB_TERMINFO}
++fi
++
++cat << EOF
++  terminfo -g ${X}x${Y} ${TERMINAL}
++EOF
diff --git a/SOURCES/0090-Add-fw_path-variable-revised.patch b/SOURCES/0090-Add-fw_path-variable-revised.patch
new file mode 100644
index 0000000..80510db
--- /dev/null
+++ b/SOURCES/0090-Add-fw_path-variable-revised.patch
@@ -0,0 +1,78 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
+Date: Wed, 19 Sep 2012 21:22:55 -0300
+Subject: [PATCH] Add fw_path variable (revised)
+
+This patch makes grub look for its config file on efi where the app was
+found. It was originally written by Matthew Garrett, and adapted to fix the
+"No modules are loaded on grub2 network boot" issue:
+
+https://bugzilla.redhat.com/show_bug.cgi?id=857936
+---
+ grub-core/kern/main.c   | 13 ++++++-------
+ grub-core/normal/main.c | 25 ++++++++++++++++++++++++-
+ 2 files changed, 30 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
+index 9cad0c4485c..8ab7794c47b 100644
+--- a/grub-core/kern/main.c
++++ b/grub-core/kern/main.c
+@@ -127,16 +127,15 @@ grub_set_prefix_and_root (void)
+ 
+   grub_machine_get_bootlocation (&fwdevice, &fwpath);
+ 
+-  if (fwdevice)
++  if (fwdevice && fwpath)
+     {
+-      char *cmdpath;
++      char *fw_path;
+ 
+-      cmdpath = grub_xasprintf ("(%s)%s", fwdevice, fwpath ? : "");
+-      if (cmdpath)
++      fw_path = grub_xasprintf ("(%s)/%s", fwdevice, fwpath);
++      if (fw_path)
+ 	{
+-	  grub_env_set ("cmdpath", cmdpath);
+-	  grub_env_export ("cmdpath");
+-	  grub_free (cmdpath);
++	  grub_env_set ("fw_path", fw_path);
++	  grub_free (fw_path);
+ 	}
+     }
+ 
+diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
+index 3a926fc5fa9..6f4970f71c1 100644
+--- a/grub-core/normal/main.c
++++ b/grub-core/normal/main.c
+@@ -319,7 +319,30 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
+       /* Guess the config filename. It is necessary to make CONFIG static,
+ 	 so that it won't get broken by longjmp.  */
+       char *config;
+-      const char *prefix;
++      const char *prefix, *fw_path;
++
++      fw_path = grub_env_get ("fw_path");
++      if (fw_path)
++	{
++	  config = grub_xasprintf ("%s/grub.cfg", fw_path);
++	  if (config)
++	    {
++	      grub_file_t file;
++
++	      file = grub_file_open (config);
++	      if (file)
++		{
++		  grub_file_close (file);
++		  grub_enter_normal_mode (config);
++		}
++              else
++                {
++                  /*  Ignore all errors.  */
++                  grub_errno = 0;
++                }
++	      grub_free (config);
++	    }
++	}
+ 
+       prefix = grub_env_get ("prefix");
+       if (prefix)
diff --git a/SOURCES/0091-Add-support-for-linuxefi.patch b/SOURCES/0091-Add-support-for-linuxefi.patch
new file mode 100644
index 0000000..4738452
--- /dev/null
+++ b/SOURCES/0091-Add-support-for-linuxefi.patch
@@ -0,0 +1,479 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Matthew Garrett <mjg@redhat.com>
+Date: Tue, 10 Jul 2012 11:58:52 -0400
+Subject: [PATCH] Add support for linuxefi
+
+---
+ grub-core/Makefile.core.def       |   8 +
+ grub-core/kern/efi/mm.c           |  32 ++++
+ grub-core/loader/i386/efi/linux.c | 371 ++++++++++++++++++++++++++++++++++++++
+ include/grub/efi/efi.h            |   3 +
+ include/grub/i386/linux.h         |   1 +
+ 5 files changed, 415 insertions(+)
+ create mode 100644 grub-core/loader/i386/efi/linux.c
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 42443bc00b9..ec46506e39e 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -1705,6 +1705,14 @@ module = {
+   enable = x86_64_efi;
+ };
+ 
++module = {
++  name = linuxefi;
++  efi = loader/i386/efi/linux.c;
++  efi = lib/cmdline.c;
++  enable = i386_efi;
++  enable = x86_64_efi;
++};
++
+ module = {
+   name = chain;
+   efi = loader/efi/chainloader.c;
+diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
+index be37afd9dc4..ddeca6073f6 100644
+--- a/grub-core/kern/efi/mm.c
++++ b/grub-core/kern/efi/mm.c
+@@ -49,6 +49,38 @@ static grub_efi_uintn_t finish_desc_size;
+ static grub_efi_uint32_t finish_desc_version;
+ int grub_efi_is_finished = 0;
+ 
++/* Allocate pages below a specified address */
++void *
++grub_efi_allocate_pages_max (grub_efi_physical_address_t max,
++			     grub_efi_uintn_t pages)
++{
++  grub_efi_status_t status;
++  grub_efi_boot_services_t *b;
++  grub_efi_physical_address_t address = max;
++
++  if (max > 0xffffffff)
++    return 0;
++
++  b = grub_efi_system_table->boot_services;
++  status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++
++  if (address == 0)
++    {
++      /* Uggh, the address 0 was allocated... This is too annoying,
++	 so reallocate another one.  */
++      address = max;
++      status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address);
++      grub_efi_free_pages (0, pages);
++      if (status != GRUB_EFI_SUCCESS)
++	return 0;
++    }
++
++  return (void *) ((grub_addr_t) address);
++}
++
+ /* Allocate pages. Return the pointer to the first of allocated pages.  */
+ void *
+ grub_efi_allocate_pages (grub_efi_physical_address_t address,
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+new file mode 100644
+index 00000000000..b79e6320ba9
+--- /dev/null
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -0,0 +1,371 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2012  Free Software Foundation, Inc.
++ *
++ *  GRUB 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 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <grub/loader.h>
++#include <grub/file.h>
++#include <grub/err.h>
++#include <grub/types.h>
++#include <grub/mm.h>
++#include <grub/cpu/linux.h>
++#include <grub/command.h>
++#include <grub/i18n.h>
++#include <grub/lib/cmdline.h>
++#include <grub/efi/efi.h>
++
++GRUB_MOD_LICENSE ("GPLv3+");
++
++static grub_dl_t my_mod;
++static int loaded;
++static void *kernel_mem;
++static grub_uint64_t kernel_size;
++static grub_uint8_t *initrd_mem;
++static grub_uint32_t handover_offset;
++struct linux_kernel_params *params;
++static char *linux_cmdline;
++
++#define BYTES_TO_PAGES(bytes)   (((bytes) + 0xfff) >> 12)
++
++#define SHIM_LOCK_GUID \
++  { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
++
++struct grub_efi_shim_lock
++{
++  grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
++};
++typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
++
++static grub_efi_boolean_t
++grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
++{
++  grub_efi_guid_t guid = SHIM_LOCK_GUID;
++  grub_efi_shim_lock_t *shim_lock;
++
++  shim_lock = grub_efi_locate_protocol(&guid, NULL);
++
++  if (!shim_lock)
++    return 1;
++
++  if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS)
++    return 1;
++
++  return 0;
++}
++
++typedef void(*handover_func)(void *, grub_efi_system_table_t *, struct linux_kernel_params *);
++
++static grub_err_t
++grub_linuxefi_boot (void)
++{
++  handover_func hf;
++  int offset = 0;
++
++#ifdef __x86_64__
++  offset = 512;
++#endif
++
++  hf = (handover_func)((char *)kernel_mem + handover_offset + offset);
++
++  asm volatile ("cli");
++
++  hf (grub_efi_image_handle, grub_efi_system_table, params);
++
++  /* Not reached */
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_linuxefi_unload (void)
++{
++  grub_dl_unref (my_mod);
++  loaded = 0;
++  if (initrd_mem)
++    grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(params->ramdisk_size));
++  if (linux_cmdline)
++    grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(params->cmdline_size + 1));
++  if (kernel_mem)
++    grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
++  if (params)
++    grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384));
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
++                 int argc, char *argv[])
++{
++  grub_file_t *files = 0;
++  int i, nfiles = 0;
++  grub_size_t size = 0;
++  grub_uint8_t *ptr;
++
++  if (argc == 0)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
++      goto fail;
++    }
++
++  if (!loaded)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
++      goto fail;
++    }
++
++  files = grub_zalloc (argc * sizeof (files[0]));
++  if (!files)
++    goto fail;
++
++  for (i = 0; i < argc; i++)
++    {
++      grub_file_filter_disable_compression ();
++      files[i] = grub_file_open (argv[i]);
++      if (! files[i])
++        goto fail;
++      nfiles++;
++      size += ALIGN_UP (grub_file_size (files[i]), 4);
++    }
++
++  initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
++
++  if (!initrd_mem)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
++      goto fail;
++    }
++
++  params->ramdisk_size = size;
++  params->ramdisk_image = (grub_uint32_t)(grub_uint64_t) initrd_mem;
++
++  ptr = initrd_mem;
++
++  for (i = 0; i < nfiles; i++)
++    {
++      grub_ssize_t cursize = grub_file_size (files[i]);
++      if (grub_file_read (files[i], ptr, cursize) != cursize)
++        {
++          if (!grub_errno)
++            grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
++                        argv[i]);
++          goto fail;
++        }
++      ptr += cursize;
++      grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
++      ptr += ALIGN_UP_OVERHEAD (cursize, 4);
++    }
++
++  params->ramdisk_size = size;
++
++ fail:
++  for (i = 0; i < nfiles; i++)
++    grub_file_close (files[i]);
++  grub_free (files);
++
++  if (initrd_mem && grub_errno)
++    grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(size));
++
++  return grub_errno;
++}
++
++static grub_err_t
++grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
++		int argc, char *argv[])
++{
++  grub_file_t file = 0;
++  struct linux_kernel_header lh;
++  grub_ssize_t len, start, filelen;
++  void *kernel;
++
++  grub_dl_ref (my_mod);
++
++  if (argc == 0)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
++      goto fail;
++    }
++
++  file = grub_file_open (argv[0]);
++  if (! file)
++    goto fail;
++
++  filelen = grub_file_size (file);
++
++  kernel = grub_malloc(filelen);
++
++  if (!kernel)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
++      goto fail;
++    }
++
++  if (grub_file_read (file, kernel, filelen) != filelen)
++    {
++      grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]);
++      goto fail;
++    }
++
++  if (! grub_linuxefi_secure_validate (kernel, filelen))
++    {
++      grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
++      grub_free (kernel);
++      goto fail;
++    }
++
++  grub_file_seek (file, 0);
++
++  grub_free(kernel);
++
++  params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
++
++  if (! params)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
++      goto fail;
++    }
++
++  memset (params, 0, 16384);
++
++  if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
++    {
++      if (!grub_errno)
++	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
++		    argv[0]);
++      goto fail;
++    }
++
++  if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
++    {
++      grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number"));
++      goto fail;
++    }
++
++  if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
++    {
++      grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
++      goto fail;
++    }
++
++  if (lh.version < grub_cpu_to_le16 (0x020b))
++    {
++      grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
++      goto fail;
++    }
++
++  if (!lh.handover_offset)
++    {
++      grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
++      goto fail;
++    }
++
++  linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
++					 BYTES_TO_PAGES(lh.cmdline_size + 1));
++
++  if (!linux_cmdline)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
++      goto fail;
++    }
++
++  grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
++  grub_create_loader_cmdline (argc, argv,
++                              linux_cmdline + sizeof (LINUX_IMAGE) - 1,
++			      lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1));
++
++  lh.cmd_line_ptr = (grub_uint32_t)(grub_uint64_t)linux_cmdline;
++
++  handover_offset = lh.handover_offset;
++
++  start = (lh.setup_sects + 1) * 512;
++  len = grub_file_size(file) - start;
++
++  kernel_mem = grub_efi_allocate_pages(lh.pref_address,
++				       BYTES_TO_PAGES(lh.init_size));
++
++  if (!kernel_mem)
++    kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
++					     BYTES_TO_PAGES(lh.init_size));
++
++  if (!kernel_mem)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
++      goto fail;
++    }
++
++  if (grub_file_seek (file, start) == (grub_off_t) -1)
++    {
++      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
++		  argv[0]);
++      goto fail;
++    }
++
++  if (grub_file_read (file, kernel_mem, len) != len && !grub_errno)
++    {
++      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
++		  argv[0]);
++    }
++
++  if (grub_errno == GRUB_ERR_NONE)
++    {
++      grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
++      loaded = 1;
++      lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
++    }
++
++  memcpy(params, &lh, 2 * 512);
++
++  params->type_of_loader = 0x21;
++
++ fail:
++
++  if (file)
++    grub_file_close (file);
++
++  if (grub_errno != GRUB_ERR_NONE)
++    {
++      grub_dl_unref (my_mod);
++      loaded = 0;
++    }
++
++  if (linux_cmdline && !loaded)
++    grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(lh.cmdline_size + 1));
++
++  if (kernel_mem && !loaded)
++    grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
++
++  if (params && !loaded)
++    grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384));
++
++  return grub_errno;
++}
++
++static grub_command_t cmd_linux, cmd_initrd;
++
++GRUB_MOD_INIT(linuxefi)
++{
++  cmd_linux =
++    grub_register_command ("linuxefi", grub_cmd_linux,
++                           0, N_("Load Linux."));
++  cmd_initrd =
++    grub_register_command ("initrdefi", grub_cmd_initrd,
++                           0, N_("Load initrd."));
++  my_mod = mod;
++}
++
++GRUB_MOD_FINI(linuxefi)
++{
++  grub_unregister_command (cmd_linux);
++  grub_unregister_command (cmd_initrd);
++}
+diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
+index 489cf9e6da7..9370fd53096 100644
+--- a/include/grub/efi/efi.h
++++ b/include/grub/efi/efi.h
+@@ -40,6 +40,9 @@ void EXPORT_FUNC(grub_efi_stall) (grub_efi_uintn_t microseconds);
+ void *
+ EXPORT_FUNC(grub_efi_allocate_pages) (grub_efi_physical_address_t address,
+ 				      grub_efi_uintn_t pages);
++void *
++EXPORT_FUNC(grub_efi_allocate_pages_max) (grub_efi_physical_address_t max,
++					  grub_efi_uintn_t pages);
+ void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address,
+ 				       grub_efi_uintn_t pages);
+ int
+diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
+index da0ca3b83cd..fc36bdaf367 100644
+--- a/include/grub/i386/linux.h
++++ b/include/grub/i386/linux.h
+@@ -139,6 +139,7 @@ struct linux_kernel_header
+   grub_uint64_t setup_data;
+   grub_uint64_t pref_address;
+   grub_uint32_t init_size;
++  grub_uint32_t handover_offset;
+ } GRUB_PACKED;
+ 
+ /* Boot parameters for Linux based on 2.6.12. This is used by the setup
diff --git a/SOURCES/0092-Use-linuxefi-and-initrdefi-where-appropriate.patch b/SOURCES/0092-Use-linuxefi-and-initrdefi-where-appropriate.patch
new file mode 100644
index 0000000..99a024d
--- /dev/null
+++ b/SOURCES/0092-Use-linuxefi-and-initrdefi-where-appropriate.patch
@@ -0,0 +1,47 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 16 Jul 2012 18:57:11 -0400
+Subject: [PATCH] Use "linuxefi" and "initrdefi" where appropriate.
+
+---
+ util/grub.d/10_linux.in | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 00d193159e9..ad34cc02d36 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -127,17 +127,31 @@ linux_entry ()
+     printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/"
+   fi
+   message="$(gettext_printf "Loading Linux %s ..." ${version})"
+-  sed "s/^/$submenu_indentation/" << EOF
++  if [ -d /sys/firmware/efi ]; then
++    sed "s/^/$submenu_indentation/" << EOF
++	echo	'$(echo "$message" | grub_quote)'
++	linuxefi ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
++EOF
++  else
++    sed "s/^/$submenu_indentation/" << EOF
+ 	echo	'$(echo "$message" | grub_quote)'
+ 	linux	${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
+ EOF
++  fi
+   if test -n "${initrd}" ; then
+     # TRANSLATORS: ramdisk isn't identifier. Should be translated.
+     message="$(gettext_printf "Loading initial ramdisk ...")"
+-    sed "s/^/$submenu_indentation/" << EOF
++    if [ -d /sys/firmware/efi ]; then
++      sed "s/^/$submenu_indentation/" << EOF
+ 	echo	'$(echo "$message" | grub_quote)'
++	initrdefi ${rel_dirname}/${initrd}
++EOF
++    else
++      sed "s/^/$submenu_indentation/" << EOF
++	echo	'$message'
+ 	initrd	${rel_dirname}/${initrd}
+ EOF
++    fi
+   fi
+   sed "s/^/$submenu_indentation/" << EOF
+ }
diff --git a/SOURCES/0093-Don-t-allow-insmod-when-secure-boot-is-enabled.patch b/SOURCES/0093-Don-t-allow-insmod-when-secure-boot-is-enabled.patch
new file mode 100644
index 0000000..78b6685
--- /dev/null
+++ b/SOURCES/0093-Don-t-allow-insmod-when-secure-boot-is-enabled.patch
@@ -0,0 +1,114 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Tue, 23 Oct 2012 10:40:49 -0400
+Subject: [PATCH] Don't allow insmod when secure boot is enabled.
+
+Hi,
+
+Fedora's patch to forbid insmod in UEFI Secure Boot environments is fine
+as far as it goes.  However, the insmod command is not the only way that
+modules can be loaded.  In particular, the 'normal' command, which
+implements the usual GRUB menu and the fully-featured command prompt,
+will implicitly load commands not currently loaded into memory.  This
+permits trivial Secure Boot violations by writing commands implementing
+whatever you want to do and pointing $prefix at the malicious code.
+
+I'm currently test-building this patch (replacing your current
+grub-2.00-no-insmod-on-sb.patch), but this should be more correct.  It
+moves the check into grub_dl_load_file.
+---
+ grub-core/kern/dl.c      | 21 +++++++++++++++++++++
+ grub-core/kern/efi/efi.c | 28 ++++++++++++++++++++++++++++
+ include/grub/efi/efi.h   |  1 +
+ 3 files changed, 50 insertions(+)
+
+diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
+index 6850e049741..b0b0405fcbe 100644
+--- a/grub-core/kern/dl.c
++++ b/grub-core/kern/dl.c
+@@ -38,6 +38,14 @@
+ #define GRUB_MODULES_MACHINE_READONLY
+ #endif
+ 
++#ifdef GRUB_MACHINE_EMU
++#include <sys/mman.h>
++#endif
++
++#ifdef GRUB_MACHINE_EFI
++#include <grub/efi/efi.h>
++#endif
++
+ 
+ 
+ #pragma GCC diagnostic ignored "-Wcast-align"
+@@ -680,6 +688,19 @@ grub_dl_load_file (const char *filename)
+   void *core = 0;
+   grub_dl_t mod = 0;
+ 
++#ifdef GRUB_MACHINE_EFI
++  if (grub_efi_secure_boot ())
++    {
++#if 0
++      /* This is an error, but grub2-mkconfig still generates a pile of
++       * insmod commands, so emitting it would be mostly just obnoxious. */
++      grub_error (GRUB_ERR_ACCESS_DENIED,
++		  "Secure Boot forbids loading module from %s", filename);
++#endif
++      return 0;
++    }
++#endif
++
+   grub_boot_time ("Loading module %s", filename);
+ 
+   file = grub_file_open (filename);
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index b9eb1ab1e33..cd839cc988a 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -259,6 +259,34 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
+   return NULL;
+ }
+ 
++grub_efi_boolean_t
++grub_efi_secure_boot (void)
++{
++  grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
++  grub_size_t datasize;
++  char *secure_boot = NULL;
++  char *setup_mode = NULL;
++  grub_efi_boolean_t ret = 0;
++
++  secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
++
++  if (datasize != 1 || !secure_boot)
++    goto out;
++
++  setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
++
++  if (datasize != 1 || !setup_mode)
++    goto out;
++
++  if (*secure_boot && !*setup_mode)
++    ret = 1;
++
++ out:
++  grub_free (secure_boot);
++  grub_free (setup_mode);
++  return ret;
++}
++
+ #pragma GCC diagnostic ignored "-Wcast-align"
+ 
+ /* Search the mods section from the PE32/PE32+ image. This code uses
+diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
+index 9370fd53096..a000c383e81 100644
+--- a/include/grub/efi/efi.h
++++ b/include/grub/efi/efi.h
+@@ -72,6 +72,7 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var,
+ 				     const grub_efi_guid_t *guid,
+ 				     void *data,
+ 				     grub_size_t datasize);
++grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void);
+ int
+ EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
+ 					     const grub_efi_device_path_t *dp2);
diff --git a/SOURCES/0094-Pass-x-hex-hex-straight-through-unmolested.patch b/SOURCES/0094-Pass-x-hex-hex-straight-through-unmolested.patch
new file mode 100644
index 0000000..c51c06a
--- /dev/null
+++ b/SOURCES/0094-Pass-x-hex-hex-straight-through-unmolested.patch
@@ -0,0 +1,179 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 Oct 2012 13:24:37 -0400
+Subject: [PATCH] Pass "\x[[:hex:]][[:hex:]]" straight through unmolested.
+
+---
+ grub-core/commands/wildcard.c | 16 +++++++++++++++-
+ grub-core/lib/cmdline.c       | 34 ++++++++++++++++++++++++++++++++--
+ grub-core/script/execute.c    | 43 +++++++++++++++++++++++++++++++++++++------
+ 3 files changed, 84 insertions(+), 9 deletions(-)
+
+diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c
+index 2807f806bd4..0f40e041541 100644
+--- a/grub-core/commands/wildcard.c
++++ b/grub-core/commands/wildcard.c
+@@ -458,6 +458,12 @@ check_file (const char *dir, const char *basename)
+   return ctx.found;
+ }
+ 
++static int
++is_hex(char c)
++{
++  return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
++}
++
+ static void
+ unescape (char *out, const char *in, const char *end)
+ {
+@@ -466,7 +472,15 @@ unescape (char *out, const char *in, const char *end)
+ 
+   for (optr = out, iptr = in; iptr < end;)
+     {
+-      if (*iptr == '\\' && iptr + 1 < end)
++      if (*iptr == '\\' && iptr + 3 < end && iptr[1] == 'x' && is_hex(iptr[2]) && is_hex(iptr[3]))
++	{
++	  *optr++ = *iptr++;
++	  *optr++ = *iptr++;
++	  *optr++ = *iptr++;
++	  *optr++ = *iptr++;
++	  continue;
++	}
++      else if (*iptr == '\\' && iptr + 1 < end)
+ 	{
+ 	  *optr++ = iptr[1];
+ 	  iptr += 2;
+diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c
+index d5e10ee8798..0a5b2afb94b 100644
+--- a/grub-core/lib/cmdline.c
++++ b/grub-core/lib/cmdline.c
+@@ -20,6 +20,12 @@
+ #include <grub/lib/cmdline.h>
+ #include <grub/misc.h>
+ 
++static int
++is_hex(char c)
++{
++  return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
++}
++
+ static unsigned int check_arg (char *c, int *has_space)
+ {
+   int space = 0;
+@@ -27,7 +33,13 @@ static unsigned int check_arg (char *c, int *has_space)
+ 
+   while (*c)
+     {
+-      if (*c == '\\' || *c == '\'' || *c == '"')
++      if (*c == '\\' && *(c+1) == 'x' && is_hex(*(c+2)) && is_hex(*(c+3)))
++	{
++	  size += 4;
++	  c += 4;
++	  continue;
++	}
++      else if (*c == '\\' || *c == '\'' || *c == '"')
+ 	size++;
+       else if (*c == ' ')
+ 	space = 1;
+@@ -85,7 +97,25 @@ int grub_create_loader_cmdline (int argc, char *argv[], char *buf,
+ 
+       while (*c)
+ 	{
+-	  if (*c == '\\' || *c == '\'' || *c == '"')
++	  if (*c == ' ')
++	    {
++	      *buf++ = '\\';
++	      *buf++ = 'x';
++	      *buf++ = '2';
++	      *buf++ = '0';
++	      c++;
++	      continue;
++	    }
++	  else if (*c == '\\' && *(c+1) == 'x' &&
++		   is_hex(*(c+2)) && is_hex(*(c+3)))
++	    {
++	      *buf++ = *c++;
++	      *buf++ = *c++;
++	      *buf++ = *c++;
++	      *buf++ = *c++;
++	      continue;
++	    }
++	  else if (*c == '\\' || *c == '\'' || *c == '"')
+ 	    *buf++ = '\\';
+ 
+ 	  *buf++ = *c;
+diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
+index afd551320f7..8f01c1bbfa2 100644
+--- a/grub-core/script/execute.c
++++ b/grub-core/script/execute.c
+@@ -52,6 +52,12 @@ static struct grub_script_scope *scope = 0;
+ /* Wildcard translator for GRUB script.  */
+ struct grub_script_wildcard_translator *grub_wildcard_translator;
+ 
++static int
++is_hex(char c)
++{
++  return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
++}
++
+ static char*
+ wildcard_escape (const char *s)
+ {
+@@ -68,7 +74,15 @@ wildcard_escape (const char *s)
+   i = 0;
+   while ((ch = *s++))
+     {
+-      if (ch == '*' || ch == '\\' || ch == '?')
++      if (ch == '\\' && s[0] == 'x' && is_hex(s[1]) && is_hex(s[2]))
++	{
++	  p[i++] = ch;
++	  p[i++] = *s++;
++	  p[i++] = *s++;
++	  p[i++] = *s++;
++	  continue;
++	}
++      else if (ch == '*' || ch == '\\' || ch == '?')
+ 	p[i++] = '\\';
+       p[i++] = ch;
+     }
+@@ -92,7 +106,14 @@ wildcard_unescape (const char *s)
+   i = 0;
+   while ((ch = *s++))
+     {
+-      if (ch == '\\')
++      if (ch == '\\' && s[0] == 'x' && is_hex(s[1]) && is_hex(s[2]))
++	{
++	  p[i++] = '\\';
++	  p[i++] = *s++;
++	  p[i++] = *s++;
++	  p[i++] = *s++;
++	}
++      else if (ch == '\\')
+ 	p[i++] = *s++;
+       else
+ 	p[i++] = ch;
+@@ -394,10 +415,20 @@ parse_string (const char *str,
+     switch (*ptr)
+       {
+       case '\\':
+-	escaped = !escaped;
+-	if (!escaped && put)
+-	  *(put++) = '\\';
+-	ptr++;
++	if (!escaped && put && *(ptr+1) == 'x' && is_hex(*(ptr+2)) && is_hex(*(ptr+3)))
++	  {
++	    *(put++) = *ptr++;
++	    *(put++) = *ptr++;
++	    *(put++) = *ptr++;
++	    *(put++) = *ptr++;
++	  }
++	else
++	  {
++	    escaped = !escaped;
++	    if (!escaped && put)
++	      *(put++) = '\\';
++	    ptr++;
++	  }
+ 	break;
+       case '$':
+ 	if (escaped)
diff --git a/SOURCES/0095-Fix-crash-on-http.patch b/SOURCES/0095-Fix-crash-on-http.patch
new file mode 100644
index 0000000..a691528
--- /dev/null
+++ b/SOURCES/0095-Fix-crash-on-http.patch
@@ -0,0 +1,25 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Gustavo Luiz Duarte <gustavold@linux.vnet.ibm.com>
+Date: Tue, 25 Sep 2012 18:40:55 -0400
+Subject: [PATCH] Fix crash on http
+
+Don't free file->data on receiving FIN flag since it is used all over without
+checking. http_close() will be called later to free that memory.
+https://bugzilla.redhat.com/show_bug.cgi?id=860834
+---
+ grub-core/net/http.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/net/http.c b/grub-core/net/http.c
+index 4684f8b333c..ef9538c539c 100644
+--- a/grub-core/net/http.c
++++ b/grub-core/net/http.c
+@@ -393,7 +393,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
+ 
+   data->sock = grub_net_tcp_open (file->device->net->server,
+ 				  HTTP_PORT, http_receive,
+-				  http_err, http_err,
++				  http_err, NULL,
+ 				  file);
+   if (!data->sock)
+     {
diff --git a/SOURCES/0096-IBM-client-architecture-CAS-reboot-support.patch b/SOURCES/0096-IBM-client-architecture-CAS-reboot-support.patch
new file mode 100644
index 0000000..1326fff
--- /dev/null
+++ b/SOURCES/0096-IBM-client-architecture-CAS-reboot-support.patch
@@ -0,0 +1,171 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
+Date: Thu, 20 Sep 2012 18:07:39 -0300
+Subject: [PATCH] IBM client architecture (CAS) reboot support
+
+This is an implementation of IBM client architecture (CAS) reboot for GRUB.
+
+There are cases where the POWER firmware must reboot in order to support
+specific features requested by a kernel. The kernel calls
+ibm,client-architecture-support and it may either return or reboot with the new
+feature set. eg:
+
+Calling ibm,client-architecture-support.../
+Elapsed time since release of system processors: 70959 mins 50 secs
+Welcome to GRUB!
+
+Instead of return to the GRUB menu, it will check if the flag for CAS reboot is
+set. If so, grub will automatically boot the last booted kernel using the same
+parameters
+---
+ grub-core/kern/ieee1275/openfw.c | 62 ++++++++++++++++++++++++++++++++++++++++
+ grub-core/normal/main.c          | 19 ++++++++++++
+ grub-core/script/execute.c       |  7 +++++
+ include/grub/ieee1275/ieee1275.h |  2 ++
+ 4 files changed, 90 insertions(+)
+
+diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
+index ddb778340e4..6db8b986551 100644
+--- a/grub-core/kern/ieee1275/openfw.c
++++ b/grub-core/kern/ieee1275/openfw.c
+@@ -561,3 +561,65 @@ grub_ieee1275_canonicalise_devname (const char *path)
+   return NULL;
+ }
+ 
++/* Check if it's a CAS reboot. If so, set the script to be executed.  */
++int
++grub_ieee1275_cas_reboot (char *script)
++{
++  grub_uint32_t ibm_ca_support_reboot;
++  grub_uint32_t ibm_fw_nbr_reboots;
++  char property_value[10];
++  grub_ssize_t actual;
++  grub_ieee1275_ihandle_t options;
++
++  if (grub_ieee1275_finddevice ("/options", &options) < 0)
++    return -1;
++
++  /* Check two properties, one is enough to get cas reboot value */
++  ibm_ca_support_reboot = 0;
++  if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen,
++                                          "ibm,client-architecture-support-reboot",
++                                          &ibm_ca_support_reboot,
++                                          sizeof (ibm_ca_support_reboot),
++                                          &actual) >= 0)
++    grub_dprintf("ieee1275", "ibm,client-architecture-support-reboot: %u\n",
++                 ibm_ca_support_reboot);
++
++  ibm_fw_nbr_reboots = 0;
++  if (grub_ieee1275_get_property (options, "ibm,fw-nbr-reboots",
++                                  property_value, sizeof (property_value),
++                                  &actual) >= 0)
++    {
++      property_value[sizeof (property_value) - 1] = 0;
++      ibm_fw_nbr_reboots = (grub_uint8_t) grub_strtoul (property_value, 0, 10);
++      grub_dprintf("ieee1275", "ibm,fw-nbr-reboots: %u\n", ibm_fw_nbr_reboots);
++    }
++
++  if (ibm_ca_support_reboot || ibm_fw_nbr_reboots)
++    {
++      if (! grub_ieee1275_get_property_length (options, "boot-last-label", &actual))
++        {
++          if (actual > 1024)
++            script = grub_realloc (script, actual + 1);
++          grub_ieee1275_get_property (options, "boot-last-label", script, actual,
++                                      &actual);
++          return 0;
++        }
++    }
++
++  grub_ieee1275_set_boot_last_label ("");
++
++  return -1;
++}
++
++int grub_ieee1275_set_boot_last_label (const char *text)
++{
++  grub_ieee1275_ihandle_t options;
++  grub_ssize_t actual;
++
++  grub_dprintf("ieee1275", "set boot_last_label (size: %u)\n", grub_strlen(text));
++  if (! grub_ieee1275_finddevice ("/options", &options) &&
++      options != (grub_ieee1275_ihandle_t) -1)
++    grub_ieee1275_set_property (options, "boot-last-label", text,
++                                grub_strlen (text), &actual);
++  return 0;
++}
+diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
+index 6f4970f71c1..f72844c9f37 100644
+--- a/grub-core/normal/main.c
++++ b/grub-core/normal/main.c
+@@ -33,6 +33,9 @@
+ #include <grub/charset.h>
+ #include <grub/script_sh.h>
+ #include <grub/bufio.h>
++#ifdef GRUB_MACHINE_IEEE1275
++#include <grub/ieee1275/ieee1275.h>
++#endif
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -275,6 +278,22 @@ grub_normal_execute (const char *config, int nested, int batch)
+     {
+       menu = read_config_file (config);
+ 
++#ifdef GRUB_MACHINE_IEEE1275
++      int boot;
++      boot = 0;
++      char *script;
++      script = grub_malloc (1024);
++      if (! grub_ieee1275_cas_reboot (script))
++        {
++          char *dummy[1] = { NULL };
++          if (! grub_script_execute_sourcecode (script, 0, dummy))
++            boot = 1;
++        }
++      grub_free (script);
++      if (boot)
++        grub_command_execute ("boot", 0, 0);
++#endif
++
+       /* Ignore any error.  */
+       grub_errno = GRUB_ERR_NONE;
+     }
+diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
+index 8f01c1bbfa2..cec9539a47c 100644
+--- a/grub-core/script/execute.c
++++ b/grub-core/script/execute.c
+@@ -27,6 +27,9 @@
+ #include <grub/normal.h>
+ #include <grub/extcmd.h>
+ #include <grub/i18n.h>
++#ifdef GRUB_MACHINE_IEEE1275
++#include <grub/ieee1275/ieee1275.h>
++#endif
+ 
+ /* Max digits for a char is 3 (0xFF is 255), similarly for an int it
+    is sizeof (int) * 3, and one extra for a possible -ve sign.  */
+@@ -892,6 +895,10 @@ grub_script_execute_sourcecode (const char *source)
+   grub_err_t ret = 0;
+   struct grub_script *parsed_script;
+ 
++#ifdef GRUB_MACHINE_IEEE1275
++  grub_ieee1275_set_boot_last_label (source);
++#endif
++
+   while (source)
+     {
+       char *line;
+diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
+index 8e425130327..9f26c69a2df 100644
+--- a/include/grub/ieee1275/ieee1275.h
++++ b/include/grub/ieee1275/ieee1275.h
+@@ -234,6 +234,8 @@ int EXPORT_FUNC(grub_ieee1275_devalias_next) (struct grub_ieee1275_devalias *ali
+ void EXPORT_FUNC(grub_ieee1275_children_peer) (struct grub_ieee1275_devalias *alias);
+ void EXPORT_FUNC(grub_ieee1275_children_first) (const char *devpath,
+ 						struct grub_ieee1275_devalias *alias);
++int EXPORT_FUNC(grub_ieee1275_cas_reboot) (char *script);
++int EXPORT_FUNC(grub_ieee1275_set_boot_last_label) (const char *text);
+ 
+ #define FOR_IEEE1275_DEVALIASES(alias) for (grub_ieee1275_devalias_init_iterator (&(alias)); grub_ieee1275_devalias_next (&(alias));)
+ 
diff --git a/SOURCES/0097-Add-vlan-tag-support.patch b/SOURCES/0097-Add-vlan-tag-support.patch
new file mode 100644
index 0000000..6181b62
--- /dev/null
+++ b/SOURCES/0097-Add-vlan-tag-support.patch
@@ -0,0 +1,183 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
+Date: Tue, 30 Oct 2012 15:19:39 -0200
+Subject: [PATCH] Add vlan-tag support
+
+This patch adds support for virtual LAN (VLAN) tagging. VLAN tagging allows
+multiple VLANs in a bridged network to share the same physical network link but
+maintain isolation:
+
+http://en.wikipedia.org/wiki/IEEE_802.1Q
+
+This patch should fix this bugzilla:
+https://bugzilla.redhat.com/show_bug.cgi?id=871563
+---
+ grub-core/kern/ieee1275/init.c   |  1 +
+ grub-core/kern/ieee1275/openfw.c | 30 ++++++++++++++++++++++++++++
+ grub-core/net/ethernet.c         | 42 +++++++++++++++++++++++++++++++++++++---
+ include/grub/ieee1275/ieee1275.h |  1 +
+ include/grub/net.h               |  2 ++
+ 5 files changed, 73 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
+index d5bd74d3552..8191f8cd658 100644
+--- a/grub-core/kern/ieee1275/init.c
++++ b/grub-core/kern/ieee1275/init.c
+@@ -117,6 +117,7 @@ grub_machine_get_bootlocation (char **device, char **path)
+       char *dev, *canon;
+       char *ptr;
+       dev = grub_ieee1275_get_aliasdevname (bootpath);
++      grub_ieee1275_parse_net_options (bootpath);
+       canon = grub_ieee1275_canonicalise_devname (dev);
+       ptr = canon + grub_strlen (canon) - 1;
+       while (ptr > canon && (*ptr == ',' || *ptr == ':'))
+diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
+index 6db8b986551..81276fae7b7 100644
+--- a/grub-core/kern/ieee1275/openfw.c
++++ b/grub-core/kern/ieee1275/openfw.c
+@@ -23,6 +23,7 @@
+ #include <grub/mm.h>
+ #include <grub/ieee1275/ieee1275.h>
+ #include <grub/net.h>
++#include <grub/env.h>
+ 
+ enum grub_ieee1275_parse_type
+ {
+@@ -451,6 +452,35 @@ fail:
+   return ret;
+ }
+ 
++int
++grub_ieee1275_parse_net_options (const char *path)
++{
++  char *comma;
++  char *args;
++  char *option = 0;
++
++  args = grub_ieee1275_get_devargs (path);
++  if (!args)
++    /* There is no option.  */
++    return -1;
++
++  do
++    {
++      comma = grub_strchr (args, ',');
++      if (! comma)
++        option = grub_strdup (args);
++      else
++        option = grub_strndup (args, (grub_size_t)(comma - args));
++      args = comma + 1;
++
++      if (! grub_strncmp(option, "vtag", 4))
++          grub_env_set ("vlan-tag", option + grub_strlen("vtag="));
++
++    } while (comma);
++
++  return 0;
++}
++
+ char *
+ grub_ieee1275_get_device_type (const char *path)
+ {
+diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c
+index c397b1b348c..faaca67c50e 100644
+--- a/grub-core/net/ethernet.c
++++ b/grub-core/net/ethernet.c
+@@ -23,6 +23,7 @@
+ #include <grub/net/arp.h>
+ #include <grub/net/netbuff.h>
+ #include <grub/net.h>
++#include <grub/env.h>
+ #include <grub/time.h>
+ #include <grub/net/arp.h>
+ 
+@@ -56,10 +57,19 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
+ {
+   struct etherhdr *eth;
+   grub_err_t err;
++  grub_uint32_t vlantag = 0;
++  grub_uint8_t etherhdr_size;
+ 
+-  COMPILE_TIME_ASSERT (sizeof (*eth) < GRUB_NET_MAX_LINK_HEADER_SIZE);
++  etherhdr_size = sizeof (*eth);
++  COMPILE_TIME_ASSERT (sizeof (*eth) + 4 < GRUB_NET_MAX_LINK_HEADER_SIZE);
+ 
+-  err = grub_netbuff_push (nb, sizeof (*eth));
++  const char *vlantag_text = grub_env_get ("vlan-tag");
++  if (vlantag_text != 0) {
++      etherhdr_size += 4;
++      vlantag = grub_strtoul (vlantag_text, 0, 16);
++  }
++
++  err = grub_netbuff_push (nb, etherhdr_size);
+   if (err)
+     return err;
+   eth = (struct etherhdr *) nb->data;
+@@ -76,6 +86,19 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
+ 	return err;
+       inf->card->opened = 1;
+     }
++
++  /* Check if a vlan-tag is needed. */
++  if (vlantag != 0)
++    {
++      /* Move eth type to the right */
++      grub_memcpy((char *) nb->data + etherhdr_size - 2,
++                  (char *) nb->data + etherhdr_size - 6, 2);
++
++      /* Add the tag in the middle */
++      grub_memcpy((char *) nb->data + etherhdr_size - 6,
++                  &vlantag, 4);
++    }
++
+   return inf->card->driver->send (inf->card, nb);
+ }
+ 
+@@ -90,10 +113,23 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
+   grub_net_link_level_address_t hwaddress;
+   grub_net_link_level_address_t src_hwaddress;
+   grub_err_t err;
++  grub_uint8_t etherhdr_size = sizeof (*eth);
++
++  grub_uint16_t vlantag_identifier = 0;
++  grub_memcpy (&vlantag_identifier, nb->data + etherhdr_size - 2, 2);
++
++  /* Check if a vlan-tag is present. */
++  if (vlantag_identifier == VLANTAG_IDENTIFIER)
++    {
++      etherhdr_size += 4;
++      /* Move eth type to the original position */
++      grub_memcpy((char *) nb->data + etherhdr_size - 6,
++                  (char *) nb->data + etherhdr_size - 2, 2);
++    }
+ 
+   eth = (struct etherhdr *) nb->data;
+   type = grub_be_to_cpu16 (eth->type);
+-  err = grub_netbuff_pull (nb, sizeof (*eth));
++  err = grub_netbuff_pull (nb, etherhdr_size);
+   if (err)
+     return err;
+ 
+diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
+index 9f26c69a2df..6a21f5d6de8 100644
+--- a/include/grub/ieee1275/ieee1275.h
++++ b/include/grub/ieee1275/ieee1275.h
+@@ -236,6 +236,7 @@ void EXPORT_FUNC(grub_ieee1275_children_first) (const char *devpath,
+ 						struct grub_ieee1275_devalias *alias);
+ int EXPORT_FUNC(grub_ieee1275_cas_reboot) (char *script);
+ int EXPORT_FUNC(grub_ieee1275_set_boot_last_label) (const char *text);
++int EXPORT_FUNC(grub_ieee1275_parse_net_options) (const char *path);
+ 
+ #define FOR_IEEE1275_DEVALIASES(alias) for (grub_ieee1275_devalias_init_iterator (&(alias)); grub_ieee1275_devalias_next (&(alias));)
+ 
+diff --git a/include/grub/net.h b/include/grub/net.h
+index 538baa33eca..a799e6b8b69 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -538,4 +538,6 @@ extern char *grub_net_default_server;
+ #define GRUB_NET_INTERVAL 400
+ #define GRUB_NET_INTERVAL_ADDITION 20
+ 
++#define VLANTAG_IDENTIFIER 0x8100
++
+ #endif /* ! GRUB_NET_HEADER */
diff --git a/SOURCES/0098-Add-X-option-to-printf-functions.patch b/SOURCES/0098-Add-X-option-to-printf-functions.patch
new file mode 100644
index 0000000..9631a38
--- /dev/null
+++ b/SOURCES/0098-Add-X-option-to-printf-functions.patch
@@ -0,0 +1,55 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
+Date: Tue, 27 Nov 2012 16:58:39 -0200
+Subject: [PATCH] Add %X option to printf functions.
+
+---
+ grub-core/kern/misc.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
+index c5c815d8d13..a56cfe78994 100644
+--- a/grub-core/kern/misc.c
++++ b/grub-core/kern/misc.c
+@@ -762,7 +762,7 @@ __umoddi3 (grub_uint64_t a, grub_uint64_t b)
+ static inline char *
+ grub_lltoa (char *str, int c, unsigned long long n)
+ {
+-  unsigned base = (c == 'x') ? 16 : 10;
++  unsigned base = ((c == 'x') || (c == 'X')) ? 16 : 10;
+   char *p;
+ 
+   if ((long long) n < 0 && c == 'd')
+@@ -777,7 +777,7 @@ grub_lltoa (char *str, int c, unsigned long long n)
+     do
+       {
+ 	unsigned d = (unsigned) (n & 0xf);
+-	*p++ = (d > 9) ? d + 'a' - 10 : d + '0';
++	*p++ = (d > 9) ? d + ((c == 'x') ? 'a' : 'A') - 10 : d + '0';
+       }
+     while (n >>= 4);
+   else
+@@ -850,6 +850,7 @@ parse_printf_args (const char *fmt0, struct printf_args *args,
+ 	{
+ 	case 'p':
+ 	case 'x':
++	case 'X':
+ 	case 'u':
+ 	case 'd':
+ 	case 'c':
+@@ -930,6 +931,7 @@ parse_printf_args (const char *fmt0, struct printf_args *args,
+       switch (c)
+ 	{
+ 	case 'x':
++	case 'X':
+ 	case 'u':
+ 	  args->ptr[curn].type = UNSIGNED_INT + longfmt;
+ 	  break;
+@@ -1067,6 +1069,7 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0,
+ 	  c = 'x';
+ 	  /* Fall through. */
+ 	case 'x':
++	case 'X':
+ 	case 'u':
+ 	case 'd':
+ 	  {
diff --git a/SOURCES/0099-DHCP-client-ID-and-UUID-options-added.patch b/SOURCES/0099-DHCP-client-ID-and-UUID-options-added.patch
new file mode 100644
index 0000000..16053af
--- /dev/null
+++ b/SOURCES/0099-DHCP-client-ID-and-UUID-options-added.patch
@@ -0,0 +1,142 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
+Date: Tue, 27 Nov 2012 17:18:53 -0200
+Subject: [PATCH] DHCP client ID and UUID options added.
+
+---
+ grub-core/net/bootp.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++-----
+ include/grub/net.h    |  2 ++
+ 2 files changed, 81 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index 6310ed447e8..88f20568914 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -25,6 +25,49 @@
+ #include <grub/net/udp.h>
+ #include <grub/datetime.h>
+ 
++static char *
++grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
++			 const char *val __attribute__ ((unused)))
++{
++  return NULL;
++}
++
++static void
++set_env_limn_ro (const char *intername, const char *suffix,
++		 const char *value, grub_size_t len)
++{
++  char *varname, *varvalue;
++  char *ptr;
++  varname = grub_xasprintf ("net_%s_%s", intername, suffix);
++  if (!varname)
++    return;
++  for (ptr = varname; *ptr; ptr++)
++    if (*ptr == ':')
++      *ptr = '_';
++  varvalue = grub_malloc (len + 1);
++  if (!varvalue)
++    {
++      grub_free (varname);
++      return;
++    }
++
++  grub_memcpy (varvalue, value, len);
++  varvalue[len] = 0;
++  grub_env_set (varname, varvalue);
++  grub_register_variable_hook (varname, 0, grub_env_write_readonly);
++  grub_env_export (varname);
++  grub_free (varname);
++  grub_free (varvalue);
++}
++
++static char
++hexdigit (grub_uint8_t val)
++{
++  if (val < 10)
++    return val + '0';
++  return val + 'a' - 10;
++}
++
+ static void
+ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
+ {
+@@ -55,6 +98,9 @@ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
+ 
+       taglength = *ptr++;
+ 
++      grub_dprintf("net", "DHCP option %u (0x%02x) found with length %u.\n",
++                   tagtype, tagtype, taglength);
++
+       switch (tagtype)
+ 	{
+ 	case GRUB_NET_BOOTP_NETMASK:
+@@ -120,6 +166,39 @@ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
+                                      taglength);
+           break;
+ 
++        case GRUB_NET_BOOTP_CLIENT_ID:
++	  set_env_limn_ro (name, "clientid", (char *) ptr, taglength);
++          break;
++
++        case GRUB_NET_BOOTP_CLIENT_UUID:
++            {
++              if (taglength != 17)
++                break;
++
++              /* The format is 9cfe245e-d0c8-bd45-a79f-54ea5fbd3d97 */
++
++              ptr += 1;
++              taglength -= 1;
++
++              char *val = grub_malloc (2 * taglength + 4 + 1);
++              int i = 0;
++              int j = 0;
++              for (i = 0; i < taglength; i++)
++                {
++                  val[2 * i + j] = hexdigit (ptr[i] >> 4);
++                  val[2 * i + 1 + j] = hexdigit (ptr[i] & 0xf);
++
++                  if ((i == 3) || (i == 5) || (i == 7) || (i == 9))
++                    {
++                      j++;
++                      val[2 * i + 1+ j] = '-';
++                    }
++                }
++
++              set_env_limn_ro (name, "clientuuid", (char *) val, 2 * taglength + 4);
++            }
++          break;
++
+ 	  /* If you need any other options please contact GRUB
+ 	     development team.  */
+ 	}
+@@ -288,14 +367,6 @@ grub_net_process_dhcp (struct grub_net_buff *nb,
+     }
+ }
+ 
+-static char
+-hexdigit (grub_uint8_t val)
+-{
+-  if (val < 10)
+-    return val + '0';
+-  return val + 'a' - 10;
+-}
+-
+ static grub_err_t
+ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
+ 		  int argc, char **args)
+diff --git a/include/grub/net.h b/include/grub/net.h
+index a799e6b8b69..59e5975b11f 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -433,6 +433,8 @@ enum
+     GRUB_NET_BOOTP_DOMAIN = 0x0f,
+     GRUB_NET_BOOTP_ROOT_PATH = 0x11,
+     GRUB_NET_BOOTP_EXTENSIONS_PATH = 0x12,
++    GRUB_NET_BOOTP_CLIENT_ID = 0x3d,
++    GRUB_NET_BOOTP_CLIENT_UUID = 0x61,
+     GRUB_NET_BOOTP_END = 0xff
+   };
+ 
diff --git a/SOURCES/0100-Search-for-specific-config-file-for-netboot.patch b/SOURCES/0100-Search-for-specific-config-file-for-netboot.patch
new file mode 100644
index 0000000..b72bea3
--- /dev/null
+++ b/SOURCES/0100-Search-for-specific-config-file-for-netboot.patch
@@ -0,0 +1,200 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
+Date: Tue, 27 Nov 2012 17:22:07 -0200
+Subject: [PATCH] Search for specific config file for netboot
+
+This patch implements a search for a specific configuration when the config
+file is on a remoteserver. It uses the following order:
+   1) DHCP client UUID option.
+   2) MAC address (in lower case hexadecimal with dash separators);
+   3) IP (in upper case hexadecimal) or IPv6;
+   4) The original grub.cfg file.
+
+This procedure is similar to what is used by pxelinux and yaboot:
+http://www.syslinux.org/wiki/index.php/PXELINUX#config
+
+This should close the bugzilla:
+https://bugzilla.redhat.com/show_bug.cgi?id=873406
+---
+ grub-core/net/net.c     | 118 ++++++++++++++++++++++++++++++++++++++++++++++++
+ grub-core/normal/main.c |  18 ++++++--
+ include/grub/net.h      |   3 ++
+ 3 files changed, 135 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index f2e723bd409..578e057e18f 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -1702,6 +1702,124 @@ grub_net_restore_hw (void)
+   return GRUB_ERR_NONE;
+ }
+ 
++grub_err_t
++grub_net_search_configfile (char *config)
++{
++  grub_size_t config_len;
++  char *suffix;
++
++  auto int search_through (grub_size_t num_tries, grub_size_t slice_size);
++  int search_through (grub_size_t num_tries, grub_size_t slice_size)
++    {
++      while (num_tries-- > 0)
++        {
++	  grub_dprintf ("net", "probe %s\n", config);
++
++          grub_file_t file;
++          file = grub_file_open (config);
++
++          if (file)
++            {
++              grub_file_close (file);
++              grub_dprintf ("net", "found!\n");
++              return 0;
++            }
++          else
++            {
++              if (grub_errno == GRUB_ERR_IO)
++                grub_errno = GRUB_ERR_NONE;
++            }
++
++          if (grub_strlen (suffix) < slice_size)
++            break;
++
++          config[grub_strlen (config) - slice_size] = '\0';
++        }
++
++      return 1;
++    }
++
++  config_len = grub_strlen (config);
++  config[config_len] = '-';
++  suffix = config + config_len + 1;
++
++  struct grub_net_network_level_interface *inf;
++  FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
++    {
++      /* By the Client UUID. */
++
++      char client_uuid_var[sizeof ("net_") + grub_strlen (inf->name) +
++                           sizeof ("_clientuuid") + 1];
++      grub_snprintf (client_uuid_var, sizeof (client_uuid_var),
++                     "net_%s_clientuuid", inf->name);
++
++      const char *client_uuid;
++      client_uuid = grub_env_get (client_uuid_var);
++
++      if (client_uuid)
++        {
++          grub_strcpy (suffix, client_uuid);
++          if (search_through (1, 0) == 0) return GRUB_ERR_NONE;
++        }
++
++      /* By the MAC address. */
++
++      /* Add ethernet type */
++      grub_strcpy (suffix, "01-");
++
++      grub_net_hwaddr_to_str (&inf->hwaddress, suffix + 3);
++
++      char *ptr;
++      for (ptr = suffix; *ptr; ptr++)
++        if (*ptr == ':')
++          *ptr = '-';
++
++      if (search_through (1, 0) == 0) return GRUB_ERR_NONE;
++
++      /* By IP address */
++
++      switch ((&inf->address)->type)
++        {
++        case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
++            {
++              grub_uint32_t n = grub_be_to_cpu32 ((&inf->address)->ipv4);
++              grub_snprintf (suffix, GRUB_NET_MAX_STR_ADDR_LEN, "%02X%02X%02X%02X", \
++                             ((n >> 24) & 0xff), ((n >> 16) & 0xff), \
++                             ((n >> 8) & 0xff), ((n >> 0) & 0xff));
++
++              if (search_through (8, 1) == 0) return GRUB_ERR_NONE;
++              break;
++            }
++        case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
++            {
++              char buf[GRUB_NET_MAX_STR_ADDR_LEN];
++              struct grub_net_network_level_address base;
++              base.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
++              grub_memcpy (&base.ipv6, ((&inf->address)->ipv6), 16);
++              grub_net_addr_to_str (&base, buf);
++
++              for (ptr = buf; *ptr; ptr++)
++                if (*ptr == ':')
++                  *ptr = '-';
++
++              grub_snprintf (suffix, GRUB_NET_MAX_STR_ADDR_LEN, "%s", buf);
++              if (search_through (1, 0) == 0) return GRUB_ERR_NONE;
++              break;
++            }
++        case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
++          return grub_error (GRUB_ERR_BUG, "shouldn't reach here");
++        default:
++          return grub_error (GRUB_ERR_BUG,
++                             "unsupported address type %d", (&inf->address)->type);
++        }
++    }
++
++  /* Remove the remaining minus sign at the end. */
++  config[config_len] = '\0';
++
++  return GRUB_ERR_NONE;
++}
++
+ static struct grub_preboot *fini_hnd;
+ 
+ static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute;
+diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
+index f72844c9f37..85d2a2862d4 100644
+--- a/grub-core/normal/main.c
++++ b/grub-core/normal/main.c
+@@ -33,6 +33,7 @@
+ #include <grub/charset.h>
+ #include <grub/script_sh.h>
+ #include <grub/bufio.h>
++#include <grub/net.h>
+ #ifdef GRUB_MACHINE_IEEE1275
+ #include <grub/ieee1275/ieee1275.h>
+ #endif
+@@ -365,10 +366,19 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
+ 
+       prefix = grub_env_get ("prefix");
+       if (prefix)
+-	{
+-	  config = grub_xasprintf ("%s/grub.cfg", prefix);
+-	  if (! config)
+-	    goto quit;
++        {
++          grub_size_t config_len;
++          config_len = grub_strlen (prefix) +
++                      sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
++          config = grub_malloc (config_len);
++
++          if (! config)
++            goto quit;
++
++          grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
++
++          if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0)
++            grub_net_search_configfile (config);
+ 
+ 	  grub_enter_normal_mode (config);
+ 	  grub_free (config);
+diff --git a/include/grub/net.h b/include/grub/net.h
+index 59e5975b11f..88fc71ceffe 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -542,4 +542,7 @@ extern char *grub_net_default_server;
+ 
+ #define VLANTAG_IDENTIFIER 0x8100
+ 
++grub_err_t
++grub_net_search_configfile (char *config);
++
+ #endif /* ! GRUB_NET_HEADER */
diff --git a/SOURCES/0101-blscfg-add-blscfg-module-to-parse-Boot-Loader-Specif.patch b/SOURCES/0101-blscfg-add-blscfg-module-to-parse-Boot-Loader-Specif.patch
new file mode 100644
index 0000000..9889d72
--- /dev/null
+++ b/SOURCES/0101-blscfg-add-blscfg-module-to-parse-Boot-Loader-Specif.patch
@@ -0,0 +1,248 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Fedora Ninjas <grub2-owner@fedoraproject.org>
+Date: Tue, 22 Jan 2013 06:31:38 +0100
+Subject: [PATCH] blscfg: add blscfg module to parse Boot Loader Specification
+ snippets
+
+http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec
+
+Works like this:
+
+ insmod blscfg
+ bls_import
+
+Done! You should now have menu items for your snippets in place.
+
+Signed-off-by: Peter Jones <grub2-owner@fedoraproject.org>
+---
+ grub-core/Makefile.core.def |   8 ++
+ grub-core/commands/blscfg.c | 201 ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 209 insertions(+)
+ create mode 100644 grub-core/commands/blscfg.c
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index ec46506e39e..7bf1c8a5880 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -746,6 +746,14 @@ module = {
+   common = commands/blocklist.c;
+ };
+ 
++module = {
++  name = blscfg;
++  common = commands/blscfg.c;
++  enable = i386_efi;
++  enable = x86_64_efi;
++  enable = i386_pc;
++};
++
+ module = {
+   name = boot;
+   common = commands/boot.c;
+diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
+new file mode 100644
+index 00000000000..4274aca5a9d
+--- /dev/null
++++ b/grub-core/commands/blscfg.c
+@@ -0,0 +1,201 @@
++/*-*- Mode: C; c-basic-offset: 2; indent-tabs-mode: t -*-*/
++
++/* bls.c - implementation of the boot loader spec */
++
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *
++ *  GRUB 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 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <grub/types.h>
++#include <grub/misc.h>
++#include <grub/mm.h>
++#include <grub/err.h>
++#include <grub/dl.h>
++#include <grub/extcmd.h>
++#include <grub/i18n.h>
++#include <grub/fs.h>
++#include <grub/env.h>
++#include <grub/file.h>
++#include <grub/normal.h>
++
++GRUB_MOD_LICENSE ("GPLv3+");
++
++#ifdef GRUB_MACHINE_EFI
++#define GRUB_LINUX_CMD "linuxefi"
++#define GRUB_INITRD_CMD "initrdefi"
++#define GRUB_BLS_CONFIG_PATH "/EFI/fedora/loader/entries/"
++#define GRUB_BOOT_DEVICE "($boot)"
++#else
++#define GRUB_LINUX_CMD "linux"
++#define GRUB_INITRD_CMD "initrd"
++#define GRUB_BLS_CONFIG_PATH "/loader/entries/"
++#define GRUB_BOOT_DEVICE "($root)"
++#endif
++
++static int parse_entry (
++    const char *filename,
++    const struct grub_dirhook_info *info __attribute__ ((unused)),
++    void *data __attribute__ ((unused)))
++{
++  grub_size_t n;
++  char *p;
++  grub_file_t f = NULL;
++  grub_off_t sz;
++  char *title = NULL, *options = NULL, *clinux = NULL, *initrd = NULL, *src = NULL;
++  const char *args[2] = { NULL, NULL };
++
++  if (filename[0] == '.')
++    return 0;
++
++  n = grub_strlen (filename);
++  if (n <= 5)
++    return 0;
++
++  if (grub_strcmp (filename + n - 5, ".conf") != 0)
++    return 0;
++
++  p = grub_xasprintf (GRUB_BLS_CONFIG_PATH "%s", filename);
++
++  f = grub_file_open (p);
++  if (!f)
++    goto finish;
++
++  sz = grub_file_size (f);
++  if (sz == GRUB_FILE_SIZE_UNKNOWN || sz > 1024*1024)
++    goto finish;
++
++  for (;;)
++    {
++      char *buf;
++
++      buf = grub_file_getline (f);
++      if (!buf)
++	break;
++
++      if (grub_strncmp (buf, "title ", 6) == 0)
++	{
++	  grub_free (title);
++	  title = grub_strdup (buf + 6);
++	  if (!title)
++	    goto finish;
++	}
++      else if (grub_strncmp (buf, "options ", 8) == 0)
++	{
++	  grub_free (options);
++	  options = grub_strdup (buf + 8);
++	  if (!options)
++	    goto finish;
++	}
++      else if (grub_strncmp (buf, "linux ", 6) == 0)
++	{
++	  grub_free (clinux);
++	  clinux = grub_strdup (buf + 6);
++	  if (!clinux)
++	    goto finish;
++	}
++      else if (grub_strncmp (buf, "initrd ", 7) == 0)
++	{
++	  grub_free (initrd);
++	  initrd = grub_strdup (buf + 7);
++	  if (!initrd)
++	    goto finish;
++	}
++
++      grub_free(buf);
++    }
++
++  if (!linux)
++    {
++      grub_printf ("Skipping file %s with no 'linux' key.", p);
++      goto finish;
++    }
++
++  args[0] = title ? title : filename;
++
++  src = grub_xasprintf ("load_video\n"
++			"set gfx_payload=keep\n"
++			"insmod gzio\n"
++			GRUB_LINUX_CMD " %s%s%s%s\n"
++			"%s%s%s%s",
++			GRUB_BOOT_DEVICE, clinux, options ? " " : "", options ? options : "",
++			initrd ? GRUB_INITRD_CMD " " : "", initrd ? GRUB_BOOT_DEVICE : "", initrd ? initrd : "", initrd ? "\n" : "");
++
++  grub_normal_add_menu_entry (1, args, NULL, NULL, "bls", NULL, NULL, src, 0);
++
++finish:
++  grub_free (p);
++  grub_free (title);
++  grub_free (options);
++  grub_free (clinux);
++  grub_free (initrd);
++  grub_free (src);
++
++  if (f)
++    grub_file_close (f);
++
++  return 0;
++}
++
++static grub_err_t
++grub_cmd_bls_import (grub_extcmd_context_t ctxt __attribute__ ((unused)),
++		     int argc __attribute__ ((unused)),
++		     char **args __attribute__ ((unused)))
++{
++  grub_fs_t fs;
++  grub_device_t dev;
++  static grub_err_t r;
++  const char *devid;
++
++  devid = grub_env_get ("root");
++  if (!devid)
++    return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "root");
++
++  dev = grub_device_open (devid);
++  if (!dev)
++    return grub_errno;
++
++  fs = grub_fs_probe (dev);
++  if (!fs)
++    {
++      r = grub_errno;
++      goto finish;
++    }
++
++  r = fs->dir (dev, GRUB_BLS_CONFIG_PATH, parse_entry, NULL);
++
++finish:
++  if (dev)
++    grub_device_close (dev);
++
++  return r;
++}
++
++static grub_extcmd_t cmd;
++
++GRUB_MOD_INIT(bls)
++{
++  cmd = grub_register_extcmd ("bls_import",
++			      grub_cmd_bls_import,
++			      0,
++			      NULL,
++			      N_("Import Boot Loader Specification snippets."),
++			      NULL);
++}
++
++GRUB_MOD_FINI(bls)
++{
++  grub_unregister_extcmd (cmd);
++}
diff --git a/SOURCES/0102-Move-bash-completion-script-922997.patch b/SOURCES/0102-Move-bash-completion-script-922997.patch
new file mode 100644
index 0000000..1da0068
--- /dev/null
+++ b/SOURCES/0102-Move-bash-completion-script-922997.patch
@@ -0,0 +1,23 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 3 Apr 2013 14:35:34 -0400
+Subject: [PATCH] Move bash completion script (#922997)
+
+Apparently these go in a new place now.
+---
+ util/bash-completion.d/Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/util/bash-completion.d/Makefile.am b/util/bash-completion.d/Makefile.am
+index 136287cf1bf..0bcdb060e84 100644
+--- a/util/bash-completion.d/Makefile.am
++++ b/util/bash-completion.d/Makefile.am
+@@ -6,7 +6,7 @@ EXTRA_DIST = $(bash_completion_source)
+ 
+ CLEANFILES = $(bash_completion_script) config.log
+ 
+-bashcompletiondir = $(sysconfdir)/bash_completion.d
++bashcompletiondir = $(datarootdir)/bash-completion/completions
+ bashcompletion_DATA = $(bash_completion_script)
+ 
+ $(bash_completion_script): $(bash_completion_source) $(top_builddir)/config.status
diff --git a/SOURCES/0103-for-ppc-reset-console-display-attr-when-clear-screen.patch b/SOURCES/0103-for-ppc-reset-console-display-attr-when-clear-screen.patch
new file mode 100644
index 0000000..853c150
--- /dev/null
+++ b/SOURCES/0103-for-ppc-reset-console-display-attr-when-clear-screen.patch
@@ -0,0 +1,24 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
+Date: Wed, 24 Apr 2013 10:51:48 -0300
+Subject: [PATCH] for ppc, reset console display attr when clear screen
+
+This should fix this bugzilla:
+https://bugzilla.redhat.com/show_bug.cgi?id=908519
+---
+ grub-core/term/terminfo.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c
+index f0d3e3debc6..7cb7909c8cf 100644
+--- a/grub-core/term/terminfo.c
++++ b/grub-core/term/terminfo.c
+@@ -151,7 +151,7 @@ grub_terminfo_set_current (struct grub_term_output *term,
+       /* Clear the screen.  Using serial console, screen(1) only recognizes the
+        * ANSI escape sequence.  Using video console, Apple Open Firmware
+        * (version 3.1.1) only recognizes the literal ^L.  So use both.  */
+-      data->cls               = grub_strdup ("\e[2J");
++      data->cls               = grub_strdup ("\e[2J\e[m");
+       data->reverse_video_on  = grub_strdup ("\e[7m");
+       data->reverse_video_off = grub_strdup ("\e[m");
+       if (grub_strcmp ("ieee1275", str) == 0)
diff --git a/SOURCES/0104-Don-t-write-messages-to-the-screen.patch b/SOURCES/0104-Don-t-write-messages-to-the-screen.patch
new file mode 100644
index 0000000..c4d8945
--- /dev/null
+++ b/SOURCES/0104-Don-t-write-messages-to-the-screen.patch
@@ -0,0 +1,155 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: William Jon McCann <william.jon.mccann@gmail.com>
+Date: Wed, 15 May 2013 13:30:20 -0400
+Subject: [PATCH] Don't write messages to the screen
+
+Writing messages to the screen before the menus or boot splash
+happens so quickly it looks like something is wrong and isn't
+very appealing.
+---
+ grub-core/gettext/gettext.c       | 15 ---------------
+ grub-core/kern/main.c             |  5 -----
+ grub-core/boot/i386/pc/boot.S     |  3 ---
+ grub-core/boot/i386/pc/diskboot.S |  5 -----
+ util/grub.d/10_linux.in           |  7 -------
+ 5 files changed, 35 deletions(-)
+
+diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c
+index 4880cefe3f8..1e5c21d7ef2 100644
+--- a/grub-core/gettext/gettext.c
++++ b/grub-core/gettext/gettext.c
+@@ -437,13 +437,9 @@ grub_gettext_env_write_lang (struct grub_env_var *var
+   grub_err_t err;
+   err = grub_gettext_init_ext (&main_context, val, grub_env_get ("locale_dir"),
+ 			       grub_env_get ("prefix"));
+-  if (err)
+-    grub_print_error ();
+ 
+   err = grub_gettext_init_ext (&secondary_context, val,
+ 			       grub_env_get ("secondary_locale_dir"), 0);
+-  if (err)
+-    grub_print_error ();
+ 
+   return grub_strdup (val);
+ }
+@@ -455,8 +451,6 @@ grub_gettext_reread_prefix (const char *val)
+   err = grub_gettext_init_ext (&main_context, grub_env_get ("lang"), 
+ 			       grub_env_get ("locale_dir"),
+ 			       val);
+-  if (err)
+-    grub_print_error ();
+ }
+ 
+ static char *
+@@ -466,8 +460,6 @@ read_main (struct grub_env_var *var
+   grub_err_t err;
+   err = grub_gettext_init_ext (&main_context, grub_env_get ("lang"), val,
+ 			       grub_env_get ("prefix"));
+-  if (err)
+-    grub_print_error ();
+   return grub_strdup (val);
+ }
+ 
+@@ -478,9 +470,6 @@ read_secondary (struct grub_env_var *var
+   grub_err_t err;
+   err = grub_gettext_init_ext (&secondary_context, grub_env_get ("lang"), val,
+ 			       0);
+-  if (err)
+-    grub_print_error ();
+-
+   return grub_strdup (val);
+ }
+ 
+@@ -506,12 +495,8 @@ GRUB_MOD_INIT (gettext)
+ 
+   err = grub_gettext_init_ext (&main_context, lang, grub_env_get ("locale_dir"),
+ 			       grub_env_get ("prefix"));
+-  if (err)
+-    grub_print_error ();
+   err = grub_gettext_init_ext (&secondary_context, lang,
+ 			       grub_env_get ("secondary_locale_dir"), 0);
+-  if (err)
+-    grub_print_error ();
+ 
+   grub_register_variable_hook ("locale_dir", NULL, read_main);
+   grub_register_variable_hook ("secondary_locale_dir", NULL, read_secondary);
+diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
+index 8ab7794c47b..da47b18b50e 100644
+--- a/grub-core/kern/main.c
++++ b/grub-core/kern/main.c
+@@ -268,11 +268,6 @@ grub_main (void)
+ 
+   grub_boot_time ("After machine init.");
+ 
+-  /* Hello.  */
+-  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
+-  grub_printf ("Welcome to GRUB!\n\n");
+-  grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
+-
+   grub_load_config ();
+ 
+   grub_boot_time ("Before loading embedded modules.");
+diff --git a/grub-core/boot/i386/pc/boot.S b/grub-core/boot/i386/pc/boot.S
+index b4975e2d029..432a472d529 100644
+--- a/grub-core/boot/i386/pc/boot.S
++++ b/grub-core/boot/i386/pc/boot.S
+@@ -249,9 +249,6 @@ real_start:
+ 	/* save drive reference first thing! */
+ 	pushw	%dx
+ 
+-	/* print a notification message on the screen */
+-	MSG(notification_string)
+-
+ 	/* set %si to the disk address packet */
+ 	movw	$disk_address_packet, %si
+ 
+diff --git a/grub-core/boot/i386/pc/diskboot.S b/grub-core/boot/i386/pc/diskboot.S
+index d030a14c916..a494d029c61 100644
+--- a/grub-core/boot/i386/pc/diskboot.S
++++ b/grub-core/boot/i386/pc/diskboot.S
+@@ -50,11 +50,6 @@ _start:
+ 	/* save drive reference first thing! */
+ 	pushw	%dx
+ 
+-	/* print a notification message on the screen */
+-	pushw	%si
+-	MSG(notification_string)
+-	popw	%si
+-
+ 	/* this sets up for the first run through "bootloop" */
+ 	movw	$LOCAL(firstlist), %di
+ 
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index ad34cc02d36..e762e1f4e37 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -126,29 +126,22 @@ linux_entry ()
+     fi
+     printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/"
+   fi
+-  message="$(gettext_printf "Loading Linux %s ..." ${version})"
+   if [ -d /sys/firmware/efi ]; then
+     sed "s/^/$submenu_indentation/" << EOF
+-	echo	'$(echo "$message" | grub_quote)'
+ 	linuxefi ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
+ EOF
+   else
+     sed "s/^/$submenu_indentation/" << EOF
+-	echo	'$(echo "$message" | grub_quote)'
+ 	linux	${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
+ EOF
+   fi
+   if test -n "${initrd}" ; then
+-    # TRANSLATORS: ramdisk isn't identifier. Should be translated.
+-    message="$(gettext_printf "Loading initial ramdisk ...")"
+     if [ -d /sys/firmware/efi ]; then
+       sed "s/^/$submenu_indentation/" << EOF
+-	echo	'$(echo "$message" | grub_quote)'
+ 	initrdefi ${rel_dirname}/${initrd}
+ EOF
+     else
+       sed "s/^/$submenu_indentation/" << EOF
+-	echo	'$message'
+ 	initrd	${rel_dirname}/${initrd}
+ EOF
+     fi
diff --git a/SOURCES/0105-Don-t-print-GNU-GRUB-header.patch b/SOURCES/0105-Don-t-print-GNU-GRUB-header.patch
new file mode 100644
index 0000000..2ee1c91
--- /dev/null
+++ b/SOURCES/0105-Don-t-print-GNU-GRUB-header.patch
@@ -0,0 +1,30 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: William Jon McCann <william.jon.mccann@gmail.com>
+Date: Wed, 15 May 2013 13:53:48 -0400
+Subject: [PATCH] Don't print GNU GRUB header
+
+No one cares.
+---
+ grub-core/normal/main.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
+index 85d2a2862d4..3777cd22ce3 100644
+--- a/grub-core/normal/main.c
++++ b/grub-core/normal/main.c
+@@ -212,6 +212,7 @@ grub_normal_init_page (struct grub_term_output *term,
+  
+   grub_term_cls (term);
+ 
++#if 0
+   msg_formatted = grub_xasprintf (_("GNU GRUB  version %s"), PACKAGE_VERSION);
+   if (!msg_formatted)
+     return;
+@@ -235,6 +236,7 @@ grub_normal_init_page (struct grub_term_output *term,
+   grub_putcode ('\n', term);
+   grub_putcode ('\n', term);
+   grub_free (unicode_msg);
++#endif
+ }
+ 
+ static void
diff --git a/SOURCES/0106-Don-t-add-to-highlighted-row.patch b/SOURCES/0106-Don-t-add-to-highlighted-row.patch
new file mode 100644
index 0000000..ef6dc25
--- /dev/null
+++ b/SOURCES/0106-Don-t-add-to-highlighted-row.patch
@@ -0,0 +1,23 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: William Jon McCann <william.jon.mccann@gmail.com>
+Date: Wed, 15 May 2013 17:49:45 -0400
+Subject: [PATCH] Don't add '*' to highlighted row
+
+It is already highlighted.
+---
+ grub-core/normal/menu_text.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
+index 2ff294101d8..2f84fccb6fe 100644
+--- a/grub-core/normal/menu_text.c
++++ b/grub-core/normal/menu_text.c
+@@ -242,7 +242,7 @@ print_entry (int y, int highlight, grub_menu_entry_t entry,
+       unicode_title[i] = ' ';
+ 
+   if (data->geo.num_entries > 1)
+-    grub_putcode (highlight ? '*' : ' ', data->term);
++    grub_putcode (' ', data->term);
+ 
+   grub_print_ucs4_menu (unicode_title,
+ 			unicode_title + len,
diff --git a/SOURCES/0107-Message-string-cleanups.patch b/SOURCES/0107-Message-string-cleanups.patch
new file mode 100644
index 0000000..42502c1
--- /dev/null
+++ b/SOURCES/0107-Message-string-cleanups.patch
@@ -0,0 +1,68 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: William Jon McCann <william.jon.mccann@gmail.com>
+Date: Fri, 7 Jun 2013 11:09:04 -0400
+Subject: [PATCH] Message string cleanups
+
+Make use of terminology consistent. Remove jargon.
+---
+ grub-core/normal/menu_text.c | 21 +++++++++------------
+ 1 file changed, 9 insertions(+), 12 deletions(-)
+
+diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
+index 2f84fccb6fe..9d20c6b85b2 100644
+--- a/grub-core/normal/menu_text.c
++++ b/grub-core/normal/menu_text.c
+@@ -157,9 +157,8 @@ print_message (int nested, int edit, struct grub_term_output *term, int dry_run)
+ 
+   if (edit)
+     {
+-      ret += grub_print_message_indented_real (_("Minimum Emacs-like screen editing is \
+-supported. TAB lists completions. Press Ctrl-x or F10 to boot, Ctrl-c or F2 for a \
+-command-line or ESC to discard edits and return to the GRUB menu."),
++      ret += grub_print_message_indented_real (_("Press Ctrl-x or F10 to start, Ctrl-c or F2 for a \
++command prompt or Escape to discard edits and return to the menu. Pressing Tab lists possible completions."),
+ 					       STANDARD_MARGIN, STANDARD_MARGIN,
+ 					       term, dry_run);
+     }
+@@ -167,8 +166,8 @@ command-line or ESC to discard edits and return to the GRUB menu."),
+     {
+       char *msg_translated;
+ 
+-      msg_translated = grub_xasprintf (_("Use the %C and %C keys to select which "
+-					 "entry is highlighted."),
++      msg_translated = grub_xasprintf (_("Use the %C and %C keys to change the "
++					 "selection."),
+ 				       GRUB_UNICODE_UPARROW,
+ 				       GRUB_UNICODE_DOWNARROW);
+       if (!msg_translated)
+@@ -181,17 +180,15 @@ command-line or ESC to discard edits and return to the GRUB menu."),
+       if (nested)
+ 	{
+ 	  ret += grub_print_message_indented_real
+-	    (_("Press enter to boot the selected OS, "
+-	       "`e' to edit the commands before booting "
+-	       "or `c' for a command-line. ESC to return previous menu."),
++	    (_("Press 'e' to edit the selected item, "
++	       "or 'c' for a command prompt. Press Escape to return to the previous menu."),
+ 	     STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
+ 	}
+       else
+ 	{
+ 	  ret += grub_print_message_indented_real
+-	    (_("Press enter to boot the selected OS, "
+-	       "`e' to edit the commands before booting "
+-	       "or `c' for a command-line."),
++	    (_("Press 'e' to edit the selected item, "
++	       "or 'c' for a command prompt."),
+ 	     STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
+ 	}	
+     }
+@@ -440,7 +437,7 @@ menu_text_print_timeout (int timeout, void *dataptr)
+       || data->timeout_msg == TIMEOUT_TERSE_NO_MARGIN)
+     msg_translated = grub_xasprintf (_("%ds"), timeout);
+   else
+-    msg_translated = grub_xasprintf (_("The highlighted entry will be executed automatically in %ds."), timeout);
++    msg_translated = grub_xasprintf (_("The selected entry will be started automatically in %ds."), timeout);
+   if (!msg_translated)
+     {
+       grub_print_error ();
diff --git a/SOURCES/0108-Fix-border-spacing-now-that-we-aren-t-displaying-it.patch b/SOURCES/0108-Fix-border-spacing-now-that-we-aren-t-displaying-it.patch
new file mode 100644
index 0000000..0c1a9ab
--- /dev/null
+++ b/SOURCES/0108-Fix-border-spacing-now-that-we-aren-t-displaying-it.patch
@@ -0,0 +1,29 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: William Jon McCann <william.jon.mccann@gmail.com>
+Date: Fri, 7 Jun 2013 14:08:23 -0400
+Subject: [PATCH] Fix border spacing now that we aren't displaying it
+
+---
+ grub-core/normal/menu_text.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
+index 9d20c6b85b2..aa3454ff525 100644
+--- a/grub-core/normal/menu_text.c
++++ b/grub-core/normal/menu_text.c
+@@ -331,12 +331,12 @@ grub_menu_init_page (int nested, int edit,
+   int empty_lines = 1;
+   int version_msg = 1;
+ 
+-  geo->border = 1;
+-  geo->first_entry_x = 1 /* margin */ + 1 /* border */;
++  geo->border = 0;
++  geo->first_entry_x = 0 /* margin */ + 0 /* border */;
+   geo->entry_width = grub_term_width (term) - 5;
+ 
+   geo->first_entry_y = 2 /* two empty lines*/
+-    + 1 /* GNU GRUB version text  */ + 1 /* top border */;
++    + 0 /* GNU GRUB version text  */ + 1 /* top border */;
+ 
+   geo->timeout_lines = 2;
+ 
diff --git a/SOURCES/0109-Use-the-correct-indentation-for-the-term-help-text.patch b/SOURCES/0109-Use-the-correct-indentation-for-the-term-help-text.patch
new file mode 100644
index 0000000..cbeb9fd
--- /dev/null
+++ b/SOURCES/0109-Use-the-correct-indentation-for-the-term-help-text.patch
@@ -0,0 +1,25 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: William Jon McCann <william.jon.mccann@gmail.com>
+Date: Fri, 7 Jun 2013 14:08:49 -0400
+Subject: [PATCH] Use the correct indentation for the term help text
+
+That is consistent with the menu help text
+---
+ grub-core/normal/main.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
+index 3777cd22ce3..0da2a520d2d 100644
+--- a/grub-core/normal/main.c
++++ b/grub-core/normal/main.c
+@@ -426,8 +426,8 @@ grub_normal_reader_init (int nested)
+     grub_normal_init_page (term, 1);
+     grub_term_setcursor (term, 1);
+ 
+-    if (grub_term_width (term) > 3 + STANDARD_MARGIN + 20)
+-      grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN, term);
++    if (grub_term_width (term) > 2 * STANDARD_MARGIN + 20)
++      grub_print_message_indented (msg_formatted, STANDARD_MARGIN, STANDARD_MARGIN, term);
+     else
+       grub_print_message_indented (msg_formatted, 0, 0, term);
+     grub_putcode ('\n', term);
diff --git a/SOURCES/0110-Indent-menu-entries.patch b/SOURCES/0110-Indent-menu-entries.patch
new file mode 100644
index 0000000..98c3b7d
--- /dev/null
+++ b/SOURCES/0110-Indent-menu-entries.patch
@@ -0,0 +1,23 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: William Jon McCann <william.jon.mccann@gmail.com>
+Date: Fri, 7 Jun 2013 14:30:55 -0400
+Subject: [PATCH] Indent menu entries
+
+---
+ grub-core/normal/menu_text.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
+index aa3454ff525..01b6f1c739f 100644
+--- a/grub-core/normal/menu_text.c
++++ b/grub-core/normal/menu_text.c
+@@ -239,7 +239,8 @@ print_entry (int y, int highlight, grub_menu_entry_t entry,
+       unicode_title[i] = ' ';
+ 
+   if (data->geo.num_entries > 1)
+-    grub_putcode (' ', data->term);
++    for (i = 0; i < STANDARD_MARGIN; i++)
++      grub_putcode (' ', data->term);
+ 
+   grub_print_ucs4_menu (unicode_title,
+ 			unicode_title + len,
diff --git a/SOURCES/0111-Fix-margins.patch b/SOURCES/0111-Fix-margins.patch
new file mode 100644
index 0000000..5c5ae10
--- /dev/null
+++ b/SOURCES/0111-Fix-margins.patch
@@ -0,0 +1,34 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: William Jon McCann <william.jon.mccann@gmail.com>
+Date: Fri, 7 Jun 2013 14:59:36 -0400
+Subject: [PATCH] Fix margins
+
+---
+ grub-core/normal/menu_text.c | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
+index 01b6f1c739f..ead3391b7bb 100644
+--- a/grub-core/normal/menu_text.c
++++ b/grub-core/normal/menu_text.c
+@@ -333,17 +333,15 @@ grub_menu_init_page (int nested, int edit,
+   int version_msg = 1;
+ 
+   geo->border = 0;
+-  geo->first_entry_x = 0 /* margin */ + 0 /* border */;
+-  geo->entry_width = grub_term_width (term) - 5;
++  geo->first_entry_x = 0; /* no margin */
++  geo->entry_width = grub_term_width (term) - 1;
+ 
+-  geo->first_entry_y = 2 /* two empty lines*/
+-    + 0 /* GNU GRUB version text  */ + 1 /* top border */;
++  geo->first_entry_y = 3; /* three empty lines*/
+ 
+   geo->timeout_lines = 2;
+ 
+   /* 3 lines for timeout message and bottom margin.  2 lines for the border.  */
+   geo->num_entries = grub_term_height (term) - geo->first_entry_y
+-    - 1 /* bottom border */
+     - 1 /* empty line before info message*/
+     - geo->timeout_lines /* timeout */
+     - 1 /* empty final line  */;
diff --git a/SOURCES/0112-Add-support-for-UEFI-operating-systems-returned-by-o.patch b/SOURCES/0112-Add-support-for-UEFI-operating-systems-returned-by-o.patch
new file mode 100644
index 0000000..f093824
--- /dev/null
+++ b/SOURCES/0112-Add-support-for-UEFI-operating-systems-returned-by-o.patch
@@ -0,0 +1,47 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Matthew Garrett <matthew.garrett@nebula.com>
+Date: Wed, 12 Jun 2013 11:51:49 -0400
+Subject: [PATCH] Add support for UEFI operating systems returned by os-prober
+
+os-prober returns UEFI operating systems in the form:
+
+path:long-name:name
+
+where path is the path under the EFI directory on the ESP. This is in
+contrast to legacy OSes, where path is the device string. Handle this case.
+---
+ util/grub.d/30_os-prober.in | 22 ++++++++++++++++++----
+ 1 file changed, 18 insertions(+), 4 deletions(-)
+
+diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
+index 6f38c82a554..9f955abb788 100644
+--- a/util/grub.d/30_os-prober.in
++++ b/util/grub.d/30_os-prober.in
+@@ -322,9 +322,23 @@ EOF
+ EOF
+     ;;
+     *)
+-      echo -n "  "
+-      # TRANSLATORS: %s is replaced by OS name.
+-      gettext_printf "%s is not yet supported by grub-mkconfig.\n" "${LONGNAME}" >&2
+-    ;;
++      case ${DEVICE} in
++	*.efi)
++	  cat << EOF
++menuentry '$(echo "${LONGNAME}" | grub_quote)' {
++EOF
++	  save_default_entry | grub_add_tab
++	  cat << EOF
++	  chainloader /EFI/${DEVICE}
++	  boot
++}
++EOF
++	  ;;
++	*)
++          echo -n "  "
++          # TRANSLATORS: %s is replaced by OS name.
++          gettext_printf "%s is not yet supported by grub-mkconfig.\n" "${LONGNAME}" >&2
++        ;;
++      esac
+   esac
+ done
diff --git a/SOURCES/0113-Disable-GRUB-video-support-for-IBM-power-machines.patch b/SOURCES/0113-Disable-GRUB-video-support-for-IBM-power-machines.patch
new file mode 100644
index 0000000..32f4c3a
--- /dev/null
+++ b/SOURCES/0113-Disable-GRUB-video-support-for-IBM-power-machines.patch
@@ -0,0 +1,62 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
+Date: Tue, 11 Jun 2013 15:14:05 -0300
+Subject: [PATCH] Disable GRUB video support for IBM power machines
+
+Should fix the problem in bugzilla:
+https://bugzilla.redhat.com/show_bug.cgi?id=973205
+---
+ grub-core/kern/ieee1275/cmain.c  | 5 ++++-
+ grub-core/video/ieee1275.c       | 9 ++++++---
+ include/grub/ieee1275/ieee1275.h | 2 ++
+ 3 files changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c
+index 3e12e6b24e1..3e14f539368 100644
+--- a/grub-core/kern/ieee1275/cmain.c
++++ b/grub-core/kern/ieee1275/cmain.c
+@@ -90,7 +90,10 @@ grub_ieee1275_find_options (void)
+   }
+ 
+   if (rc >= 0 && grub_strncmp (tmp, "IBM", 3) == 0)
+-    grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS);
++    {
++      grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS);
++      grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT);
++    }
+ 
+   /* Old Macs have no key repeat, newer ones have fully working one.
+      The ones inbetween when repeated key generates an escaoe sequence
+diff --git a/grub-core/video/ieee1275.c b/grub-core/video/ieee1275.c
+index 0b150ec2406..813ab38e1e0 100644
+--- a/grub-core/video/ieee1275.c
++++ b/grub-core/video/ieee1275.c
+@@ -351,9 +351,12 @@ static struct grub_video_adapter grub_video_ieee1275_adapter =
+ 
+ GRUB_MOD_INIT(ieee1275_fb)
+ {
+-  find_display ();
+-  if (display)
+-    grub_video_register (&grub_video_ieee1275_adapter);
++  if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT))
++    {
++      find_display ();
++      if (display)
++        grub_video_register (&grub_video_ieee1275_adapter);
++    }
+ }
+ 
+ GRUB_MOD_FINI(ieee1275_fb)
+diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
+index 6a21f5d6de8..663935da7a5 100644
+--- a/include/grub/ieee1275/ieee1275.h
++++ b/include/grub/ieee1275/ieee1275.h
+@@ -146,6 +146,8 @@ enum grub_ieee1275_flag
+   GRUB_IEEE1275_FLAG_BROKEN_REPEAT,
+ 
+   GRUB_IEEE1275_FLAG_CURSORONOFF_ANSI_BROKEN,
++
++  GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT
+ };
+ 
+ extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag);
diff --git a/SOURCES/0114-Use-2-instead-of-1-for-our-right-hand-margin-so-line.patch b/SOURCES/0114-Use-2-instead-of-1-for-our-right-hand-margin-so-line.patch
new file mode 100644
index 0000000..2f81996
--- /dev/null
+++ b/SOURCES/0114-Use-2-instead-of-1-for-our-right-hand-margin-so-line.patch
@@ -0,0 +1,24 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Fri, 21 Jun 2013 14:44:08 -0400
+Subject: [PATCH] Use -2 instead of -1 for our right-hand margin, so
+ linewrapping works (#976643).
+
+Signed-off-by: Peter Jones <grub2-owner@fedoraproject.org>
+---
+ grub-core/normal/menu_text.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
+index ead3391b7bb..bc1fc718fc0 100644
+--- a/grub-core/normal/menu_text.c
++++ b/grub-core/normal/menu_text.c
+@@ -334,7 +334,7 @@ grub_menu_init_page (int nested, int edit,
+ 
+   geo->border = 0;
+   geo->first_entry_x = 0; /* no margin */
+-  geo->entry_width = grub_term_width (term) - 1;
++  geo->entry_width = grub_term_width (term) - 2;
+ 
+   geo->first_entry_y = 3; /* three empty lines*/
+ 
diff --git a/SOURCES/0115-Use-linux16-when-appropriate-880840.patch b/SOURCES/0115-Use-linux16-when-appropriate-880840.patch
new file mode 100644
index 0000000..2bbab63
--- /dev/null
+++ b/SOURCES/0115-Use-linux16-when-appropriate-880840.patch
@@ -0,0 +1,49 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 28 Oct 2013 10:05:07 -0400
+Subject: [PATCH] Use linux16 when appropriate (#880840)
+
+The kernel group really would prefer that we use the 16 bit entry point
+on x86 bios machines.
+
+Resolves: rhbz#880840
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ util/grub.d/10_linux.in | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index e762e1f4e37..600bfd29dc7 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -74,6 +74,11 @@ linux_entry ()
+   type="$3"
+   args="$4"
+ 
++  sixteenbit=""
++  case "$machine" in
++    i?86|x86_64) sixteenbit="16" ;;
++  esac
++
+   if [ -z "$boot_device_id" ]; then
+       boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
+   fi
+@@ -132,7 +137,7 @@ linux_entry ()
+ EOF
+   else
+     sed "s/^/$submenu_indentation/" << EOF
+-	linux	${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
++	linux${sixteenbit} ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
+ EOF
+   fi
+   if test -n "${initrd}" ; then
+@@ -142,7 +147,7 @@ EOF
+ EOF
+     else
+       sed "s/^/$submenu_indentation/" << EOF
+-	initrd	${rel_dirname}/${initrd}
++	initrd${sixteenbit} ${rel_dirname}/${initrd}
+ EOF
+     fi
+   fi
diff --git a/SOURCES/0116-Enable-pager-by-default.-985860.patch b/SOURCES/0116-Enable-pager-by-default.-985860.patch
new file mode 100644
index 0000000..8c545b7
--- /dev/null
+++ b/SOURCES/0116-Enable-pager-by-default.-985860.patch
@@ -0,0 +1,23 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 28 Oct 2013 10:09:27 -0400
+Subject: [PATCH] Enable pager by default. (#985860)
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ util/grub.d/00_header.in | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
+index ce2ec819d8c..fefa7ddfcc0 100644
+--- a/util/grub.d/00_header.in
++++ b/util/grub.d/00_header.in
+@@ -43,6 +43,8 @@ if [ "x${GRUB_DEFAULT_BUTTON}" = "xsaved" ] ; then GRUB_DEFAULT_BUTTON='${saved_
+ if [ "x${GRUB_TIMEOUT_BUTTON}" = "x" ] ; then GRUB_TIMEOUT_BUTTON="$GRUB_TIMEOUT" ; fi
+ 
+ cat << EOF
++set pager=1
++
+ if [ -s \$prefix/grubenv ]; then
+   load_env
+ fi
diff --git a/SOURCES/0117-F10-doesn-t-work-on-serial-so-don-t-tell-the-user-to.patch b/SOURCES/0117-F10-doesn-t-work-on-serial-so-don-t-tell-the-user-to.patch
new file mode 100644
index 0000000..82f00d6
--- /dev/null
+++ b/SOURCES/0117-F10-doesn-t-work-on-serial-so-don-t-tell-the-user-to.patch
@@ -0,0 +1,24 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 28 Oct 2013 10:13:27 -0400
+Subject: [PATCH] F10 doesn't work on serial, so don't tell the user to hit it
+ (#987443)
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/normal/menu_text.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
+index bc1fc718fc0..6202c2a16c9 100644
+--- a/grub-core/normal/menu_text.c
++++ b/grub-core/normal/menu_text.c
+@@ -157,7 +157,7 @@ print_message (int nested, int edit, struct grub_term_output *term, int dry_run)
+ 
+   if (edit)
+     {
+-      ret += grub_print_message_indented_real (_("Press Ctrl-x or F10 to start, Ctrl-c or F2 for a \
++      ret += grub_print_message_indented_real (_("Press Ctrl-x to start, Ctrl-c for a \
+ command prompt or Escape to discard edits and return to the menu. Pressing Tab lists possible completions."),
+ 					       STANDARD_MARGIN, STANDARD_MARGIN,
+ 					       term, dry_run);
diff --git a/SOURCES/0118-Don-t-say-GNU-Linux-in-generated-menus.patch b/SOURCES/0118-Don-t-say-GNU-Linux-in-generated-menus.patch
new file mode 100644
index 0000000..9210b89
--- /dev/null
+++ b/SOURCES/0118-Don-t-say-GNU-Linux-in-generated-menus.patch
@@ -0,0 +1,42 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 14 Mar 2011 14:27:42 -0400
+Subject: [PATCH] Don't say "GNU/Linux" in generated menus.
+
+---
+ util/grub.d/10_linux.in     | 4 ++--
+ util/grub.d/20_linux_xen.in | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 600bfd29dc7..c943a1e403e 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -29,9 +29,9 @@ export TEXTDOMAINDIR="@localedir@"
+ CLASS="--class gnu-linux --class gnu --class os"
+ 
+ if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+-  OS=GNU/Linux
++  OS="$(sed 's, release .*$,,g' /etc/system-release)"
+ else
+-  OS="${GRUB_DISTRIBUTOR} GNU/Linux"
++  OS="${GRUB_DISTRIBUTOR}"
+   CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}"
+ fi
+ 
+diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
+index a60843500ed..79d4e38d643 100644
+--- a/util/grub.d/20_linux_xen.in
++++ b/util/grub.d/20_linux_xen.in
+@@ -29,9 +29,9 @@ export TEXTDOMAINDIR="@localedir@"
+ CLASS="--class gnu-linux --class gnu --class os --class xen"
+ 
+ if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+-  OS=GNU/Linux
++  OS="$(sed 's, release .*$,,g' /etc/system-release)"
+ else
+-  OS="${GRUB_DISTRIBUTOR} GNU/Linux"
++  OS="${GRUB_DISTRIBUTOR}"
+   CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}"
+ fi
+ 
diff --git a/SOURCES/0119-Don-t-draw-a-border-around-the-menu.patch b/SOURCES/0119-Don-t-draw-a-border-around-the-menu.patch
new file mode 100644
index 0000000..409c472
--- /dev/null
+++ b/SOURCES/0119-Don-t-draw-a-border-around-the-menu.patch
@@ -0,0 +1,71 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: William Jon McCann <william.jon.mccann@gmail.com>
+Date: Wed, 15 May 2013 16:47:33 -0400
+Subject: [PATCH] Don't draw a border around the menu
+
+It looks cleaner without it.
+---
+ grub-core/normal/menu_text.c | 43 -------------------------------------------
+ 1 file changed, 43 deletions(-)
+
+diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
+index 6202c2a16c9..beddd7f81c1 100644
+--- a/grub-core/normal/menu_text.c
++++ b/grub-core/normal/menu_text.c
+@@ -108,47 +108,6 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right,
+   grub_print_message_indented_real (msg, margin_left, margin_right, term, 0);
+ }
+ 
+-static void
+-draw_border (struct grub_term_output *term, const struct grub_term_screen_geometry *geo)
+-{
+-  int i;
+-
+-  grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
+-
+-  grub_term_gotoxy (term, (struct grub_term_coordinate) { geo->first_entry_x - 1,
+-	geo->first_entry_y - 1 });
+-  grub_putcode (GRUB_UNICODE_CORNER_UL, term);
+-  for (i = 0; i < geo->entry_width + 1; i++)
+-    grub_putcode (GRUB_UNICODE_HLINE, term);
+-  grub_putcode (GRUB_UNICODE_CORNER_UR, term);
+-
+-  for (i = 0; i < geo->num_entries; i++)
+-    {
+-      grub_term_gotoxy (term, (struct grub_term_coordinate) { geo->first_entry_x - 1,
+-	    geo->first_entry_y + i });
+-      grub_putcode (GRUB_UNICODE_VLINE, term);
+-      grub_term_gotoxy (term,
+-			(struct grub_term_coordinate) { geo->first_entry_x + geo->entry_width + 1,
+-			    geo->first_entry_y + i });
+-      grub_putcode (GRUB_UNICODE_VLINE, term);
+-    }
+-
+-  grub_term_gotoxy (term,
+-		    (struct grub_term_coordinate) { geo->first_entry_x - 1,
+-			geo->first_entry_y - 1 + geo->num_entries + 1 });
+-  grub_putcode (GRUB_UNICODE_CORNER_LL, term);
+-  for (i = 0; i < geo->entry_width + 1; i++)
+-    grub_putcode (GRUB_UNICODE_HLINE, term);
+-  grub_putcode (GRUB_UNICODE_CORNER_LR, term);
+-
+-  grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
+-
+-  grub_term_gotoxy (term,
+-		    (struct grub_term_coordinate) { geo->first_entry_x - 1,
+-			(geo->first_entry_y - 1 + geo->num_entries
+-			 + GRUB_TERM_MARGIN + 1) });
+-}
+-
+ static int
+ print_message (int nested, int edit, struct grub_term_output *term, int dry_run)
+ {
+@@ -403,8 +362,6 @@ grub_menu_init_page (int nested, int edit,
+ 
+   grub_term_normal_color = grub_color_menu_normal;
+   grub_term_highlight_color = grub_color_menu_highlight;
+-  if (geo->border)
+-    draw_border (term, geo);
+   grub_term_normal_color = old_color_normal;
+   grub_term_highlight_color = old_color_highlight;
+   geo->timeout_y = geo->first_entry_y + geo->num_entries
diff --git a/SOURCES/0120-Use-the-standard-margin-for-the-timeout-string.patch b/SOURCES/0120-Use-the-standard-margin-for-the-timeout-string.patch
new file mode 100644
index 0000000..046af91
--- /dev/null
+++ b/SOURCES/0120-Use-the-standard-margin-for-the-timeout-string.patch
@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: William Jon McCann <william.jon.mccann@gmail.com>
+Date: Fri, 7 Jun 2013 10:52:32 -0400
+Subject: [PATCH] Use the standard margin for the timeout string
+
+So that it aligns with the other messages
+---
+ grub-core/normal/menu_text.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
+index beddd7f81c1..33b208bcf44 100644
+--- a/grub-core/normal/menu_text.c
++++ b/grub-core/normal/menu_text.c
+@@ -369,7 +369,7 @@ grub_menu_init_page (int nested, int edit,
+   if (bottom_message)
+     {
+       grub_term_gotoxy (term,
+-			(struct grub_term_coordinate) { GRUB_TERM_MARGIN,
++			(struct grub_term_coordinate) { STANDARD_MARGIN,
+ 			    geo->timeout_y });
+ 
+       print_message (nested, edit, term, 0);
+@@ -404,14 +404,14 @@ menu_text_print_timeout (int timeout, void *dataptr)
+   if (data->timeout_msg == TIMEOUT_UNKNOWN)
+     {
+       data->timeout_msg = grub_print_message_indented_real (msg_translated,
+-							    3, 1, data->term, 1)
++							    STANDARD_MARGIN, 1, data->term, 1)
+ 	<= data->geo.timeout_lines ? TIMEOUT_NORMAL : TIMEOUT_TERSE;
+       if (data->timeout_msg == TIMEOUT_TERSE)
+ 	{
+ 	  grub_free (msg_translated);
+ 	  msg_translated = grub_xasprintf (_("%ds"), timeout);
+ 	  if (grub_term_width (data->term) < 10)
+-	    data->timeout_msg = TIMEOUT_TERSE_NO_MARGIN;
++	    data->timeout_msg = STANDARD_MARGIN;
+ 	}
+     }
+ 
diff --git a/SOURCES/0121-Fix-grub_script_execute_sourcecode-usage-on-ppc.patch b/SOURCES/0121-Fix-grub_script_execute_sourcecode-usage-on-ppc.patch
new file mode 100644
index 0000000..d4d88d2
--- /dev/null
+++ b/SOURCES/0121-Fix-grub_script_execute_sourcecode-usage-on-ppc.patch
@@ -0,0 +1,26 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Fri, 10 Jan 2014 09:36:24 -0500
+Subject: [PATCH] Fix grub_script_execute_sourcecode() usage on ppc.
+
+593e430c made it not take the extra argc/argv that this code still
+passes it.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/normal/main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
+index 0da2a520d2d..f66c03c4c6e 100644
+--- a/grub-core/normal/main.c
++++ b/grub-core/normal/main.c
+@@ -289,7 +289,7 @@ grub_normal_execute (const char *config, int nested, int batch)
+       if (! grub_ieee1275_cas_reboot (script))
+         {
+           char *dummy[1] = { NULL };
+-          if (! grub_script_execute_sourcecode (script, 0, dummy))
++          if (! grub_script_execute_sourcecode (script))
+             boot = 1;
+         }
+       grub_free (script);
diff --git a/SOURCES/0122-Add-.eh_frame-to-list-of-relocations-stripped.patch b/SOURCES/0122-Add-.eh_frame-to-list-of-relocations-stripped.patch
new file mode 100644
index 0000000..68d6089
--- /dev/null
+++ b/SOURCES/0122-Add-.eh_frame-to-list-of-relocations-stripped.patch
@@ -0,0 +1,22 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Fedora Ninjas <grub2-owner@fedoraproject.org>
+Date: Mon, 13 Jan 2014 21:50:59 -0500
+Subject: [PATCH] Add .eh_frame to list of relocations stripped
+
+---
+ conf/Makefile.common | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/conf/Makefile.common b/conf/Makefile.common
+index e4c301fb6b6..6f836d82771 100644
+--- a/conf/Makefile.common
++++ b/conf/Makefile.common
+@@ -45,7 +45,7 @@ CFLAGS_KERNEL = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding
+ LDFLAGS_KERNEL = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) $(TARGET_LDFLAGS_STATIC_LIBGCC)
+ CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1
+ CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM)
+-STRIPFLAGS_KERNEL = -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version
++STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version
+ 
+ CFLAGS_MODULE = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding
+ LDFLAGS_MODULE = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d
diff --git a/SOURCES/0123-Make-10_linux-work-with-our-changes-for-linux16-and-.patch b/SOURCES/0123-Make-10_linux-work-with-our-changes-for-linux16-and-.patch
new file mode 100644
index 0000000..8b30f95
--- /dev/null
+++ b/SOURCES/0123-Make-10_linux-work-with-our-changes-for-linux16-and-.patch
@@ -0,0 +1,82 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 14 Jan 2014 13:12:23 -0500
+Subject: [PATCH] Make 10_linux work with our changes for linux16 and linuxefi
+ on aarch64
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ util/grub.d/10_linux.in | 31 ++++++++++++++++++++++++++++---
+ 1 file changed, 28 insertions(+), 3 deletions(-)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index c943a1e403e..2b8c561ff7b 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -75,8 +75,18 @@ linux_entry ()
+   args="$4"
+ 
+   sixteenbit=""
++  linuxefi="linux"
++  initrdefi="initrd"
+   case "$machine" in
+-    i?86|x86_64) sixteenbit="16" ;;
++    i?86|x86_64)
++	sixteenbit="16"
++	linuxefi="linuxefi"
++	initrdefi="initrdefi"
++	;;
++    aarch64)
++	linuxefi="linux"
++	initrdefi="initrd"
++	;;
+   esac
+ 
+   if [ -z "$boot_device_id" ]; then
+@@ -133,7 +143,7 @@ linux_entry ()
+   fi
+   if [ -d /sys/firmware/efi ]; then
+     sed "s/^/$submenu_indentation/" << EOF
+-	linuxefi ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
++	${linuxefi} ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
+ EOF
+   else
+     sed "s/^/$submenu_indentation/" << EOF
+@@ -143,7 +153,7 @@ EOF
+   if test -n "${initrd}" ; then
+     if [ -d /sys/firmware/efi ]; then
+       sed "s/^/$submenu_indentation/" << EOF
+-	initrdefi ${rel_dirname}/${initrd}
++	${initrdefi} ${rel_dirname}/${initrd}
+ EOF
+     else
+       sed "s/^/$submenu_indentation/" << EOF
+@@ -151,6 +161,13 @@ EOF
+ EOF
+     fi
+   fi
++  if test -n "${fdt}" ; then
++    message="$(gettext_printf "Loading fdt ...")"
++    sed "s/^/$submenu_indentation/" << EOF
++	echo	'$(echo "$message" | grub_quote)'
++	devicetree	${rel_dirname}/${fdt}
++EOF
++  fi
+   sed "s/^/$submenu_indentation/" << EOF
+ }
+ EOF
+@@ -211,6 +228,14 @@ while [ "x$list" != "x" ] ; do
+     fi
+   done
+ 
++  fdt=
++  for i in "dtb-${version}" "dtb-${alt_version}"; do
++    if test -e "${dirname}/${i}/foundation-v8.dtb" ; then
++      fdt="${i}/foundation-v8.dtb"
++      break
++    fi
++  done
++
+   config=
+   for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
+     if test -e "${i}" ; then
diff --git a/SOURCES/0124-Don-t-print-during-fdt-loading-method.patch b/SOURCES/0124-Don-t-print-during-fdt-loading-method.patch
new file mode 100644
index 0000000..d826d5e
--- /dev/null
+++ b/SOURCES/0124-Don-t-print-during-fdt-loading-method.patch
@@ -0,0 +1,24 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 14 Jan 2014 16:15:46 -0500
+Subject: [PATCH] Don't print during fdt loading method.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ util/grub.d/10_linux.in | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 2b8c561ff7b..acf2e0e2d37 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -162,9 +162,7 @@ EOF
+     fi
+   fi
+   if test -n "${fdt}" ; then
+-    message="$(gettext_printf "Loading fdt ...")"
+     sed "s/^/$submenu_indentation/" << EOF
+-	echo	'$(echo "$message" | grub_quote)'
+ 	devicetree	${rel_dirname}/${fdt}
+ EOF
+   fi
diff --git a/SOURCES/0125-Honor-a-symlink-when-generating-configuration-by-gru.patch b/SOURCES/0125-Honor-a-symlink-when-generating-configuration-by-gru.patch
new file mode 100644
index 0000000..36735ab
--- /dev/null
+++ b/SOURCES/0125-Honor-a-symlink-when-generating-configuration-by-gru.patch
@@ -0,0 +1,26 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Marcel Kolaja <mkolaja@redhat.com>
+Date: Tue, 21 Jan 2014 10:57:08 -0500
+Subject: [PATCH] Honor a symlink when generating configuration by
+ grub2-mkconfig
+
+Honor a symlink when generating configuration by grub2-mkconfig, so that
+the -o option follows it rather than overwriting it with a regular file.
+---
+ util/grub-mkconfig.in | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index ca040dd776c..b00f9e61f40 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -272,7 +272,8 @@ and /etc/grub.d/* files or please file a bug report with
+     echo >&2
+   else
+     # none of the children aborted with error, install the new grub.cfg
+-    mv -f ${grub_cfg}.new ${grub_cfg}
++    cat ${grub_cfg}.new > ${grub_cfg}
++    rm -f ${grub_cfg}.new
+   fi
+ fi
+ 
diff --git a/SOURCES/0126-Don-t-munge-raw-spaces-when-we-re-doing-our-cmdline-.patch b/SOURCES/0126-Don-t-munge-raw-spaces-when-we-re-doing-our-cmdline-.patch
new file mode 100644
index 0000000..33bdad2
--- /dev/null
+++ b/SOURCES/0126-Don-t-munge-raw-spaces-when-we-re-doing-our-cmdline-.patch
@@ -0,0 +1,33 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 30 Jun 2014 14:16:46 -0400
+Subject: [PATCH] Don't munge raw spaces when we're doing our cmdline escaping
+ (#923374)
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/lib/cmdline.c | 11 +----------
+ 1 file changed, 1 insertion(+), 10 deletions(-)
+
+diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c
+index 0a5b2afb94b..970ea868c14 100644
+--- a/grub-core/lib/cmdline.c
++++ b/grub-core/lib/cmdline.c
+@@ -97,16 +97,7 @@ int grub_create_loader_cmdline (int argc, char *argv[], char *buf,
+ 
+       while (*c)
+ 	{
+-	  if (*c == ' ')
+-	    {
+-	      *buf++ = '\\';
+-	      *buf++ = 'x';
+-	      *buf++ = '2';
+-	      *buf++ = '0';
+-	      c++;
+-	      continue;
+-	    }
+-	  else if (*c == '\\' && *(c+1) == 'x' &&
++	  if (*c == '\\' && *(c+1) == 'x' &&
+ 		   is_hex(*(c+2)) && is_hex(*(c+3)))
+ 	    {
+ 	      *buf++ = *c++;
diff --git a/SOURCES/0127-Don-t-require-a-password-to-boot-entries-generated-b.patch b/SOURCES/0127-Don-t-require-a-password-to-boot-entries-generated-b.patch
new file mode 100644
index 0000000..f907ad8
--- /dev/null
+++ b/SOURCES/0127-Don-t-require-a-password-to-boot-entries-generated-b.patch
@@ -0,0 +1,28 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 11 Feb 2014 11:14:50 -0500
+Subject: [PATCH] Don't require a password to boot entries generated by
+ grub-mkconfig.
+
+When we set a password, we just want that to mean you can't /edit/ an entry.
+
+Resolves: rhbz#1030176
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ util/grub.d/10_linux.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index acf2e0e2d37..136abd7a6e3 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -26,7 +26,7 @@ datarootdir="@datarootdir@"
+ export TEXTDOMAIN=@PACKAGE@
+ export TEXTDOMAINDIR="@localedir@"
+ 
+-CLASS="--class gnu-linux --class gnu --class os"
++CLASS="--class gnu-linux --class gnu --class os --unrestricted"
+ 
+ if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+   OS="$(sed 's, release .*$,,g' /etc/system-release)"
diff --git a/SOURCES/0128-Don-t-emit-Booting-.-message.patch b/SOURCES/0128-Don-t-emit-Booting-.-message.patch
new file mode 100644
index 0000000..a39e7b2
--- /dev/null
+++ b/SOURCES/0128-Don-t-emit-Booting-.-message.patch
@@ -0,0 +1,45 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 18 Feb 2014 09:37:49 -0500
+Subject: [PATCH] Don't emit "Booting ..." message.
+
+UI team still hates this stuff, so we're disabling it for RHEL 7.
+
+Resolves: rhbz#1023142
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/normal/menu.c       | 2 ++
+ grub-core/normal/menu_entry.c | 3 ---
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
+index b47991ababa..cc27c370776 100644
+--- a/grub-core/normal/menu.c
++++ b/grub-core/normal/menu.c
+@@ -810,9 +810,11 @@ static void
+ notify_booting (grub_menu_entry_t entry,
+ 		void *userdata __attribute__((unused)))
+ {
++#if 0
+   grub_printf ("  ");
+   grub_printf_ (N_("Booting `%s'"), entry->title);
+   grub_printf ("\n\n");
++#endif
+ }
+ 
+ /* Callback invoked when a default menu entry executed because of a timeout
+diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c
+index b485df82122..62e5db1fef8 100644
+--- a/grub-core/normal/menu_entry.c
++++ b/grub-core/normal/menu_entry.c
+@@ -1156,9 +1156,6 @@ run (struct screen *screen)
+   char *dummy[1] = { NULL };
+ 
+   grub_cls ();
+-  grub_printf ("  ");
+-  grub_printf_ (N_("Booting a command list"));
+-  grub_printf ("\n\n");
+ 
+   errs_before = grub_err_printed_errors;
+ 
diff --git a/SOURCES/0129-Make-CTRL-and-ALT-keys-work-as-expected-on-EFI-syste.patch b/SOURCES/0129-Make-CTRL-and-ALT-keys-work-as-expected-on-EFI-syste.patch
new file mode 100644
index 0000000..140c207
--- /dev/null
+++ b/SOURCES/0129-Make-CTRL-and-ALT-keys-work-as-expected-on-EFI-syste.patch
@@ -0,0 +1,301 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 3 Feb 2014 15:21:46 -0500
+Subject: [PATCH] Make CTRL and ALT keys work as expected on EFI systems
+ (version 5).
+
+This is version 4.
+
+Changes from version 1:
+- handles SHIFT as a modifier
+- handles F11 and F12 keys
+- uses the handle provided by the system table to find our _EX protocol.
+
+Changes from version 2:
+- eliminate duplicate keycode translation.
+
+Changes from version 3:
+- Do not add the shift modifier for any ascii character between space
+  (0x20) and DEL (0x7f); the combination of the modifier and many of the
+  keys causes it not to be recognized at all.  Specifically, if we
+  include the modifier on any querty punctuation character, i.e.
+  anything the string "~!@#$%^&*()_+{}|:\"<>?" represents in C, it stops
+  being recognized whatsoever.
+
+Changes from version 4:
+- Always initialize term->data from locate protocol (i.e. make it
+  unconditional.)
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/term/efi/console.c | 118 +++++++++++++++++++++++++++++++++++--------
+ include/grub/efi/api.h       |  65 +++++++++++++++++++++++-
+ 2 files changed, 161 insertions(+), 22 deletions(-)
+
+diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c
+index a37eb841c72..677eab5820f 100644
+--- a/grub-core/term/efi/console.c
++++ b/grub-core/term/efi/console.c
+@@ -104,26 +104,12 @@ const unsigned efi_codes[] =
+     GRUB_TERM_KEY_DC, GRUB_TERM_KEY_PPAGE, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_F1,
+     GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5,
+     GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9,
+-    GRUB_TERM_KEY_F10, 0, 0, '\e'
++    GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, '\e'
+   };
+ 
+-
+ static int
+-grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
++grub_efi_translate_key (grub_efi_input_key_t key)
+ {
+-  grub_efi_simple_input_interface_t *i;
+-  grub_efi_input_key_t key;
+-  grub_efi_status_t status;
+-
+-  if (grub_efi_is_finished)
+-    return 0;
+-
+-  i = grub_efi_system_table->con_in;
+-  status = efi_call_2 (i->read_key_stroke, i, &key);
+-
+-  if (status != GRUB_EFI_SUCCESS)
+-    return GRUB_TERM_NO_KEY;
+-
+   if (key.scan_code == 0)
+     {
+       /* Some firmware implementations use VT100-style codes against the spec.
+@@ -139,9 +125,98 @@ grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
+   else if (key.scan_code < ARRAY_SIZE (efi_codes))
+     return efi_codes[key.scan_code];
+ 
++  if (key.unicode_char >= 0x20 && key.unicode_char <= 0x7f)
++    return key.unicode_char;
++
+   return GRUB_TERM_NO_KEY;
+ }
+ 
++static int
++grub_console_getkey_con (struct grub_term_input *term __attribute__ ((unused)))
++{
++  grub_efi_simple_input_interface_t *i;
++  grub_efi_input_key_t key;
++  grub_efi_status_t status;
++
++  i = grub_efi_system_table->con_in;
++  status = efi_call_2 (i->read_key_stroke, i, &key);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return GRUB_TERM_NO_KEY;
++
++  return grub_efi_translate_key(key);
++}
++
++static int
++grub_console_getkey_ex(struct grub_term_input *term)
++{
++  grub_efi_key_data_t key_data;
++  grub_efi_status_t status;
++  grub_efi_uint32_t kss;
++  int key = -1;
++
++  grub_efi_simple_text_input_ex_interface_t *text_input = term->data;
++
++  status = efi_call_2 (text_input->read_key_stroke, text_input, &key_data);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return GRUB_TERM_NO_KEY;
++
++  kss = key_data.key_state.key_shift_state;
++  key = grub_efi_translate_key(key_data.key);
++
++  if (key == GRUB_TERM_NO_KEY)
++    return GRUB_TERM_NO_KEY;
++
++  if (kss & GRUB_EFI_SHIFT_STATE_VALID)
++    {
++      if ((kss & GRUB_EFI_LEFT_SHIFT_PRESSED
++	   || kss & GRUB_EFI_RIGHT_SHIFT_PRESSED)
++	  && !(key >= 0x20 && key <= 0x7f))
++	key |= GRUB_TERM_SHIFT;
++      if (kss & GRUB_EFI_LEFT_ALT_PRESSED || kss & GRUB_EFI_RIGHT_ALT_PRESSED)
++	key |= GRUB_TERM_ALT;
++      if (kss & GRUB_EFI_LEFT_CONTROL_PRESSED
++	  || kss & GRUB_EFI_RIGHT_CONTROL_PRESSED)
++	key |= GRUB_TERM_CTRL;
++    }
++
++  return key;
++}
++
++static grub_err_t
++grub_efi_console_input_init (struct grub_term_input *term)
++{
++  grub_efi_guid_t text_input_ex_guid =
++    GRUB_EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
++
++  if (grub_efi_is_finished)
++    return 0;
++
++  grub_efi_simple_text_input_ex_interface_t *text_input = term->data;
++  if (text_input)
++    return 0;
++
++  text_input = grub_efi_open_protocol(grub_efi_system_table->console_in_handler,
++				      &text_input_ex_guid,
++				      GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++  term->data = (void *)text_input;
++
++  return 0;
++}
++
++static int
++grub_console_getkey (struct grub_term_input *term)
++{
++  if (grub_efi_is_finished)
++    return 0;
++
++  if (term->data)
++    return grub_console_getkey_ex(term);
++  else
++    return grub_console_getkey_con(term);
++}
++
+ static struct grub_term_coordinate
+ grub_console_getwh (struct grub_term_output *term __attribute__ ((unused)))
+ {
+@@ -243,7 +318,7 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
+ }
+ 
+ static grub_err_t
+-grub_efi_console_init (struct grub_term_output *term)
++grub_efi_console_output_init (struct grub_term_output *term)
+ {
+   grub_efi_set_text_mode (1);
+   grub_console_setcursor (term, 1);
+@@ -251,7 +326,7 @@ grub_efi_console_init (struct grub_term_output *term)
+ }
+ 
+ static grub_err_t
+-grub_efi_console_fini (struct grub_term_output *term)
++grub_efi_console_output_fini (struct grub_term_output *term)
+ {
+   grub_console_setcursor (term, 0);
+   grub_efi_set_text_mode (0);
+@@ -262,13 +337,14 @@ static struct grub_term_input grub_console_term_input =
+   {
+     .name = "console",
+     .getkey = grub_console_getkey,
++    .init = grub_efi_console_input_init,
+   };
+ 
+ static struct grub_term_output grub_console_term_output =
+   {
+     .name = "console",
+-    .init = grub_efi_console_init,
+-    .fini = grub_efi_console_fini,
++    .init = grub_efi_console_output_init,
++    .fini = grub_efi_console_output_fini,
+     .putchar = grub_console_putchar,
+     .getwh = grub_console_getwh,
+     .getxy = grub_console_getxy,
+@@ -291,8 +367,8 @@ grub_console_init (void)
+       return;
+     }
+ 
+-  grub_term_register_input ("console", &grub_console_term_input);
+   grub_term_register_output ("console", &grub_console_term_output);
++  grub_term_register_input ("console", &grub_console_term_input);
+ }
+ 
+ void
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index e5dd543a801..142340372e1 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -111,7 +111,7 @@
+     { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+   }
+ 
+-#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
++#define GRUB_EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
+   { 0xdd9e7534, 0x7762, 0x4698, \
+     { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } \
+   }
+@@ -952,6 +952,32 @@ struct grub_efi_input_key
+ };
+ typedef struct grub_efi_input_key grub_efi_input_key_t;
+ 
++typedef grub_efi_uint8_t grub_efi_key_toggle_state_t;
++struct grub_efi_key_state
++{
++	grub_efi_uint32_t key_shift_state;
++	grub_efi_key_toggle_state_t key_toggle_state;
++};
++typedef struct grub_efi_key_state grub_efi_key_state_t;
++
++#define GRUB_EFI_SHIFT_STATE_VALID     0x80000000
++#define GRUB_EFI_RIGHT_SHIFT_PRESSED   0x00000001
++#define GRUB_EFI_LEFT_SHIFT_PRESSED    0x00000002
++#define GRUB_EFI_RIGHT_CONTROL_PRESSED 0x00000004
++#define GRUB_EFI_LEFT_CONTROL_PRESSED  0x00000008
++#define GRUB_EFI_RIGHT_ALT_PRESSED     0x00000010
++#define GRUB_EFI_LEFT_ALT_PRESSED      0x00000020
++#define GRUB_EFI_RIGHT_LOGO_PRESSED    0x00000040
++#define GRUB_EFI_LEFT_LOGO_PRESSED     0x00000080
++#define GRUB_EFI_MENU_KEY_PRESSED      0x00000100
++#define GRUB_EFI_SYS_REQ_PRESSED       0x00000200
++
++#define GRUB_EFI_TOGGLE_STATE_VALID 0x80
++#define GRUB_EFI_KEY_STATE_EXPOSED  0x40
++#define GRUB_EFI_SCROLL_LOCK_ACTIVE 0x01
++#define GRUB_EFI_NUM_LOCK_ACTIVE    0x02
++#define GRUB_EFI_CAPS_LOCK_ACTIVE   0x04
++
+ struct grub_efi_simple_text_output_mode
+ {
+   grub_efi_int32_t max_mode;
+@@ -1294,6 +1320,43 @@ struct grub_efi_simple_input_interface
+ };
+ typedef struct grub_efi_simple_input_interface grub_efi_simple_input_interface_t;
+ 
++struct grub_efi_key_data {
++	grub_efi_input_key_t key;
++	grub_efi_key_state_t key_state;
++};
++typedef struct grub_efi_key_data grub_efi_key_data_t;
++
++typedef grub_efi_status_t (*grub_efi_key_notify_function_t) (
++	grub_efi_key_data_t *key_data
++	);
++
++struct grub_efi_simple_text_input_ex_interface
++{
++	grub_efi_status_t
++	(*reset) (struct grub_efi_simple_text_input_ex_interface *this,
++		  grub_efi_boolean_t extended_verification);
++
++	grub_efi_status_t
++	(*read_key_stroke) (struct grub_efi_simple_text_input_ex_interface *this,
++			    grub_efi_key_data_t *key_data);
++
++	grub_efi_event_t wait_for_key;
++
++	grub_efi_status_t
++	(*set_state) (struct grub_efi_simple_text_input_ex_interface *this,
++		      grub_efi_key_toggle_state_t *key_toggle_state);
++
++	grub_efi_status_t
++	(*register_key_notify) (struct grub_efi_simple_text_input_ex_interface *this,
++				grub_efi_key_data_t *key_data,
++				grub_efi_key_notify_function_t key_notification_function);
++
++	grub_efi_status_t
++	(*unregister_key_notify) (struct grub_efi_simple_text_input_ex_interface *this,
++				  void *notification_handle);
++};
++typedef struct grub_efi_simple_text_input_ex_interface grub_efi_simple_text_input_ex_interface_t;
++
+ struct grub_efi_simple_text_output_interface
+ {
+   grub_efi_status_t
diff --git a/SOURCES/0130-May-as-well-try-it.patch b/SOURCES/0130-May-as-well-try-it.patch
new file mode 100644
index 0000000..73d2b16
--- /dev/null
+++ b/SOURCES/0130-May-as-well-try-it.patch
@@ -0,0 +1,1959 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 4 Mar 2014 11:00:23 -0500
+Subject: [PATCH] May as well try it.
+
+---
+ configure.ac                      |  23 ++++++
+ conf/Makefile.extra-dist          |   1 -
+ docs/Makefile.am                  |   2 -
+ docs/man/grub-bios-setup.h2m      |   6 --
+ docs/man/grub-editenv.h2m         |   5 --
+ docs/man/grub-emu.h2m             |   6 --
+ docs/man/grub-file.h2m            |   2 -
+ docs/man/grub-fstest.h2m          |   4 -
+ docs/man/grub-glue-efi.h2m        |   4 -
+ docs/man/grub-install.h2m         |   6 --
+ docs/man/grub-kbdcomp.h2m         |  10 ---
+ docs/man/grub-macbless.h2m        |   4 -
+ docs/man/grub-macho2img.h2m       |   4 -
+ docs/man/grub-menulst2cfg.h2m     |   4 -
+ docs/man/grub-mkconfig.h2m        |   4 -
+ docs/man/grub-mkfont.h2m          |   4 -
+ docs/man/grub-mkimage.h2m         |   6 --
+ docs/man/grub-mklayout.h2m        |  10 ---
+ docs/man/grub-mknetdir.h2m        |   4 -
+ docs/man/grub-mkpasswd-pbkdf2.h2m |   4 -
+ docs/man/grub-mkrelpath.h2m       |   4 -
+ docs/man/grub-mkrescue.h2m        |   4 -
+ docs/man/grub-mkstandalone.h2m    |   4 -
+ docs/man/grub-mount.h2m           |   2 -
+ docs/man/grub-ofpathname.h2m      |   4 -
+ docs/man/grub-pe2elf.h2m          |   4 -
+ docs/man/grub-probe.h2m           |   4 -
+ docs/man/grub-reboot.h2m          |   5 --
+ docs/man/grub-render-label.h2m    |   3 -
+ docs/man/grub-script-check.h2m    |   4 -
+ docs/man/grub-set-default.h2m     |   5 --
+ docs/man/grub-sparc64-setup.h2m   |   6 --
+ docs/man/grub-syslinux2cfg.h2m    |   4 -
+ gentpl.py                         |   5 +-
+ util/grub-bios-setup.8            |  54 +++++++++++++
+ util/grub-editenv.1               |  46 +++++++++++
+ util/grub-file.1                  | 165 ++++++++++++++++++++++++++++++++++++++
+ util/grub-fstest.1                |  99 +++++++++++++++++++++++
+ util/grub-glue-efi.1              |  31 +++++++
+ util/grub-install.8               | 129 +++++++++++++++++++++++++++++
+ util/grub-kbdcomp.1               |  19 +++++
+ util/grub-macbless.1              |  22 +++++
+ util/grub-menulst2cfg.1           |  12 +++
+ util/grub-mkconfig.8              |  17 ++++
+ util/grub-mkfont.1                |  87 ++++++++++++++++++++
+ util/grub-mkimage.1               |  95 ++++++++++++++++++++++
+ util/grub-mklayout.1              |  27 +++++++
+ util/grub-mknetdir.1              |  12 +++
+ util/grub-mkpasswd-pbkdf2.1       |  27 +++++++
+ util/grub-mkrelpath.1             |  12 +++
+ util/grub-mkrescue.1              | 123 ++++++++++++++++++++++++++++
+ util/grub-mkstandalone.1          | 100 +++++++++++++++++++++++
+ util/grub-ofpathname.8            |  12 +++
+ util/grub-probe.8                 |  80 ++++++++++++++++++
+ util/grub-reboot.8                |  21 +++++
+ util/grub-render-label.1          |  51 ++++++++++++
+ util/grub-script-check.1          |  21 +++++
+ util/grub-set-default.8           |  21 +++++
+ util/grub-sparc64-setup.8         |  12 +++
+ 59 files changed, 1319 insertions(+), 147 deletions(-)
+ delete mode 100644 docs/man/grub-bios-setup.h2m
+ delete mode 100644 docs/man/grub-editenv.h2m
+ delete mode 100644 docs/man/grub-emu.h2m
+ delete mode 100644 docs/man/grub-file.h2m
+ delete mode 100644 docs/man/grub-fstest.h2m
+ delete mode 100644 docs/man/grub-glue-efi.h2m
+ delete mode 100644 docs/man/grub-install.h2m
+ delete mode 100644 docs/man/grub-kbdcomp.h2m
+ delete mode 100644 docs/man/grub-macbless.h2m
+ delete mode 100644 docs/man/grub-macho2img.h2m
+ delete mode 100644 docs/man/grub-menulst2cfg.h2m
+ delete mode 100644 docs/man/grub-mkconfig.h2m
+ delete mode 100644 docs/man/grub-mkfont.h2m
+ delete mode 100644 docs/man/grub-mkimage.h2m
+ delete mode 100644 docs/man/grub-mklayout.h2m
+ delete mode 100644 docs/man/grub-mknetdir.h2m
+ delete mode 100644 docs/man/grub-mkpasswd-pbkdf2.h2m
+ delete mode 100644 docs/man/grub-mkrelpath.h2m
+ delete mode 100644 docs/man/grub-mkrescue.h2m
+ delete mode 100644 docs/man/grub-mkstandalone.h2m
+ delete mode 100644 docs/man/grub-mount.h2m
+ delete mode 100644 docs/man/grub-ofpathname.h2m
+ delete mode 100644 docs/man/grub-pe2elf.h2m
+ delete mode 100644 docs/man/grub-probe.h2m
+ delete mode 100644 docs/man/grub-reboot.h2m
+ delete mode 100644 docs/man/grub-render-label.h2m
+ delete mode 100644 docs/man/grub-script-check.h2m
+ delete mode 100644 docs/man/grub-set-default.h2m
+ delete mode 100644 docs/man/grub-sparc64-setup.h2m
+ delete mode 100644 docs/man/grub-syslinux2cfg.h2m
+ create mode 100644 util/grub-bios-setup.8
+ create mode 100644 util/grub-editenv.1
+ create mode 100644 util/grub-file.1
+ create mode 100644 util/grub-fstest.1
+ create mode 100644 util/grub-glue-efi.1
+ create mode 100644 util/grub-install.8
+ create mode 100644 util/grub-kbdcomp.1
+ create mode 100644 util/grub-macbless.1
+ create mode 100644 util/grub-menulst2cfg.1
+ create mode 100644 util/grub-mkconfig.8
+ create mode 100644 util/grub-mkfont.1
+ create mode 100644 util/grub-mkimage.1
+ create mode 100644 util/grub-mklayout.1
+ create mode 100644 util/grub-mknetdir.1
+ create mode 100644 util/grub-mkpasswd-pbkdf2.1
+ create mode 100644 util/grub-mkrelpath.1
+ create mode 100644 util/grub-mkrescue.1
+ create mode 100644 util/grub-mkstandalone.1
+ create mode 100644 util/grub-ofpathname.8
+ create mode 100644 util/grub-probe.8
+ create mode 100644 util/grub-reboot.8
+ create mode 100644 util/grub-render-label.1
+ create mode 100644 util/grub-script-check.1
+ create mode 100644 util/grub-set-default.8
+ create mode 100644 util/grub-sparc64-setup.8
+
+diff --git a/configure.ac b/configure.ac
+index 8888c2ff29c..2632e2dad9b 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -70,6 +70,29 @@ grub_TRANSFORM([grub-set-default])
+ grub_TRANSFORM([grub-sparc64-setup])
+ grub_TRANSFORM([grub-render-label])
+ grub_TRANSFORM([grub-file])
++grub_TRANSFORM([grub-bios-setup.3])
++grub_TRANSFORM([grub-editenv.1])
++grub_TRANSFORM([grub-fstest.3])
++grub_TRANSFORM([grub-glue-efi.3])
++grub_TRANSFORM([grub-install.1])
++grub_TRANSFORM([grub-kbdcomp.3])
++grub_TRANSFORM([grub-menulst2cfg.1])
++grub_TRANSFORM([grub-mkconfig.1])
++grub_TRANSFORM([grub-mkfont.3])
++grub_TRANSFORM([grub-mkimage.1])
++grub_TRANSFORM([grub-mklayout.3])
++grub_TRANSFORM([grub-mknetdir.3])
++grub_TRANSFORM([grub-mkpasswd-pbkdf2.3])
++grub_TRANSFORM([grub-mkrelpath.3])
++grub_TRANSFORM([grub-mkrescue.1])
++grub_TRANSFORM([grub-mkstandalone.3])
++grub_TRANSFORM([grub-ofpathname.3])
++grub_TRANSFORM([grub-probe.3])
++grub_TRANSFORM([grub-reboot.3])
++grub_TRANSFORM([grub-render-label.3])
++grub_TRANSFORM([grub-script-check.3])
++grub_TRANSFORM([grub-set-default.1])
++grub_TRANSFORM([grub-sparc64-setup.3])
+ 
+ # Optimization flag.  Allow user to override.
+ if test "x$TARGET_CFLAGS" = x; then
+diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist
+index 51f08c1f901..e914dfd897e 100644
+--- a/conf/Makefile.extra-dist
++++ b/conf/Makefile.extra-dist
+@@ -10,7 +10,6 @@ EXTRA_DIST += unicode
+ EXTRA_DIST += util/import_gcry.py
+ EXTRA_DIST += util/import_unicode.py
+ 
+-EXTRA_DIST += docs/man
+ EXTRA_DIST += docs/autoiso.cfg
+ EXTRA_DIST += docs/grub.cfg
+ EXTRA_DIST += docs/osdetect.cfg
+diff --git a/docs/Makefile.am b/docs/Makefile.am
+index 93eb3962765..ab28f199694 100644
+--- a/docs/Makefile.am
++++ b/docs/Makefile.am
+@@ -5,5 +5,3 @@ info_TEXINFOS = grub.texi grub-dev.texi
+ grub_TEXINFOS = fdl.texi
+ 
+ EXTRA_DIST = font_char_metrics.png font_char_metrics.txt
+-
+-
+diff --git a/docs/man/grub-bios-setup.h2m b/docs/man/grub-bios-setup.h2m
+deleted file mode 100644
+index ac6ede36296..00000000000
+--- a/docs/man/grub-bios-setup.h2m
++++ /dev/null
+@@ -1,6 +0,0 @@
+-[NAME]
+-grub-bios-setup \- set up a device to boot using GRUB
+-[SEE ALSO]
+-.BR grub-install (8),
+-.BR grub-mkimage (1),
+-.BR grub-mkrescue (1)
+diff --git a/docs/man/grub-editenv.h2m b/docs/man/grub-editenv.h2m
+deleted file mode 100644
+index 3859d3d4c4f..00000000000
+--- a/docs/man/grub-editenv.h2m
++++ /dev/null
+@@ -1,5 +0,0 @@
+-[NAME]
+-grub-editenv \- edit GRUB environment block
+-[SEE ALSO]
+-.BR grub-reboot (8),
+-.BR grub-set-default (8)
+diff --git a/docs/man/grub-emu.h2m b/docs/man/grub-emu.h2m
+deleted file mode 100644
+index ef1c000656a..00000000000
+--- a/docs/man/grub-emu.h2m
++++ /dev/null
+@@ -1,6 +0,0 @@
+-[NAME]
+-grub-emu \- GRUB emulator
+-[SEE ALSO]
+-If you are trying to install GRUB, then you should use
+-.BR grub-install (8)
+-rather than this program.
+diff --git a/docs/man/grub-file.h2m b/docs/man/grub-file.h2m
+deleted file mode 100644
+index e09bb4d3101..00000000000
+--- a/docs/man/grub-file.h2m
++++ /dev/null
+@@ -1,2 +0,0 @@
+-[NAME]
+-grub-file \- check file type
+diff --git a/docs/man/grub-fstest.h2m b/docs/man/grub-fstest.h2m
+deleted file mode 100644
+index 9676b159afd..00000000000
+--- a/docs/man/grub-fstest.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-fstest \- debug tool for GRUB filesystem drivers
+-[SEE ALSO]
+-.BR grub-probe (8)
+diff --git a/docs/man/grub-glue-efi.h2m b/docs/man/grub-glue-efi.h2m
+deleted file mode 100644
+index c1c6ded49ff..00000000000
+--- a/docs/man/grub-glue-efi.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-glue-efi \- generate a fat binary for EFI
+-[DESCRIPTION]
+-grub-glue-efi processes ia32 and amd64 EFI images and glues them according to Apple format.
+diff --git a/docs/man/grub-install.h2m b/docs/man/grub-install.h2m
+deleted file mode 100644
+index 8cbbc87a0f2..00000000000
+--- a/docs/man/grub-install.h2m
++++ /dev/null
+@@ -1,6 +0,0 @@
+-[NAME]
+-grub-install \- install GRUB to a device
+-[SEE ALSO]
+-.BR grub-mkconfig (8),
+-.BR grub-mkimage (1),
+-.BR grub-mkrescue (1)
+diff --git a/docs/man/grub-kbdcomp.h2m b/docs/man/grub-kbdcomp.h2m
+deleted file mode 100644
+index d81f9157e01..00000000000
+--- a/docs/man/grub-kbdcomp.h2m
++++ /dev/null
+@@ -1,10 +0,0 @@
+-[NAME]
+-grub-kbdcomp \- generate a GRUB keyboard layout file
+-[DESCRIPTION]
+-grub-kbdcomp processes a X keyboard layout description in
+-.BR keymaps (5)
+-format into a format that can be used by GRUB's
+-.B keymap
+-command.
+-[SEE ALSO]
+-.BR grub-mklayout (8)
+diff --git a/docs/man/grub-macbless.h2m b/docs/man/grub-macbless.h2m
+deleted file mode 100644
+index 0197c0087d7..00000000000
+--- a/docs/man/grub-macbless.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-macbless \- bless a mac file/directory
+-[SEE ALSO]
+-.BR grub-install (1)
+diff --git a/docs/man/grub-macho2img.h2m b/docs/man/grub-macho2img.h2m
+deleted file mode 100644
+index d79aaeed8f9..00000000000
+--- a/docs/man/grub-macho2img.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-macho2img \- convert Mach-O to raw image
+-[SEE ALSO]
+-.BR grub-mkimage (1)
+diff --git a/docs/man/grub-menulst2cfg.h2m b/docs/man/grub-menulst2cfg.h2m
+deleted file mode 100644
+index c2e0055ed7e..00000000000
+--- a/docs/man/grub-menulst2cfg.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-menulst2cfg \- transform legacy menu.lst into grub.cfg
+-[SEE ALSO]
+-.BR grub-mkconfig (8)
+diff --git a/docs/man/grub-mkconfig.h2m b/docs/man/grub-mkconfig.h2m
+deleted file mode 100644
+index 9b42f813010..00000000000
+--- a/docs/man/grub-mkconfig.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-mkconfig \- generate a GRUB configuration file
+-[SEE ALSO]
+-.BR grub-install (8)
+diff --git a/docs/man/grub-mkfont.h2m b/docs/man/grub-mkfont.h2m
+deleted file mode 100644
+index d46fe600eca..00000000000
+--- a/docs/man/grub-mkfont.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-mkfont \- make GRUB font files
+-[SEE ALSO]
+-.BR grub-mkconfig (8)
+diff --git a/docs/man/grub-mkimage.h2m b/docs/man/grub-mkimage.h2m
+deleted file mode 100644
+index f0fbc2bb197..00000000000
+--- a/docs/man/grub-mkimage.h2m
++++ /dev/null
+@@ -1,6 +0,0 @@
+-[NAME]
+-grub-mkimage \- make a bootable image of GRUB
+-[SEE ALSO]
+-.BR grub-install (8),
+-.BR grub-mkrescue (1),
+-.BR grub-mknetdir (8)
+diff --git a/docs/man/grub-mklayout.h2m b/docs/man/grub-mklayout.h2m
+deleted file mode 100644
+index 1e43409c0ab..00000000000
+--- a/docs/man/grub-mklayout.h2m
++++ /dev/null
+@@ -1,10 +0,0 @@
+-[NAME]
+-grub-mklayout \- generate a GRUB keyboard layout file
+-[DESCRIPTION]
+-grub-mklayout processes a keyboard layout description in
+-.BR keymaps (5)
+-format into a format that can be used by GRUB's
+-.B keymap
+-command.
+-[SEE ALSO]
+-.BR grub-mkconfig (8)
+diff --git a/docs/man/grub-mknetdir.h2m b/docs/man/grub-mknetdir.h2m
+deleted file mode 100644
+index a2ef13ec111..00000000000
+--- a/docs/man/grub-mknetdir.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-mknetdir \- prepare a GRUB netboot directory.
+-[SEE ALSO]
+-.BR grub-mkimage (1)
+diff --git a/docs/man/grub-mkpasswd-pbkdf2.h2m b/docs/man/grub-mkpasswd-pbkdf2.h2m
+deleted file mode 100644
+index 4d202f3da7e..00000000000
+--- a/docs/man/grub-mkpasswd-pbkdf2.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-mkpasswd-pbkdf2 \- generate hashed password for GRUB
+-[SEE ALSO]
+-.BR grub-mkconfig (8)
+diff --git a/docs/man/grub-mkrelpath.h2m b/docs/man/grub-mkrelpath.h2m
+deleted file mode 100644
+index d01f3961e3f..00000000000
+--- a/docs/man/grub-mkrelpath.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-mkrelpath \- make a system path relative to its root
+-[SEE ALSO]
+-.BR grub-probe (8)
+diff --git a/docs/man/grub-mkrescue.h2m b/docs/man/grub-mkrescue.h2m
+deleted file mode 100644
+index a427f02e3c6..00000000000
+--- a/docs/man/grub-mkrescue.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-mkrescue \- make a GRUB rescue image
+-[SEE ALSO]
+-.BR grub-mkimage (1)
+diff --git a/docs/man/grub-mkstandalone.h2m b/docs/man/grub-mkstandalone.h2m
+deleted file mode 100644
+index c77313978ad..00000000000
+--- a/docs/man/grub-mkstandalone.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-mkstandalone \- make a memdisk-based GRUB image
+-[SEE ALSO]
+-.BR grub-mkimage (1)
+diff --git a/docs/man/grub-mount.h2m b/docs/man/grub-mount.h2m
+deleted file mode 100644
+index 8d168982d72..00000000000
+--- a/docs/man/grub-mount.h2m
++++ /dev/null
+@@ -1,2 +0,0 @@
+-[NAME]
+-grub-mount \- export GRUB filesystem with FUSE
+diff --git a/docs/man/grub-ofpathname.h2m b/docs/man/grub-ofpathname.h2m
+deleted file mode 100644
+index 74b43eea039..00000000000
+--- a/docs/man/grub-ofpathname.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-ofpathname \- find OpenBOOT path for a device
+-[SEE ALSO]
+-.BR grub-probe (8)
+diff --git a/docs/man/grub-pe2elf.h2m b/docs/man/grub-pe2elf.h2m
+deleted file mode 100644
+index 7ca29bd703c..00000000000
+--- a/docs/man/grub-pe2elf.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-pe2elf \- convert PE image to ELF
+-[SEE ALSO]
+-.BR grub-mkimage (1)
+diff --git a/docs/man/grub-probe.h2m b/docs/man/grub-probe.h2m
+deleted file mode 100644
+index 6e1ffdcf937..00000000000
+--- a/docs/man/grub-probe.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-probe \- probe device information for GRUB
+-[SEE ALSO]
+-.BR grub-fstest (1)
+diff --git a/docs/man/grub-reboot.h2m b/docs/man/grub-reboot.h2m
+deleted file mode 100644
+index e4acace65ce..00000000000
+--- a/docs/man/grub-reboot.h2m
++++ /dev/null
+@@ -1,5 +0,0 @@
+-[NAME]
+-grub-reboot \- set the default boot entry for GRUB, for the next boot only
+-[SEE ALSO]
+-.BR grub-set-default (8),
+-.BR grub-editenv (1)
+diff --git a/docs/man/grub-render-label.h2m b/docs/man/grub-render-label.h2m
+deleted file mode 100644
+index 50ae5247c05..00000000000
+--- a/docs/man/grub-render-label.h2m
++++ /dev/null
+@@ -1,3 +0,0 @@
+-[NAME]
+-grub-render-label \- generate a .disk_label for Apple Macs.
+-
+diff --git a/docs/man/grub-script-check.h2m b/docs/man/grub-script-check.h2m
+deleted file mode 100644
+index 3653682671a..00000000000
+--- a/docs/man/grub-script-check.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-script-check \- check grub.cfg for syntax errors
+-[SEE ALSO]
+-.BR grub-mkconfig (8)
+diff --git a/docs/man/grub-set-default.h2m b/docs/man/grub-set-default.h2m
+deleted file mode 100644
+index 7945001c154..00000000000
+--- a/docs/man/grub-set-default.h2m
++++ /dev/null
+@@ -1,5 +0,0 @@
+-[NAME]
+-grub-set-default \- set the saved default boot entry for GRUB
+-[SEE ALSO]
+-.BR grub-reboot (8),
+-.BR grub-editenv (1)
+diff --git a/docs/man/grub-sparc64-setup.h2m b/docs/man/grub-sparc64-setup.h2m
+deleted file mode 100644
+index 18f803a50db..00000000000
+--- a/docs/man/grub-sparc64-setup.h2m
++++ /dev/null
+@@ -1,6 +0,0 @@
+-[NAME]
+-grub-sparc64-setup \- set up a device to boot using GRUB
+-[SEE ALSO]
+-.BR grub-install (8),
+-.BR grub-mkimage (1),
+-.BR grub-mkrescue (1)
+diff --git a/docs/man/grub-syslinux2cfg.h2m b/docs/man/grub-syslinux2cfg.h2m
+deleted file mode 100644
+index ad25c8ab753..00000000000
+--- a/docs/man/grub-syslinux2cfg.h2m
++++ /dev/null
+@@ -1,4 +0,0 @@
+-[NAME]
+-grub-syslinux2cfg \- transform syslinux config into grub.cfg
+-[SEE ALSO]
+-.BR grub-menulst2cfg (8)
+diff --git a/gentpl.py b/gentpl.py
+index bdcae1a1c1b..889cc91d39c 100644
+--- a/gentpl.py
++++ b/gentpl.py
+@@ -792,10 +792,7 @@ def manpage(defn, adddeps):
+ 
+     output("if COND_MAN_PAGES\n")
+     gvar_add("man_MANS", name + "." + mansection)
+-    rule(name + "." + mansection, name + " " + adddeps, """
+-chmod a+x """ + name + """
+-PATH=$(builddir):$$PATH pkgdatadir=$(builddir) $(HELP2MAN) --section=""" + mansection + """ -i $(top_srcdir)/docs/man/""" + name + """.h2m -o $@ """ + name + """
+-""")
++    rule(name + "." + mansection, name + " " + adddeps, "cat $(top_srcdir)/util/" + name + "." + mansection + " | $(top_builddir)/config.status --file=$@:-")
+     gvar_add("CLEANFILES", name + "." + mansection)
+     output("endif\n")
+ 
+diff --git a/util/grub-bios-setup.8 b/util/grub-bios-setup.8
+new file mode 100644
+index 00000000000..56f582b3d75
+--- /dev/null
++++ b/util/grub-bios-setup.8
+@@ -0,0 +1,54 @@
++.TH GRUB-BIOS-SETUP 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-bios-setup\fR \(em Set up images to boot from a device.
++
++.SH SYNOPSIS
++\fBgrub-bios-setup\fR [-a | --allow-floppy] [-b | --boot-image=\fIFILE\fR]
++.RS 17
++[-c | --core-image=\fIFILE\fR] [-d | --directory=\fIDIR\fR]
++.RE
++.RS 17
++[-f | --force] [-m | --device-map=\fIFILE\fR]
++.RE
++.RS 17
++[-s | --skip-fs-probe] [-v | --verbose] \fIDEVICE\fR
++
++.SH DESCRIPTION
++You should not normally run this program directly.  Use grub-install instead.
++
++.SH OPTIONS
++.TP
++\fB--allow-floppy\fR
++Make the device also bootable as a floppy.  This option is the default for
++/dev/fdX devices.  Some BIOSes will not boot images created with this option.
++
++.TP
++\fB--boot-image\fR=\fIFILE\fR
++Use FILE as the boot image.  The default value is \fBboot.img\fR.
++
++.TP
++\fB--core-image\fR=\fIFILE\fR
++Use FILE as ther core image.  The default value is \fBcore.img\fR.
++
++.TP
++\fB--directory\fR=\fIDIR\fR
++Use GRUB files in the directory DIR.  The default value is \fB/boot/grub\fR.
++
++.TP
++\fB--force\fR
++Install even if problems are detected.
++
++.TP
++\fB--device-map\fR=\fIFILE\fR
++Use FILE as the device map.  The default value is /boot/grub/device.map .
++
++.TP
++\fB--skip-fs-probe\fR
++Do not probe DEVICE for filesystems.
++
++.TP
++\fB--verbose\fR
++Print verbose messages.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-editenv.1 b/util/grub-editenv.1
+new file mode 100644
+index 00000000000..8dad33f8db6
+--- /dev/null
++++ b/util/grub-editenv.1
+@@ -0,0 +1,46 @@
++.TH GRUB-EDITENV 1 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-editenv\fR \(em Manage the GRUB environment block.
++
++.SH SYNOPSIS
++\fBgrub-editenv\fR [-v | --verbose] [\fIFILE\fR]
++.RS 14
++<create | list | set \fINAME\fR=\fIVALUE\fR | unset \fINAME\fR>
++
++.SH DESCRIPTION
++\fBgrub-editenv\fR is a command line tool to manage GRUB's stored environment.
++
++.SH OPTIONS
++.TP
++\fB--verbose\fR 
++Print verbose messages.
++
++.TP
++\fBFILE\fR
++.RS 7
++File name to use for grub environment.  Default is /boot/grub/grubenv .
++.RE
++
++.SH COMMANDS
++.TP
++\fBcreate\fR
++.RS 7
++Create a blank environment block file.
++.RE
++
++.TP
++\fBlist\fR
++.RS 7
++List the current variables.
++.RE
++
++.TP
++\fBset\fR [\fINAME\fR=\fIVALUE\fR ...]
++Set variables.
++
++.TP
++\fBunset [\fINAME\fR ...]
++Delete variables.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-file.1 b/util/grub-file.1
+new file mode 100644
+index 00000000000..b29cb327889
+--- /dev/null
++++ b/util/grub-file.1
+@@ -0,0 +1,165 @@
++.TH GRUB-FILE 1 "Web Feb 26 2014"
++.SH NAME
++\fBgrub-file\fR \(em Check if FILE is of specified type.
++
++.SH SYNOPSIS
++\fBgrub-file\fR (--is-i386-xen-pae-domu | --is-x86_64-xen-domu |
++.RS 11
++--is-x86-xen-dom0 | --is-x86-multiboot |
++.RE
++.RS 11
++--is-x86-multiboot2 | --is-arm-linux | --is-arm64-linux |
++.RE
++.RS 11
++--is-ia64-linux | --is-mips-linux | --is-mipsel-linux |
++.RE
++.RS 11
++--is-sparc64-linux | --is-powerpc-linux | --is-x86-linux |
++.RE
++.RS 11
++--is-x86-linux32 | --is-x86-kfreebsd | --is-i386-kfreebsd |
++.RE
++.RS 11
++--is-x86_64-kfreebsd | --is-x86-knetbsd |
++.RE
++.RS 11
++--is-i386-knetbsd | --is-x86_64-knetbsd | --is-i386-efi |
++.RE
++.RS 11
++--is-x86_64-efi | --is-ia64-efi | --is-arm64-efi |
++.RE
++.RS 11
++--is-arm-efi | --is-hibernated-hiberfil | --is-x86_64-xnu |
++.RE
++.RS 11
++--is-i386-xnu | --is-xnu-hibr | --is-x86-bios-bootsector)
++.RE
++.RS 11
++\fIFILE\fR
++
++.SH DESCRIPTION
++\fBgrub-file\fR is used to check if \fIFILE\fR is of a specified type.
++
++.SH OPTIONS
++.TP
++--is-i386-xen-pae-domu
++Check if FILE can be booted as i386 PAE Xen unprivileged guest kernel
++
++.TP
++--is-x86_64-xen-domu
++Check if FILE can be booted as x86_64 Xen unprivileged guest kernel
++
++.TP
++--is-x86-xen-dom0
++Check if FILE can be used as Xen x86 privileged guest kernel
++
++.TP
++--is-x86-multiboot
++Check if FILE can be used as x86 multiboot kernel
++
++.TP
++--is-x86-multiboot2
++Check if FILE can be used as x86 multiboot2 kernel
++
++.TP
++--is-arm-linux
++Check if FILE is ARM Linux
++
++.TP
++--is-arm64-linux
++Check if FILE is ARM64 Linux
++
++.TP
++--is-ia64-linux
++Check if FILE is IA64 Linux
++
++.TP
++--is-mips-linux
++Check if FILE is MIPS Linux
++
++.TP
++--is-mipsel-linux
++Check if FILE is MIPSEL Linux
++
++.TP
++--is-sparc64-linux
++Check if FILE is SPARC64 Linux
++
++.TP
++--is-powerpc-linux
++Check if FILE is POWERPC Linux
++
++.TP
++--is-x86-linux
++Check if FILE is x86 Linux
++
++.TP
++--is-x86-linux32
++Check if FILE is x86 Linux supporting 32-bit protocol
++
++.TP
++--is-x86-kfreebsd
++Check if FILE is x86 kFreeBSD
++
++.TP
++--is-i386-kfreebsd
++Check if FILE is i386 kFreeBSD
++
++.TP
++--is-x86_64-kfreebsd
++Check if FILE is x86_64 kFreeBSD
++
++.TP
++--is-x86-knetbsd
++Check if FILE is x86 kNetBSD
++
++.TP
++--is-i386-knetbsd
++Check if FILE is i386 kNetBSD
++
++.TP
++--is-x86_64-knetbsd
++Check if FILE is x86_64 kNetBSD
++
++.TP
++--is-i386-efi
++Check if FILE is i386 EFI file
++
++.TP
++--is-x86_64-efi
++Check if FILE is x86_64 EFI file
++
++.TP
++--is-ia64-efi
++Check if FILE is IA64 EFI file
++
++.TP
++--is-arm64-efi
++Check if FILE is ARM64 EFI file
++
++.TP
++--is-arm-efi
++Check if FILE is ARM EFI file
++
++.TP
++--is-hibernated-hiberfil
++Check if FILE is hiberfil.sys in hibernated state
++
++.TP
++--is-x86_64-xnu
++Check if FILE is x86_64 XNU (Mac OS X kernel)
++
++.TP
++--is-i386-xnu
++Check if FILE is i386 XNU (Mac OS X kernel)
++
++.TP
++--is-xnu-hibr
++Check if FILE is XNU (Mac OS X kernel) hibernated image
++
++.TP
++--is-x86-bios-bootsector
++Check if FILE is BIOS bootsector
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-fstest.1 b/util/grub-fstest.1
+new file mode 100644
+index 00000000000..792fa78634c
+--- /dev/null
++++ b/util/grub-fstest.1
+@@ -0,0 +1,99 @@
++.TH GRUB-FSTEST 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-fstest\fR — Debug tool for GRUB's filesystem driver.
++
++.SH SYNOPSIS
++\fBgrub-fstest\fR [-c | --diskcount=\fINUM\fR] [-C | --crypto]
++.RS 13
++[-d | --debug=\fISTRING\fR] [-K | --zfs-key=\fIFILE\fR|\fIprompt\fR]
++.RE
++.RS 13
++[-n | --length=\fINUM\fR] [-r | --root=\fIDEVICE_NAME\fR]
++.RE
++.RS 13
++[-s | --skip=\fINUM\fR] [-u | --uncompress] [-v | --verbose]
++.RE
++.RS 13
++\fIIMAGE_PATH\fR <blocklist \fIFILE\fR | cat \fIFILE\fR |
++.RE
++.RS 13
++cmp \fIFILE\fR \fILOCAL\fR | cp \fIFILE\fR \fILOCAL\fR | crc \fIFILE\fR |
++.RE
++.RS 13
++hex \fIFILE\fR | ls \fIPATH\fR | xnu_uuid \fIDEVICE\fR>
++
++.SH DESCRIPTION
++\fBgrub-fstest\fR is a tool for testing GRUB's filesystem drivers.  You should not normally need to run this program.
++
++.SH OPTIONS
++.TP
++\fB--diskcount\fR=\fINUM\fR
++Specify the number of input files.
++
++.TP
++\fB--crypto\fR
++Mount cryptographic devices.
++
++.TP
++\fB--debug\fR=\fISTRING\fR
++Set debug environment variable.
++
++.TP
++\fB--zfs-key\fR=\fIFILE\fR|\fIprompt\fR
++Load ZFS cryptographic key.
++
++.TP
++\fB--length\fR=\fINUM\fR
++Handle NUM bytes in output file.
++
++.TP
++\fB--root\fR=\fIDEVICE_NAME\fR
++Set root device.
++
++.TP
++\fB--skip\fR=\fINUM\fR
++Skip NUM bytes from output file.
++
++.TP
++\fB--uncompress\fR
++Uncompress data.
++
++.TP
++\fB--verbose\fR
++Print verbose messages.
++
++.SH COMMANDS
++.TP
++\fBblocklist\fR \fIFILE\fR
++Display block list of \fIFILE\fR.
++
++.TP
++\fBcat\fR \fIFILE\fR
++Display \fIFILE\fR on standard output.
++
++.TP
++\fBcmp\fR \fIFILE\fR \fILOCAL\fR
++Compare \fIFILE\fR with local file \fILOCAL\fR.
++
++.TP
++\fBcp\fR \fIFILE\fR \fILOCAL\fR
++Copy \fIFILE\fR to local file \fILOCAL\fR.
++
++.TP
++\fBcrc\fR \fIFILE\fR
++Display the CRC-32 checksum of \fIFILE\fR.
++
++.TP
++\fBhex\fR \fIFILE\fR
++Display contents of \fIFILE\fR in hexidecimal.
++
++.TP
++\fBls\fR \fIPATH\fR
++List files at \fIPATH\fR.
++
++.TP
++\fBxnu_uuid\fR \fIDEVICE\fR
++Display the XNU UUID of \fIDEVICE\fR.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-glue-efi.1 b/util/grub-glue-efi.1
+new file mode 100644
+index 00000000000..72bd555d577
+--- /dev/null
++++ b/util/grub-glue-efi.1
+@@ -0,0 +1,31 @@
++.TH GRUB-GLUE-EFI 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-glue-efi\fR \(em Create an Apple fat EFI binary.
++
++.SH SYNOPSIS
++\fBgrub-glue-efi\fR <-3 | --input32=\fIFILE\fR> <-6 | --input64=\fIFILE\fR>
++.RS 15
++<-o | --output=\fIFILE\fR> [-v | --verbose]
++
++.SH DESCRIPTION
++\fBgrub-glue-efi\fR creates an Apple fat EFI binary from two EFI binaries.
++
++.SH OPTIONS
++.TP
++\fB--input32\fR=\fIFILE\fR
++Read 32-bit binary from \fIFILE\fR.
++
++.TP
++\fB--input64\fR=\fIFILE\fR
++Read 64-bit binary from \fIFILE\fR.
++
++.TP
++\fB--output\fR=\fIFILE\fR
++Write resulting fat binary to \fIFILE\fR.
++
++.TP
++\fB--verbose\fR
++Print verbose messages.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-install.8 b/util/grub-install.8
+new file mode 100644
+index 00000000000..76272a39d2e
+--- /dev/null
++++ b/util/grub-install.8
+@@ -0,0 +1,129 @@
++.TH GRUB-INSTALL 1 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-install\fR \(em Install GRUB on a device.
++
++.SH SYNOPSIS
++\fBgrub-install\fR [--modules=\fIMODULES\fR] [--install-modules=\fIMODULES\fR]
++.RS 14
++[--themes=\fITHEMES\fR] [--fonts=\fIFONTS\fR] [--locales=\fILOCALES\fR]
++.RE
++.RS 14
++[--compress[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR]] [-d | --directory=\fIDIR\fR]
++.RE
++.RS 14
++[--grub-mkimage=\fIFILE\fR] [--boot-directory=\fIDIR\fR]
++.RE
++.RS 14
++[--target=\fITARGET\fR] [--grub-setup=\fIFILE\fR]
++.RE
++.RS 14
++[--grub-mkrelpath=\fIFILE\fR] [--grub-probe=\fIFILE\fR]
++.RE
++.RS 14
++[--allow-floppy] [--recheck] [--force] [--force-file-id]
++.RE
++.RS 14
++[--disk-module=\fIMODULE\fR] [--no-nvram] [--removable]
++.RE
++.RS 14
++[--bootloader-id=\fIID\fR] [--efi-directory=\fIDIR\fR] \fIINSTALL_DEVICE\fR
++
++.SH DESCRIPTION
++\fBgrub-install\fR installs GRUB onto a device.  This includes copying GRUB images into the target directory (generally \fI/boot/grub\fR), and on some platforms may also include installing GRUB onto a boot sector.
++
++.SH OPTIONS
++.TP
++\fB--modules\fR=\fIMODULES\fR\!
++Pre-load modules specified by \fIMODULES\fR.
++
++.TP
++\fB--install-modules\fR=\fIMODULES\fR
++Install only \fIMODULES\fR and their dependencies.  The default is to install all available modules.
++
++.TP
++\fB--themes\fR=\fITHEMES\fR
++Install \fITHEMES\fR.  The default is to install the \fIstarfield\fR theme, if available.
++
++.TP
++\fB--fonts\fR=\fIFONTS\fR
++Install \fIFONTS\fR.  The default is to install the \fIunicode\fR font.
++
++.TP
++\fB--locales\fR=\fILOCALES\fR
++Install only locales listed in \fILOCALES\fR.  The default is to install all available locales.
++
++.TP
++\fB--compress\fR=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR
++Compress GRUB files using the specified compression algorithm.
++
++.TP
++\fB--directory\fR=\fIDIR\fR
++Use images and modules in \fIDIR\fR.
++
++.TP
++\fB--grub-mkimage\fR=\fIFILE\fR
++Use \fIFILE\fR as \fBgrub-mkimage\fR.  The default is \fI/usr/bin/grub-mkimage\fR.
++
++.TP
++\fB--boot-directory\fR=\fIDIR\fR
++Use \fIDIR\fR as the boot directory.  The default is \fI/boot\fR.  GRUB will put its files in a subdirectory of this directory named \fIgrub\fR.
++
++.TP
++\fB--target\fR=\fITARGET\fR
++Install GRUB for \fITARGET\fR platform.  The default is the platform \fBgrub-install\fR is running on.
++
++.TP
++\fB--grub-setup\fR=\fIFILE\fR
++Use \fIFILE\fR as \fBgrub-setup\fR.  The default is \fI/usr/bin/grub-setup\fR.
++
++.TP
++\fB--grub-mkrelpath\fR=\fIFILE\fR
++Use \fIFILE\fR as \fBgrub-mkrelpath\fR.  The default is \fI/usr/bin/grub-mkrelpath\fR.
++
++.TP
++\fB--grub-probe\fR=\fIFILE\fR
++Use \fIFILE\fR as \fBgrub-probe\fR.  The default is \fI/usr/bin/grub-mkrelpath\fR.
++
++.TP
++\fB--allow-floppy
++Make the device also bootable as a floppy.  This option is the default for /dev/fdX devices. Some BIOSes will not boot images created with this option.
++
++.TP
++\fB--recheck
++Delete any existing device map and create a new one if necessary.
++
++.TP
++\fB--force
++Install even if problems are detected.
++
++.TP
++\fB--force-file-id
++Use identifier file even if UUID is available.
++
++.TP
++\fB--disk-module\fR=\fIMODULE\fR
++Use \fIMODULE\fR for disk access.  This allows you to manually specify either \fIbiosdisk\fR or \fInative\fR disk access.  This option is only available on the BIOS target platform.
++
++.TP
++\fB--no-nvram
++Do not update the \fIboot-device\fR NVRAM variable.  This option is only available on IEEE1275 target platforms.
++
++.TP
++\fB--removable
++Treat the target device as if it is removeable.  This option is only available on the EFI target platform.
++
++.TP
++\fB--bootloader-id\fR=\fIID\fR
++Use \fIID\fR as the bootloader ID.  This opption is only available on the EFI target platform.
++
++.TP
++\fB--efi-directory\fR=\fIDIR\fR
++Use \fIDIR\fR as the EFI System Partition root.  This opption is only available on the EFI ta
++rget platform.
++
++.TP
++\fIINSTALL_DEVICE\fR
++Install GRUB to the block device \fIINSTALL_DEVICE\fR.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-kbdcomp.1 b/util/grub-kbdcomp.1
+new file mode 100644
+index 00000000000..0bb969a5b43
+--- /dev/null
++++ b/util/grub-kbdcomp.1
+@@ -0,0 +1,19 @@
++.TH GRUB-KBDCOMP 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-kbdcomp\fR \(em Generate a GRUB keyboard layout file.
++
++.SH SYNOPSIS
++\fBgrub-kbdcomp\fR <-o | --output=\fIFILE\fR> \fICKBMAP_ARGUMENTS\fR
++
++.SH DESCRIPTION
++\fBgrub-kbdcomp\fR processes an X keyboard layout description in
++\fBkeymaps\fR(5) format into a format that can be used by GRUB's \fBkeymap\fR
++command.
++
++.SH OPTIONS
++.TP
++\fB--output\fR=\fIFILE\fR
++Write output to \fIFILE\fR.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-macbless.1 b/util/grub-macbless.1
+new file mode 100644
+index 00000000000..41a96186f70
+--- /dev/null
++++ b/util/grub-macbless.1
+@@ -0,0 +1,22 @@
++.TH GRUB-MACBLESS 1 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-macbless\fR \(em Mac-style bless on HFS or HFS+
++
++.SH SYNOPSIS
++\fBgrub-macbless\fR [-v | --verbose] [-p | --ppc] \fIFILE\fR | [-x | --x86] \fIFILE\fR
++
++.SH OPTIONS
++.TP
++--x86
++Bless for x86 based Macs.
++
++.TP
++--ppc
++Bless for PPC based Macs.
++
++.TP
++--verbose
++Print verbose messages.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-menulst2cfg.1 b/util/grub-menulst2cfg.1
+new file mode 100644
+index 00000000000..91e2ef87113
+--- /dev/null
++++ b/util/grub-menulst2cfg.1
+@@ -0,0 +1,12 @@
++.TH GRUB-MENULST2CFG 1 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-menulst2cfg\fR \(em Convert a configuration file from GRUB 0.xx to GRUB 2.xx format.
++
++.SH SYNOPSIS
++\fBgrub-menulst2cfg\fR [\fIINFILE\fR [\fIOUTFILE\fR]]
++
++.SH DESCRIPTION
++\fBgrub-menulst2cfg\fR converts a configuration file from GRUB 0.xx to the current format.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-mkconfig.8 b/util/grub-mkconfig.8
+new file mode 100644
+index 00000000000..a2d1f577b9b
+--- /dev/null
++++ b/util/grub-mkconfig.8
+@@ -0,0 +1,17 @@
++.TH GRUB-MKCONFIG 1 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-mkconfig\fR \(em Generate a GRUB configuration file.
++
++.SH SYNOPSIS
++\fBgrub-mkconfig\fR [-o | --output=\fIFILE\fR]
++
++.SH DESCRIPTION
++\fBgrub-mkconfig\fR generates a configuration file for GRUB.
++
++.SH OPTIONS
++.TP
++\fB--output\fR=\fIFILE\fR
++Write generated output to \fIFILE\fR.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-mkfont.1 b/util/grub-mkfont.1
+new file mode 100644
+index 00000000000..3494857987d
+--- /dev/null
++++ b/util/grub-mkfont.1
+@@ -0,0 +1,87 @@
++.TH GRUB-MKFONT 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-mkfont\fR \(em Convert common font file formats into the PF2 format.
++
++.SH SYNOPSIS
++\fBgrub-mkfont\fR [--ascii-bitmaps] [-a | --force-autohint]
++.RS 13
++[-b | --bold] [-c | --asce=\fINUM\fR] [-d | --desc=\fINUM\fR]
++.RE
++.RS 13
++[-i | --index=\fINUM\fR] [-n | --name=\fINAME\fR] [--no-bitmap]
++.RE
++.RS 13
++[--no-hinting] <-o | --output=\fIFILE\fR>
++.RE
++.RS 13
++[-r | --range=\fIFROM-TO\fR[\fI,FROM-TO\fR]] [-s | --size=\fISIZE\fR]
++.RE
++.RS 13
++[-v | --verbose] [--width-spec] \fIFONT_FILES\fR
++
++.SH DESCRIPTION
++\fBgrub-mkfont\fR converts font files from common formats into the PF2 format used by GRUB.
++
++.SH OPTIONS
++.TP
++--ascii-bitmaps
++Save only bitmaps for ASCII characters.
++
++.TP
++--force-autohint
++Force generation of automatic hinting.
++
++.TP
++--bold
++Convert font to bold.
++
++.TP
++--asce=\fINUM\fR
++Set font ascent to \fINUM\fR.
++
++.TP
++--desc=\fINUM\fR
++Set font descent to \fINUM\fR.
++
++.TP
++--index=\fINUM\fR
++Select face index \fINUM\fR.
++
++.TP
++--name=\fINAME\fR
++Set font family to \fINAME\fR.
++
++.TP
++--no-bitmap
++Ignore bitmap strikes when loading.
++
++.TP
++--no-hinting
++Disable hinting.
++
++.TP
++--output=\fIFILE\fR
++Save ouptut to \fIFILE\fR.  This argument is required.
++
++.TP
++--range=\fIFROM-TO\fR\fI,FROM-TO\fR
++Set the font ranges to each pair of \fIFROM\fR,\fITO\fR.
++
++.TP
++--size=\fISIZE\fR
++Set font size to \fISIZE\fR.
++
++.TP
++--verbose
++Print verbose messages.
++
++.TP
++--width-spec
++Create a width summary file.
++
++.TP
++\fIFONT_FILES\fR
++The input files to be converted.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-mkimage.1 b/util/grub-mkimage.1
+new file mode 100644
+index 00000000000..4dea4f54597
+--- /dev/null
++++ b/util/grub-mkimage.1
+@@ -0,0 +1,95 @@
++.TH GRUB-MKIMAGE 1 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-mkimage\fR \(em Make a bootable GRUB image.
++
++.SH SYNOPSIS
++\fBgrub-mkimage\fR [-c | --config=\fRFILE\fI] [-C | --compression=(\fIxz\fR,\fInone\fR,\fIauto\fR)]
++.RS 14
++[-d | --directory=\fRDIR\fR] [-k | --pubkey=\fIFILE\fR]
++.RE
++.RS 14
++[-m | --memdisk=\fIFILE\fR] [-n | --note] [-o | --output=\fIFILE\fR]
++.RE
++.RS 14
++[-O | --format=\fIFORMAT\fR] [-p | --prefix=\fIDIR\fR]
++.RE
++.RS 14
++[-v | --verbose] \fIMODULES\fR
++
++.SH DESCRIPTION
++\fBgrub-mkimage\fI builds a bootable image of GRUB.
++
++.SH OPTIONS
++.TP
++--config=\fIFILE\fR
++Embed \fIFILE\fR as the image's initial configuration file.
++
++.TP
++--compression=(\fIxz\fR,\fInone\fR,\fIauto\fR)
++Use one of \fIxz\fR, \fInone\fR, or \fIauto\fR as the compression method for the core image.
++
++.TP
++--directory=\fIDIR\fR
++Use images and modules from \fIDIR\fR.  The default value is \fB/usr/lib/grub/<platform>\fR.
++
++.TP
++--pubkey=\fIFILE\fR
++Embed the public key \fIFILE\fR for signature checking.
++
++.TP
++--memdisk=\fIFILE\fR
++Embed the memdisk image \fIFILE\fR.  If no \fB-p\fR option is also specified, this implies \fI-p (memdisk)/boot/grub\fR.
++
++.TP
++--note
++Add a CHRP \fINOTE\fR section.  This option is only valid on IEEE1275 platforms.
++
++.TP
++--output=\fIFILE\fR
++Write the generated file to \fIFILE\fR.  The default is to write to standard output.
++
++.TP
++--format=\fIFORMAT\fR
++Generate an image in the specified \fIFORMAT\fR.  Valid values are:
++.RS
++.RS 4
++.P
++i386-coreboot,
++i386-multiboot,
++i386-pc,
++i386-pc-pxe,
++i386-efi,
++i386-ieee1275,
++i386-qemu,
++x86_64-efi,
++mipsel-yeeloong-flash,
++mipsel-fuloong2f-flash,
++mipself-loongson-elf,
++powerpc-ieee1275,
++sparc64-ieee1275-raw,
++sparc64-ieee1275-cdcore,
++sparc64-ieee1275-aout,
++ia64-efi,
++mips-arc,
++mipsel-arc,
++mipsel-qemu_mips-elf,
++mips-qemu_mips-flash,
++mipsel-qemu_mips-flash,
++mips-qemu_mips-elf
++.RE
++.RE
++
++.TP
++--prefix=\fIDIR\fR
++Set prefix directory.  The default value is \fI/boot/grub\fR.
++
++.TP
++--verbose
++Print verbose messages.
++
++.TP
++\fIMODULES\fR
++Include \fIMODULES\fR.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-mklayout.1 b/util/grub-mklayout.1
+new file mode 100644
+index 00000000000..d1bbc2ec515
+--- /dev/null
++++ b/util/grub-mklayout.1
+@@ -0,0 +1,27 @@
++.TH GRUB-MKLAYOUT 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-mklayout\fR \(em Generate a GRUB keyboard layout file.
++
++.SH SYNOPSIS
++\fBgrub-mklayout\fR [-i | --input=\fIFILE\fR] [-o | --output=\fIFILE\fR]
++.RS 15
++[-v | --verbose]
++
++.SH DESCRIPTION
++\fBgrub-mklayout\fR generates a GRUB keyboard layout description which corresponds with the Linux console layout description given as input.
++
++.SH OPTIONS
++.TP
++--input=\fIFILE\fR
++Use \fIFILE\fR as the input.  The default value is the standard input device.
++
++.TP
++--output=\fIFILE\fR
++Use \fIFILE\fR as the output.  The default value is the standard output device.
++
++.TP
++--verbose
++Print verbose messages.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-mknetdir.1 b/util/grub-mknetdir.1
+new file mode 100644
+index 00000000000..69c22628f82
+--- /dev/null
++++ b/util/grub-mknetdir.1
+@@ -0,0 +1,12 @@
++.TH GRUB-MKNETDIR 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-mknetdir\fR \(em Prepare a GRUB netboot directory.
++
++.SH SYNOPSIS
++\fBgrub-mknetdir\fR 
++
++.SH DESCRIPTION
++\fBgrub-mknetdir\fR prepares a directory for GRUB to be netbooted from.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-mkpasswd-pbkdf2.1 b/util/grub-mkpasswd-pbkdf2.1
+new file mode 100644
+index 00000000000..73c437c15d8
+--- /dev/null
++++ b/util/grub-mkpasswd-pbkdf2.1
+@@ -0,0 +1,27 @@
++.TH GRUB-MKPASSWD-PBKDF2 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-mkpasswd-pbkdf2\fR \(em Generate a PBKDF2 password hash.
++
++.SH SYNOPSIS
++\fBgrub-mkpasswd-pbkdf2\fR [-c | --iteration-count=\fINUM\fR] [-l | --buflen=\fINUM\fR]
++.RS 22
++[-s | --salt=\fINUM\fR]
++
++.SH DESCRIPTION
++\fBgrub-mkpasswd-pbkdf2\fR generates a PBKDF2 password string suitable for use in a GRUB configuration file.
++
++.SH OPTIONS
++.TP
++--iteration-count=\fINUM\fR
++Number of PBKDF2 iterations.
++
++.TP
++--buflen=\fINUM\fR
++Length of generated hash.
++
++.TP
++--salt=\fINUM\fR
++Length of salt to use.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-mkrelpath.1 b/util/grub-mkrelpath.1
+new file mode 100644
+index 00000000000..85f1113621d
+--- /dev/null
++++ b/util/grub-mkrelpath.1
+@@ -0,0 +1,12 @@
++.TH GRUB-MKRELPATH 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-mkrelpath\fR \(em Generate a relative GRUB path given an OS path.
++
++.SH SYNOPSIS
++\fBgrub-mkrelpath\fR \fIFILE\fR
++
++.SH DESCRIPTION
++\fBgrub-mkrelpath\fR takes an OS filesystem path for \fIFILE\fR and returns a relative path suitable for use in a GRUB configuration file.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-mkrescue.1 b/util/grub-mkrescue.1
+new file mode 100644
+index 00000000000..4ed9fc723fd
+--- /dev/null
++++ b/util/grub-mkrescue.1
+@@ -0,0 +1,123 @@
++.TH GRUB-MKRESCUE 3 "Wed Feb 26 2014"
++.SH NAME
++grub-mkrescue \(em Generate a GRUB rescue image using GNU Xorriso.
++
++.SH SYNOPSIS
++\fBgrub-mkrescue\fR [-o | --output=\fIFILE\fR] [--modules=\fIMODULES\fR]
++.RS 15
++[--install-modules=\fIMODULES\fR] [--themes=\fITHEMES\fR]
++.RE
++.RS 15
++[--fonts=\fIFONTS\fR] [--locales=\fILOCALES\fR]
++.RE
++.RS 15
++[--compress[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR]] [-d | --directory=\fIDIR\fR]
++.RE
++.RS 15
++[--grub-mkimage=\fIFILE\fR] [--rom-directory=\fIDIR\fR]
++.RE
++.RS 15
++[--xorriso=\fIFILE\fR] [--grub-glue-efi=\fIFILE\fR]
++.RE
++.RS 15
++[--grub-render-label=\fIFILE\fR] [--label-font=\fIFILE\fR]
++.RE
++.RS 15
++[--label-color=\fICOLOR\fR] [--label-bgcolor=\fIFILE\fR]
++.RE
++.RS 15
++[--product-name=\fISTRING\fR] [--product-version=\fISTRING\fR]
++.RE
++.RS 15
++[--sparc-boot] [--arcs-boot]
++
++.SH DESCRIPTION
++\fBgrub-mkrescue\fR can be used to generate a rescue image with the GRUB bootloader.
++
++.SH OPTIONS
++.TP
++\fB--output\fR=\fIFILE\fR
++Write the generated file to \fIFILE\fR.  The default is to write to standard output.
++
++.TP
++\fB--modules\fR=\fIMODULES\fR
++Pre-load modules specified by \fIMODULES\fR.
++
++.TP
++\fB--install-modules\fR=\fIMODULES\fR
++Install only \fIMODULES\fR and their dependencies.  The default is to install all available modules.
++
++.TP
++\fB--themes\fR=\fITHEMES\fR
++Install \fITHEMES\fR.  The default is to install the \fIstarfield\fR theme, if available.
++
++.TP
++\fB--fonts\fR=\fIFONTS\fR
++Install \fIFONTS\fR.  The default is to install the \fIunicode\fR font.
++
++.TP
++\fB--locales\fR=\fILOCALES\fR
++Install only locales listed in \fILOCALES\fR.  The default is to install all available locales.
++
++.TP
++\fB--compress\fR[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR]
++Compress GRUB files using the specified compression algorithm.
++
++.TP
++\fB--directory\fR=\fIDIR\fR
++Use images and modules in \fIDIR\fR.
++
++.TP
++\fB--grub-mkimage\fR=\fIFILE\fR
++Use \fIFILE\fR as \fBgrub-mkimage\fR(1).  The default is \fI/usr/bin/grub-mkimage\fR.
++
++.TP
++\fB--rom-directory\fR=\fIDIR\fR
++Save ROM images in \fIDIR\fR.
++
++.TP
++\fB--xorriso\fR=\fIFILE\fR
++Use \fIFILE\fR as \fBxorriso\fI.
++
++.TP
++\fB--grub-glue-efi\fR=\fIFILE\fR
++Use \fIFILE\fR as \fBgrub-glue-efi\fR(3).
++
++.TP
++\fB--grub-render-label\fR=\fIFILE\fR
++Use \fIFILE\fR as \fBgrub-render-label\fR(3).
++
++.TP
++\fB--label-font\fR=\fIFILE\fR
++Use \fIFILE\fR as the font file for generated labels.
++
++.TP
++\fB--label-color\fR=\fICOLOR\fR
++Use \fICOLOR\fI as the color for generated labels.
++
++.TP
++\fB--label-bgcolor\fR=\fICOLOR\fR
++Use \fICOLOR\fR as the background color for generated labels.
++
++.TP
++\fB--product-name\fR=\fISTRING\fR
++Use \fISTRING\fR as the product name in generated labels.
++
++.TP
++\fB--product-version\fR=\fISTRING\fR
++Use \fISTRING\fR as the product version in generated labels.
++
++.TP
++\fB--sparc-boot\fR
++Enable booting the SPARC platform.  This disables HFS+, APM, ARCS, and "boot as disk image" on the \fIi386-pc\fR target platform.
++
++.TP
++\fB--arcs-boot\fR
++Enable ARCS booting.  This is typically for big-endian MIPS machines, and disables HFS+, APM, sparc64, and "boot as disk image" on the \fIi386-pc\fR target platform.
++
++.TP
++\fB--\fR
++All options after a \fB--\fR will be passed directly to xorriso's command line when generating the image.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-mkstandalone.1 b/util/grub-mkstandalone.1
+new file mode 100644
+index 00000000000..ba2d2bdf279
+--- /dev/null
++++ b/util/grub-mkstandalone.1
+@@ -0,0 +1,100 @@
++.TH GRUB-MKSTANDALONE 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-mkstandalone\fR \(em Generate a standalone image in the selected format.
++
++.SH SYNOPSIS
++\fBgrub-mkstandalone\fR [-o | --output=\fIFILE\fR] [-O | --format=\fIFORMAT\fR]
++.RS 19
++[-C | --compression=(\fIxz\fR|\fInone\fR|\fIauto\fR)]
++.RE
++.RS 19
++[--modules=\fIMODULES\fR] [--install-modules=\fIMODULES\fR]
++.RE
++.RS 19
++[--themes=\fITHEMES\fR] [--fonts=\fIFONTS\fR]
++.RE
++.RS 19
++[--locales=\fILOCALES\fR] [--compress[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR]]
++.RE
++.RS 19
++[-d | --directory=\fIDIR\fR] [--grub-mkimage=\fIFILE\fR]
++.RE
++.RS 19
++\fISOURCE...\fR
++
++.SH DESCRIPTION
++
++.SH OPTIONS
++.TP
++--output=\fIFILE\fR
++Write the generated file to \fIFILE\fR.  The default is to write to standard output.
++
++.TP
++--format=\fIFORMAT\fR
++Generate an image in the specified \fIFORMAT\fR.  Valid values are:
++.RS
++.RS 4
++.P
++i386-coreboot,
++i386-multiboot,
++i386-pc,
++i386-pc-pxe,
++i386-efi,
++i386-ieee1275,
++i386-qemu,
++x86_64-efi,
++mipsel-yeeloong-flash,
++mipsel-fuloong2f-flash,
++mipself-loongson-elf,
++powerpc-ieee1275,
++sparc64-ieee1275-raw,
++sparc64-ieee1275-cdcore,
++sparc64-ieee1275-aout,
++ia64-efi,
++mips-arc,
++mipsel-arc,
++mipsel-qemu_mips-elf,
++mips-qemu_mips-flash,
++mipsel-qemu_mips-flash,
++mips-qemu_mips-elf
++.RE
++.RE
++
++.TP
++--compression=(\fIxz\fR|\fInone\fR|\fIauto\fR)
++Use one of \fIxz\fR, \fInone\fR, or \fIauto\fR as the compression method for the core image.
++
++.TP
++--modules=\fIMODULES\fR
++Pre-load modules specified by \fIMODULES\fR.
++
++.TP
++--install-modules=\fIMODULES\fR
++Install only \fIMODULES\fR and their dependencies.  The default is to install all available modules.
++
++.TP
++--themes=\fITHEMES\fR
++Install \fITHEMES\fR.  The default is to install the \fIstarfield\fR theme, if available.
++
++.TP
++--fonts=\fIFONTS\fR
++Install \fIFONTS\fR.  The default is to install the \fIunicode\fR font.
++
++.TP
++--locales=\fILOCALES\fR
++Install only locales listed in \fILOCALES\fR.  The default is to install all available locales.
++
++.TP
++--compress[=\fIno\fR,\fIxz\fR,\fIgz\fR,\fIlzo\fR]
++Compress GRUB files using the specified compression algorithm.
++
++.TP
++--directory=\fIDIR\fR
++Use images and modules in \fIDIR\fR.
++
++.TP
++--grub-mkimage=\fIFILE\fR
++Use \fIFILE\fR as \fBgrub-mkimage\fR.  The default is \fI/usr/bin/grub-mkimage\fR.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-ofpathname.8 b/util/grub-ofpathname.8
+new file mode 100644
+index 00000000000..bf3743aeba1
+--- /dev/null
++++ b/util/grub-ofpathname.8
+@@ -0,0 +1,12 @@
++.TH GRUB-OFPATHNAME 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-ofpathname\fR \(em Generate an IEEE-1275 device path for a specified device.
++
++.SH SYNOPSIS
++\fBgrub-ofpathname\fR \fIDEVICE\fR
++
++.SH DESCRIPTION
++\fBgrub-ofpathname\fR generates an IEEE-1275 device path for the specified \fIDEVICE\fR.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-probe.8 b/util/grub-probe.8
+new file mode 100644
+index 00000000000..04e26c832bb
+--- /dev/null
++++ b/util/grub-probe.8
+@@ -0,0 +1,80 @@
++.TH GRUB-PROBE 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-probe\fR \(em Probe device information for a given path.
++
++.SH SYNOPSIS
++\fBgrub-probe\fR \[-d | --device] [-m | --device-map=\fIFILE\fR]
++.RS 12
++[-t | --target=(fs|fs_uuid|fs_label|drive|device|partmap|
++.RE
++.RS 28
++abstraction|cryptodisk_uuid|
++.RE
++.RS 28
++msdos_parttype)]
++.RE
++.RS 12
++[-v | --verbose] (PATH|DEVICE)
++
++.SH DESCRIPTION
++\fBgrub-probe\fR probes a path or device for filesystem and related information.
++
++.SH OPTIONS
++.TP
++--device
++Final option represents a \fIDEVICE\fR, rather than a filesystem \fIPATH\fR.
++.TP
++--device-map=\fIFILE\fR
++Use \fIFILE\fR as the device map.  The default value is \fI/boot/grub/device.map\fR.
++
++.TP
++--target=(fs|fs_uuid|fs_label|drive|device|partmap|msdos_parttype)
++Select among various output definitions.  The default is \fIfs\fR.
++.RS
++.TP
++\fIfs\fR
++filesystem module
++
++.TP
++\fIfs_uuid\fR
++filesystem UUID
++
++.TP
++\fIfs_label\fR
++filesystem label
++
++.TP
++\fIdrive\fR
++GRUB drive name
++
++.TP
++\fIdevice\fR
++System device
++
++.TP
++\fIpartmap\fR
++partition map module
++
++.TP
++\fIabstraction\fR
++abstraction module
++
++.TP
++\fIcryptodisk_uuid\fR
++cryptographic container
++
++.TP
++\fImsdos_partmap\fR
++MS-DOS partition map
++.RE
++
++.TP
++--verbose
++Print verbose output.
++
++.TP
++(\fIPATH\fR|\fIDEVICE\fR)
++If --device is passed, a block \fIDEVICE\fR.  Otherwise, the \fIPATH\fR of a file on the filesystem.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-reboot.8 b/util/grub-reboot.8
+new file mode 100644
+index 00000000000..faa5e4eece2
+--- /dev/null
++++ b/util/grub-reboot.8
+@@ -0,0 +1,21 @@
++.TH GRUB-REBOOT 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-reboot\fR \(em Set the default boot menu entry for the next boot only.
++
++.SH SYNOPSIS
++\fBgrub-reboot\fR [--boot-directory=\fIDIR\fR] \fIMENU_ENTRY\fR
++
++.SH DESCRIPTION
++\fBgrub-reboot\fR sets the default boot menu entry for the next boot, but not further boots after that.  This command only works for GRUB configuration files created with \fIGRUB_DEFAULT=saved\fR in \fI/etc/default/grub\fR.
++
++.SH OPTIONS
++.TP
++--boot-directory=\fIDIR\fR
++Find GRUB images under \fIDIR/grub\fR.  The default value is \fI/boot\fR, resulting in grub images being search for at \fI/boot/grub\fR.
++
++.TP
++\fIMENU_ENTRY\fR
++A number, a menu item title or a menu item identifier.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-render-label.1 b/util/grub-render-label.1
+new file mode 100644
+index 00000000000..4d51c8abf01
+--- /dev/null
++++ b/util/grub-render-label.1
+@@ -0,0 +1,51 @@
++.TH GRUB-RENDER-LABEL 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-render-label\fR \(em Render an Apple disk label.
++
++.SH SYNOPSIS
++\fBgrub-render-label\fR [-b | --bgcolor=\fICOLOR\fR] [-c | --color=\fICOLOR\fR]
++.RS 19
++[-f | --font=\fIFILE\fR] [-i | --input=\fIFILE\fR]
++.RE
++.RS 19
++[-o | --output=\fIFILE\fR] [-t | --text=\fISTRING\fR]
++.RE
++.RS 19
++[-v | --verbose]
++
++.SH DESCRIPTION
++\fBgrub-render-label\fR renders an Apple disk label (.disk_label) file.
++
++
++.SH OPTIONS
++.TP
++\fB--color\fR=\fICOLOR\fR
++Use \fICOLOR\fI as the color for generated labels.
++
++.TP
++\fB--bgcolor\fR=\fICOLOR\fR
++Use \fICOLOR\fR as the background color for generated labels.
++
++.TP
++\fB--font\fR=\fIFILE\fR
++Use \fIFILE\fR as the font file for generated labels.
++
++.TP
++--input=\fIFILE\fR
++Read input text from \fIFILE\fR.
++
++.TP
++--output=\fIFILE\fR
++Render output to \fIFILE\fR.
++
++.TP
++--text=\fISTRING\fR
++Use \fISTRING\fR as input text.
++
++.TP
++--verbose
++Print verbose output.
++
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-script-check.1 b/util/grub-script-check.1
+new file mode 100644
+index 00000000000..0f1f625b05d
+--- /dev/null
++++ b/util/grub-script-check.1
+@@ -0,0 +1,21 @@
++.TH GRUB-SCRIPT-CHECK 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-script-check\fR \(em Check GRUB configuration file for syntax errors.
++
++.SH SYNOPSIS
++\fBgrub-script-check\fR [-v | --verbose] \fIPATH\fR
++
++.SH DESCRIPTION
++\fBgrub-script-check\fR verifies that a specified GRUB configuration file does not contain syntax errors.
++
++.SH OPTIONS
++.TP
++--verbose
++Print verbose output.
++
++.TP
++\fIPATH\fR
++Path of the file to use as input.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-set-default.8 b/util/grub-set-default.8
+new file mode 100644
+index 00000000000..a96265a1509
+--- /dev/null
++++ b/util/grub-set-default.8
+@@ -0,0 +1,21 @@
++.TH GRUB-SET-DEFAULT 1 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-set-default\fR \(em Set the default boot menu entry for GRUB.
++
++.SH SYNOPSIS
++\fBgrub-set-default\fR [--boot-directory=\fIDIR\fR] \fIMENU_ENTRY\fR
++
++.SH DESCRIPTION
++\fBgrub-set-default\fR sets the default boot menu entry for all subsequent boots.  This command only works for GRUB configuration files created with \fIGRUB_DEFAULT=saved\fR in \fI/etc/default/grub\fR.
++
++.SH OPTIONS
++.TP
++--boot-directory=\fIDIR\fR
++Find GRUB images under \fIDIR/grub\fR.  The default value is \fI/boot\fR, resulting in grub images being search for at \fI/boot/grub\fR.
++
++.TP
++\fIMENU_ENTRY\fR
++A number, a menu item title or a menu item identifier.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-sparc64-setup.8 b/util/grub-sparc64-setup.8
+new file mode 100644
+index 00000000000..37ea2dd5eaa
+--- /dev/null
++++ b/util/grub-sparc64-setup.8
+@@ -0,0 +1,12 @@
++.TH GRUB-SPARC64-SETUP 3 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-sparc64-setup\fR \(em Set up a device to boot a sparc64 GRUB image.
++
++.SH SYNOPSIS
++\fBgrub-sparc64-setup\fR [OPTIONS].
++
++.SH DESCRIPTION
++You should not normally run this program directly.  Use grub-install instead.
++
++.SH SEE ALSO
++.BR "info grub"
diff --git a/SOURCES/0131-use-fw_path-prefix-when-fallback-searching-for-grub-.patch b/SOURCES/0131-use-fw_path-prefix-when-fallback-searching-for-grub-.patch
new file mode 100644
index 0000000..c5899aa
--- /dev/null
+++ b/SOURCES/0131-use-fw_path-prefix-when-fallback-searching-for-grub-.patch
@@ -0,0 +1,41 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Fedora Ninjas <grub2-owner@fedoraproject.org>
+Date: Wed, 19 Feb 2014 15:58:43 -0500
+Subject: [PATCH] use fw_path prefix when fallback searching for grub config
+
+When PXE booting via UEFI firmware, grub was searching for grub.cfg
+in the fw_path directory where the grub application was found. If
+that didn't exist, a fallback search would look for config file names
+based on MAC and IP address. However, the search would look in the
+prefix directory which may not be the same fw_path. This patch
+changes that behavior to use the fw_path directory for the fallback
+search. Only if fw_path is NULL will the prefix directory be searched.
+
+Signed-off-by: Mark Salter <msalter@redhat.com>
+---
+ grub-core/normal/main.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
+index f66c03c4c6e..5e2ac150e12 100644
+--- a/grub-core/normal/main.c
++++ b/grub-core/normal/main.c
+@@ -343,7 +343,7 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
+       char *config;
+       const char *prefix, *fw_path;
+ 
+-      fw_path = grub_env_get ("fw_path");
++      prefix = fw_path = grub_env_get ("fw_path");
+       if (fw_path)
+ 	{
+ 	  config = grub_xasprintf ("%s/grub.cfg", fw_path);
+@@ -366,7 +366,8 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
+ 	    }
+ 	}
+ 
+-      prefix = grub_env_get ("prefix");
++      if (! prefix)
++	      prefix = grub_env_get ("prefix");
+       if (prefix)
+         {
+           grub_size_t config_len;
diff --git a/SOURCES/0132-Try-mac-guid-etc-before-grub.cfg-on-tftp-config-file.patch b/SOURCES/0132-Try-mac-guid-etc-before-grub.cfg-on-tftp-config-file.patch
new file mode 100644
index 0000000..31bd38c
--- /dev/null
+++ b/SOURCES/0132-Try-mac-guid-etc-before-grub.cfg-on-tftp-config-file.patch
@@ -0,0 +1,111 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 6 Mar 2014 11:51:33 -0500
+Subject: [PATCH] Try mac/guid/etc before grub.cfg on tftp config files.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/normal/main.c | 80 ++++++++++++++++++++++++++-----------------------
+ 1 file changed, 43 insertions(+), 37 deletions(-)
+
+diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
+index 5e2ac150e12..4190985ad37 100644
+--- a/grub-core/normal/main.c
++++ b/grub-core/normal/main.c
+@@ -341,53 +341,59 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
+       /* Guess the config filename. It is necessary to make CONFIG static,
+ 	 so that it won't get broken by longjmp.  */
+       char *config;
+-      const char *prefix, *fw_path;
+-
+-      prefix = fw_path = grub_env_get ("fw_path");
+-      if (fw_path)
+-	{
+-	  config = grub_xasprintf ("%s/grub.cfg", fw_path);
+-	  if (config)
+-	    {
+-	      grub_file_t file;
+-
+-	      file = grub_file_open (config);
+-	      if (file)
+-		{
+-		  grub_file_close (file);
+-		  grub_enter_normal_mode (config);
+-		}
+-              else
+-                {
+-                  /*  Ignore all errors.  */
+-                  grub_errno = 0;
+-                }
+-	      grub_free (config);
+-	    }
+-	}
++      const char *prefix;
+ 
++      prefix = grub_env_get ("fw_path");
+       if (! prefix)
+ 	      prefix = grub_env_get ("prefix");
++
+       if (prefix)
+-        {
+-          grub_size_t config_len;
+-          config_len = grub_strlen (prefix) +
+-                      sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
+-          config = grub_malloc (config_len);
++	{
++	  if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0)
++	    {
++	      grub_size_t config_len;
++	      config_len = grub_strlen (prefix) +
++		sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
++	      config = grub_malloc (config_len);
+ 
+-          if (! config)
+-            goto quit;
++	      if (! config)
++		goto quit;
+ 
+-          grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
++	      grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
+ 
+-          if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0)
+-            grub_net_search_configfile (config);
++	      grub_net_search_configfile (config);
+ 
+-	  grub_enter_normal_mode (config);
+-	  grub_free (config);
++	      grub_enter_normal_mode (config);
++	      grub_free (config);
++	      config = NULL;
++	    }
++
++	  if (!config)
++	    {
++	      config = grub_xasprintf ("%s/grub.cfg", prefix);
++	      if (config)
++		{
++		  grub_file_t file;
++
++		  file = grub_file_open (config);
++		  if (file)
++		    {
++		      grub_file_close (file);
++		      grub_enter_normal_mode (config);
++		    }
++		  else
++		    {
++		      /*  Ignore all errors.  */
++		      grub_errno = 0;
++		    }
++		  grub_free (config);
++		}
++	    }
+ 	}
+       else
+-	grub_enter_normal_mode (0);
++	{
++	  grub_enter_normal_mode (0);
++	}
+     }
+   else
+     grub_enter_normal_mode (argv[0]);
diff --git a/SOURCES/0133-trim-arp-packets-with-abnormal-size.patch b/SOURCES/0133-trim-arp-packets-with-abnormal-size.patch
new file mode 100644
index 0000000..944050f
--- /dev/null
+++ b/SOURCES/0133-trim-arp-packets-with-abnormal-size.patch
@@ -0,0 +1,28 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
+Date: Wed, 5 Feb 2014 09:42:42 -0200
+Subject: [PATCH] trim arp packets with abnormal size
+
+GRUB uses arp request to create the arp response. If the incoming packet
+is foobared, GRUB needs to trim the arp response packet before sending it.
+---
+ grub-core/net/arp.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c
+index d62d0cc1e01..77581f4b29a 100644
+--- a/grub-core/net/arp.c
++++ b/grub-core/net/arp.c
+@@ -162,6 +162,12 @@ grub_net_arp_receive (struct grub_net_buff *nb,
+     if (grub_net_addr_cmp (&inf->address, &target_addr) == 0
+ 	&& grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST)
+       {
++        if ((nb->tail - nb->data) > 50)
++          {
++            grub_dprintf ("net", "arp packet with abnormal size (%ld bytes).\n",
++                         nb->tail - nb->data);
++            nb->tail = nb->data + 50;
++          }
+ 	grub_net_link_level_address_t target;
+ 	/* We've already checked that pln is either 4 or 16.  */
+ 	char tmp[16];
diff --git a/SOURCES/0134-Fix-convert-function-to-support-NVMe-devices.patch b/SOURCES/0134-Fix-convert-function-to-support-NVMe-devices.patch
new file mode 100644
index 0000000..d3dc3d3
--- /dev/null
+++ b/SOURCES/0134-Fix-convert-function-to-support-NVMe-devices.patch
@@ -0,0 +1,56 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 18 Feb 2014 11:34:00 -0500
+Subject: [PATCH] Fix convert function to support NVMe devices
+
+This is adapted from the patch at
+https://bugzilla.redhat.com/show_bug.cgi?id=1019660 , which is against
+the now very old version of convert_system_partition_to_system_disk().
+
+As such, it certainly not the right thing for upstream, but should
+function for now.
+
+Resolves: rhbz#1019660
+
+Signed-off-by: Peter Jones <grub2-owner@fedoraproject.org>
+---
+ util/getroot.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/util/getroot.c b/util/getroot.c
+index 3958105d819..e70061099b3 100644
+--- a/util/getroot.c
++++ b/util/getroot.c
+@@ -152,6 +152,7 @@ convert_system_partition_to_system_disk (const char *os_dev, int *is_part)
+ {
+ #if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL
+   struct stat st;
++  char *path = xmalloc(PATH_MAX);
+ 
+   if (stat (os_dev, &st) < 0)
+     {
+@@ -164,6 +165,24 @@ convert_system_partition_to_system_disk (const char *os_dev, int *is_part)
+ 
+   *is_part = 0;
+ 
++  if (realpath(os_dev, path))
++    {
++      if ((strncmp ("/dev/nvme", path, 9) == 0))
++	{
++	  char *p = path + 5;
++	  p = strchr(p, 'p');
++	  if (p)
++	    {
++	      *is_part = 1;
++	      *p = '\0';
++	    }
++	  return path;
++	}
++    }
++
++  grub_free (path);
++  *is_part = 0;
++
+   if (grub_util_device_is_mapped_stat (&st))
+     return grub_util_devmapper_part_to_disk (&st, is_part, os_dev);
+ 
diff --git a/SOURCES/0135-Fix-bad-test-on-GRUB_DISABLE_SUBMENU.patch b/SOURCES/0135-Fix-bad-test-on-GRUB_DISABLE_SUBMENU.patch
new file mode 100644
index 0000000..3e50793
--- /dev/null
+++ b/SOURCES/0135-Fix-bad-test-on-GRUB_DISABLE_SUBMENU.patch
@@ -0,0 +1,38 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Prarit Bhargava <prarit@redhat.com>
+Date: Wed, 12 Mar 2014 10:58:16 -0400
+Subject: [PATCH] Fix bad test on GRUB_DISABLE_SUBMENU.
+
+The file /etc/grub.d/10_linux does
+
+if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then
+
+when it should do
+
+if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then
+
+which results in submenus in /boot/grub2/grub.cfg when
+GRUB_DISABLE_SUBMENU="yes".
+
+Resolves: rhbz#1063414
+---
+ util/grub.d/10_linux.in | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 136abd7a6e3..767093c636a 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -255,7 +255,11 @@ while [ "x$list" != "x" ] ; do
+     linux_root_device_thisversion=${GRUB_DEVICE}
+   fi
+ 
+-  if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then
++  if [ "x${GRUB_DISABLE_SUBMENU}" = "xyes" ] || [ "x${GRUB_DISABLE_SUBMENU}" = "xy" ]; then
++    GRUB_DISABLE_SUBMENU="true"
++  fi
++
++  if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then
+     linux_entry "${OS}" "${version}" simple \
+     "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+ 
diff --git a/SOURCES/0136-Switch-to-use-APM-Mustang-device-tree-for-hardware-t.patch b/SOURCES/0136-Switch-to-use-APM-Mustang-device-tree-for-hardware-t.patch
new file mode 100644
index 0000000..2c2a1c3
--- /dev/null
+++ b/SOURCES/0136-Switch-to-use-APM-Mustang-device-tree-for-hardware-t.patch
@@ -0,0 +1,25 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Fedora Ninjas <grub2-owner@fedoraproject.org>
+Date: Mon, 10 Feb 2014 16:13:10 -0500
+Subject: [PATCH] Switch to use APM Mustang device tree, for hardware testing.
+
+Signed-off-by: David A. Marlin <d.marlin@redhat.com>
+---
+ util/grub.d/10_linux.in | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 767093c636a..3722c1ea263 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -228,8 +228,8 @@ while [ "x$list" != "x" ] ; do
+ 
+   fdt=
+   for i in "dtb-${version}" "dtb-${alt_version}"; do
+-    if test -e "${dirname}/${i}/foundation-v8.dtb" ; then
+-      fdt="${i}/foundation-v8.dtb"
++    if test -e "${dirname}/${i}/apm-mustang.dtb" ; then
++      fdt="${i}/apm-mustang.dtb"
+       break
+     fi
+   done
diff --git a/SOURCES/0137-Use-the-default-device-tree-from-the-grub-default-fi.patch b/SOURCES/0137-Use-the-default-device-tree-from-the-grub-default-fi.patch
new file mode 100644
index 0000000..418a3a6
--- /dev/null
+++ b/SOURCES/0137-Use-the-default-device-tree-from-the-grub-default-fi.patch
@@ -0,0 +1,42 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Fedora Ninjas <grub2-owner@fedoraproject.org>
+Date: Wed, 12 Feb 2014 14:54:04 -0500
+Subject: [PATCH] Use the default device tree from the grub default file
+
+instead of hardcoding a value.
+
+Signed-off-by: David A. Marlin <dmarlin@redhat.com>
+---
+ util/grub-mkconfig.in   | 3 ++-
+ util/grub.d/10_linux.in | 4 ++--
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index b00f9e61f40..beb22deee79 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -224,7 +224,8 @@ export GRUB_DEFAULT \
+   GRUB_ENABLE_CRYPTODISK \
+   GRUB_BADRAM \
+   GRUB_OS_PROBER_SKIP_LIST \
+-  GRUB_DISABLE_SUBMENU
++  GRUB_DISABLE_SUBMENU \
++  GRUB_DEFAULT_DTB
+ 
+ if test "x${grub_cfg}" != "x"; then
+   rm -f "${grub_cfg}.new"
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 3722c1ea263..8782d8c67cf 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -228,8 +228,8 @@ while [ "x$list" != "x" ] ; do
+ 
+   fdt=
+   for i in "dtb-${version}" "dtb-${alt_version}"; do
+-    if test -e "${dirname}/${i}/apm-mustang.dtb" ; then
+-      fdt="${i}/apm-mustang.dtb"
++    if test -f "${dirname}/${i}/${GRUB_DEFAULT_DTB}" ; then
++      fdt="${i}/${GRUB_DEFAULT_DTB}"
+       break
+     fi
+   done
diff --git a/SOURCES/0138-reopen-SNP-protocol-for-exclusive-use-by-grub.patch b/SOURCES/0138-reopen-SNP-protocol-for-exclusive-use-by-grub.patch
new file mode 100644
index 0000000..09f60d8
--- /dev/null
+++ b/SOURCES/0138-reopen-SNP-protocol-for-exclusive-use-by-grub.patch
@@ -0,0 +1,43 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Fedora Ninjas <grub2-owner@fedoraproject.org>
+Date: Sat, 15 Feb 2014 15:10:22 -0500
+Subject: [PATCH] reopen SNP protocol for exclusive use by grub
+
+---
+ grub-core/net/drivers/efi/efinet.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 2b344d6ef78..a6e4c7992f7 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -223,6 +223,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ {
+   struct grub_net_card *card;
+   grub_efi_device_path_t *dp;
++  grub_efi_simple_network_t *net;
+ 
+   dp = grub_efi_get_device_path (hnd);
+   if (! dp)
+@@ -250,6 +251,21 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 				    &pxe_mode->dhcp_ack,
+ 				    sizeof (pxe_mode->dhcp_ack),
+ 				    1, device, path);
++    net = grub_efi_open_protocol (card->efi_handle, &net_io_guid,
++				  GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE);
++    if (net) {
++      if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
++	  && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS)
++	continue;
++
++      if (net->mode->state == GRUB_EFI_NETWORK_STOPPED)
++	continue;
++
++      if (net->mode->state == GRUB_EFI_NETWORK_STARTED
++	  && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS)
++	continue;
++      card->efi_net = net;
++    }
+     return;
+   }
+ }
diff --git a/SOURCES/0139-Reduce-timer-event-frequency-by-10.patch b/SOURCES/0139-Reduce-timer-event-frequency-by-10.patch
new file mode 100644
index 0000000..bb614d3
--- /dev/null
+++ b/SOURCES/0139-Reduce-timer-event-frequency-by-10.patch
@@ -0,0 +1,37 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Mark Salter <msalter@redhat.com>
+Date: Thu, 20 Feb 2014 12:54:52 -0500
+Subject: [PATCH] Reduce timer event frequency by 10
+
+Timer event to keep grub msec counter was running at 1000HZ. This was too
+fast for UEFI timer driver and resulted in a 10x slowdown in grub time
+versus wallclock. Reduce the timer event frequency and increase tick
+increment accordingly to keep better time.
+
+Signed-off-by: Mark Salter <msalter@redhat.com>
+---
+ grub-core/kern/arm/efi/init.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/kern/arm/efi/init.c b/grub-core/kern/arm/efi/init.c
+index a6ae03475cc..0c17d8390fa 100644
+--- a/grub-core/kern/arm/efi/init.c
++++ b/grub-core/kern/arm/efi/init.c
+@@ -38,7 +38,7 @@ static void
+ increment_timer (grub_efi_event_t event __attribute__ ((unused)),
+ 		 void *context __attribute__ ((unused)))
+ {
+-  tmr++;
++  tmr += 10;
+ }
+ 
+ void
+@@ -52,7 +52,7 @@ grub_machine_init (void)
+ 
+   efi_call_5 (b->create_event, GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL,
+ 	      GRUB_EFI_TPL_CALLBACK, increment_timer, NULL, &tmr_evt);
+-  efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 10000);
++  efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 100000);
+ 
+   grub_install_get_time_ms (grub_efi_get_time_ms);
+ }
diff --git a/SOURCES/0140-always-return-error-to-UEFI.patch b/SOURCES/0140-always-return-error-to-UEFI.patch
new file mode 100644
index 0000000..4720fba
--- /dev/null
+++ b/SOURCES/0140-always-return-error-to-UEFI.patch
@@ -0,0 +1,22 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Fedora Ninjas <grub2-owner@fedoraproject.org>
+Date: Wed, 26 Feb 2014 21:49:12 -0500
+Subject: [PATCH] always return error to UEFI
+
+---
+ grub-core/kern/efi/efi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index cd839cc988a..1a8dba531b6 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -158,7 +158,7 @@ grub_exit (void)
+ {
+   grub_efi_fini ();
+   efi_call_4 (grub_efi_system_table->boot_services->exit,
+-              grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0);
++              grub_efi_image_handle, GRUB_EFI_LOAD_ERROR, 0, 0);
+   for (;;) ;
+ }
+ 
diff --git a/SOURCES/0141-Add-powerpc-little-endian-ppc64le-flags.patch b/SOURCES/0141-Add-powerpc-little-endian-ppc64le-flags.patch
new file mode 100644
index 0000000..7920668
--- /dev/null
+++ b/SOURCES/0141-Add-powerpc-little-endian-ppc64le-flags.patch
@@ -0,0 +1,93 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@linux.vnet.ibm.com>
+Date: Wed, 13 Aug 2014 18:59:58 +0000
+Subject: [PATCH] Add powerpc little-endian (ppc64le) flags
+
+libgcc dependency was removed *just* for this target because
+the distros that use ppc64el doesn't have 32-bit support on it.
+
+* configure.ac: Add targets for powerpc64el and skip libgcc.
+* Makefile.am: Likewise.
+---
+ configure.ac          | 17 +++++++++++++++--
+ grub-core/Makefile.am |  2 ++
+ 2 files changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 2632e2dad9b..53fd7c73ee6 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -142,6 +142,7 @@ if test "x$with_platform" = x; then
+     x86_64-*) platform=pc ;;
+     powerpc-*) platform=ieee1275 ;;
+     powerpc64-*) platform=ieee1275 ;;
++    powerpc64le-*) platform=ieee1275 ;;
+     sparc64-*) platform=ieee1275 ;;
+     mipsel-*) platform=loongson ;;
+     mips-*) platform=arc ;;
+@@ -160,6 +161,7 @@ case "$target_cpu"-"$platform" in
+   x86_64-xen) ;;
+   x86_64-*) target_cpu=i386 ;;
+   powerpc64-ieee1275) target_cpu=powerpc ;;
++  powerpc64le-ieee1275) target_cpu=powerpc ;;
+ esac
+ 
+ # Check if the platform is supported, make final adjustments.
+@@ -604,6 +606,13 @@ if test "x$target_cpu" = xi386 && test "x$platform" != xemu; then
+   TARGET_CFLAGS="$TARGET_CFLAGS -march=i386"
+ fi
+ 
++if test x$target_cpu = xpowerpc && test x$ac_cv_c_bigendian = xno; then
++	LD_FORCE_LE=1
++	TARGET_CFLAGS="$TARGET_CFLAGS -mbig-endian -DNO_LIBGCC=1"
++	TARGET_CCASFLAGS="$TARGET_CCASFLAGS -mbig-endian"
++	TARGET_LDFLAGS="$TARGET_LDFLAGS -static -mbig-endian"
++fi
++
+ if test "x$target_m32" = x1; then
+   # Force 32-bit mode.
+   TARGET_CFLAGS="$TARGET_CFLAGS -m32"
+@@ -1047,7 +1056,8 @@ else
+ CFLAGS="$TARGET_CFLAGS -nostdlib -Wno-error"
+ fi
+ CPPFLAGS="$TARGET_CPPFLAGS"
+-if test x$target_cpu = xi386 || test x$target_cpu = xx86_64 || test "x$grub_cv_cc_target_clang" = xyes ; then
++if test x$target_cpu = xi386 || test x$target_cpu = xx86_64 || test "x$grub_cv_cc_target_clang" = xyes \
++	|| ( test x$target_cpu = xpowerpc && test x$ac_cv_c_bigendian = xno ); then
+ TARGET_LIBGCC=
+ else
+ TARGET_LIBGCC=-lgcc
+@@ -1631,7 +1641,9 @@ if test x"$enable_werror" != xno ; then
+   HOST_CFLAGS="$HOST_CFLAGS -Werror"
+ fi
+ 
+-if test "x$grub_cv_cc_target_clang" = xno; then
++# if not clang or power LE, use static libgcc
++if test "x$grub_cv_cc_target_clang" = xno \
++   || ! ( test x$target_cpu = xpowerpc && test x$ac_cv_c_bigendian = xno ); then
+    TARGET_LDFLAGS_STATIC_LIBGCC="-static-libgcc"
+ else
+    TARGET_LDFLAGS_STATIC_LIBGCC=
+@@ -1694,6 +1706,7 @@ AM_CONDITIONAL([COND_mips_arc], [test "(" x$target_cpu = xmips -o x$target_cpu =
+ AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275])
+ AM_CONDITIONAL([COND_sparc64_emu], [test x$target_cpu = xsparc64 -a x$platform = xemu])
+ AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275])
++AM_CONDITIONAL([COND_powerpc_le], [test x$target_cpu = xpowerpc -a x$ac_cv_c_bigendian = xno])
+ AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips -o x$target_cpu = xmipsel])
+ AM_CONDITIONAL([COND_mipsel], [test x$target_cpu = xmipsel])
+ AM_CONDITIONAL([COND_mipseb], [test x$target_cpu = xmips])
+diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
+index 5c087c83b8f..cb7fd9f98e8 100644
+--- a/grub-core/Makefile.am
++++ b/grub-core/Makefile.am
+@@ -84,8 +84,10 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
+ if !COND_clang
++if !COND_powerpc_le
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
+ endif
++endif
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
+ 
+ if COND_i386_pc
diff --git a/SOURCES/0142-Files-reorganization-and-include-some-libgcc-fuction.patch b/SOURCES/0142-Files-reorganization-and-include-some-libgcc-fuction.patch
new file mode 100644
index 0000000..05cbdd3
--- /dev/null
+++ b/SOURCES/0142-Files-reorganization-and-include-some-libgcc-fuction.patch
@@ -0,0 +1,436 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@linux.vnet.ibm.com>
+Date: Wed, 13 Aug 2014 19:00:19 +0000
+Subject: [PATCH] Files reorganization and include some libgcc fuctions
+
+As we avoid libgcc dependency for powerpc64el, we moved some functions
+to other files and add the necessary ones.
+
+* Makefile.core.def: Include compiler-rt.S.
+* misc.c: Add the necessary libgcc functions.
+* compiler-rt.S: New file.
+* libgcc.h: Move some content from here ...
+* compiler.h: ... to here.
+
+Also-By: Brent Baude <bbaude@redhat.com>
+Also-By: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
+---
+ grub-core/Makefile.core.def          |   1 +
+ grub-core/kern/misc.c                | 107 ++++++++++++++++++++++++++++
+ include/grub/compiler.h              |  61 ++++++++++++++++
+ include/grub/libgcc.h                |  67 ------------------
+ grub-core/kern/powerpc/compiler-rt.S | 130 +++++++++++++++++++++++++++++++++++
+ 5 files changed, 299 insertions(+), 67 deletions(-)
+ create mode 100644 grub-core/kern/powerpc/compiler-rt.S
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 7bf1c8a5880..9ff9ae5a311 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -252,6 +252,7 @@ kernel = {
+ 
+   powerpc_ieee1275 = kern/powerpc/cache.S;
+   powerpc_ieee1275 = kern/powerpc/dl.c;
++  powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
+ 
+   sparc64_ieee1275 = kern/sparc64/cache.S;
+   sparc64_ieee1275 = kern/sparc64/dl.c;
+diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
+index a56cfe78994..a3e5056db3f 100644
+--- a/grub-core/kern/misc.c
++++ b/grub-core/kern/misc.c
+@@ -1345,3 +1345,110 @@ grub_real_boot_time (const char *file,
+   grub_error_pop ();
+ }
+ #endif
++
++#if defined (NO_LIBGCC)
++
++/* Based on libgcc2.c from gcc suite.  */
++int
++__ucmpdi2 (grub_uint64_t a, grub_uint64_t b)
++{
++  union component64 ac, bc;
++  ac.full = a;
++  bc.full = b;
++
++  if (ac.high < bc.high)
++    return 0;
++  else if (ac.high > bc.high)
++    return 2;
++
++  if (ac.low < bc.low)
++    return 0;
++  else if (ac.low > bc.low)
++    return 2;
++  return 1;
++}
++
++
++/* Based on libgcc2.c from gcc suite.  */
++grub_uint64_t
++__lshrdi3 (grub_uint64_t u, int b)
++{
++  if (b == 0)
++    return u;
++
++  const union component64 uu = {.full = u};
++  const int bm = 32 - b;
++  union component64 w;
++
++  if (bm <= 0)
++    {
++      w.high = 0;
++      w.low = (grub_uint32_t) uu.high >> -bm;
++    }
++  else
++    {
++      const grub_uint32_t carries = (grub_uint32_t) uu.high << bm;
++
++      w.high = (grub_uint32_t) uu.high >> b;
++      w.low = ((grub_uint32_t) uu.low >> b) | carries;
++    }
++
++  return w.full;
++}
++
++/* Based on libgcc2.c from gcc suite.  */
++grub_uint64_t
++__ashrdi3 (grub_uint64_t u, int b)
++{
++  if (b == 0)
++    return u;
++
++  const union component64 uu = {.full = u};
++  const int bm = 32 - b;
++  union component64 w;
++
++  if (bm <= 0)
++    {
++      /* w.high = 1..1 or 0..0 */
++      w.high = uu.high >> (32 - 1);
++      w.low = uu.high >> -bm;
++    }
++  else
++    {
++      const grub_uint32_t carries = (grub_uint32_t) uu.high << bm;
++
++      w.high = uu.high >> b;
++      w.low = ((grub_uint32_t) uu.low >> b) | carries;
++    }
++
++  return w.full;
++}
++
++/* Based on libgcc2.c from gcc suite.  */
++grub_uint64_t
++__ashldi3 (grub_uint64_t u, int b)
++{
++  if (b == 0)
++    return u;
++
++  const union component64 uu = {.full = u};
++  const int bm = 32 - b;
++  union component64 w;
++
++  if (bm <= 0)
++    {
++      w.low = 0;
++      w.high = (grub_uint32_t) uu.low << -bm;
++    }
++  else
++    {
++      const grub_uint32_t carries = (grub_uint32_t) uu.low >> bm;
++
++      w.low = (grub_uint32_t) uu.low << b;
++      w.high = ((grub_uint32_t) uu.high << b) | carries;
++    }
++
++  return w.full;
++}
++
++#endif
+diff --git a/include/grub/compiler.h b/include/grub/compiler.h
+index c9e1d7a73dc..a9a684ccba6 100644
+--- a/include/grub/compiler.h
++++ b/include/grub/compiler.h
+@@ -48,4 +48,65 @@
+ #  define WARN_UNUSED_RESULT
+ #endif
+ 
++#include "types.h"
++
++union component64
++{
++  grub_uint64_t full;
++  struct
++  {
++#ifdef GRUB_CPU_WORDS_BIGENDIAN
++    grub_uint32_t high;
++    grub_uint32_t low;
++#else
++    grub_uint32_t low;
++    grub_uint32_t high;
++#endif
++  };
++};
++
++#if defined (__powerpc__)
++grub_uint64_t EXPORT_FUNC (__lshrdi3) (grub_uint64_t u, int b);
++grub_uint64_t EXPORT_FUNC (__ashrdi3) (grub_uint64_t u, int b);
++grub_uint64_t EXPORT_FUNC (__ashldi3) (grub_uint64_t u, int b);
++int EXPORT_FUNC(__ucmpdi2) (grub_uint64_t a, grub_uint64_t b);
++void EXPORT_FUNC (_restgpr_14_x) (void);
++void EXPORT_FUNC (_restgpr_15_x) (void);
++void EXPORT_FUNC (_restgpr_16_x) (void);
++void EXPORT_FUNC (_restgpr_17_x) (void);
++void EXPORT_FUNC (_restgpr_18_x) (void);
++void EXPORT_FUNC (_restgpr_19_x) (void);
++void EXPORT_FUNC (_restgpr_20_x) (void);
++void EXPORT_FUNC (_restgpr_21_x) (void);
++void EXPORT_FUNC (_restgpr_22_x) (void);
++void EXPORT_FUNC (_restgpr_23_x) (void);
++void EXPORT_FUNC (_restgpr_24_x) (void);
++void EXPORT_FUNC (_restgpr_25_x) (void);
++void EXPORT_FUNC (_restgpr_26_x) (void);
++void EXPORT_FUNC (_restgpr_27_x) (void);
++void EXPORT_FUNC (_restgpr_28_x) (void);
++void EXPORT_FUNC (_restgpr_29_x) (void);
++void EXPORT_FUNC (_restgpr_30_x) (void);
++void EXPORT_FUNC (_restgpr_31_x) (void);
++void EXPORT_FUNC (_savegpr_14) (void);
++void EXPORT_FUNC (_savegpr_15) (void);
++void EXPORT_FUNC (_savegpr_16) (void);
++void EXPORT_FUNC (_savegpr_17) (void);
++void EXPORT_FUNC (_savegpr_18) (void);
++void EXPORT_FUNC (_savegpr_19) (void);
++void EXPORT_FUNC (_savegpr_20) (void);
++void EXPORT_FUNC (_savegpr_21) (void);
++void EXPORT_FUNC (_savegpr_22) (void);
++void EXPORT_FUNC (_savegpr_23) (void);
++void EXPORT_FUNC (_savegpr_24) (void);
++void EXPORT_FUNC (_savegpr_25) (void);
++void EXPORT_FUNC (_savegpr_26) (void);
++void EXPORT_FUNC (_savegpr_27) (void);
++void EXPORT_FUNC (_savegpr_28) (void);
++void EXPORT_FUNC (_savegpr_29) (void);
++void EXPORT_FUNC (_savegpr_30) (void);
++void EXPORT_FUNC (_savegpr_31) (void);
++
++#endif
++
+ #endif /* ! GRUB_COMPILER_HEADER */
+diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h
+index 8e93b6792d9..5bdb8fb5cb9 100644
+--- a/include/grub/libgcc.h
++++ b/include/grub/libgcc.h
+@@ -16,73 +16,6 @@
+  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+  */
+ 
+-/* We need to include config-util.h.in for HAVE_*.  */
+-#ifndef __STDC_VERSION__
+-#define __STDC_VERSION__ 0
+-#endif
+-#include <config-util.h>
+-
+-/* On x86 these functions aren't really needed. Save some space.  */
+-#if !defined (__i386__) && !defined (__x86_64__)
+-# ifdef HAVE___ASHLDI3
+-void EXPORT_FUNC (__ashldi3) (void);
+-# endif
+-# ifdef HAVE___ASHRDI3
+-void EXPORT_FUNC (__ashrdi3) (void);
+-# endif
+-# ifdef HAVE___LSHRDI3
+-void EXPORT_FUNC (__lshrdi3) (void);
+-# endif
+-# ifdef HAVE___UCMPDI2
+-void EXPORT_FUNC (__ucmpdi2) (void);
+-# endif
+-# ifdef HAVE___BSWAPSI2
+-void EXPORT_FUNC (__bswapsi2) (void);
+-# endif
+-# ifdef HAVE___BSWAPDI2
+-void EXPORT_FUNC (__bswapdi2) (void);
+-# endif
+-#endif
+-
+-#ifdef HAVE__RESTGPR_14_X
+-void EXPORT_FUNC (_restgpr_14_x) (void);
+-void EXPORT_FUNC (_restgpr_15_x) (void);
+-void EXPORT_FUNC (_restgpr_16_x) (void);
+-void EXPORT_FUNC (_restgpr_17_x) (void);
+-void EXPORT_FUNC (_restgpr_18_x) (void);
+-void EXPORT_FUNC (_restgpr_19_x) (void);
+-void EXPORT_FUNC (_restgpr_20_x) (void);
+-void EXPORT_FUNC (_restgpr_21_x) (void);
+-void EXPORT_FUNC (_restgpr_22_x) (void);
+-void EXPORT_FUNC (_restgpr_23_x) (void);
+-void EXPORT_FUNC (_restgpr_24_x) (void);
+-void EXPORT_FUNC (_restgpr_25_x) (void);
+-void EXPORT_FUNC (_restgpr_26_x) (void);
+-void EXPORT_FUNC (_restgpr_27_x) (void);
+-void EXPORT_FUNC (_restgpr_28_x) (void);
+-void EXPORT_FUNC (_restgpr_29_x) (void);
+-void EXPORT_FUNC (_restgpr_30_x) (void);
+-void EXPORT_FUNC (_restgpr_31_x) (void);
+-void EXPORT_FUNC (_savegpr_14) (void);
+-void EXPORT_FUNC (_savegpr_15) (void);
+-void EXPORT_FUNC (_savegpr_16) (void);
+-void EXPORT_FUNC (_savegpr_17) (void);
+-void EXPORT_FUNC (_savegpr_18) (void);
+-void EXPORT_FUNC (_savegpr_19) (void);
+-void EXPORT_FUNC (_savegpr_20) (void);
+-void EXPORT_FUNC (_savegpr_21) (void);
+-void EXPORT_FUNC (_savegpr_22) (void);
+-void EXPORT_FUNC (_savegpr_23) (void);
+-void EXPORT_FUNC (_savegpr_24) (void);
+-void EXPORT_FUNC (_savegpr_25) (void);
+-void EXPORT_FUNC (_savegpr_26) (void);
+-void EXPORT_FUNC (_savegpr_27) (void);
+-void EXPORT_FUNC (_savegpr_28) (void);
+-void EXPORT_FUNC (_savegpr_29) (void);
+-void EXPORT_FUNC (_savegpr_30) (void);
+-void EXPORT_FUNC (_savegpr_31) (void);
+-#endif
+-
+ #if defined (__arm__)
+ void EXPORT_FUNC (__aeabi_lasr) (void);
+ void EXPORT_FUNC (__aeabi_llsl) (void);
+diff --git a/grub-core/kern/powerpc/compiler-rt.S b/grub-core/kern/powerpc/compiler-rt.S
+new file mode 100644
+index 00000000000..63e3a0d4e89
+--- /dev/null
++++ b/grub-core/kern/powerpc/compiler-rt.S
+@@ -0,0 +1,130 @@
++/*
++ * Special support for eabi and SVR4
++ *
++ *   Copyright (C) 1995-2014 Free Software Foundation, Inc.
++ *   Written By Michael Meissner
++ *   64-bit support written by David Edelsohn
++ *
++ * This file 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 3, or (at your option) any
++ * later version.
++ *
++ * This file 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.
++ *
++ * Under Section 7 of GPL version 3, you are granted additional
++ * permissions described in the GCC Runtime Library Exception, version
++ * 3.1, as published by the Free Software Foundation.
++ *
++ * You should have received a copy of the GNU General Public License and
++ * a copy of the GCC Runtime Library Exception along with this program;
++ * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
++ * <http://www.gnu.org/licenses/>.
++ */
++
++/* Do any initializations needed for the eabi environment */
++
++#include <grub/symbol.h>
++#include <grub/dl.h>
++
++	.section ".text"
++
++#define CFI_RESTORE(reg)		.cfi_restore reg
++#define CFI_OFFSET(reg, off)		.cfi_offset reg, off
++#define CFI_DEF_CFA_REGISTER(reg)	.cfi_def_cfa_register reg
++#define CFI_STARTPROC			.cfi_startproc
++#define CFI_ENDPROC			.cfi_endproc
++
++/* Routines for restoring integer registers, called by the compiler.  */
++/* Called with r11 pointing to the stack header word of the caller of the */
++/* function, just beyond the end of the integer restore area.  */
++
++CFI_STARTPROC
++CFI_DEF_CFA_REGISTER (11)
++CFI_OFFSET (65, 4)
++CFI_OFFSET (14, -72)
++CFI_OFFSET (15, -68)
++CFI_OFFSET (16, -64)
++CFI_OFFSET (17, -60)
++CFI_OFFSET (18, -56)
++CFI_OFFSET (19, -52)
++CFI_OFFSET (20, -48)
++CFI_OFFSET (21, -44)
++CFI_OFFSET (22, -40)
++CFI_OFFSET (23, -36)
++CFI_OFFSET (24, -32)
++CFI_OFFSET (25, -28)
++CFI_OFFSET (26, -24)
++CFI_OFFSET (27, -20)
++CFI_OFFSET (28, -16)
++CFI_OFFSET (29, -12)
++CFI_OFFSET (30, -8)
++CFI_OFFSET (31, -4)
++FUNCTION(_restgpr_14_x)	lwz	14,-72(11)	/* restore gp registers */
++CFI_RESTORE (14)
++FUNCTION(_restgpr_15_x)	lwz	15,-68(11)
++CFI_RESTORE (15)
++FUNCTION(_restgpr_16_x)	lwz	16,-64(11)
++CFI_RESTORE (16)
++FUNCTION(_restgpr_17_x)	lwz	17,-60(11)
++CFI_RESTORE (17)
++FUNCTION(_restgpr_18_x)	lwz	18,-56(11)
++CFI_RESTORE (18)
++FUNCTION(_restgpr_19_x)	lwz	19,-52(11)
++CFI_RESTORE (19)
++FUNCTION(_restgpr_20_x)	lwz	20,-48(11)
++CFI_RESTORE (20)
++FUNCTION(_restgpr_21_x)	lwz	21,-44(11)
++CFI_RESTORE (21)
++FUNCTION(_restgpr_22_x)	lwz	22,-40(11)
++CFI_RESTORE (22)
++FUNCTION(_restgpr_23_x)	lwz	23,-36(11)
++CFI_RESTORE (23)
++FUNCTION(_restgpr_24_x)	lwz	24,-32(11)
++CFI_RESTORE (24)
++FUNCTION(_restgpr_25_x)	lwz	25,-28(11)
++CFI_RESTORE (25)
++FUNCTION(_restgpr_26_x)	lwz	26,-24(11)
++CFI_RESTORE (26)
++FUNCTION(_restgpr_27_x)	lwz	27,-20(11)
++CFI_RESTORE (27)
++FUNCTION(_restgpr_28_x)	lwz	28,-16(11)
++CFI_RESTORE (28)
++FUNCTION(_restgpr_29_x)	lwz	29,-12(11)
++CFI_RESTORE (29)
++FUNCTION(_restgpr_30_x)	lwz	30,-8(11)
++CFI_RESTORE (30)
++FUNCTION(_restgpr_31_x)	lwz	0,4(11)
++				lwz	31,-4(11)
++CFI_RESTORE (31)
++				mtlr	0
++CFI_RESTORE (65)
++				mr	1,11
++CFI_DEF_CFA_REGISTER (1)
++				blr
++CFI_ENDPROC
++
++CFI_STARTPROC
++FUNCTION(_savegpr_14)	stw	14,-72(11)	/* save gp registers */
++FUNCTION(_savegpr_15)	stw	15,-68(11)
++FUNCTION(_savegpr_16)	stw	16,-64(11)
++FUNCTION(_savegpr_17)	stw	17,-60(11)
++FUNCTION(_savegpr_18)	stw	18,-56(11)
++FUNCTION(_savegpr_19)	stw	19,-52(11)
++FUNCTION(_savegpr_20)	stw	20,-48(11)
++FUNCTION(_savegpr_21)	stw	21,-44(11)
++FUNCTION(_savegpr_22)	stw	22,-40(11)
++FUNCTION(_savegpr_23)	stw	23,-36(11)
++FUNCTION(_savegpr_24)	stw	24,-32(11)
++FUNCTION(_savegpr_25)	stw	25,-28(11)
++FUNCTION(_savegpr_26)	stw	26,-24(11)
++FUNCTION(_savegpr_27)	stw	27,-20(11)
++FUNCTION(_savegpr_28)	stw	28,-16(11)
++FUNCTION(_savegpr_29)	stw	29,-12(11)
++FUNCTION(_savegpr_30)	stw	30,-8(11)
++FUNCTION(_savegpr_31)	stw	31,-4(11)
++			blr
++CFI_ENDPROC
diff --git a/SOURCES/0143-Suport-for-bi-endianess-in-elf-file.patch b/SOURCES/0143-Suport-for-bi-endianess-in-elf-file.patch
new file mode 100644
index 0000000..e7089ab
--- /dev/null
+++ b/SOURCES/0143-Suport-for-bi-endianess-in-elf-file.patch
@@ -0,0 +1,199 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paulo Flabiano Smorigo <pfsmorigo@linux.vnet.ibm.com>
+Date: Fri, 15 Aug 2014 14:39:53 -0300
+Subject: [PATCH] Suport for bi-endianess in elf file
+
+* grub-core/kern/elf.c: check and switch endianess with grub_{be,le}_to
+  cpu functions.
+* grub-core/kern/elfXX.c: Likewise.
+
+Also-by: Tomohiro B Berry <tbberry@us.ibm.com>
+---
+ grub-core/kern/elf.c   | 60 +++++++++++++++++++++++++++++++++++++++--
+ grub-core/kern/elfXX.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 131 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/kern/elf.c b/grub-core/kern/elf.c
+index 5f99c43cc81..de9081180f0 100644
+--- a/grub-core/kern/elf.c
++++ b/grub-core/kern/elf.c
+@@ -28,6 +28,11 @@
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
++void grub_elf32_check_endianess (grub_elf_t elf);
++void grub_elf64_check_endianess (grub_elf_t elf);
++grub_err_t grub_elf32_check_version (grub_elf_t elf);
++grub_err_t grub_elf64_check_version (grub_elf_t elf);
++
+ /* Check if EHDR is a valid ELF header.  */
+ static grub_err_t
+ grub_elf_check_header (grub_elf_t elf)
+@@ -38,10 +43,22 @@ grub_elf_check_header (grub_elf_t elf)
+       || e->e_ident[EI_MAG1] != ELFMAG1
+       || e->e_ident[EI_MAG2] != ELFMAG2
+       || e->e_ident[EI_MAG3] != ELFMAG3
+-      || e->e_ident[EI_VERSION] != EV_CURRENT
+-      || e->e_version != EV_CURRENT)
++      || e->e_ident[EI_VERSION] != EV_CURRENT)
+     return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-independent ELF magic"));
+ 
++  if (grub_elf_is_elf32 (elf))
++    {
++      grub_elf32_check_endianess (elf);
++      grub_elf32_check_version (elf);
++    }
++  else if (grub_elf_is_elf64 (elf))
++    {
++      grub_elf64_check_endianess (elf);
++      grub_elf64_check_version (elf);
++    }
++  else
++    return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic"));
++
+   return GRUB_ERR_NONE;
+ }
+ 
+@@ -127,7 +144,20 @@ grub_elf_open (const char *name)
+ #define grub_elf_is_elfXX grub_elf_is_elf32
+ #define grub_elfXX_load_phdrs grub_elf32_load_phdrs
+ #define ElfXX_Phdr Elf32_Phdr
++#define ElfXX_Ehdr Elf32_Ehdr
+ #define grub_uintXX_t grub_uint32_t
++#define grub_be_to_halfXX grub_be_to_cpu16
++#define grub_be_to_wordXX grub_be_to_cpu32
++#define grub_be_to_addrXX grub_be_to_cpu32
++#define grub_be_to_offXX grub_be_to_cpu32
++#define grub_be_to_XwordXX grub_be_to_wordXX
++#define grub_le_to_halfXX grub_le_to_cpu16
++#define grub_le_to_wordXX grub_le_to_cpu32
++#define grub_le_to_addrXX grub_le_to_cpu32
++#define grub_le_to_offXX grub_le_to_cpu32
++#define grub_le_to_XwordXX grub_le_to_wordXX
++#define grub_elfXX_check_endianess grub_elf32_check_endianess
++#define grub_elfXX_check_version grub_elf32_check_version
+ 
+ #include "elfXX.c"
+ 
+@@ -140,7 +170,20 @@ grub_elf_open (const char *name)
+ #undef grub_elf_is_elfXX
+ #undef grub_elfXX_load_phdrs
+ #undef ElfXX_Phdr
++#undef ElfXX_Ehdr
+ #undef grub_uintXX_t
++#undef grub_be_to_halfXX
++#undef grub_be_to_wordXX
++#undef grub_be_to_addrXX
++#undef grub_be_to_offXX
++#undef grub_be_to_XwordXX
++#undef grub_le_to_halfXX
++#undef grub_le_to_wordXX
++#undef grub_le_to_addrXX
++#undef grub_le_to_offXX
++#undef grub_le_to_XwordXX
++#undef grub_elfXX_check_endianess
++#undef grub_elfXX_check_version
+ 
+ 
+ /* 64-bit */
+@@ -153,6 +196,19 @@ grub_elf_open (const char *name)
+ #define grub_elf_is_elfXX grub_elf_is_elf64
+ #define grub_elfXX_load_phdrs grub_elf64_load_phdrs
+ #define ElfXX_Phdr Elf64_Phdr
++#define ElfXX_Ehdr Elf64_Ehdr
+ #define grub_uintXX_t grub_uint64_t
++#define grub_be_to_halfXX grub_be_to_cpu16
++#define grub_be_to_wordXX grub_be_to_cpu32
++#define grub_be_to_addrXX grub_be_to_cpu64
++#define grub_be_to_offXX grub_be_to_cpu64
++#define grub_be_to_XwordXX grub_be_to_cpu64
++#define grub_le_to_halfXX grub_le_to_cpu16
++#define grub_le_to_wordXX grub_le_to_cpu32
++#define grub_le_to_addrXX grub_le_to_cpu64
++#define grub_le_to_offXX grub_le_to_cpu64
++#define grub_le_to_XwordXX grub_le_to_cpu64
++#define grub_elfXX_check_endianess grub_elf64_check_endianess
++#define grub_elfXX_check_version grub_elf64_check_version
+ 
+ #include "elfXX.c"
+diff --git a/grub-core/kern/elfXX.c b/grub-core/kern/elfXX.c
+index 1d0997186f7..ecf9df63a5e 100644
+--- a/grub-core/kern/elfXX.c
++++ b/grub-core/kern/elfXX.c
+@@ -154,3 +154,76 @@ grub_elfXX_load (grub_elf_t elf, const char *filename,
+ 
+   return grub_errno;
+ }
++
++void
++grub_elfXX_check_endianess (grub_elf_t elf)
++{
++  ElfXX_Ehdr *e = &(elf->ehdr.ehdrXX);
++  ElfXX_Phdr *phdr;
++
++  if (e->e_ident[EI_DATA] == ELFDATA2MSB)
++    {
++      e->e_type = grub_be_to_halfXX (e->e_type);
++      e->e_machine = grub_be_to_halfXX (e->e_machine);
++      e->e_version = grub_be_to_wordXX (e->e_version);
++      e->e_entry = grub_be_to_addrXX (e->e_entry);
++      e->e_phoff = grub_be_to_offXX (e->e_phoff);
++      e->e_shoff = grub_be_to_offXX (e->e_shoff);
++      e->e_flags = grub_be_to_wordXX (e->e_flags);
++      e->e_ehsize = grub_be_to_halfXX (e->e_ehsize);
++      e->e_phentsize = grub_be_to_halfXX (e->e_phentsize);
++      e->e_phnum = grub_be_to_halfXX (e->e_phnum);
++      e->e_shentsize = grub_be_to_halfXX (e->e_shentsize);
++      e->e_shnum = grub_be_to_halfXX (e->e_shnum);
++      e->e_shstrndx = grub_be_to_halfXX (e->e_shstrndx);
++
++      FOR_ELFXX_PHDRS (elf,phdr)
++        {
++          phdr->p_type = grub_be_to_wordXX (phdr->p_type);
++          phdr->p_flags = grub_be_to_wordXX (phdr->p_flags);
++          phdr->p_offset = grub_be_to_offXX (phdr->p_offset);
++          phdr->p_vaddr = grub_be_to_addrXX (phdr->p_vaddr);
++          phdr->p_paddr = grub_be_to_addrXX (phdr->p_paddr);
++          phdr->p_filesz = grub_be_to_XwordXX (phdr->p_filesz);
++          phdr->p_memsz = grub_be_to_XwordXX (phdr->p_memsz);
++          phdr->p_align = grub_be_to_XwordXX (phdr->p_align);
++        }
++    }
++  else if (e->e_ident[EI_DATA] == ELFDATA2LSB)
++    {
++      e->e_type = grub_le_to_halfXX (e->e_type);
++      e->e_machine = grub_le_to_halfXX (e->e_machine);
++      e->e_version = grub_le_to_wordXX (e->e_version);
++      e->e_entry = grub_le_to_addrXX (e->e_entry);
++      e->e_phoff = grub_le_to_offXX (e->e_phoff);
++      e->e_shoff = grub_le_to_offXX (e->e_shoff);
++      e->e_flags = grub_le_to_wordXX (e->e_flags);
++      e->e_ehsize = grub_le_to_halfXX (e->e_ehsize);
++      e->e_phentsize = grub_le_to_halfXX (e->e_phentsize);
++      e->e_phnum = grub_le_to_halfXX (e->e_phnum);
++      e->e_shentsize = grub_le_to_halfXX (e->e_shentsize);
++      e->e_shnum = grub_le_to_halfXX (e->e_shnum);
++      e->e_shstrndx = grub_le_to_halfXX (e->e_shstrndx);
++
++      FOR_ELFXX_PHDRS (elf,phdr)
++        {
++          phdr->p_type = grub_le_to_wordXX (phdr->p_type);
++          phdr->p_flags = grub_le_to_wordXX (phdr->p_flags);
++          phdr->p_offset = grub_le_to_offXX (phdr->p_offset);
++          phdr->p_vaddr = grub_le_to_addrXX (phdr->p_vaddr);
++          phdr->p_paddr = grub_le_to_addrXX (phdr->p_paddr);
++          phdr->p_filesz = grub_le_to_XwordXX (phdr->p_filesz);
++          phdr->p_memsz = grub_le_to_XwordXX (phdr->p_memsz);
++          phdr->p_align = grub_le_to_XwordXX (phdr->p_align);
++        }
++    }
++}
++
++grub_err_t
++grub_elfXX_check_version (grub_elf_t elf)
++{
++  if (elf->ehdr.ehdrXX.e_version != EV_CURRENT)
++    return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-independent ELF magic"));
++
++  return GRUB_ERR_NONE;
++}
diff --git a/SOURCES/0144-Fix-exit-back-to-EFI-firmware.patch b/SOURCES/0144-Fix-exit-back-to-EFI-firmware.patch
new file mode 100644
index 0000000..5478dd2
--- /dev/null
+++ b/SOURCES/0144-Fix-exit-back-to-EFI-firmware.patch
@@ -0,0 +1,49 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Fedora Ninjas <grub2-owner@fedoraproject.org>
+Date: Fri, 15 Aug 2014 11:29:22 -0400
+Subject: [PATCH] Fix exit back to EFI firmware
+
+Arm/AArch64 machines set up a timer event which is not getting
+canceled when returning to firmware. This is because grub_exit()
+calls grub_efi_fini() instead of grub_machine_fini(). The latter
+will shutdown the timer (and other machine-specific things) as
+well as make the call to grub_efi_fini().
+---
+ grub-core/kern/arm/efi/init.c | 2 +-
+ grub-core/kern/efi/efi.c      | 3 ++-
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/kern/arm/efi/init.c b/grub-core/kern/arm/efi/init.c
+index 0c17d8390fa..06df60e2f0e 100644
+--- a/grub-core/kern/arm/efi/init.c
++++ b/grub-core/kern/arm/efi/init.c
+@@ -67,7 +67,7 @@ grub_machine_fini (int flags)
+ 
+   b = grub_efi_system_table->boot_services;
+ 
+-  efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 0);
++  efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_CANCEL, 0);
+   efi_call_1 (b->close_event, tmr_evt);
+ 
+   grub_efi_fini ();
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index 1a8dba531b6..d99a6fbdf0d 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -27,6 +27,7 @@
+ #include <grub/term.h>
+ #include <grub/kernel.h>
+ #include <grub/mm.h>
++#include <grub/loader.h>
+ 
+ /* The handle of GRUB itself. Filled in by the startup code.  */
+ grub_efi_handle_t grub_efi_image_handle;
+@@ -156,7 +157,7 @@ grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
+ void
+ grub_exit (void)
+ {
+-  grub_efi_fini ();
++  grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
+   efi_call_4 (grub_efi_system_table->boot_services->exit,
+               grub_efi_image_handle, GRUB_EFI_LOAD_ERROR, 0, 0);
+   for (;;) ;
diff --git a/SOURCES/0145-Add-grub_util_readlink.patch b/SOURCES/0145-Add-grub_util_readlink.patch
new file mode 100644
index 0000000..122f799
--- /dev/null
+++ b/SOURCES/0145-Add-grub_util_readlink.patch
@@ -0,0 +1,3731 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 3 Sep 2014 10:01:03 -0400
+Subject: [PATCH] Add grub_util_readlink()
+
+Add grub_util_readlink().  This requires pulling in stat and readlink from
+gnulib, which pulls in stat and related headers, but after that the
+implementation is straightforward.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Reviewed-by: Adam Jackson <ajax@redhat.com>
+---
+ grub-core/gnulib/gettimeofday.c       | 154 +++++++
+ grub-core/gnulib/readlink.c           |  74 ++++
+ grub-core/gnulib/stat.c               | 138 +++++++
+ grub-core/osdep/windows/hostdisk.c    |   6 +
+ grub-core/gnulib/pathmax.h            |  83 ++++
+ grub-core/gnulib/sys_stat.in.h        | 732 ++++++++++++++++++++++++++++++++++
+ grub-core/gnulib/sys_time.in.h        | 213 ++++++++++
+ grub-core/gnulib/sys_types.in.h       |   2 +
+ grub-core/gnulib/time.h               | 586 +++++++++++++++++++++++++++
+ grub-core/gnulib/time.in.h            | 274 +++++++++++++
+ include/grub/osdep/hostfile_aros.h    |   6 +
+ include/grub/osdep/hostfile_unix.h    |   6 +
+ include/grub/osdep/hostfile_windows.h |   2 +
+ grub-core/gnulib/Makefile.am          | 177 +++++++-
+ m4/gettimeofday.m4                    | 138 +++++++
+ m4/gnulib-cache.m4                    |   3 +-
+ m4/gnulib-comp.m4                     |  49 +++
+ m4/largefile.m4                       | 146 +++++++
+ m4/pathmax.m4                         |  42 ++
+ m4/readlink.m4                        |  71 ++++
+ m4/stat.m4                            |  71 ++++
+ m4/sys_stat_h.m4                      |  96 +++++
+ m4/sys_time_h.m4                      | 110 +++++
+ m4/time_h.m4                          | 118 ++++++
+ 24 files changed, 3295 insertions(+), 2 deletions(-)
+ create mode 100644 grub-core/gnulib/gettimeofday.c
+ create mode 100644 grub-core/gnulib/readlink.c
+ create mode 100644 grub-core/gnulib/stat.c
+ create mode 100644 grub-core/gnulib/pathmax.h
+ create mode 100644 grub-core/gnulib/sys_stat.in.h
+ create mode 100644 grub-core/gnulib/sys_time.in.h
+ create mode 100644 grub-core/gnulib/time.h
+ create mode 100644 grub-core/gnulib/time.in.h
+ create mode 100644 m4/gettimeofday.m4
+ create mode 100644 m4/largefile.m4
+ create mode 100644 m4/pathmax.m4
+ create mode 100644 m4/readlink.m4
+ create mode 100644 m4/stat.m4
+ create mode 100644 m4/sys_stat_h.m4
+ create mode 100644 m4/sys_time_h.m4
+ create mode 100644 m4/time_h.m4
+
+diff --git a/grub-core/gnulib/gettimeofday.c b/grub-core/gnulib/gettimeofday.c
+new file mode 100644
+index 00000000000..8b2058e8c87
+--- /dev/null
++++ b/grub-core/gnulib/gettimeofday.c
+@@ -0,0 +1,154 @@
++/* Provide gettimeofday for systems that don't have it or for which it's broken.
++
++   Copyright (C) 2001-2003, 2005-2007, 2009-2014 Free Software Foundation, Inc.
++
++   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 3, 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/>.  */
++
++/* written by Jim Meyering */
++
++#include <config.h>
++
++/* Specification.  */
++#include <sys/time.h>
++
++#include <time.h>
++
++#if HAVE_SYS_TIMEB_H
++# include <sys/timeb.h>
++#endif
++
++#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME
++
++/* Work around the bug in some systems whereby gettimeofday clobbers
++   the static buffer that localtime uses for its return value.  The
++   gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has
++   this problem.  The tzset replacement is necessary for at least
++   Solaris 2.5, 2.5.1, and 2.6.  */
++
++static struct tm tm_zero_buffer;
++static struct tm *localtime_buffer_addr = &tm_zero_buffer;
++
++# undef localtime
++extern struct tm *localtime (time_t const *);
++
++# undef gmtime
++extern struct tm *gmtime (time_t const *);
++
++/* This is a wrapper for localtime.  It is used only on systems for which
++   gettimeofday clobbers the static buffer used for localtime's result.
++
++   On the first call, record the address of the static buffer that
++   localtime uses for its result.  */
++
++struct tm *
++rpl_localtime (time_t const *timep)
++{
++  struct tm *tm = localtime (timep);
++
++  if (localtime_buffer_addr == &tm_zero_buffer)
++    localtime_buffer_addr = tm;
++
++  return tm;
++}
++
++/* Same as above, since gmtime and localtime use the same buffer.  */
++struct tm *
++rpl_gmtime (time_t const *timep)
++{
++  struct tm *tm = gmtime (timep);
++
++  if (localtime_buffer_addr == &tm_zero_buffer)
++    localtime_buffer_addr = tm;
++
++  return tm;
++}
++
++#endif /* GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME */
++
++#if TZSET_CLOBBERS_LOCALTIME
++
++# undef tzset
++extern void tzset (void);
++
++/* This is a wrapper for tzset, for systems on which tzset may clobber
++   the static buffer used for localtime's result.  */
++void
++rpl_tzset (void)
++{
++  /* Save and restore the contents of the buffer used for localtime's
++     result around the call to tzset.  */
++  struct tm save = *localtime_buffer_addr;
++  tzset ();
++  *localtime_buffer_addr = save;
++}
++#endif
++
++/* This is a wrapper for gettimeofday.  It is used only on systems
++   that lack this function, or whose implementation of this function
++   causes problems.  */
++
++int
++gettimeofday (struct timeval *restrict tv, void *restrict tz)
++{
++#undef gettimeofday
++#if HAVE_GETTIMEOFDAY
++# if GETTIMEOFDAY_CLOBBERS_LOCALTIME
++  /* Save and restore the contents of the buffer used for localtime's
++     result around the call to gettimeofday.  */
++  struct tm save = *localtime_buffer_addr;
++# endif
++
++# if defined timeval /* 'struct timeval' overridden by gnulib?  */
++#  undef timeval
++  struct timeval otv;
++  int result = gettimeofday (&otv, (struct timezone *) tz);
++  if (result == 0)
++    {
++      tv->tv_sec = otv.tv_sec;
++      tv->tv_usec = otv.tv_usec;
++    }
++# else
++  int result = gettimeofday (tv, (struct timezone *) tz);
++# endif
++
++# if GETTIMEOFDAY_CLOBBERS_LOCALTIME
++  *localtime_buffer_addr = save;
++# endif
++
++  return result;
++
++#else
++
++# if HAVE__FTIME
++
++  struct _timeb timebuf;
++  _ftime (&timebuf);
++  tv->tv_sec = timebuf.time;
++  tv->tv_usec = timebuf.millitm * 1000;
++
++# else
++
++#  if !defined OK_TO_USE_1S_CLOCK
++#   error "Only 1-second nominal clock resolution found.  Is that intended?" \
++          "If so, compile with the -DOK_TO_USE_1S_CLOCK option."
++#  endif
++  tv->tv_sec = time (NULL);
++  tv->tv_usec = 0;
++
++# endif
++
++  return 0;
++
++#endif
++}
+diff --git a/grub-core/gnulib/readlink.c b/grub-core/gnulib/readlink.c
+new file mode 100644
+index 00000000000..4c496395176
+--- /dev/null
++++ b/grub-core/gnulib/readlink.c
+@@ -0,0 +1,74 @@
++/* Stub for readlink().
++   Copyright (C) 2003-2007, 2009-2014 Free Software Foundation, Inc.
++
++   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 3 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/>.  */
++
++#include <config.h>
++
++/* Specification.  */
++#include <unistd.h>
++
++#include <errno.h>
++#include <string.h>
++#include <sys/stat.h>
++
++#if !HAVE_READLINK
++
++/* readlink() substitute for systems that don't have a readlink() function,
++   such as DJGPP 2.03 and mingw32.  */
++
++ssize_t
++readlink (const char *name, char *buf _GL_UNUSED,
++          size_t bufsize _GL_UNUSED)
++{
++  struct stat statbuf;
++
++  /* In general we should use lstat() here, not stat().  But on platforms
++     without symbolic links, lstat() - if it exists - would be equivalent to
++     stat(), therefore we can use stat().  This saves us a configure check.  */
++  if (stat (name, &statbuf) >= 0)
++    errno = EINVAL;
++  return -1;
++}
++
++#else /* HAVE_READLINK */
++
++# undef readlink
++
++/* readlink() wrapper that uses correct types, for systems like cygwin
++   1.5.x where readlink returns int, and which rejects trailing slash,
++   for Solaris 9.  */
++
++ssize_t
++rpl_readlink (const char *name, char *buf, size_t bufsize)
++{
++# if READLINK_TRAILING_SLASH_BUG
++  size_t len = strlen (name);
++  if (len && name[len - 1] == '/')
++    {
++      /* Even if name without the slash is a symlink to a directory,
++         both lstat() and stat() must resolve the trailing slash to
++         the directory rather than the symlink.  We can therefore
++         safely use stat() to distinguish between EINVAL and
++         ENOTDIR/ENOENT, avoiding extra overhead of rpl_lstat().  */
++      struct stat st;
++      if (stat (name, &st) == 0)
++        errno = EINVAL;
++      return -1;
++    }
++# endif /* READLINK_TRAILING_SLASH_BUG */
++  return readlink (name, buf, bufsize);
++}
++
++#endif /* HAVE_READLINK */
+diff --git a/grub-core/gnulib/stat.c b/grub-core/gnulib/stat.c
+new file mode 100644
+index 00000000000..35f4b0b1a51
+--- /dev/null
++++ b/grub-core/gnulib/stat.c
+@@ -0,0 +1,138 @@
++/* Work around platform bugs in stat.
++   Copyright (C) 2009-2014 Free Software Foundation, Inc.
++
++   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 3 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/>.  */
++
++/* written by Eric Blake */
++
++/* If the user's config.h happens to include <sys/stat.h>, let it include only
++   the system's <sys/stat.h> here, so that orig_stat doesn't recurse to
++   rpl_stat.  */
++#define __need_system_sys_stat_h
++#include <config.h>
++
++/* Get the original definition of stat.  It might be defined as a macro.  */
++#include <sys/types.h>
++#include <sys/stat.h>
++#undef __need_system_sys_stat_h
++
++#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
++# if _GL_WINDOWS_64_BIT_ST_SIZE
++#  undef stat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */
++#  define stat _stati64
++#  define REPLACE_FUNC_STAT_DIR 1
++#  undef REPLACE_FUNC_STAT_FILE
++# elif REPLACE_FUNC_STAT_FILE
++/* mingw64 has a broken stat() function, based on _stat(), in libmingwex.a.
++   Bypass it.  */
++#  define stat _stat
++#  define REPLACE_FUNC_STAT_DIR 1
++#  undef REPLACE_FUNC_STAT_FILE
++# endif
++#endif
++
++static int
++orig_stat (const char *filename, struct stat *buf)
++{
++  return stat (filename, buf);
++}
++
++/* Specification.  */
++/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
++   eliminates this include because of the preliminary #include <sys/stat.h>
++   above.  */
++#include "sys/stat.h"
++
++#include <errno.h>
++#include <limits.h>
++#include <stdbool.h>
++#include <string.h>
++#include "dosname.h"
++#include "verify.h"
++
++#if REPLACE_FUNC_STAT_DIR
++# include "pathmax.h"
++  /* The only known systems where REPLACE_FUNC_STAT_DIR is needed also
++     have a constant PATH_MAX.  */
++# ifndef PATH_MAX
++#  error "Please port this replacement to your platform"
++# endif
++#endif
++
++/* Store information about NAME into ST.  Work around bugs with
++   trailing slashes.  Mingw has other bugs (such as st_ino always
++   being 0 on success) which this wrapper does not work around.  But
++   at least this implementation provides the ability to emulate fchdir
++   correctly.  */
++
++int
++rpl_stat (char const *name, struct stat *st)
++{
++  int result = orig_stat (name, st);
++#if REPLACE_FUNC_STAT_FILE
++  /* Solaris 9 mistakenly succeeds when given a non-directory with a
++     trailing slash.  */
++  if (result == 0 && !S_ISDIR (st->st_mode))
++    {
++      size_t len = strlen (name);
++      if (ISSLASH (name[len - 1]))
++        {
++          errno = ENOTDIR;
++          return -1;
++        }
++    }
++#endif /* REPLACE_FUNC_STAT_FILE */
++#if REPLACE_FUNC_STAT_DIR
++
++  if (result == -1 && errno == ENOENT)
++    {
++      /* Due to mingw's oddities, there are some directories (like
++         c:\) where stat() only succeeds with a trailing slash, and
++         other directories (like c:\windows) where stat() only
++         succeeds without a trailing slash.  But we want the two to be
++         synonymous, since chdir() manages either style.  Likewise, Mingw also
++         reports ENOENT for names longer than PATH_MAX, when we want
++         ENAMETOOLONG, and for stat("file/"), when we want ENOTDIR.
++         Fortunately, mingw PATH_MAX is small enough for stack
++         allocation.  */
++      char fixed_name[PATH_MAX + 1] = {0};
++      size_t len = strlen (name);
++      bool check_dir = false;
++      verify (PATH_MAX <= 4096);
++      if (PATH_MAX <= len)
++        errno = ENAMETOOLONG;
++      else if (len)
++        {
++          strcpy (fixed_name, name);
++          if (ISSLASH (fixed_name[len - 1]))
++            {
++              check_dir = true;
++              while (len && ISSLASH (fixed_name[len - 1]))
++                fixed_name[--len] = '\0';
++              if (!len)
++                fixed_name[0] = '/';
++            }
++          else
++            fixed_name[len++] = '/';
++          result = orig_stat (fixed_name, st);
++          if (result == 0 && check_dir && !S_ISDIR (st->st_mode))
++            {
++              result = -1;
++              errno = ENOTDIR;
++            }
++        }
++    }
++#endif /* REPLACE_FUNC_STAT_DIR */
++  return result;
++}
+diff --git a/grub-core/osdep/windows/hostdisk.c b/grub-core/osdep/windows/hostdisk.c
+index d390b25fcbe..9127e9263b1 100644
+--- a/grub-core/osdep/windows/hostdisk.c
++++ b/grub-core/osdep/windows/hostdisk.c
+@@ -353,6 +353,12 @@ grub_util_mkdir (const char *dir)
+   free (windows_name);
+ }
+ 
++ssize_t
++grub_util_readlink (const char *name, char *buf, size_t bufsize)
++{
++  return readlink(name, buf, bufsize);
++}
++
+ int
+ grub_util_rename (const char *from, const char *to)
+ {
+diff --git a/grub-core/gnulib/pathmax.h b/grub-core/gnulib/pathmax.h
+new file mode 100644
+index 00000000000..33fc3553d75
+--- /dev/null
++++ b/grub-core/gnulib/pathmax.h
+@@ -0,0 +1,83 @@
++/* Define PATH_MAX somehow.  Requires sys/types.h.
++   Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2014 Free Software
++   Foundation, Inc.
++
++   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 3, 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/>.  */
++
++#ifndef _PATHMAX_H
++# define _PATHMAX_H
++
++/* POSIX:2008 defines PATH_MAX to be the maximum number of bytes in a filename,
++   including the terminating NUL byte.
++   <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html>
++   PATH_MAX is not defined on systems which have no limit on filename length,
++   such as GNU/Hurd.
++
++   This file does *not* define PATH_MAX always.  Programs that use this file
++   can handle the GNU/Hurd case in several ways:
++     - Either with a package-wide handling, or with a per-file handling,
++     - Either through a
++         #ifdef PATH_MAX
++       or through a fallback like
++         #ifndef PATH_MAX
++         # define PATH_MAX 8192
++         #endif
++       or through a fallback like
++         #ifndef PATH_MAX
++         # define PATH_MAX pathconf ("/", _PC_PATH_MAX)
++         #endif
++ */
++
++# include <unistd.h>
++
++# include <limits.h>
++
++# ifndef _POSIX_PATH_MAX
++#  define _POSIX_PATH_MAX 256
++# endif
++
++/* Don't include sys/param.h if it already has been.  */
++# if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
++#  include <sys/param.h>
++# endif
++
++# if !defined PATH_MAX && defined MAXPATHLEN
++#  define PATH_MAX MAXPATHLEN
++# endif
++
++# ifdef __hpux
++/* On HP-UX, PATH_MAX designates the maximum number of bytes in a filename,
++   *not* including the terminating NUL byte, and is set to 1023.
++   Additionally, when _XOPEN_SOURCE is defined to 500 or more, PATH_MAX is
++   not defined at all any more.  */
++#  undef PATH_MAX
++#  define PATH_MAX 1024
++# endif
++
++# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
++/* The page "Naming Files, Paths, and Namespaces" on msdn.microsoft.com,
++   section "Maximum Path Length Limitation",
++   <http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85).aspx#maxpath>
++   explains that the maximum size of a filename, including the terminating
++   NUL byte, is 260 = 3 + 256 + 1.
++   This is the same value as
++     - FILENAME_MAX in <stdio.h>,
++     - _MAX_PATH in <stdlib.h>,
++     - MAX_PATH in <windef.h>.
++   Undefine the original value, because mingw's <limits.h> gets it wrong.  */
++#  undef PATH_MAX
++#  define PATH_MAX 260
++# endif
++
++#endif /* _PATHMAX_H */
+diff --git a/grub-core/gnulib/sys_stat.in.h b/grub-core/gnulib/sys_stat.in.h
+new file mode 100644
+index 00000000000..b47a7ff0ae7
+--- /dev/null
++++ b/grub-core/gnulib/sys_stat.in.h
+@@ -0,0 +1,732 @@
++/* Provide a more complete sys/stat header file.
++   Copyright (C) 2005-2014 Free Software Foundation, Inc.
++
++   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 3, 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/>.  */
++
++/* Written by Eric Blake, Paul Eggert, and Jim Meyering.  */
++
++/* This file is supposed to be used on platforms where <sys/stat.h> is
++   incomplete.  It is intended to provide definitions and prototypes
++   needed by an application.  Start with what the system provides.  */
++
++#if __GNUC__ >= 3
++@PRAGMA_SYSTEM_HEADER@
++#endif
++@PRAGMA_COLUMNS@
++
++#if defined __need_system_sys_stat_h
++/* Special invocation convention.  */
++
++#@INCLUDE_NEXT@ @NEXT_SYS_STAT_H@
++
++#else
++/* Normal invocation convention.  */
++
++#ifndef _@GUARD_PREFIX@_SYS_STAT_H
++
++/* Get nlink_t.
++   May also define off_t to a 64-bit type on native Windows.  */
++#include <sys/types.h>
++
++/* Get struct timespec.  */
++#include <time.h>
++
++/* The include_next requires a split double-inclusion guard.  */
++#@INCLUDE_NEXT@ @NEXT_SYS_STAT_H@
++
++#ifndef _@GUARD_PREFIX@_SYS_STAT_H
++#define _@GUARD_PREFIX@_SYS_STAT_H
++
++/* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
++
++/* The definition of _GL_ARG_NONNULL is copied here.  */
++
++/* The definition of _GL_WARN_ON_USE is copied here.  */
++
++/* Before doing "#define mkdir rpl_mkdir" below, we need to include all
++   headers that may declare mkdir().  Native Windows platforms declare mkdir
++   in <io.h> and/or <direct.h>, not in <unistd.h>.  */
++#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
++# include <io.h>     /* mingw32, mingw64 */
++# include <direct.h> /* mingw64, MSVC 9 */
++#endif
++
++/* Native Windows platforms declare umask() in <io.h>.  */
++#if 0 && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
++# include <io.h>
++#endif
++
++/* Large File Support on native Windows.  */
++#if @WINDOWS_64_BIT_ST_SIZE@
++# define stat _stati64
++#endif
++
++#ifndef S_IFIFO
++# ifdef _S_IFIFO
++#  define S_IFIFO _S_IFIFO
++# endif
++#endif
++
++#ifndef S_IFMT
++# define S_IFMT 0170000
++#endif
++
++#if STAT_MACROS_BROKEN
++# undef S_ISBLK
++# undef S_ISCHR
++# undef S_ISDIR
++# undef S_ISFIFO
++# undef S_ISLNK
++# undef S_ISNAM
++# undef S_ISMPB
++# undef S_ISMPC
++# undef S_ISNWK
++# undef S_ISREG
++# undef S_ISSOCK
++#endif
++
++#ifndef S_ISBLK
++# ifdef S_IFBLK
++#  define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
++# else
++#  define S_ISBLK(m) 0
++# endif
++#endif
++
++#ifndef S_ISCHR
++# ifdef S_IFCHR
++#  define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
++# else
++#  define S_ISCHR(m) 0
++# endif
++#endif
++
++#ifndef S_ISDIR
++# ifdef S_IFDIR
++#  define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
++# else
++#  define S_ISDIR(m) 0
++# endif
++#endif
++
++#ifndef S_ISDOOR /* Solaris 2.5 and up */
++# define S_ISDOOR(m) 0
++#endif
++
++#ifndef S_ISFIFO
++# ifdef S_IFIFO
++#  define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
++# else
++#  define S_ISFIFO(m) 0
++# endif
++#endif
++
++#ifndef S_ISLNK
++# ifdef S_IFLNK
++#  define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
++# else
++#  define S_ISLNK(m) 0
++# endif
++#endif
++
++#ifndef S_ISMPB /* V7 */
++# ifdef S_IFMPB
++#  define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
++#  define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
++# else
++#  define S_ISMPB(m) 0
++#  define S_ISMPC(m) 0
++# endif
++#endif
++
++#ifndef S_ISMPX /* AIX */
++# define S_ISMPX(m) 0
++#endif
++
++#ifndef S_ISNAM /* Xenix */
++# ifdef S_IFNAM
++#  define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM)
++# else
++#  define S_ISNAM(m) 0
++# endif
++#endif
++
++#ifndef S_ISNWK /* HP/UX */
++# ifdef S_IFNWK
++#  define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
++# else
++#  define S_ISNWK(m) 0
++# endif
++#endif
++
++#ifndef S_ISPORT /* Solaris 10 and up */
++# define S_ISPORT(m) 0
++#endif
++
++#ifndef S_ISREG
++# ifdef S_IFREG
++#  define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
++# else
++#  define S_ISREG(m) 0
++# endif
++#endif
++
++#ifndef S_ISSOCK
++# ifdef S_IFSOCK
++#  define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
++# else
++#  define S_ISSOCK(m) 0
++# endif
++#endif
++
++
++#ifndef S_TYPEISMQ
++# define S_TYPEISMQ(p) 0
++#endif
++
++#ifndef S_TYPEISTMO
++# define S_TYPEISTMO(p) 0
++#endif
++
++
++#ifndef S_TYPEISSEM
++# ifdef S_INSEM
++#  define S_TYPEISSEM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSEM)
++# else
++#  define S_TYPEISSEM(p) 0
++# endif
++#endif
++
++#ifndef S_TYPEISSHM
++# ifdef S_INSHD
++#  define S_TYPEISSHM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSHD)
++# else
++#  define S_TYPEISSHM(p) 0
++# endif
++#endif
++
++/* high performance ("contiguous data") */
++#ifndef S_ISCTG
++# define S_ISCTG(p) 0
++#endif
++
++/* Cray DMF (data migration facility): off line, with data  */
++#ifndef S_ISOFD
++# define S_ISOFD(p) 0
++#endif
++
++/* Cray DMF (data migration facility): off line, with no data  */
++#ifndef S_ISOFL
++# define S_ISOFL(p) 0
++#endif
++
++/* 4.4BSD whiteout */
++#ifndef S_ISWHT
++# define S_ISWHT(m) 0
++#endif
++
++/* If any of the following are undefined,
++   define them to their de facto standard values.  */
++#if !S_ISUID
++# define S_ISUID 04000
++#endif
++#if !S_ISGID
++# define S_ISGID 02000
++#endif
++
++/* S_ISVTX is a common extension to POSIX.  */
++#ifndef S_ISVTX
++# define S_ISVTX 01000
++#endif
++
++#if !S_IRUSR && S_IREAD
++# define S_IRUSR S_IREAD
++#endif
++#if !S_IRUSR
++# define S_IRUSR 00400
++#endif
++#if !S_IRGRP
++# define S_IRGRP (S_IRUSR >> 3)
++#endif
++#if !S_IROTH
++# define S_IROTH (S_IRUSR >> 6)
++#endif
++
++#if !S_IWUSR && S_IWRITE
++# define S_IWUSR S_IWRITE
++#endif
++#if !S_IWUSR
++# define S_IWUSR 00200
++#endif
++#if !S_IWGRP
++# define S_IWGRP (S_IWUSR >> 3)
++#endif
++#if !S_IWOTH
++# define S_IWOTH (S_IWUSR >> 6)
++#endif
++
++#if !S_IXUSR && S_IEXEC
++# define S_IXUSR S_IEXEC
++#endif
++#if !S_IXUSR
++# define S_IXUSR 00100
++#endif
++#if !S_IXGRP
++# define S_IXGRP (S_IXUSR >> 3)
++#endif
++#if !S_IXOTH
++# define S_IXOTH (S_IXUSR >> 6)
++#endif
++
++#if !S_IRWXU
++# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
++#endif
++#if !S_IRWXG
++# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
++#endif
++#if !S_IRWXO
++# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
++#endif
++
++/* S_IXUGO is a common extension to POSIX.  */
++#if !S_IXUGO
++# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
++#endif
++
++#ifndef S_IRWXUGO
++# define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO)
++#endif
++
++/* Macros for futimens and utimensat.  */
++#ifndef UTIME_NOW
++# define UTIME_NOW (-1)
++# define UTIME_OMIT (-2)
++#endif
++
++
++#if @GNULIB_FCHMODAT@
++# if !@HAVE_FCHMODAT@
++_GL_FUNCDECL_SYS (fchmodat, int,
++                  (int fd, char const *file, mode_t mode, int flag)
++                  _GL_ARG_NONNULL ((2)));
++# endif
++_GL_CXXALIAS_SYS (fchmodat, int,
++                  (int fd, char const *file, mode_t mode, int flag));
++_GL_CXXALIASWARN (fchmodat);
++#elif defined GNULIB_POSIXCHECK
++# undef fchmodat
++# if HAVE_RAW_DECL_FCHMODAT
++_GL_WARN_ON_USE (fchmodat, "fchmodat is not portable - "
++                 "use gnulib module openat for portability");
++# endif
++#endif
++
++
++#if @GNULIB_FSTAT@
++# if @REPLACE_FSTAT@
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   undef fstat
++#   define fstat rpl_fstat
++#  endif
++_GL_FUNCDECL_RPL (fstat, int, (int fd, struct stat *buf) _GL_ARG_NONNULL ((2)));
++_GL_CXXALIAS_RPL (fstat, int, (int fd, struct stat *buf));
++# else
++_GL_CXXALIAS_SYS (fstat, int, (int fd, struct stat *buf));
++# endif
++_GL_CXXALIASWARN (fstat);
++#elif @WINDOWS_64_BIT_ST_SIZE@
++/* Above, we define stat to _stati64.  */
++# define fstat _fstati64
++#elif defined GNULIB_POSIXCHECK
++# undef fstat
++# if HAVE_RAW_DECL_FSTAT
++_GL_WARN_ON_USE (fstat, "fstat has portability problems - "
++                 "use gnulib module fstat for portability");
++# endif
++#endif
++
++
++#if @GNULIB_FSTATAT@
++# if @REPLACE_FSTATAT@
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   undef fstatat
++#   define fstatat rpl_fstatat
++#  endif
++_GL_FUNCDECL_RPL (fstatat, int,
++                  (int fd, char const *name, struct stat *st, int flags)
++                  _GL_ARG_NONNULL ((2, 3)));
++_GL_CXXALIAS_RPL (fstatat, int,
++                  (int fd, char const *name, struct stat *st, int flags));
++# else
++#  if !@HAVE_FSTATAT@
++_GL_FUNCDECL_SYS (fstatat, int,
++                  (int fd, char const *name, struct stat *st, int flags)
++                  _GL_ARG_NONNULL ((2, 3)));
++#  endif
++_GL_CXXALIAS_SYS (fstatat, int,
++                  (int fd, char const *name, struct stat *st, int flags));
++# endif
++_GL_CXXALIASWARN (fstatat);
++#elif defined GNULIB_POSIXCHECK
++# undef fstatat
++# if HAVE_RAW_DECL_FSTATAT
++_GL_WARN_ON_USE (fstatat, "fstatat is not portable - "
++                 "use gnulib module openat for portability");
++# endif
++#endif
++
++
++#if @GNULIB_FUTIMENS@
++/* Use the rpl_ prefix also on Solaris <= 9, because on Solaris 9 our futimens
++   implementation relies on futimesat, which on Solaris 10 makes an invocation
++   to futimens that is meant to invoke the libc's futimens(), not gnulib's
++   futimens().  */
++# if @REPLACE_FUTIMENS@ || (!@HAVE_FUTIMENS@ && defined __sun)
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   undef futimens
++#   define futimens rpl_futimens
++#  endif
++_GL_FUNCDECL_RPL (futimens, int, (int fd, struct timespec const times[2]));
++_GL_CXXALIAS_RPL (futimens, int, (int fd, struct timespec const times[2]));
++# else
++#  if !@HAVE_FUTIMENS@
++_GL_FUNCDECL_SYS (futimens, int, (int fd, struct timespec const times[2]));
++#  endif
++_GL_CXXALIAS_SYS (futimens, int, (int fd, struct timespec const times[2]));
++# endif
++# if @HAVE_FUTIMENS@
++_GL_CXXALIASWARN (futimens);
++# endif
++#elif defined GNULIB_POSIXCHECK
++# undef futimens
++# if HAVE_RAW_DECL_FUTIMENS
++_GL_WARN_ON_USE (futimens, "futimens is not portable - "
++                 "use gnulib module futimens for portability");
++# endif
++#endif
++
++
++#if @GNULIB_LCHMOD@
++/* Change the mode of FILENAME to MODE, without dereferencing it if FILENAME
++   denotes a symbolic link.  */
++# if !@HAVE_LCHMOD@
++/* The lchmod replacement follows symbolic links.  Callers should take
++   this into account; lchmod should be applied only to arguments that
++   are known to not be symbolic links.  On hosts that lack lchmod,
++   this can lead to race conditions between the check and the
++   invocation of lchmod, but we know of no workarounds that are
++   reliable in general.  You might try requesting support for lchmod
++   from your operating system supplier.  */
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   define lchmod chmod
++#  endif
++/* Need to cast, because on mingw, the second parameter of chmod is
++                                                int mode.  */
++_GL_CXXALIAS_RPL_CAST_1 (lchmod, chmod, int,
++                         (const char *filename, mode_t mode));
++# else
++#  if 0 /* assume already declared */
++_GL_FUNCDECL_SYS (lchmod, int, (const char *filename, mode_t mode)
++                               _GL_ARG_NONNULL ((1)));
++#  endif
++_GL_CXXALIAS_SYS (lchmod, int, (const char *filename, mode_t mode));
++# endif
++# if @HAVE_LCHMOD@
++_GL_CXXALIASWARN (lchmod);
++# endif
++#elif defined GNULIB_POSIXCHECK
++# undef lchmod
++# if HAVE_RAW_DECL_LCHMOD
++_GL_WARN_ON_USE (lchmod, "lchmod is unportable - "
++                 "use gnulib module lchmod for portability");
++# endif
++#endif
++
++
++#if @GNULIB_LSTAT@
++# if ! @HAVE_LSTAT@
++/* mingw does not support symlinks, therefore it does not have lstat.  But
++   without links, stat does just fine.  */
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   define lstat stat
++#  endif
++_GL_CXXALIAS_RPL_1 (lstat, stat, int, (const char *name, struct stat *buf));
++# elif @REPLACE_LSTAT@
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   undef lstat
++#   define lstat rpl_lstat
++#  endif
++_GL_FUNCDECL_RPL (lstat, int, (const char *name, struct stat *buf)
++                              _GL_ARG_NONNULL ((1, 2)));
++_GL_CXXALIAS_RPL (lstat, int, (const char *name, struct stat *buf));
++# else
++_GL_CXXALIAS_SYS (lstat, int, (const char *name, struct stat *buf));
++# endif
++# if @HAVE_LSTAT@
++_GL_CXXALIASWARN (lstat);
++# endif
++#elif defined GNULIB_POSIXCHECK
++# undef lstat
++# if HAVE_RAW_DECL_LSTAT
++_GL_WARN_ON_USE (lstat, "lstat is unportable - "
++                 "use gnulib module lstat for portability");
++# endif
++#endif
++
++
++#if @REPLACE_MKDIR@
++# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#  undef mkdir
++#  define mkdir rpl_mkdir
++# endif
++_GL_FUNCDECL_RPL (mkdir, int, (char const *name, mode_t mode)
++                              _GL_ARG_NONNULL ((1)));
++_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode));
++#else
++/* mingw's _mkdir() function has 1 argument, but we pass 2 arguments.
++   Additionally, it declares _mkdir (and depending on compile flags, an
++   alias mkdir), only in the nonstandard includes <direct.h> and <io.h>,
++   which are included above.  */
++# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
++
++#  if !GNULIB_defined_rpl_mkdir
++static int
++rpl_mkdir (char const *name, mode_t mode)
++{
++  return _mkdir (name);
++}
++#   define GNULIB_defined_rpl_mkdir 1
++#  endif
++
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   define mkdir rpl_mkdir
++#  endif
++_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode));
++# else
++_GL_CXXALIAS_SYS (mkdir, int, (char const *name, mode_t mode));
++# endif
++#endif
++_GL_CXXALIASWARN (mkdir);
++
++
++#if @GNULIB_MKDIRAT@
++# if !@HAVE_MKDIRAT@
++_GL_FUNCDECL_SYS (mkdirat, int, (int fd, char const *file, mode_t mode)
++                                _GL_ARG_NONNULL ((2)));
++# endif
++_GL_CXXALIAS_SYS (mkdirat, int, (int fd, char const *file, mode_t mode));
++_GL_CXXALIASWARN (mkdirat);
++#elif defined GNULIB_POSIXCHECK
++# undef mkdirat
++# if HAVE_RAW_DECL_MKDIRAT
++_GL_WARN_ON_USE (mkdirat, "mkdirat is not portable - "
++                 "use gnulib module openat for portability");
++# endif
++#endif
++
++
++#if @GNULIB_MKFIFO@
++# if @REPLACE_MKFIFO@
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   undef mkfifo
++#   define mkfifo rpl_mkfifo
++#  endif
++_GL_FUNCDECL_RPL (mkfifo, int, (char const *file, mode_t mode)
++                               _GL_ARG_NONNULL ((1)));
++_GL_CXXALIAS_RPL (mkfifo, int, (char const *file, mode_t mode));
++# else
++#  if !@HAVE_MKFIFO@
++_GL_FUNCDECL_SYS (mkfifo, int, (char const *file, mode_t mode)
++                               _GL_ARG_NONNULL ((1)));
++#  endif
++_GL_CXXALIAS_SYS (mkfifo, int, (char const *file, mode_t mode));
++# endif
++_GL_CXXALIASWARN (mkfifo);
++#elif defined GNULIB_POSIXCHECK
++# undef mkfifo
++# if HAVE_RAW_DECL_MKFIFO
++_GL_WARN_ON_USE (mkfifo, "mkfifo is not portable - "
++                 "use gnulib module mkfifo for portability");
++# endif
++#endif
++
++
++#if @GNULIB_MKFIFOAT@
++# if !@HAVE_MKFIFOAT@
++_GL_FUNCDECL_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode)
++                                 _GL_ARG_NONNULL ((2)));
++# endif
++_GL_CXXALIAS_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode));
++_GL_CXXALIASWARN (mkfifoat);
++#elif defined GNULIB_POSIXCHECK
++# undef mkfifoat
++# if HAVE_RAW_DECL_MKFIFOAT
++_GL_WARN_ON_USE (mkfifoat, "mkfifoat is not portable - "
++                 "use gnulib module mkfifoat for portability");
++# endif
++#endif
++
++
++#if @GNULIB_MKNOD@
++# if @REPLACE_MKNOD@
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   undef mknod
++#   define mknod rpl_mknod
++#  endif
++_GL_FUNCDECL_RPL (mknod, int, (char const *file, mode_t mode, dev_t dev)
++                              _GL_ARG_NONNULL ((1)));
++_GL_CXXALIAS_RPL (mknod, int, (char const *file, mode_t mode, dev_t dev));
++# else
++#  if !@HAVE_MKNOD@
++_GL_FUNCDECL_SYS (mknod, int, (char const *file, mode_t mode, dev_t dev)
++                              _GL_ARG_NONNULL ((1)));
++#  endif
++/* Need to cast, because on OSF/1 5.1, the third parameter is '...'.  */
++_GL_CXXALIAS_SYS_CAST (mknod, int, (char const *file, mode_t mode, dev_t dev));
++# endif
++_GL_CXXALIASWARN (mknod);
++#elif defined GNULIB_POSIXCHECK
++# undef mknod
++# if HAVE_RAW_DECL_MKNOD
++_GL_WARN_ON_USE (mknod, "mknod is not portable - "
++                 "use gnulib module mknod for portability");
++# endif
++#endif
++
++
++#if @GNULIB_MKNODAT@
++# if !@HAVE_MKNODAT@
++_GL_FUNCDECL_SYS (mknodat, int,
++                  (int fd, char const *file, mode_t mode, dev_t dev)
++                  _GL_ARG_NONNULL ((2)));
++# endif
++_GL_CXXALIAS_SYS (mknodat, int,
++                  (int fd, char const *file, mode_t mode, dev_t dev));
++_GL_CXXALIASWARN (mknodat);
++#elif defined GNULIB_POSIXCHECK
++# undef mknodat
++# if HAVE_RAW_DECL_MKNODAT
++_GL_WARN_ON_USE (mknodat, "mknodat is not portable - "
++                 "use gnulib module mkfifoat for portability");
++# endif
++#endif
++
++
++#if @GNULIB_STAT@
++# if @REPLACE_STAT@
++/* We can't use the object-like #define stat rpl_stat, because of
++   struct stat.  This means that rpl_stat will not be used if the user
++   does (stat)(a,b).  Oh well.  */
++#  if defined _AIX && defined stat && defined _LARGE_FILES
++    /* With _LARGE_FILES defined, AIX (only) defines stat to stat64,
++       so we have to replace stat64() instead of stat(). */
++#   undef stat64
++#   define stat64(name, st) rpl_stat (name, st)
++#  elif @WINDOWS_64_BIT_ST_SIZE@
++    /* Above, we define stat to _stati64.  */
++#   if defined __MINGW32__ && defined _stati64
++#    ifndef _USE_32BIT_TIME_T
++      /* The system headers define _stati64 to _stat64.  */
++#     undef _stat64
++#     define _stat64(name, st) rpl_stat (name, st)
++#    endif
++#   elif defined _MSC_VER && defined _stati64
++#    ifdef _USE_32BIT_TIME_T
++      /* The system headers define _stati64 to _stat32i64.  */
++#     undef _stat32i64
++#     define _stat32i64(name, st) rpl_stat (name, st)
++#    else
++      /* The system headers define _stati64 to _stat64.  */
++#     undef _stat64
++#     define _stat64(name, st) rpl_stat (name, st)
++#    endif
++#   else
++#    undef _stati64
++#    define _stati64(name, st) rpl_stat (name, st)
++#   endif
++#  elif defined __MINGW32__ && defined stat
++#   ifdef _USE_32BIT_TIME_T
++     /* The system headers define stat to _stat32i64.  */
++#    undef _stat32i64
++#    define _stat32i64(name, st) rpl_stat (name, st)
++#   else
++     /* The system headers define stat to _stat64.  */
++#    undef _stat64
++#    define _stat64(name, st) rpl_stat (name, st)
++#   endif
++#  elif defined _MSC_VER && defined stat
++#   ifdef _USE_32BIT_TIME_T
++     /* The system headers define stat to _stat32.  */
++#    undef _stat32
++#    define _stat32(name, st) rpl_stat (name, st)
++#   else
++     /* The system headers define stat to _stat64i32.  */
++#    undef _stat64i32
++#    define _stat64i32(name, st) rpl_stat (name, st)
++#   endif
++#  else /* !(_AIX ||__MINGW32__ ||  _MSC_VER) */
++#   undef stat
++#   define stat(name, st) rpl_stat (name, st)
++#  endif /* !_LARGE_FILES */
++_GL_EXTERN_C int stat (const char *name, struct stat *buf)
++                      _GL_ARG_NONNULL ((1, 2));
++# endif
++#elif defined GNULIB_POSIXCHECK
++# undef stat
++# if HAVE_RAW_DECL_STAT
++_GL_WARN_ON_USE (stat, "stat is unportable - "
++                 "use gnulib module stat for portability");
++# endif
++#endif
++
++
++#if @GNULIB_UTIMENSAT@
++/* Use the rpl_ prefix also on Solaris <= 9, because on Solaris 9 our utimensat
++   implementation relies on futimesat, which on Solaris 10 makes an invocation
++   to utimensat that is meant to invoke the libc's utimensat(), not gnulib's
++   utimensat().  */
++# if @REPLACE_UTIMENSAT@ || (!@HAVE_UTIMENSAT@ && defined __sun)
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   undef utimensat
++#   define utimensat rpl_utimensat
++#  endif
++_GL_FUNCDECL_RPL (utimensat, int, (int fd, char const *name,
++                                   struct timespec const times[2], int flag)
++                                  _GL_ARG_NONNULL ((2)));
++_GL_CXXALIAS_RPL (utimensat, int, (int fd, char const *name,
++                                   struct timespec const times[2], int flag));
++# else
++#  if !@HAVE_UTIMENSAT@
++_GL_FUNCDECL_SYS (utimensat, int, (int fd, char const *name,
++                                   struct timespec const times[2], int flag)
++                                  _GL_ARG_NONNULL ((2)));
++#  endif
++_GL_CXXALIAS_SYS (utimensat, int, (int fd, char const *name,
++                                   struct timespec const times[2], int flag));
++# endif
++# if @HAVE_UTIMENSAT@
++_GL_CXXALIASWARN (utimensat);
++# endif
++#elif defined GNULIB_POSIXCHECK
++# undef utimensat
++# if HAVE_RAW_DECL_UTIMENSAT
++_GL_WARN_ON_USE (utimensat, "utimensat is not portable - "
++                 "use gnulib module utimensat for portability");
++# endif
++#endif
++
++
++#endif /* _@GUARD_PREFIX@_SYS_STAT_H */
++#endif /* _@GUARD_PREFIX@_SYS_STAT_H */
++#endif
+diff --git a/grub-core/gnulib/sys_time.in.h b/grub-core/gnulib/sys_time.in.h
+new file mode 100644
+index 00000000000..30057ad49fd
+--- /dev/null
++++ b/grub-core/gnulib/sys_time.in.h
+@@ -0,0 +1,213 @@
++/* Provide a more complete sys/time.h.
++
++   Copyright (C) 2007-2014 Free Software Foundation, Inc.
++
++   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 3, 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/>.  */
++
++/* Written by Paul Eggert.  */
++
++#ifndef _@GUARD_PREFIX@_SYS_TIME_H
++
++#if __GNUC__ >= 3
++@PRAGMA_SYSTEM_HEADER@
++#endif
++@PRAGMA_COLUMNS@
++
++/* On Cygwin and on many BSDish systems, <sys/time.h> includes itself
++   recursively via <sys/select.h>.
++   Simply delegate to the system's header in this case; it is a no-op.
++   Without this extra ifdef, the C++ gettimeofday declaration below
++   would be a forward declaration in gnulib's nested <sys/time.h>.  */
++#if defined _CYGWIN_SYS_TIME_H || defined _SYS_TIME_H || defined _SYS_TIME_H_
++# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@
++#else
++
++/* The include_next requires a split double-inclusion guard.  */
++#if @HAVE_SYS_TIME_H@
++# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@
++#endif
++
++#ifndef _@GUARD_PREFIX@_SYS_TIME_H
++#define _@GUARD_PREFIX@_SYS_TIME_H
++
++#if ! @HAVE_SYS_TIME_H@
++# include <time.h>
++#endif
++
++/* On native Windows with MSVC, get the 'struct timeval' type.
++   Also, on native Windows with a 64-bit time_t, where we are overriding the
++   'struct timeval' type, get all declarations of system functions whose
++   signature contains 'struct timeval'.  */
++#if (defined _MSC_VER || @REPLACE_STRUCT_TIMEVAL@) && @HAVE_WINSOCK2_H@ && !defined _GL_INCLUDING_WINSOCK2_H
++# define _GL_INCLUDING_WINSOCK2_H
++# include <winsock2.h>
++# undef _GL_INCLUDING_WINSOCK2_H
++#endif
++
++/* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
++
++/* The definition of _GL_ARG_NONNULL is copied here.  */
++
++/* The definition of _GL_WARN_ON_USE is copied here.  */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#if !@HAVE_STRUCT_TIMEVAL@ || @REPLACE_STRUCT_TIMEVAL@
++
++# if @REPLACE_STRUCT_TIMEVAL@
++#  define timeval rpl_timeval
++# endif
++
++# if !GNULIB_defined_struct_timeval
++struct timeval
++{
++  time_t tv_sec;
++  long int tv_usec;
++};
++#  define GNULIB_defined_struct_timeval 1
++# endif
++
++#endif
++
++#ifdef __cplusplus
++}
++#endif
++
++#if @GNULIB_GETTIMEOFDAY@
++# if @REPLACE_GETTIMEOFDAY@
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   undef gettimeofday
++#   define gettimeofday rpl_gettimeofday
++#  endif
++_GL_FUNCDECL_RPL (gettimeofday, int,
++                  (struct timeval *restrict, void *restrict)
++                  _GL_ARG_NONNULL ((1)));
++_GL_CXXALIAS_RPL (gettimeofday, int,
++                  (struct timeval *restrict, void *restrict));
++# else
++#  if !@HAVE_GETTIMEOFDAY@
++_GL_FUNCDECL_SYS (gettimeofday, int,
++                  (struct timeval *restrict, void *restrict)
++                  _GL_ARG_NONNULL ((1)));
++#  endif
++/* Need to cast, because on glibc systems, by default, the second argument is
++                                                  struct timezone *.  */
++_GL_CXXALIAS_SYS_CAST (gettimeofday, int,
++                       (struct timeval *restrict, void *restrict));
++# endif
++_GL_CXXALIASWARN (gettimeofday);
++#elif defined GNULIB_POSIXCHECK
++# undef gettimeofday
++# if HAVE_RAW_DECL_GETTIMEOFDAY
++_GL_WARN_ON_USE (gettimeofday, "gettimeofday is unportable - "
++                 "use gnulib module gettimeofday for portability");
++# endif
++#endif
++
++/* Hide some function declarations from <winsock2.h>.  */
++
++#if defined _MSC_VER && @HAVE_WINSOCK2_H@
++# if !defined _@GUARD_PREFIX@_UNISTD_H
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   undef close
++#   define close close_used_without_including_unistd_h
++#  else
++     _GL_WARN_ON_USE (close,
++                      "close() used without including <unistd.h>");
++#  endif
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   undef gethostname
++#   define gethostname gethostname_used_without_including_unistd_h
++#  else
++     _GL_WARN_ON_USE (gethostname,
++                      "gethostname() used without including <unistd.h>");
++#  endif
++# endif
++# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   undef socket
++#   define socket              socket_used_without_including_sys_socket_h
++#   undef connect
++#   define connect             connect_used_without_including_sys_socket_h
++#   undef accept
++#   define accept              accept_used_without_including_sys_socket_h
++#   undef bind
++#   define bind                bind_used_without_including_sys_socket_h
++#   undef getpeername
++#   define getpeername         getpeername_used_without_including_sys_socket_h
++#   undef getsockname
++#   define getsockname         getsockname_used_without_including_sys_socket_h
++#   undef getsockopt
++#   define getsockopt          getsockopt_used_without_including_sys_socket_h
++#   undef listen
++#   define listen              listen_used_without_including_sys_socket_h
++#   undef recv
++#   define recv                recv_used_without_including_sys_socket_h
++#   undef send
++#   define send                send_used_without_including_sys_socket_h
++#   undef recvfrom
++#   define recvfrom            recvfrom_used_without_including_sys_socket_h
++#   undef sendto
++#   define sendto              sendto_used_without_including_sys_socket_h
++#   undef setsockopt
++#   define setsockopt          setsockopt_used_without_including_sys_socket_h
++#   undef shutdown
++#   define shutdown            shutdown_used_without_including_sys_socket_h
++#  else
++     _GL_WARN_ON_USE (socket,
++                      "socket() used without including <sys/socket.h>");
++     _GL_WARN_ON_USE (connect,
++                      "connect() used without including <sys/socket.h>");
++     _GL_WARN_ON_USE (accept,
++                      "accept() used without including <sys/socket.h>");
++     _GL_WARN_ON_USE (bind,
++                      "bind() used without including <sys/socket.h>");
++     _GL_WARN_ON_USE (getpeername,
++                      "getpeername() used without including <sys/socket.h>");
++     _GL_WARN_ON_USE (getsockname,
++                      "getsockname() used without including <sys/socket.h>");
++     _GL_WARN_ON_USE (getsockopt,
++                      "getsockopt() used without including <sys/socket.h>");
++     _GL_WARN_ON_USE (listen,
++                      "listen() used without including <sys/socket.h>");
++     _GL_WARN_ON_USE (recv,
++                      "recv() used without including <sys/socket.h>");
++     _GL_WARN_ON_USE (send,
++                      "send() used without including <sys/socket.h>");
++     _GL_WARN_ON_USE (recvfrom,
++                      "recvfrom() used without including <sys/socket.h>");
++     _GL_WARN_ON_USE (sendto,
++                      "sendto() used without including <sys/socket.h>");
++     _GL_WARN_ON_USE (setsockopt,
++                      "setsockopt() used without including <sys/socket.h>");
++     _GL_WARN_ON_USE (shutdown,
++                      "shutdown() used without including <sys/socket.h>");
++#  endif
++# endif
++# if !defined _@GUARD_PREFIX@_SYS_SELECT_H
++#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#   undef select
++#   define select select_used_without_including_sys_select_h
++#  else
++     _GL_WARN_ON_USE (select,
++                      "select() used without including <sys/select.h>");
++#  endif
++# endif
++#endif
++
++#endif /* _@GUARD_PREFIX@_SYS_TIME_H */
++#endif /* _CYGWIN_SYS_TIME_H */
++#endif /* _@GUARD_PREFIX@_SYS_TIME_H */
+diff --git a/grub-core/gnulib/sys_types.in.h b/grub-core/gnulib/sys_types.in.h
+index d7da35623b1..9520c09030c 100644
+--- a/grub-core/gnulib/sys_types.in.h
++++ b/grub-core/gnulib/sys_types.in.h
+@@ -23,7 +23,9 @@
+ #ifndef _@GUARD_PREFIX@_SYS_TYPES_H
+ 
+ /* The include_next requires a split double-inclusion guard.  */
++# define _GL_INCLUDING_SYS_TYPES_H
+ #@INCLUDE_NEXT@ @NEXT_SYS_TYPES_H@
++# undef _GL_INCLUDING_SYS_TYPES_H
+ 
+ #ifndef _@GUARD_PREFIX@_SYS_TYPES_H
+ #define _@GUARD_PREFIX@_SYS_TYPES_H
+diff --git a/grub-core/gnulib/time.h b/grub-core/gnulib/time.h
+new file mode 100644
+index 00000000000..b9203d5569a
+--- /dev/null
++++ b/grub-core/gnulib/time.h
+@@ -0,0 +1,586 @@
++/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
++/* A more-standard <time.h>.
++
++   Copyright (C) 2007-2014 Free Software Foundation, Inc.
++
++   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 3, 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/>.  */
++
++#if __GNUC__ >= 3
++#pragma GCC system_header
++#endif
++
++
++/* Don't get in the way of glibc when it includes time.h merely to
++   declare a few standard symbols, rather than to declare all the
++   symbols.  Also, Solaris 8 <time.h> eventually includes itself
++   recursively; if that is happening, just include the system <time.h>
++   without adding our own declarations.  */
++#if (defined __need_time_t || defined __need_clock_t \
++     || defined __need_timespec \
++     || defined _GL_TIME_H)
++
++# include_next <time.h>
++
++#else
++
++# define _GL_TIME_H
++
++# include_next <time.h>
++
++/* NetBSD 5.0 mis-defines NULL.  */
++# include <stddef.h>
++
++/* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
++#ifndef _GL_CXXDEFS_H
++#define _GL_CXXDEFS_H
++
++/* The three most frequent use cases of these macros are:
++
++   * For providing a substitute for a function that is missing on some
++     platforms, but is declared and works fine on the platforms on which
++     it exists:
++
++       #if @GNULIB_FOO@
++       # if !@HAVE_FOO@
++       _GL_FUNCDECL_SYS (foo, ...);
++       # endif
++       _GL_CXXALIAS_SYS (foo, ...);
++       _GL_CXXALIASWARN (foo);
++       #elif defined GNULIB_POSIXCHECK
++       ...
++       #endif
++
++   * For providing a replacement for a function that exists on all platforms,
++     but is broken/insufficient and needs to be replaced on some platforms:
++
++       #if @GNULIB_FOO@
++       # if @REPLACE_FOO@
++       #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++       #   undef foo
++       #   define foo rpl_foo
++       #  endif
++       _GL_FUNCDECL_RPL (foo, ...);
++       _GL_CXXALIAS_RPL (foo, ...);
++       # else
++       _GL_CXXALIAS_SYS (foo, ...);
++       # endif
++       _GL_CXXALIASWARN (foo);
++       #elif defined GNULIB_POSIXCHECK
++       ...
++       #endif
++
++   * For providing a replacement for a function that exists on some platforms
++     but is broken/insufficient and needs to be replaced on some of them and
++     is additionally either missing or undeclared on some other platforms:
++
++       #if @GNULIB_FOO@
++       # if @REPLACE_FOO@
++       #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++       #   undef foo
++       #   define foo rpl_foo
++       #  endif
++       _GL_FUNCDECL_RPL (foo, ...);
++       _GL_CXXALIAS_RPL (foo, ...);
++       # else
++       #  if !@HAVE_FOO@   or   if !@HAVE_DECL_FOO@
++       _GL_FUNCDECL_SYS (foo, ...);
++       #  endif
++       _GL_CXXALIAS_SYS (foo, ...);
++       # endif
++       _GL_CXXALIASWARN (foo);
++       #elif defined GNULIB_POSIXCHECK
++       ...
++       #endif
++*/
++
++/* _GL_EXTERN_C declaration;
++   performs the declaration with C linkage.  */
++#if defined __cplusplus
++# define _GL_EXTERN_C extern "C"
++#else
++# define _GL_EXTERN_C extern
++#endif
++
++/* _GL_FUNCDECL_RPL (func, rettype, parameters_and_attributes);
++   declares a replacement function, named rpl_func, with the given prototype,
++   consisting of return type, parameters, and attributes.
++   Example:
++     _GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...)
++                                  _GL_ARG_NONNULL ((1)));
++ */
++#define _GL_FUNCDECL_RPL(func,rettype,parameters_and_attributes) \
++  _GL_FUNCDECL_RPL_1 (rpl_##func, rettype, parameters_and_attributes)
++#define _GL_FUNCDECL_RPL_1(rpl_func,rettype,parameters_and_attributes) \
++  _GL_EXTERN_C rettype rpl_func parameters_and_attributes
++
++/* _GL_FUNCDECL_SYS (func, rettype, parameters_and_attributes);
++   declares the system function, named func, with the given prototype,
++   consisting of return type, parameters, and attributes.
++   Example:
++     _GL_FUNCDECL_SYS (open, int, (const char *filename, int flags, ...)
++                                  _GL_ARG_NONNULL ((1)));
++ */
++#define _GL_FUNCDECL_SYS(func,rettype,parameters_and_attributes) \
++  _GL_EXTERN_C rettype func parameters_and_attributes
++
++/* _GL_CXXALIAS_RPL (func, rettype, parameters);
++   declares a C++ alias called GNULIB_NAMESPACE::func
++   that redirects to rpl_func, if GNULIB_NAMESPACE is defined.
++   Example:
++     _GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...));
++ */
++#define _GL_CXXALIAS_RPL(func,rettype,parameters) \
++  _GL_CXXALIAS_RPL_1 (func, rpl_##func, rettype, parameters)
++#if defined __cplusplus && defined GNULIB_NAMESPACE
++# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \
++    namespace GNULIB_NAMESPACE                                \
++    {                                                         \
++      rettype (*const func) parameters = ::rpl_func;          \
++    }                                                         \
++    _GL_EXTERN_C int _gl_cxxalias_dummy
++#else
++# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \
++    _GL_EXTERN_C int _gl_cxxalias_dummy
++#endif
++
++/* _GL_CXXALIAS_RPL_CAST_1 (func, rpl_func, rettype, parameters);
++   is like  _GL_CXXALIAS_RPL_1 (func, rpl_func, rettype, parameters);
++   except that the C function rpl_func may have a slightly different
++   declaration.  A cast is used to silence the "invalid conversion" error
++   that would otherwise occur.  */
++#if defined __cplusplus && defined GNULIB_NAMESPACE
++# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \
++    namespace GNULIB_NAMESPACE                                     \
++    {                                                              \
++      rettype (*const func) parameters =                           \
++        reinterpret_cast<rettype(*)parameters>(::rpl_func);        \
++    }                                                              \
++    _GL_EXTERN_C int _gl_cxxalias_dummy
++#else
++# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \
++    _GL_EXTERN_C int _gl_cxxalias_dummy
++#endif
++
++/* _GL_CXXALIAS_SYS (func, rettype, parameters);
++   declares a C++ alias called GNULIB_NAMESPACE::func
++   that redirects to the system provided function func, if GNULIB_NAMESPACE
++   is defined.
++   Example:
++     _GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...));
++ */
++#if defined __cplusplus && defined GNULIB_NAMESPACE
++  /* If we were to write
++       rettype (*const func) parameters = ::func;
++     like above in _GL_CXXALIAS_RPL_1, the compiler could optimize calls
++     better (remove an indirection through a 'static' pointer variable),
++     but then the _GL_CXXALIASWARN macro below would cause a warning not only
++     for uses of ::func but also for uses of GNULIB_NAMESPACE::func.  */
++# define _GL_CXXALIAS_SYS(func,rettype,parameters) \
++    namespace GNULIB_NAMESPACE                     \
++    {                                              \
++      static rettype (*func) parameters = ::func;  \
++    }                                              \
++    _GL_EXTERN_C int _gl_cxxalias_dummy
++#else
++# define _GL_CXXALIAS_SYS(func,rettype,parameters) \
++    _GL_EXTERN_C int _gl_cxxalias_dummy
++#endif
++
++/* _GL_CXXALIAS_SYS_CAST (func, rettype, parameters);
++   is like  _GL_CXXALIAS_SYS (func, rettype, parameters);
++   except that the C function func may have a slightly different declaration.
++   A cast is used to silence the "invalid conversion" error that would
++   otherwise occur.  */
++#if defined __cplusplus && defined GNULIB_NAMESPACE
++# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \
++    namespace GNULIB_NAMESPACE                          \
++    {                                                   \
++      static rettype (*func) parameters =               \
++        reinterpret_cast<rettype(*)parameters>(::func); \
++    }                                                   \
++    _GL_EXTERN_C int _gl_cxxalias_dummy
++#else
++# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \
++    _GL_EXTERN_C int _gl_cxxalias_dummy
++#endif
++
++/* _GL_CXXALIAS_SYS_CAST2 (func, rettype, parameters, rettype2, parameters2);
++   is like  _GL_CXXALIAS_SYS (func, rettype, parameters);
++   except that the C function is picked among a set of overloaded functions,
++   namely the one with rettype2 and parameters2.  Two consecutive casts
++   are used to silence the "cannot find a match" and "invalid conversion"
++   errors that would otherwise occur.  */
++#if defined __cplusplus && defined GNULIB_NAMESPACE
++  /* The outer cast must be a reinterpret_cast.
++     The inner cast: When the function is defined as a set of overloaded
++     functions, it works as a static_cast<>, choosing the designated variant.
++     When the function is defined as a single variant, it works as a
++     reinterpret_cast<>. The parenthesized cast syntax works both ways.  */
++# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \
++    namespace GNULIB_NAMESPACE                                                \
++    {                                                                         \
++      static rettype (*func) parameters =                                     \
++        reinterpret_cast<rettype(*)parameters>(                               \
++          (rettype2(*)parameters2)(::func));                                  \
++    }                                                                         \
++    _GL_EXTERN_C int _gl_cxxalias_dummy
++#else
++# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \
++    _GL_EXTERN_C int _gl_cxxalias_dummy
++#endif
++
++/* _GL_CXXALIASWARN (func);
++   causes a warning to be emitted when ::func is used but not when
++   GNULIB_NAMESPACE::func is used.  func must be defined without overloaded
++   variants.  */
++#if defined __cplusplus && defined GNULIB_NAMESPACE
++# define _GL_CXXALIASWARN(func) \
++   _GL_CXXALIASWARN_1 (func, GNULIB_NAMESPACE)
++# define _GL_CXXALIASWARN_1(func,namespace) \
++   _GL_CXXALIASWARN_2 (func, namespace)
++/* To work around GCC bug <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>,
++   we enable the warning only when not optimizing.  */
++# if !__OPTIMIZE__
++#  define _GL_CXXALIASWARN_2(func,namespace) \
++    _GL_WARN_ON_USE (func, \
++                     "The symbol ::" #func " refers to the system function. " \
++                     "Use " #namespace "::" #func " instead.")
++# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
++#  define _GL_CXXALIASWARN_2(func,namespace) \
++     extern __typeof__ (func) func
++# else
++#  define _GL_CXXALIASWARN_2(func,namespace) \
++     _GL_EXTERN_C int _gl_cxxalias_dummy
++# endif
++#else
++# define _GL_CXXALIASWARN(func) \
++    _GL_EXTERN_C int _gl_cxxalias_dummy
++#endif
++
++/* _GL_CXXALIASWARN1 (func, rettype, parameters_and_attributes);
++   causes a warning to be emitted when the given overloaded variant of ::func
++   is used but not when GNULIB_NAMESPACE::func is used.  */
++#if defined __cplusplus && defined GNULIB_NAMESPACE
++# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \
++   _GL_CXXALIASWARN1_1 (func, rettype, parameters_and_attributes, \
++                        GNULIB_NAMESPACE)
++# define _GL_CXXALIASWARN1_1(func,rettype,parameters_and_attributes,namespace) \
++   _GL_CXXALIASWARN1_2 (func, rettype, parameters_and_attributes, namespace)
++/* To work around GCC bug <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>,
++   we enable the warning only when not optimizing.  */
++# if !__OPTIMIZE__
++#  define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
++    _GL_WARN_ON_USE_CXX (func, rettype, parameters_and_attributes, \
++                         "The symbol ::" #func " refers to the system function. " \
++                         "Use " #namespace "::" #func " instead.")
++# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
++#  define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
++     extern __typeof__ (func) func
++# else
++#  define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
++     _GL_EXTERN_C int _gl_cxxalias_dummy
++# endif
++#else
++# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \
++    _GL_EXTERN_C int _gl_cxxalias_dummy
++#endif
++
++#endif /* _GL_CXXDEFS_H */
++
++/* The definition of _GL_ARG_NONNULL is copied here.  */
++/* _GL_ARG_NONNULL((n,...,m)) tells the compiler and static analyzer tools
++   that the values passed as arguments n, ..., m must be non-NULL pointers.
++   n = 1 stands for the first argument, n = 2 for the second argument etc.  */
++#ifndef _GL_ARG_NONNULL
++# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3
++#  define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params))
++# else
++#  define _GL_ARG_NONNULL(params)
++# endif
++#endif
++
++/* The definition of _GL_WARN_ON_USE is copied here.  */
++#ifndef _GL_WARN_ON_USE
++
++# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__)
++/* A compiler attribute is available in gcc versions 4.3.0 and later.  */
++#  define _GL_WARN_ON_USE(function, message) \
++extern __typeof__ (function) function __attribute__ ((__warning__ (message)))
++# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
++/* Verify the existence of the function.  */
++#  define _GL_WARN_ON_USE(function, message) \
++extern __typeof__ (function) function
++# else /* Unsupported.  */
++#  define _GL_WARN_ON_USE(function, message) \
++_GL_WARN_EXTERN_C int _gl_warn_on_use
++# endif
++#endif
++
++/* _GL_WARN_ON_USE_CXX (function, rettype, parameters_and_attributes, "string")
++   is like _GL_WARN_ON_USE (function, "string"), except that the function is
++   declared with the given prototype, consisting of return type, parameters,
++   and attributes.
++   This variant is useful for overloaded functions in C++. _GL_WARN_ON_USE does
++   not work in this case.  */
++#ifndef _GL_WARN_ON_USE_CXX
++# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__)
++#  define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \
++extern rettype function parameters_and_attributes \
++     __attribute__ ((__warning__ (msg)))
++# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
++/* Verify the existence of the function.  */
++#  define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \
++extern rettype function parameters_and_attributes
++# else /* Unsupported.  */
++#  define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \
++_GL_WARN_EXTERN_C int _gl_warn_on_use
++# endif
++#endif
++
++/* _GL_WARN_EXTERN_C declaration;
++   performs the declaration with C linkage.  */
++#ifndef _GL_WARN_EXTERN_C
++# if defined __cplusplus
++#  define _GL_WARN_EXTERN_C extern "C"
++# else
++#  define _GL_WARN_EXTERN_C extern
++# endif
++#endif
++
++/* Some systems don't define struct timespec (e.g., AIX 4.1, Ultrix 4.3).
++   Or they define it with the wrong member names or define it in <sys/time.h>
++   (e.g., FreeBSD circa 1997).  Stock Mingw prior to 3.0 does not define it,
++   but the pthreads-win32 library defines it in <pthread.h>.  */
++# if ! 1
++#  if 0
++#   include <sys/time.h>
++#  elif 0
++#   include <pthread.h>
++#  else
++
++#   ifdef __cplusplus
++extern "C" {
++#   endif
++
++#   if !GNULIB_defined_struct_timespec
++#    undef timespec
++#    define timespec rpl_timespec
++struct timespec
++{
++  time_t tv_sec;
++  long int tv_nsec;
++};
++#    define GNULIB_defined_struct_timespec 1
++#   endif
++
++#   ifdef __cplusplus
++}
++#   endif
++
++#  endif
++# endif
++
++# if !GNULIB_defined_struct_time_t_must_be_integral
++/* Per http://austingroupbugs.net/view.php?id=327, POSIX requires
++   time_t to be an integer type, even though C99 permits floating
++   point.  We don't know of any implementation that uses floating
++   point, and it is much easier to write code that doesn't have to
++   worry about that corner case, so we force the issue.  */
++struct __time_t_must_be_integral {
++  unsigned int __floating_time_t_unsupported : (time_t) 1;
++};
++#  define GNULIB_defined_struct_time_t_must_be_integral 1
++# endif
++
++/* Sleep for at least RQTP seconds unless interrupted,  If interrupted,
++   return -1 and store the remaining time into RMTP.  See
++   <http://www.opengroup.org/susv3xsh/nanosleep.html>.  */
++# if 0
++#  if GNULIB_PORTCHECK
++#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#    define nanosleep rpl_nanosleep
++#   endif
++_GL_FUNCDECL_RPL (nanosleep, int,
++                  (struct timespec const *__rqtp, struct timespec *__rmtp)
++                  _GL_ARG_NONNULL ((1)));
++_GL_CXXALIAS_RPL (nanosleep, int,
++                  (struct timespec const *__rqtp, struct timespec *__rmtp));
++#  else
++#   if ! 1
++_GL_FUNCDECL_SYS (nanosleep, int,
++                  (struct timespec const *__rqtp, struct timespec *__rmtp)
++                  _GL_ARG_NONNULL ((1)));
++#   endif
++_GL_CXXALIAS_SYS (nanosleep, int,
++                  (struct timespec const *__rqtp, struct timespec *__rmtp));
++#  endif
++_GL_CXXALIASWARN (nanosleep);
++# endif
++
++/* Return the 'time_t' representation of TP and normalize TP.  */
++# if 0
++#  if GNULIB_PORTCHECK
++#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#    define mktime rpl_mktime
++#   endif
++_GL_FUNCDECL_RPL (mktime, time_t, (struct tm *__tp) _GL_ARG_NONNULL ((1)));
++_GL_CXXALIAS_RPL (mktime, time_t, (struct tm *__tp));
++#  else
++_GL_CXXALIAS_SYS (mktime, time_t, (struct tm *__tp));
++#  endif
++_GL_CXXALIASWARN (mktime);
++# endif
++
++/* Convert TIMER to RESULT, assuming local time and UTC respectively.  See
++   <http://www.opengroup.org/susv3xsh/localtime_r.html> and
++   <http://www.opengroup.org/susv3xsh/gmtime_r.html>.  */
++# if 0
++#  if GNULIB_PORTCHECK
++#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#    undef localtime_r
++#    define localtime_r rpl_localtime_r
++#   endif
++_GL_FUNCDECL_RPL (localtime_r, struct tm *, (time_t const *restrict __timer,
++                                             struct tm *restrict __result)
++                                            _GL_ARG_NONNULL ((1, 2)));
++_GL_CXXALIAS_RPL (localtime_r, struct tm *, (time_t const *restrict __timer,
++                                             struct tm *restrict __result));
++#  else
++#   if ! 1
++_GL_FUNCDECL_SYS (localtime_r, struct tm *, (time_t const *restrict __timer,
++                                             struct tm *restrict __result)
++                                            _GL_ARG_NONNULL ((1, 2)));
++#   endif
++_GL_CXXALIAS_SYS (localtime_r, struct tm *, (time_t const *restrict __timer,
++                                             struct tm *restrict __result));
++#  endif
++#  if 1
++_GL_CXXALIASWARN (localtime_r);
++#  endif
++#  if GNULIB_PORTCHECK
++#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#    undef gmtime_r
++#    define gmtime_r rpl_gmtime_r
++#   endif
++_GL_FUNCDECL_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer,
++                                          struct tm *restrict __result)
++                                         _GL_ARG_NONNULL ((1, 2)));
++_GL_CXXALIAS_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer,
++                                          struct tm *restrict __result));
++#  else
++#   if ! 1
++_GL_FUNCDECL_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer,
++                                          struct tm *restrict __result)
++                                         _GL_ARG_NONNULL ((1, 2)));
++#   endif
++_GL_CXXALIAS_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer,
++                                          struct tm *restrict __result));
++#  endif
++#  if 1
++_GL_CXXALIASWARN (gmtime_r);
++#  endif
++# endif
++
++/* Convert TIMER to RESULT, assuming local time and UTC respectively.  See
++   <http://www.opengroup.org/susv3xsh/localtime.html> and
++   <http://www.opengroup.org/susv3xsh/gmtime.html>.  */
++# if 1
++#  if 0
++#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#    undef localtime
++#    define localtime rpl_localtime
++#   endif
++_GL_FUNCDECL_RPL (localtime, struct tm *, (time_t const *__timer)
++		                          _GL_ARG_NONNULL ((1)));
++_GL_CXXALIAS_RPL (localtime, struct tm *, (time_t const *__timer));
++#  else
++_GL_CXXALIAS_SYS (localtime, struct tm *, (time_t const *__timer));
++#  endif
++_GL_CXXALIASWARN (localtime);
++# endif
++
++# if 1
++#  if 0
++#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#    undef gmtime
++#    define gmtime rpl_gmtime
++#   endif
++_GL_FUNCDECL_RPL (gmtime, struct tm *, (time_t const *__timer)
++                                       _GL_ARG_NONNULL ((1)));
++_GL_CXXALIAS_RPL (gmtime, struct tm *, (time_t const *__timer));
++#  else
++_GL_CXXALIAS_SYS (gmtime, struct tm *, (time_t const *__timer));
++#  endif
++_GL_CXXALIASWARN (gmtime);
++# endif
++
++/* Parse BUF as a time stamp, assuming FORMAT specifies its layout, and store
++   the resulting broken-down time into TM.  See
++   <http://www.opengroup.org/susv3xsh/strptime.html>.  */
++# if 0
++#  if ! 1
++_GL_FUNCDECL_SYS (strptime, char *, (char const *restrict __buf,
++                                     char const *restrict __format,
++                                     struct tm *restrict __tm)
++                                    _GL_ARG_NONNULL ((1, 2, 3)));
++#  endif
++_GL_CXXALIAS_SYS (strptime, char *, (char const *restrict __buf,
++                                     char const *restrict __format,
++                                     struct tm *restrict __tm));
++_GL_CXXALIASWARN (strptime);
++# endif
++
++/* Convert TM to a time_t value, assuming UTC.  */
++# if 0
++#  if GNULIB_PORTCHECK
++#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#    undef timegm
++#    define timegm rpl_timegm
++#   endif
++_GL_FUNCDECL_RPL (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1)));
++_GL_CXXALIAS_RPL (timegm, time_t, (struct tm *__tm));
++#  else
++#   if ! 1
++_GL_FUNCDECL_SYS (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1)));
++#   endif
++_GL_CXXALIAS_SYS (timegm, time_t, (struct tm *__tm));
++#  endif
++_GL_CXXALIASWARN (timegm);
++# endif
++
++/* Encourage applications to avoid unsafe functions that can overrun
++   buffers when given outlandish struct tm values.  Portable
++   applications should use strftime (or even sprintf) instead.  */
++# if defined GNULIB_POSIXCHECK
++#  undef asctime
++_GL_WARN_ON_USE (asctime, "asctime can overrun buffers in some cases - "
++                 "better use strftime (or even sprintf) instead");
++# endif
++# if defined GNULIB_POSIXCHECK
++#  undef asctime_r
++_GL_WARN_ON_USE (asctime, "asctime_r can overrun buffers in some cases - "
++                 "better use strftime (or even sprintf) instead");
++# endif
++# if defined GNULIB_POSIXCHECK
++#  undef ctime
++_GL_WARN_ON_USE (asctime, "ctime can overrun buffers in some cases - "
++                 "better use strftime (or even sprintf) instead");
++# endif
++# if defined GNULIB_POSIXCHECK
++#  undef ctime_r
++_GL_WARN_ON_USE (asctime, "ctime_r can overrun buffers in some cases - "
++                 "better use strftime (or even sprintf) instead");
++# endif
++
++#endif
+diff --git a/grub-core/gnulib/time.in.h b/grub-core/gnulib/time.in.h
+new file mode 100644
+index 00000000000..81abdf46e0b
+--- /dev/null
++++ b/grub-core/gnulib/time.in.h
+@@ -0,0 +1,274 @@
++/* A more-standard <time.h>.
++
++   Copyright (C) 2007-2014 Free Software Foundation, Inc.
++
++   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 3, 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/>.  */
++
++#if __GNUC__ >= 3
++@PRAGMA_SYSTEM_HEADER@
++#endif
++@PRAGMA_COLUMNS@
++
++/* Don't get in the way of glibc when it includes time.h merely to
++   declare a few standard symbols, rather than to declare all the
++   symbols.  Also, Solaris 8 <time.h> eventually includes itself
++   recursively; if that is happening, just include the system <time.h>
++   without adding our own declarations.  */
++#if (defined __need_time_t || defined __need_clock_t \
++     || defined __need_timespec \
++     || defined _@GUARD_PREFIX@_TIME_H)
++
++# @INCLUDE_NEXT@ @NEXT_TIME_H@
++
++#else
++
++# define _@GUARD_PREFIX@_TIME_H
++
++# @INCLUDE_NEXT@ @NEXT_TIME_H@
++
++/* NetBSD 5.0 mis-defines NULL.  */
++# include <stddef.h>
++
++/* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
++
++/* The definition of _GL_ARG_NONNULL is copied here.  */
++
++/* The definition of _GL_WARN_ON_USE is copied here.  */
++
++/* Some systems don't define struct timespec (e.g., AIX 4.1, Ultrix 4.3).
++   Or they define it with the wrong member names or define it in <sys/time.h>
++   (e.g., FreeBSD circa 1997).  Stock Mingw prior to 3.0 does not define it,
++   but the pthreads-win32 library defines it in <pthread.h>.  */
++# if ! @TIME_H_DEFINES_STRUCT_TIMESPEC@
++#  if @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@
++#   include <sys/time.h>
++#  elif @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@
++#   include <pthread.h>
++#  else
++
++#   ifdef __cplusplus
++extern "C" {
++#   endif
++
++#   if !GNULIB_defined_struct_timespec
++#    undef timespec
++#    define timespec rpl_timespec
++struct timespec
++{
++  time_t tv_sec;
++  long int tv_nsec;
++};
++#    define GNULIB_defined_struct_timespec 1
++#   endif
++
++#   ifdef __cplusplus
++}
++#   endif
++
++#  endif
++# endif
++
++# if !GNULIB_defined_struct_time_t_must_be_integral
++/* Per http://austingroupbugs.net/view.php?id=327, POSIX requires
++   time_t to be an integer type, even though C99 permits floating
++   point.  We don't know of any implementation that uses floating
++   point, and it is much easier to write code that doesn't have to
++   worry about that corner case, so we force the issue.  */
++struct __time_t_must_be_integral {
++  unsigned int __floating_time_t_unsupported : (time_t) 1;
++};
++#  define GNULIB_defined_struct_time_t_must_be_integral 1
++# endif
++
++/* Sleep for at least RQTP seconds unless interrupted,  If interrupted,
++   return -1 and store the remaining time into RMTP.  See
++   <http://www.opengroup.org/susv3xsh/nanosleep.html>.  */
++# if @GNULIB_NANOSLEEP@
++#  if @REPLACE_NANOSLEEP@
++#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#    define nanosleep rpl_nanosleep
++#   endif
++_GL_FUNCDECL_RPL (nanosleep, int,
++                  (struct timespec const *__rqtp, struct timespec *__rmtp)
++                  _GL_ARG_NONNULL ((1)));
++_GL_CXXALIAS_RPL (nanosleep, int,
++                  (struct timespec const *__rqtp, struct timespec *__rmtp));
++#  else
++#   if ! @HAVE_NANOSLEEP@
++_GL_FUNCDECL_SYS (nanosleep, int,
++                  (struct timespec const *__rqtp, struct timespec *__rmtp)
++                  _GL_ARG_NONNULL ((1)));
++#   endif
++_GL_CXXALIAS_SYS (nanosleep, int,
++                  (struct timespec const *__rqtp, struct timespec *__rmtp));
++#  endif
++_GL_CXXALIASWARN (nanosleep);
++# endif
++
++/* Return the 'time_t' representation of TP and normalize TP.  */
++# if @GNULIB_MKTIME@
++#  if @REPLACE_MKTIME@
++#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#    define mktime rpl_mktime
++#   endif
++_GL_FUNCDECL_RPL (mktime, time_t, (struct tm *__tp) _GL_ARG_NONNULL ((1)));
++_GL_CXXALIAS_RPL (mktime, time_t, (struct tm *__tp));
++#  else
++_GL_CXXALIAS_SYS (mktime, time_t, (struct tm *__tp));
++#  endif
++_GL_CXXALIASWARN (mktime);
++# endif
++
++/* Convert TIMER to RESULT, assuming local time and UTC respectively.  See
++   <http://www.opengroup.org/susv3xsh/localtime_r.html> and
++   <http://www.opengroup.org/susv3xsh/gmtime_r.html>.  */
++# if @GNULIB_TIME_R@
++#  if @REPLACE_LOCALTIME_R@
++#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#    undef localtime_r
++#    define localtime_r rpl_localtime_r
++#   endif
++_GL_FUNCDECL_RPL (localtime_r, struct tm *, (time_t const *restrict __timer,
++                                             struct tm *restrict __result)
++                                            _GL_ARG_NONNULL ((1, 2)));
++_GL_CXXALIAS_RPL (localtime_r, struct tm *, (time_t const *restrict __timer,
++                                             struct tm *restrict __result));
++#  else
++#   if ! @HAVE_DECL_LOCALTIME_R@
++_GL_FUNCDECL_SYS (localtime_r, struct tm *, (time_t const *restrict __timer,
++                                             struct tm *restrict __result)
++                                            _GL_ARG_NONNULL ((1, 2)));
++#   endif
++_GL_CXXALIAS_SYS (localtime_r, struct tm *, (time_t const *restrict __timer,
++                                             struct tm *restrict __result));
++#  endif
++#  if @HAVE_DECL_LOCALTIME_R@
++_GL_CXXALIASWARN (localtime_r);
++#  endif
++#  if @REPLACE_LOCALTIME_R@
++#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#    undef gmtime_r
++#    define gmtime_r rpl_gmtime_r
++#   endif
++_GL_FUNCDECL_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer,
++                                          struct tm *restrict __result)
++                                         _GL_ARG_NONNULL ((1, 2)));
++_GL_CXXALIAS_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer,
++                                          struct tm *restrict __result));
++#  else
++#   if ! @HAVE_DECL_LOCALTIME_R@
++_GL_FUNCDECL_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer,
++                                          struct tm *restrict __result)
++                                         _GL_ARG_NONNULL ((1, 2)));
++#   endif
++_GL_CXXALIAS_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer,
++                                          struct tm *restrict __result));
++#  endif
++#  if @HAVE_DECL_LOCALTIME_R@
++_GL_CXXALIASWARN (gmtime_r);
++#  endif
++# endif
++
++/* Convert TIMER to RESULT, assuming local time and UTC respectively.  See
++   <http://www.opengroup.org/susv3xsh/localtime.html> and
++   <http://www.opengroup.org/susv3xsh/gmtime.html>.  */
++# if @GNULIB_GETTIMEOFDAY@
++#  if @REPLACE_LOCALTIME@
++#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#    undef localtime
++#    define localtime rpl_localtime
++#   endif
++_GL_FUNCDECL_RPL (localtime, struct tm *, (time_t const *__timer)
++		                          _GL_ARG_NONNULL ((1)));
++_GL_CXXALIAS_RPL (localtime, struct tm *, (time_t const *__timer));
++#  else
++_GL_CXXALIAS_SYS (localtime, struct tm *, (time_t const *__timer));
++#  endif
++_GL_CXXALIASWARN (localtime);
++# endif
++
++# if @GNULIB_GETTIMEOFDAY@
++#  if @REPLACE_GMTIME@
++#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#    undef gmtime
++#    define gmtime rpl_gmtime
++#   endif
++_GL_FUNCDECL_RPL (gmtime, struct tm *, (time_t const *__timer)
++                                       _GL_ARG_NONNULL ((1)));
++_GL_CXXALIAS_RPL (gmtime, struct tm *, (time_t const *__timer));
++#  else
++_GL_CXXALIAS_SYS (gmtime, struct tm *, (time_t const *__timer));
++#  endif
++_GL_CXXALIASWARN (gmtime);
++# endif
++
++/* Parse BUF as a time stamp, assuming FORMAT specifies its layout, and store
++   the resulting broken-down time into TM.  See
++   <http://www.opengroup.org/susv3xsh/strptime.html>.  */
++# if @GNULIB_STRPTIME@
++#  if ! @HAVE_STRPTIME@
++_GL_FUNCDECL_SYS (strptime, char *, (char const *restrict __buf,
++                                     char const *restrict __format,
++                                     struct tm *restrict __tm)
++                                    _GL_ARG_NONNULL ((1, 2, 3)));
++#  endif
++_GL_CXXALIAS_SYS (strptime, char *, (char const *restrict __buf,
++                                     char const *restrict __format,
++                                     struct tm *restrict __tm));
++_GL_CXXALIASWARN (strptime);
++# endif
++
++/* Convert TM to a time_t value, assuming UTC.  */
++# if @GNULIB_TIMEGM@
++#  if @REPLACE_TIMEGM@
++#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
++#    undef timegm
++#    define timegm rpl_timegm
++#   endif
++_GL_FUNCDECL_RPL (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1)));
++_GL_CXXALIAS_RPL (timegm, time_t, (struct tm *__tm));
++#  else
++#   if ! @HAVE_TIMEGM@
++_GL_FUNCDECL_SYS (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1)));
++#   endif
++_GL_CXXALIAS_SYS (timegm, time_t, (struct tm *__tm));
++#  endif
++_GL_CXXALIASWARN (timegm);
++# endif
++
++/* Encourage applications to avoid unsafe functions that can overrun
++   buffers when given outlandish struct tm values.  Portable
++   applications should use strftime (or even sprintf) instead.  */
++# if defined GNULIB_POSIXCHECK
++#  undef asctime
++_GL_WARN_ON_USE (asctime, "asctime can overrun buffers in some cases - "
++                 "better use strftime (or even sprintf) instead");
++# endif
++# if defined GNULIB_POSIXCHECK
++#  undef asctime_r
++_GL_WARN_ON_USE (asctime, "asctime_r can overrun buffers in some cases - "
++                 "better use strftime (or even sprintf) instead");
++# endif
++# if defined GNULIB_POSIXCHECK
++#  undef ctime
++_GL_WARN_ON_USE (asctime, "ctime can overrun buffers in some cases - "
++                 "better use strftime (or even sprintf) instead");
++# endif
++# if defined GNULIB_POSIXCHECK
++#  undef ctime_r
++_GL_WARN_ON_USE (asctime, "ctime_r can overrun buffers in some cases - "
++                 "better use strftime (or even sprintf) instead");
++# endif
++
++#endif
+diff --git a/include/grub/osdep/hostfile_aros.h b/include/grub/osdep/hostfile_aros.h
+index a059c0fa40a..161fbb7bdfd 100644
+--- a/include/grub/osdep/hostfile_aros.h
++++ b/include/grub/osdep/hostfile_aros.h
+@@ -68,6 +68,12 @@ grub_util_rename (const char *from, const char *to)
+   return rename (from, to);
+ }
+ 
++static inline ssize_t
++grub_util_readlink (const char *name, char *buf, size_t bufsize)
++{
++  return readlink(name, buf, bufsize);
++}
++
+ #define grub_util_mkdir(a) mkdir ((a), 0755)
+ 
+ struct grub_util_fd
+diff --git a/include/grub/osdep/hostfile_unix.h b/include/grub/osdep/hostfile_unix.h
+index 9ffe46fa3ca..17cd3aa8b30 100644
+--- a/include/grub/osdep/hostfile_unix.h
++++ b/include/grub/osdep/hostfile_unix.h
+@@ -71,6 +71,12 @@ grub_util_rename (const char *from, const char *to)
+   return rename (from, to);
+ }
+ 
++static inline ssize_t
++grub_util_readlink (const char *name, char *buf, size_t bufsize)
++{
++  return readlink(name, buf, bufsize);
++}
++
+ #define grub_util_mkdir(a) mkdir ((a), 0755)
+ 
+ #if defined (__NetBSD__)
+diff --git a/include/grub/osdep/hostfile_windows.h b/include/grub/osdep/hostfile_windows.h
+index bf6451b6db4..8c92d0591bb 100644
+--- a/include/grub/osdep/hostfile_windows.h
++++ b/include/grub/osdep/hostfile_windows.h
+@@ -41,6 +41,8 @@ typedef struct grub_util_fd_dir *grub_util_fd_dir_t;
+ 
+ int
+ grub_util_rename (const char *from, const char *to);
++ssize_t
++grub_util_readlink (const char *name, char *buf, size_t bufsize);
+ int
+ grub_util_unlink (const char *name);
+ void
+diff --git a/grub-core/gnulib/Makefile.am b/grub-core/gnulib/Makefile.am
+index 3444397fe37..b7c5e60e1c3 100644
+--- a/grub-core/gnulib/Makefile.am
++++ b/grub-core/gnulib/Makefile.am
+@@ -21,7 +21,7 @@
+ # the same distribution terms as the rest of that program.
+ #
+ # Generated by gnulib-tool.
+-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=grub-core/gnulib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files argp error fnmatch getdelim getline gettext progname regex
++# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=grub-core/gnulib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files argp error fnmatch getdelim getline gettext progname readlink regex
+ 
+ AUTOMAKE_OPTIONS = 1.5 gnits subdir-objects
+ 
+@@ -326,6 +326,15 @@ libgnu_a_SOURCES += gettext.h
+ 
+ ## end   gnulib module gettext-h
+ 
++## begin gnulib module gettimeofday
++
++
++EXTRA_DIST += gettimeofday.c
++
++EXTRA_libgnu_a_SOURCES += gettimeofday.c
++
++## end   gnulib module gettimeofday
++
+ ## begin gnulib module havelib
+ 
+ 
+@@ -596,6 +605,13 @@ EXTRA_libgnu_a_SOURCES += nl_langinfo.c
+ 
+ ## end   gnulib module nl_langinfo
+ 
++## begin gnulib module pathmax
++
++
++EXTRA_DIST += pathmax.h
++
++## end   gnulib module pathmax
++
+ ## begin gnulib module progname
+ 
+ libgnu_a_SOURCES += progname.h progname.c
+@@ -611,6 +627,15 @@ EXTRA_libgnu_a_SOURCES += rawmemchr.c
+ 
+ ## end   gnulib module rawmemchr
+ 
++## begin gnulib module readlink
++
++
++EXTRA_DIST += readlink.c
++
++EXTRA_libgnu_a_SOURCES += readlink.c
++
++## end   gnulib module readlink
++
+ ## begin gnulib module realloc-posix
+ 
+ 
+@@ -725,6 +750,15 @@ EXTRA_DIST += $(top_srcdir)/build-aux/snippet/warn-on-use.h
+ 
+ ## end   gnulib module snippet/warn-on-use
+ 
++## begin gnulib module stat
++
++
++EXTRA_DIST += stat.c
++
++EXTRA_libgnu_a_SOURCES += stat.c
++
++## end   gnulib module stat
++
+ ## begin gnulib module stdalign
+ 
+ BUILT_SOURCES += $(STDALIGN_H)
+@@ -1280,6 +1314,102 @@ libgnu_a_SOURCES += strnlen1.h strnlen1.c
+ 
+ ## end   gnulib module strnlen1
+ 
++## begin gnulib module sys_stat
++
++BUILT_SOURCES += sys/stat.h
++
++# We need the following in order to create <sys/stat.h> when the system
++# has one that is incomplete.
++sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
++	$(AM_V_at)$(MKDIR_P) sys
++	$(AM_V_GEN)rm -f $@-t $@ && \
++	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
++	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
++	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
++	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
++	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
++	      -e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \
++	      -e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \
++	      -e 's/@''GNULIB_FCHMODAT''@/$(GNULIB_FCHMODAT)/g' \
++	      -e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \
++	      -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \
++	      -e 's/@''GNULIB_FUTIMENS''@/$(GNULIB_FUTIMENS)/g' \
++	      -e 's/@''GNULIB_LCHMOD''@/$(GNULIB_LCHMOD)/g' \
++	      -e 's/@''GNULIB_LSTAT''@/$(GNULIB_LSTAT)/g' \
++	      -e 's/@''GNULIB_MKDIRAT''@/$(GNULIB_MKDIRAT)/g' \
++	      -e 's/@''GNULIB_MKFIFO''@/$(GNULIB_MKFIFO)/g' \
++	      -e 's/@''GNULIB_MKFIFOAT''@/$(GNULIB_MKFIFOAT)/g' \
++	      -e 's/@''GNULIB_MKNOD''@/$(GNULIB_MKNOD)/g' \
++	      -e 's/@''GNULIB_MKNODAT''@/$(GNULIB_MKNODAT)/g' \
++	      -e 's/@''GNULIB_STAT''@/$(GNULIB_STAT)/g' \
++	      -e 's/@''GNULIB_UTIMENSAT''@/$(GNULIB_UTIMENSAT)/g' \
++	      -e 's|@''HAVE_FCHMODAT''@|$(HAVE_FCHMODAT)|g' \
++	      -e 's|@''HAVE_FSTATAT''@|$(HAVE_FSTATAT)|g' \
++	      -e 's|@''HAVE_FUTIMENS''@|$(HAVE_FUTIMENS)|g' \
++	      -e 's|@''HAVE_LCHMOD''@|$(HAVE_LCHMOD)|g' \
++	      -e 's|@''HAVE_LSTAT''@|$(HAVE_LSTAT)|g' \
++	      -e 's|@''HAVE_MKDIRAT''@|$(HAVE_MKDIRAT)|g' \
++	      -e 's|@''HAVE_MKFIFO''@|$(HAVE_MKFIFO)|g' \
++	      -e 's|@''HAVE_MKFIFOAT''@|$(HAVE_MKFIFOAT)|g' \
++	      -e 's|@''HAVE_MKNOD''@|$(HAVE_MKNOD)|g' \
++	      -e 's|@''HAVE_MKNODAT''@|$(HAVE_MKNODAT)|g' \
++	      -e 's|@''HAVE_UTIMENSAT''@|$(HAVE_UTIMENSAT)|g' \
++	      -e 's|@''REPLACE_FSTAT''@|$(REPLACE_FSTAT)|g' \
++	      -e 's|@''REPLACE_FSTATAT''@|$(REPLACE_FSTATAT)|g' \
++	      -e 's|@''REPLACE_FUTIMENS''@|$(REPLACE_FUTIMENS)|g' \
++	      -e 's|@''REPLACE_LSTAT''@|$(REPLACE_LSTAT)|g' \
++	      -e 's|@''REPLACE_MKDIR''@|$(REPLACE_MKDIR)|g' \
++	      -e 's|@''REPLACE_MKFIFO''@|$(REPLACE_MKFIFO)|g' \
++	      -e 's|@''REPLACE_MKNOD''@|$(REPLACE_MKNOD)|g' \
++	      -e 's|@''REPLACE_STAT''@|$(REPLACE_STAT)|g' \
++	      -e 's|@''REPLACE_UTIMENSAT''@|$(REPLACE_UTIMENSAT)|g' \
++	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
++	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
++	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
++	      < $(srcdir)/sys_stat.in.h; \
++	} > $@-t && \
++	mv $@-t $@
++MOSTLYCLEANFILES += sys/stat.h sys/stat.h-t
++MOSTLYCLEANDIRS += sys
++
++EXTRA_DIST += sys_stat.in.h
++
++## end   gnulib module sys_stat
++
++## begin gnulib module sys_time
++
++BUILT_SOURCES += sys/time.h
++
++# We need the following in order to create <sys/time.h> when the system
++# doesn't have one that works with the given compiler.
++sys/time.h: sys_time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
++	$(AM_V_at)$(MKDIR_P) sys
++	$(AM_V_GEN)rm -f $@-t $@ && \
++	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
++	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
++	      -e 's/@''HAVE_SYS_TIME_H''@/$(HAVE_SYS_TIME_H)/g' \
++	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
++	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
++	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
++	      -e 's|@''NEXT_SYS_TIME_H''@|$(NEXT_SYS_TIME_H)|g' \
++	      -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \
++	      -e 's|@''HAVE_WINSOCK2_H''@|$(HAVE_WINSOCK2_H)|g' \
++	      -e 's/@''HAVE_GETTIMEOFDAY''@/$(HAVE_GETTIMEOFDAY)/g' \
++	      -e 's/@''HAVE_STRUCT_TIMEVAL''@/$(HAVE_STRUCT_TIMEVAL)/g' \
++	      -e 's/@''REPLACE_GETTIMEOFDAY''@/$(REPLACE_GETTIMEOFDAY)/g' \
++	      -e 's/@''REPLACE_STRUCT_TIMEVAL''@/$(REPLACE_STRUCT_TIMEVAL)/g' \
++	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
++	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
++	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
++	      < $(srcdir)/sys_time.in.h; \
++	} > $@-t && \
++	mv $@-t $@
++MOSTLYCLEANFILES += sys/time.h sys/time.h-t
++
++EXTRA_DIST += sys_time.in.h
++
++## end   gnulib module sys_time
++
+ ## begin gnulib module sys_types
+ 
+ BUILT_SOURCES += sys/types.h
+@@ -1334,6 +1464,51 @@ EXTRA_DIST += sysexits.in.h
+ 
+ ## end   gnulib module sysexits
+ 
++## begin gnulib module time
++
++BUILT_SOURCES += time.h
++
++# We need the following in order to create <time.h> when the system
++# doesn't have one that works with the given compiler.
++time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
++	$(AM_V_GEN)rm -f $@-t $@ && \
++	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
++	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
++	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
++	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
++	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
++	      -e 's|@''NEXT_TIME_H''@|$(NEXT_TIME_H)|g' \
++	      -e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \
++	      -e 's/@''GNULIB_MKTIME''@/$(GNULIB_MKTIME)/g' \
++	      -e 's/@''GNULIB_NANOSLEEP''@/$(GNULIB_NANOSLEEP)/g' \
++	      -e 's/@''GNULIB_STRPTIME''@/$(GNULIB_STRPTIME)/g' \
++	      -e 's/@''GNULIB_TIMEGM''@/$(GNULIB_TIMEGM)/g' \
++	      -e 's/@''GNULIB_TIME_R''@/$(GNULIB_TIME_R)/g' \
++	      -e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \
++	      -e 's|@''HAVE_NANOSLEEP''@|$(HAVE_NANOSLEEP)|g' \
++	      -e 's|@''HAVE_STRPTIME''@|$(HAVE_STRPTIME)|g' \
++	      -e 's|@''HAVE_TIMEGM''@|$(HAVE_TIMEGM)|g' \
++	      -e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \
++	      -e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \
++	      -e 's|@''REPLACE_LOCALTIME_R''@|$(REPLACE_LOCALTIME_R)|g' \
++	      -e 's|@''REPLACE_MKTIME''@|$(REPLACE_MKTIME)|g' \
++	      -e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \
++	      -e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \
++	      -e 's|@''PTHREAD_H_DEFINES_STRUCT_TIMESPEC''@|$(PTHREAD_H_DEFINES_STRUCT_TIMESPEC)|g' \
++	      -e 's|@''SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \
++	      -e 's|@''TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \
++	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
++	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
++	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
++	      < $(srcdir)/time.in.h; \
++	} > $@-t && \
++	mv $@-t $@
++MOSTLYCLEANFILES += time.h time.h-t
++
++EXTRA_DIST += time.in.h
++
++## end   gnulib module time
++
+ ## begin gnulib module unistd
+ 
+ BUILT_SOURCES += unistd.h
+diff --git a/m4/gettimeofday.m4 b/m4/gettimeofday.m4
+new file mode 100644
+index 00000000000..1c2d66ee261
+--- /dev/null
++++ b/m4/gettimeofday.m4
+@@ -0,0 +1,138 @@
++# serial 21
++
++# Copyright (C) 2001-2003, 2005, 2007, 2009-2014 Free Software Foundation, Inc.
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++dnl From Jim Meyering.
++
++AC_DEFUN([gl_FUNC_GETTIMEOFDAY],
++[
++  AC_REQUIRE([AC_C_RESTRICT])
++  AC_REQUIRE([gl_HEADER_SYS_TIME_H])
++  AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS])
++  AC_CHECK_FUNCS_ONCE([gettimeofday])
++
++  gl_gettimeofday_timezone=void
++  if test $ac_cv_func_gettimeofday != yes; then
++    HAVE_GETTIMEOFDAY=0
++  else
++    gl_FUNC_GETTIMEOFDAY_CLOBBER
++    AC_CACHE_CHECK([for gettimeofday with POSIX signature],
++      [gl_cv_func_gettimeofday_posix_signature],
++      [AC_COMPILE_IFELSE(
++         [AC_LANG_PROGRAM(
++            [[#include <sys/time.h>
++              struct timeval c;
++              int gettimeofday (struct timeval *restrict, void *restrict);
++            ]],
++            [[/* glibc uses struct timezone * rather than the POSIX void *
++                 if _GNU_SOURCE is defined.  However, since the only portable
++                 use of gettimeofday uses NULL as the second parameter, and
++                 since the glibc definition is actually more typesafe, it is
++                 not worth wrapping this to get a compliant signature.  */
++              int (*f) (struct timeval *restrict, void *restrict)
++                = gettimeofday;
++              int x = f (&c, 0);
++              return !(x | c.tv_sec | c.tv_usec);
++            ]])],
++          [gl_cv_func_gettimeofday_posix_signature=yes],
++          [AC_COMPILE_IFELSE(
++            [AC_LANG_PROGRAM(
++              [[#include <sys/time.h>
++int gettimeofday (struct timeval *restrict, struct timezone *restrict);
++              ]])],
++            [gl_cv_func_gettimeofday_posix_signature=almost],
++            [gl_cv_func_gettimeofday_posix_signature=no])])])
++    if test $gl_cv_func_gettimeofday_posix_signature = almost; then
++      gl_gettimeofday_timezone='struct timezone'
++    elif test $gl_cv_func_gettimeofday_posix_signature != yes; then
++      REPLACE_GETTIMEOFDAY=1
++    fi
++    dnl If we override 'struct timeval', we also have to override gettimeofday.
++    if test $REPLACE_STRUCT_TIMEVAL = 1; then
++      REPLACE_GETTIMEOFDAY=1
++    fi
++    m4_ifdef([gl_FUNC_TZSET_CLOBBER], [
++      gl_FUNC_TZSET_CLOBBER
++      case "$gl_cv_func_tzset_clobber" in
++        *yes)
++          REPLACE_GETTIMEOFDAY=1
++          gl_GETTIMEOFDAY_REPLACE_LOCALTIME
++          AC_DEFINE([tzset], [rpl_tzset],
++            [Define to rpl_tzset if the wrapper function should be used.])
++          AC_DEFINE([TZSET_CLOBBERS_LOCALTIME], [1],
++            [Define if tzset clobbers localtime's static buffer.])
++          ;;
++      esac
++    ])
++  fi
++  AC_DEFINE_UNQUOTED([GETTIMEOFDAY_TIMEZONE], [$gl_gettimeofday_timezone],
++    [Define this to 'void' or 'struct timezone' to match the system's
++     declaration of the second argument to gettimeofday.])
++])
++
++
++dnl See if gettimeofday clobbers the static buffer that localtime uses
++dnl for its return value.  The gettimeofday function from Mac OS X 10.0.4
++dnl (i.e., Darwin 1.3.7) has this problem.
++dnl
++dnl If it does, then arrange to use gettimeofday and localtime only via
++dnl the wrapper functions that work around the problem.
++
++AC_DEFUN([gl_FUNC_GETTIMEOFDAY_CLOBBER],
++[
++ AC_REQUIRE([gl_HEADER_SYS_TIME_H])
++ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
++
++ AC_CACHE_CHECK([whether gettimeofday clobbers localtime buffer],
++  [gl_cv_func_gettimeofday_clobber],
++  [AC_RUN_IFELSE(
++     [AC_LANG_PROGRAM(
++        [[#include <string.h>
++          #include <sys/time.h>
++          #include <time.h>
++          #include <stdlib.h>
++        ]],
++        [[
++          time_t t = 0;
++          struct tm *lt;
++          struct tm saved_lt;
++          struct timeval tv;
++          lt = localtime (&t);
++          saved_lt = *lt;
++          gettimeofday (&tv, NULL);
++          return memcmp (lt, &saved_lt, sizeof (struct tm)) != 0;
++        ]])],
++     [gl_cv_func_gettimeofday_clobber=no],
++     [gl_cv_func_gettimeofday_clobber=yes],
++     [# When cross-compiling:
++      case "$host_os" in
++                # Guess all is fine on glibc systems.
++        *-gnu*) gl_cv_func_gettimeofday_clobber="guessing no" ;;
++                # If we don't know, assume the worst.
++        *)      gl_cv_func_gettimeofday_clobber="guessing yes" ;;
++      esac
++     ])])
++
++ case "$gl_cv_func_gettimeofday_clobber" in
++   *yes)
++     REPLACE_GETTIMEOFDAY=1
++     gl_GETTIMEOFDAY_REPLACE_LOCALTIME
++     AC_DEFINE([GETTIMEOFDAY_CLOBBERS_LOCALTIME], [1],
++       [Define if gettimeofday clobbers the localtime buffer.])
++     ;;
++ esac
++])
++
++AC_DEFUN([gl_GETTIMEOFDAY_REPLACE_LOCALTIME], [
++  REPLACE_GMTIME=1
++  REPLACE_LOCALTIME=1
++])
++
++# Prerequisites of lib/gettimeofday.c.
++AC_DEFUN([gl_PREREQ_GETTIMEOFDAY], [
++  AC_CHECK_HEADERS([sys/timeb.h])
++  AC_CHECK_FUNCS([_ftime])
++])
+diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4
+index 408918440b6..ef2ec5bcce0 100644
+--- a/m4/gnulib-cache.m4
++++ b/m4/gnulib-cache.m4
+@@ -27,7 +27,7 @@
+ 
+ 
+ # Specification in the form of a command-line invocation:
+-#   gnulib-tool --import --dir=. --lib=libgnu --source-base=grub-core/gnulib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files argp error fnmatch getdelim getline gettext progname regex
++#   gnulib-tool --import --dir=. --lib=libgnu --source-base=grub-core/gnulib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files argp error fnmatch getdelim getline gettext progname readlink regex
+ 
+ # Specification in the form of a few gnulib-tool.m4 macro invocations:
+ gl_LOCAL_DIR([])
+@@ -39,6 +39,7 @@ gl_MODULES([
+   getline
+   gettext
+   progname
++  readlink
+   regex
+ ])
+ gl_AVOID([])
+diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
+index 7a19f60d85e..66fd0eda901 100644
+--- a/m4/gnulib-comp.m4
++++ b/m4/gnulib-comp.m4
+@@ -60,10 +60,13 @@ AC_DEFUN([gl_EARLY],
+   # Code from module getopt-posix:
+   # Code from module gettext:
+   # Code from module gettext-h:
++  # Code from module gettimeofday:
+   # Code from module havelib:
+   # Code from module include_next:
+   # Code from module intprops:
+   # Code from module langinfo:
++  # Code from module largefile:
++  AC_REQUIRE([AC_SYS_LARGEFILE])
+   # Code from module localcharset:
+   # Code from module locale:
+   # Code from module localeconv:
+@@ -81,8 +84,10 @@ AC_DEFUN([gl_EARLY],
+   # Code from module multiarch:
+   # Code from module nl_langinfo:
+   # Code from module nocrash:
++  # Code from module pathmax:
+   # Code from module progname:
+   # Code from module rawmemchr:
++  # Code from module readlink:
+   # Code from module realloc-posix:
+   # Code from module regex:
+   # Code from module size_max:
+@@ -92,6 +97,7 @@ AC_DEFUN([gl_EARLY],
+   # Code from module snippet/c++defs:
+   # Code from module snippet/warn-on-use:
+   # Code from module ssize_t:
++  # Code from module stat:
+   # Code from module stdalign:
+   # Code from module stdbool:
+   # Code from module stddef:
+@@ -108,8 +114,11 @@ AC_DEFUN([gl_EARLY],
+   # Code from module strndup:
+   # Code from module strnlen:
+   # Code from module strnlen1:
++  # Code from module sys_stat:
++  # Code from module sys_time:
+   # Code from module sys_types:
+   # Code from module sysexits:
++  # Code from module time:
+   # Code from module unistd:
+   # Code from module unitypes:
+   # Code from module uniwidth/base:
+@@ -211,7 +220,14 @@ AC_DEFUN([gl_INIT],
+   AM_GNU_GETTEXT_VERSION([0.18.1])
+   AC_SUBST([LIBINTL])
+   AC_SUBST([LTLIBINTL])
++  gl_FUNC_GETTIMEOFDAY
++  if test $HAVE_GETTIMEOFDAY = 0 || test $REPLACE_GETTIMEOFDAY = 1; then
++    AC_LIBOBJ([gettimeofday])
++    gl_PREREQ_GETTIMEOFDAY
++  fi
++  gl_SYS_TIME_MODULE_INDICATOR([gettimeofday])
+   gl_LANGINFO_H
++  AC_REQUIRE([gl_LARGEFILE])
+   gl_LOCALCHARSET
+   LOCALCHARSET_TESTS_ENVIRONMENT="CHARSETALIASDIR=\"\$(abs_top_builddir)/$gl_source_base\""
+   AC_SUBST([LOCALCHARSET_TESTS_ENVIRONMENT])
+@@ -284,6 +300,7 @@ AC_DEFUN([gl_INIT],
+     AC_LIBOBJ([nl_langinfo])
+   fi
+   gl_LANGINFO_MODULE_INDICATOR([nl_langinfo])
++  gl_PATHMAX
+   AC_CHECK_DECLS([program_invocation_name], [], [], [#include <errno.h>])
+   AC_CHECK_DECLS([program_invocation_short_name], [], [], [#include <errno.h>])
+   gl_FUNC_RAWMEMCHR
+@@ -292,6 +309,12 @@ AC_DEFUN([gl_INIT],
+     gl_PREREQ_RAWMEMCHR
+   fi
+   gl_STRING_MODULE_INDICATOR([rawmemchr])
++  gl_FUNC_READLINK
++  if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then
++    AC_LIBOBJ([readlink])
++    gl_PREREQ_READLINK
++  fi
++  gl_UNISTD_MODULE_INDICATOR([readlink])
+   gl_FUNC_REALLOC_POSIX
+   if test $REPLACE_REALLOC = 1; then
+     AC_LIBOBJ([realloc])
+@@ -309,6 +332,12 @@ AC_DEFUN([gl_INIT],
+   fi
+   gl_UNISTD_MODULE_INDICATOR([sleep])
+   gt_TYPE_SSIZE_T
++  gl_FUNC_STAT
++  if test $REPLACE_STAT = 1; then
++    AC_LIBOBJ([stat])
++    gl_PREREQ_STAT
++  fi
++  gl_SYS_STAT_MODULE_INDICATOR([stat])
+   gl_STDALIGN_H
+   AM_STDBOOL_H
+   gl_STDDEF_H
+@@ -355,9 +384,14 @@ AC_DEFUN([gl_INIT],
+     gl_PREREQ_STRNLEN
+   fi
+   gl_STRING_MODULE_INDICATOR([strnlen])
++  gl_HEADER_SYS_STAT_H
++  AC_PROG_MKDIR_P
++  gl_HEADER_SYS_TIME_H
++  AC_PROG_MKDIR_P
+   gl_SYS_TYPES_H
+   AC_PROG_MKDIR_P
+   gl_SYSEXITS
++  gl_HEADER_TIME_H
+   gl_UNISTD_H
+   gl_LIBUNISTRING_LIBHEADER([0.9], [unitypes.h])
+   gl_LIBUNISTRING_LIBHEADER([0.9], [uniwidth.h])
+@@ -562,6 +596,7 @@ AC_DEFUN([gl_FILE_LIST], [
+   lib/getopt1.c
+   lib/getopt_int.h
+   lib/gettext.h
++  lib/gettimeofday.c
+   lib/intprops.h
+   lib/itold.c
+   lib/langinfo.in.h
+@@ -587,6 +622,7 @@ AC_DEFUN([gl_FILE_LIST], [
+   lib/msvc-nothrow.c
+   lib/msvc-nothrow.h
+   lib/nl_langinfo.c
++  lib/pathmax.h
+   lib/printf-args.c
+   lib/printf-args.h
+   lib/printf-parse.c
+@@ -595,6 +631,7 @@ AC_DEFUN([gl_FILE_LIST], [
+   lib/progname.h
+   lib/rawmemchr.c
+   lib/rawmemchr.valgrind
++  lib/readlink.c
+   lib/realloc.c
+   lib/ref-add.sin
+   lib/ref-del.sin
+@@ -606,6 +643,7 @@ AC_DEFUN([gl_FILE_LIST], [
+   lib/regexec.c
+   lib/size_max.h
+   lib/sleep.c
++  lib/stat.c
+   lib/stdalign.in.h
+   lib/stdbool.in.h
+   lib/stddef.in.h
+@@ -627,8 +665,11 @@ AC_DEFUN([gl_FILE_LIST], [
+   lib/strnlen.c
+   lib/strnlen1.c
+   lib/strnlen1.h
++  lib/sys_stat.in.h
++  lib/sys_time.in.h
+   lib/sys_types.in.h
+   lib/sysexits.in.h
++  lib/time.in.h
+   lib/unistd.c
+   lib/unistd.in.h
+   lib/unitypes.in.h
+@@ -667,6 +708,7 @@ AC_DEFUN([gl_FILE_LIST], [
+   m4/getline.m4
+   m4/getopt.m4
+   m4/gettext.m4
++  m4/gettimeofday.m4
+   m4/glibc2.m4
+   m4/glibc21.m4
+   m4/gnulib-common.m4
+@@ -681,6 +723,7 @@ AC_DEFUN([gl_FILE_LIST], [
+   m4/inttypes-pri.m4
+   m4/inttypes_h.m4
+   m4/langinfo_h.m4
++  m4/largefile.m4
+   m4/lcmessage.m4
+   m4/lib-ld.m4
+   m4/lib-link.m4
+@@ -712,16 +755,19 @@ AC_DEFUN([gl_FILE_LIST], [
+   m4/nls.m4
+   m4/nocrash.m4
+   m4/off_t.m4
++  m4/pathmax.m4
+   m4/po.m4
+   m4/printf-posix.m4
+   m4/printf.m4
+   m4/progtest.m4
+   m4/rawmemchr.m4
++  m4/readlink.m4
+   m4/realloc.m4
+   m4/regex.m4
+   m4/size_max.m4
+   m4/sleep.m4
+   m4/ssize_t.m4
++  m4/stat.m4
+   m4/stdalign.m4
+   m4/stdbool.m4
+   m4/stddef_h.m4
+@@ -737,9 +783,12 @@ AC_DEFUN([gl_FILE_LIST], [
+   m4/strndup.m4
+   m4/strnlen.m4
+   m4/sys_socket_h.m4
++  m4/sys_stat_h.m4
++  m4/sys_time_h.m4
+   m4/sys_types_h.m4
+   m4/sysexits.m4
+   m4/threadlib.m4
++  m4/time_h.m4
+   m4/uintmax_t.m4
+   m4/unistd_h.m4
+   m4/vasnprintf.m4
+diff --git a/m4/largefile.m4 b/m4/largefile.m4
+new file mode 100644
+index 00000000000..a1b564ad9af
+--- /dev/null
++++ b/m4/largefile.m4
+@@ -0,0 +1,146 @@
++# Enable large files on systems where this is not the default.
++
++# Copyright 1992-1996, 1998-2014 Free Software Foundation, Inc.
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# The following implementation works around a problem in autoconf <= 2.69;
++# AC_SYS_LARGEFILE does not configure for large inodes on Mac OS X 10.5,
++# or configures them incorrectly in some cases.
++m4_version_prereq([2.70], [] ,[
++
++# _AC_SYS_LARGEFILE_TEST_INCLUDES
++# -------------------------------
++m4_define([_AC_SYS_LARGEFILE_TEST_INCLUDES],
++[@%:@include <sys/types.h>
++ /* Check that off_t can represent 2**63 - 1 correctly.
++    We can't simply define LARGE_OFF_T to be 9223372036854775807,
++    since some C++ compilers masquerading as C compilers
++    incorrectly reject 9223372036854775807.  */
++@%:@define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
++  int off_t_is_large[[(LARGE_OFF_T % 2147483629 == 721
++                       && LARGE_OFF_T % 2147483647 == 1)
++                      ? 1 : -1]];[]dnl
++])
++
++
++# _AC_SYS_LARGEFILE_MACRO_VALUE(C-MACRO, VALUE,
++#                               CACHE-VAR,
++#                               DESCRIPTION,
++#                               PROLOGUE, [FUNCTION-BODY])
++# --------------------------------------------------------
++m4_define([_AC_SYS_LARGEFILE_MACRO_VALUE],
++[AC_CACHE_CHECK([for $1 value needed for large files], [$3],
++[while :; do
++  m4_ifval([$6], [AC_LINK_IFELSE], [AC_COMPILE_IFELSE])(
++    [AC_LANG_PROGRAM([$5], [$6])],
++    [$3=no; break])
++  m4_ifval([$6], [AC_LINK_IFELSE], [AC_COMPILE_IFELSE])(
++    [AC_LANG_PROGRAM([@%:@define $1 $2
++$5], [$6])],
++    [$3=$2; break])
++  $3=unknown
++  break
++done])
++case $$3 in #(
++  no | unknown) ;;
++  *) AC_DEFINE_UNQUOTED([$1], [$$3], [$4]);;
++esac
++rm -rf conftest*[]dnl
++])# _AC_SYS_LARGEFILE_MACRO_VALUE
++
++
++# AC_SYS_LARGEFILE
++# ----------------
++# By default, many hosts won't let programs access large files;
++# one must use special compiler options to get large-file access to work.
++# For more details about this brain damage please see:
++# http://www.unix-systems.org/version2/whatsnew/lfs20mar.html
++AC_DEFUN([AC_SYS_LARGEFILE],
++[AC_ARG_ENABLE(largefile,
++               [  --disable-largefile     omit support for large files])
++if test "$enable_largefile" != no; then
++
++  AC_CACHE_CHECK([for special C compiler options needed for large files],
++    ac_cv_sys_largefile_CC,
++    [ac_cv_sys_largefile_CC=no
++     if test "$GCC" != yes; then
++       ac_save_CC=$CC
++       while :; do
++         # IRIX 6.2 and later do not support large files by default,
++         # so use the C compiler's -n32 option if that helps.
++         AC_LANG_CONFTEST([AC_LANG_PROGRAM([_AC_SYS_LARGEFILE_TEST_INCLUDES])])
++         AC_COMPILE_IFELSE([], [break])
++         CC="$CC -n32"
++         AC_COMPILE_IFELSE([], [ac_cv_sys_largefile_CC=' -n32'; break])
++         break
++       done
++       CC=$ac_save_CC
++       rm -f conftest.$ac_ext
++    fi])
++  if test "$ac_cv_sys_largefile_CC" != no; then
++    CC=$CC$ac_cv_sys_largefile_CC
++  fi
++
++  _AC_SYS_LARGEFILE_MACRO_VALUE(_FILE_OFFSET_BITS, 64,
++    ac_cv_sys_file_offset_bits,
++    [Number of bits in a file offset, on hosts where this is settable.],
++    [_AC_SYS_LARGEFILE_TEST_INCLUDES])
++  if test $ac_cv_sys_file_offset_bits = unknown; then
++    _AC_SYS_LARGEFILE_MACRO_VALUE(_LARGE_FILES, 1,
++      ac_cv_sys_large_files,
++      [Define for large files, on AIX-style hosts.],
++      [_AC_SYS_LARGEFILE_TEST_INCLUDES])
++  fi
++
++  AC_DEFINE([_DARWIN_USE_64_BIT_INODE], [1],
++    [Enable large inode numbers on Mac OS X 10.5.])
++fi
++])# AC_SYS_LARGEFILE
++])# m4_version_prereq 2.70
++
++# Enable large files on systems where this is implemented by Gnulib, not by the
++# system headers.
++# Set the variables WINDOWS_64_BIT_OFF_T, WINDOWS_64_BIT_ST_SIZE if Gnulib
++# overrides ensure that off_t or 'struct size.st_size' are 64-bit, respectively.
++AC_DEFUN([gl_LARGEFILE],
++[
++  AC_REQUIRE([AC_CANONICAL_HOST])
++  case "$host_os" in
++    mingw*)
++      dnl Native Windows.
++      dnl mingw64 defines off_t to a 64-bit type already, if
++      dnl _FILE_OFFSET_BITS=64, which is ensured by AC_SYS_LARGEFILE.
++      AC_CACHE_CHECK([for 64-bit off_t], [gl_cv_type_off_t_64],
++        [AC_COMPILE_IFELSE(
++           [AC_LANG_PROGRAM(
++              [[#include <sys/types.h>
++                int verify_off_t_size[sizeof (off_t) >= 8 ? 1 : -1];
++              ]],
++              [[]])],
++           [gl_cv_type_off_t_64=yes], [gl_cv_type_off_t_64=no])
++        ])
++      if test $gl_cv_type_off_t_64 = no; then
++        WINDOWS_64_BIT_OFF_T=1
++      else
++        WINDOWS_64_BIT_OFF_T=0
++      fi
++      dnl But all native Windows platforms (including mingw64) have a 32-bit
++      dnl st_size member in 'struct stat'.
++      WINDOWS_64_BIT_ST_SIZE=1
++      ;;
++    *)
++      dnl Nothing to do on gnulib's side.
++      dnl A 64-bit off_t is
++      dnl   - already the default on Mac OS X, FreeBSD, NetBSD, OpenBSD, IRIX,
++      dnl     OSF/1, Cygwin,
++      dnl   - enabled by _FILE_OFFSET_BITS=64 (ensured by AC_SYS_LARGEFILE) on
++      dnl     glibc, HP-UX, Solaris,
++      dnl   - enabled by _LARGE_FILES=1 (ensured by AC_SYS_LARGEFILE) on AIX,
++      dnl   - impossible to achieve on Minix 3.1.8.
++      WINDOWS_64_BIT_OFF_T=0
++      WINDOWS_64_BIT_ST_SIZE=0
++      ;;
++  esac
++])
+diff --git a/m4/pathmax.m4 b/m4/pathmax.m4
+new file mode 100644
+index 00000000000..114f91f04b5
+--- /dev/null
++++ b/m4/pathmax.m4
+@@ -0,0 +1,42 @@
++# pathmax.m4 serial 10
++dnl Copyright (C) 2002-2003, 2005-2006, 2009-2014 Free Software Foundation,
++dnl Inc.
++dnl This file is free software; the Free Software Foundation
++dnl gives unlimited permission to copy and/or distribute it,
++dnl with or without modifications, as long as this notice is preserved.
++
++AC_DEFUN([gl_PATHMAX],
++[
++  dnl Prerequisites of lib/pathmax.h.
++  AC_CHECK_HEADERS_ONCE([sys/param.h])
++])
++
++# Expands to a piece of C program that defines PATH_MAX in the same way as
++# "pathmax.h" will do.
++AC_DEFUN([gl_PATHMAX_SNIPPET], [[
++/* Arrange to define PATH_MAX, like "pathmax.h" does. */
++#if HAVE_UNISTD_H
++# include <unistd.h>
++#endif
++#include <limits.h>
++#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
++# include <sys/param.h>
++#endif
++#if !defined PATH_MAX && defined MAXPATHLEN
++# define PATH_MAX MAXPATHLEN
++#endif
++#ifdef __hpux
++# undef PATH_MAX
++# define PATH_MAX 1024
++#endif
++#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
++# undef PATH_MAX
++# define PATH_MAX 260
++#endif
++]])
++
++# Prerequisites of gl_PATHMAX_SNIPPET.
++AC_DEFUN([gl_PATHMAX_SNIPPET_PREREQ],
++[
++  AC_CHECK_HEADERS_ONCE([unistd.h sys/param.h])
++])
+diff --git a/m4/readlink.m4 b/m4/readlink.m4
+new file mode 100644
+index 00000000000..f9ce868c2e4
+--- /dev/null
++++ b/m4/readlink.m4
+@@ -0,0 +1,71 @@
++# readlink.m4 serial 12
++dnl Copyright (C) 2003, 2007, 2009-2014 Free Software Foundation, Inc.
++dnl This file is free software; the Free Software Foundation
++dnl gives unlimited permission to copy and/or distribute it,
++dnl with or without modifications, as long as this notice is preserved.
++
++AC_DEFUN([gl_FUNC_READLINK],
++[
++  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
++  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
++  AC_CHECK_FUNCS_ONCE([readlink])
++  if test $ac_cv_func_readlink = no; then
++    HAVE_READLINK=0
++  else
++    AC_CACHE_CHECK([whether readlink signature is correct],
++      [gl_cv_decl_readlink_works],
++      [AC_COMPILE_IFELSE(
++         [AC_LANG_PROGRAM(
++           [[#include <unistd.h>
++      /* Cause compilation failure if original declaration has wrong type.  */
++      ssize_t readlink (const char *, char *, size_t);]])],
++         [gl_cv_decl_readlink_works=yes], [gl_cv_decl_readlink_works=no])])
++    dnl Solaris 9 ignores trailing slash.
++    dnl FreeBSD 7.2 dereferences only one level of links with trailing slash.
++    AC_CACHE_CHECK([whether readlink handles trailing slash correctly],
++      [gl_cv_func_readlink_works],
++      [# We have readlink, so assume ln -s works.
++       ln -s conftest.no-such conftest.link
++       ln -s conftest.link conftest.lnk2
++       AC_RUN_IFELSE(
++         [AC_LANG_PROGRAM(
++           [[#include <unistd.h>
++]], [[char buf[20];
++      return readlink ("conftest.lnk2/", buf, sizeof buf) != -1;]])],
++         [gl_cv_func_readlink_works=yes], [gl_cv_func_readlink_works=no],
++         [case "$host_os" in
++                    # Guess yes on glibc systems.
++            *-gnu*) gl_cv_func_readlink_works="guessing yes" ;;
++                    # If we don't know, assume the worst.
++            *)      gl_cv_func_readlink_works="guessing no" ;;
++          esac
++         ])
++      rm -f conftest.link conftest.lnk2])
++    case "$gl_cv_func_readlink_works" in
++      *yes)
++        if test "$gl_cv_decl_readlink_works" != yes; then
++          REPLACE_READLINK=1
++        fi
++        ;;
++      *)
++        AC_DEFINE([READLINK_TRAILING_SLASH_BUG], [1], [Define to 1 if readlink
++          fails to recognize a trailing slash.])
++        REPLACE_READLINK=1
++        ;;
++    esac
++  fi
++])
++
++# Like gl_FUNC_READLINK, except prepare for separate compilation
++# (no REPLACE_READLINK, no AC_LIBOBJ).
++AC_DEFUN([gl_FUNC_READLINK_SEPARATE],
++[
++  AC_CHECK_FUNCS_ONCE([readlink])
++  gl_PREREQ_READLINK
++])
++
++# Prerequisites of lib/readlink.c.
++AC_DEFUN([gl_PREREQ_READLINK],
++[
++  :
++])
+diff --git a/m4/stat.m4 b/m4/stat.m4
+new file mode 100644
+index 00000000000..1ae327b3684
+--- /dev/null
++++ b/m4/stat.m4
+@@ -0,0 +1,71 @@
++# serial 11
++
++# Copyright (C) 2009-2014 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++AC_DEFUN([gl_FUNC_STAT],
++[
++  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
++  AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
++  AC_CHECK_FUNCS_ONCE([lstat])
++  dnl mingw is the only known platform where stat(".") and stat("./") differ
++  AC_CACHE_CHECK([whether stat handles trailing slashes on directories],
++      [gl_cv_func_stat_dir_slash],
++      [AC_RUN_IFELSE(
++         [AC_LANG_PROGRAM(
++           [[#include <sys/stat.h>
++]], [[struct stat st; return stat (".", &st) != stat ("./", &st);]])],
++         [gl_cv_func_stat_dir_slash=yes], [gl_cv_func_stat_dir_slash=no],
++         [case $host_os in
++            mingw*) gl_cv_func_stat_dir_slash="guessing no";;
++            *) gl_cv_func_stat_dir_slash="guessing yes";;
++          esac])])
++  dnl AIX 7.1, Solaris 9, mingw64 mistakenly succeed on stat("file/").
++  dnl (For mingw, this is due to a broken stat() override in libmingwex.a.)
++  dnl FreeBSD 7.2 mistakenly succeeds on stat("link-to-file/").
++  AC_CACHE_CHECK([whether stat handles trailing slashes on files],
++      [gl_cv_func_stat_file_slash],
++      [touch conftest.tmp
++       # Assume that if we have lstat, we can also check symlinks.
++       if test $ac_cv_func_lstat = yes; then
++         ln -s conftest.tmp conftest.lnk
++       fi
++       AC_RUN_IFELSE(
++         [AC_LANG_PROGRAM(
++           [[#include <sys/stat.h>
++]], [[int result = 0;
++      struct stat st;
++      if (!stat ("conftest.tmp/", &st))
++        result |= 1;
++#if HAVE_LSTAT
++      if (!stat ("conftest.lnk/", &st))
++        result |= 2;
++#endif
++      return result;
++           ]])],
++         [gl_cv_func_stat_file_slash=yes], [gl_cv_func_stat_file_slash=no],
++         [case "$host_os" in
++                    # Guess yes on glibc systems.
++            *-gnu*) gl_cv_func_stat_file_slash="guessing yes" ;;
++                    # If we don't know, assume the worst.
++            *)      gl_cv_func_stat_file_slash="guessing no" ;;
++          esac
++         ])
++       rm -f conftest.tmp conftest.lnk])
++  case $gl_cv_func_stat_dir_slash in
++    *no) REPLACE_STAT=1
++      AC_DEFINE([REPLACE_FUNC_STAT_DIR], [1], [Define to 1 if stat needs
++        help when passed a directory name with a trailing slash]);;
++  esac
++  case $gl_cv_func_stat_file_slash in
++    *no) REPLACE_STAT=1
++      AC_DEFINE([REPLACE_FUNC_STAT_FILE], [1], [Define to 1 if stat needs
++        help when passed a file name with a trailing slash]);;
++  esac
++])
++
++# Prerequisites of lib/stat.c.
++AC_DEFUN([gl_PREREQ_STAT], [:])
+diff --git a/m4/sys_stat_h.m4 b/m4/sys_stat_h.m4
+new file mode 100644
+index 00000000000..eaa7642ba31
+--- /dev/null
++++ b/m4/sys_stat_h.m4
+@@ -0,0 +1,96 @@
++# sys_stat_h.m4 serial 28   -*- Autoconf -*-
++dnl Copyright (C) 2006-2014 Free Software Foundation, Inc.
++dnl This file is free software; the Free Software Foundation
++dnl gives unlimited permission to copy and/or distribute it,
++dnl with or without modifications, as long as this notice is preserved.
++
++dnl From Eric Blake.
++dnl Provide a GNU-like <sys/stat.h>.
++
++AC_DEFUN([gl_HEADER_SYS_STAT_H],
++[
++  AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
++
++  dnl Check for broken stat macros.
++  AC_REQUIRE([AC_HEADER_STAT])
++
++  gl_CHECK_NEXT_HEADERS([sys/stat.h])
++
++  dnl Ensure the type mode_t gets defined.
++  AC_REQUIRE([AC_TYPE_MODE_T])
++
++  dnl Whether to override 'struct stat'.
++  m4_ifdef([gl_LARGEFILE], [
++    AC_REQUIRE([gl_LARGEFILE])
++  ], [
++    WINDOWS_64_BIT_ST_SIZE=0
++  ])
++  AC_SUBST([WINDOWS_64_BIT_ST_SIZE])
++  if test $WINDOWS_64_BIT_ST_SIZE = 1; then
++    AC_DEFINE([_GL_WINDOWS_64_BIT_ST_SIZE], [1],
++      [Define to 1 if Gnulib overrides 'struct stat' on Windows so that
++       struct stat.st_size becomes 64-bit.])
++  fi
++
++  dnl Define types that are supposed to be defined in <sys/types.h> or
++  dnl <sys/stat.h>.
++  AC_CHECK_TYPE([nlink_t], [],
++    [AC_DEFINE([nlink_t], [int],
++       [Define to the type of st_nlink in struct stat, or a supertype.])],
++    [#include <sys/types.h>
++     #include <sys/stat.h>])
++
++  dnl Check for declarations of anything we want to poison if the
++  dnl corresponding gnulib module is not in use.
++  gl_WARN_ON_USE_PREPARE([[#include <sys/stat.h>
++    ]], [fchmodat fstat fstatat futimens lchmod lstat mkdirat mkfifo mkfifoat
++    mknod mknodat stat utimensat])
++]) # gl_HEADER_SYS_STAT_H
++
++AC_DEFUN([gl_SYS_STAT_MODULE_INDICATOR],
++[
++  dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
++  AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
++  gl_MODULE_INDICATOR_SET_VARIABLE([$1])
++  dnl Define it also as a C macro, for the benefit of the unit tests.
++  gl_MODULE_INDICATOR_FOR_TESTS([$1])
++])
++
++AC_DEFUN([gl_SYS_STAT_H_DEFAULTS],
++[
++  AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) dnl for REPLACE_FCHDIR
++  GNULIB_FCHMODAT=0;    AC_SUBST([GNULIB_FCHMODAT])
++  GNULIB_FSTAT=0;       AC_SUBST([GNULIB_FSTAT])
++  GNULIB_FSTATAT=0;     AC_SUBST([GNULIB_FSTATAT])
++  GNULIB_FUTIMENS=0;    AC_SUBST([GNULIB_FUTIMENS])
++  GNULIB_LCHMOD=0;      AC_SUBST([GNULIB_LCHMOD])
++  GNULIB_LSTAT=0;       AC_SUBST([GNULIB_LSTAT])
++  GNULIB_MKDIRAT=0;     AC_SUBST([GNULIB_MKDIRAT])
++  GNULIB_MKFIFO=0;      AC_SUBST([GNULIB_MKFIFO])
++  GNULIB_MKFIFOAT=0;    AC_SUBST([GNULIB_MKFIFOAT])
++  GNULIB_MKNOD=0;       AC_SUBST([GNULIB_MKNOD])
++  GNULIB_MKNODAT=0;     AC_SUBST([GNULIB_MKNODAT])
++  GNULIB_STAT=0;        AC_SUBST([GNULIB_STAT])
++  GNULIB_UTIMENSAT=0;   AC_SUBST([GNULIB_UTIMENSAT])
++  dnl Assume proper GNU behavior unless another module says otherwise.
++  HAVE_FCHMODAT=1;      AC_SUBST([HAVE_FCHMODAT])
++  HAVE_FSTATAT=1;       AC_SUBST([HAVE_FSTATAT])
++  HAVE_FUTIMENS=1;      AC_SUBST([HAVE_FUTIMENS])
++  HAVE_LCHMOD=1;        AC_SUBST([HAVE_LCHMOD])
++  HAVE_LSTAT=1;         AC_SUBST([HAVE_LSTAT])
++  HAVE_MKDIRAT=1;       AC_SUBST([HAVE_MKDIRAT])
++  HAVE_MKFIFO=1;        AC_SUBST([HAVE_MKFIFO])
++  HAVE_MKFIFOAT=1;      AC_SUBST([HAVE_MKFIFOAT])
++  HAVE_MKNOD=1;         AC_SUBST([HAVE_MKNOD])
++  HAVE_MKNODAT=1;       AC_SUBST([HAVE_MKNODAT])
++  HAVE_UTIMENSAT=1;     AC_SUBST([HAVE_UTIMENSAT])
++  REPLACE_FSTAT=0;      AC_SUBST([REPLACE_FSTAT])
++  REPLACE_FSTATAT=0;    AC_SUBST([REPLACE_FSTATAT])
++  REPLACE_FUTIMENS=0;   AC_SUBST([REPLACE_FUTIMENS])
++  REPLACE_LSTAT=0;      AC_SUBST([REPLACE_LSTAT])
++  REPLACE_MKDIR=0;      AC_SUBST([REPLACE_MKDIR])
++  REPLACE_MKFIFO=0;     AC_SUBST([REPLACE_MKFIFO])
++  REPLACE_MKNOD=0;      AC_SUBST([REPLACE_MKNOD])
++  REPLACE_STAT=0;       AC_SUBST([REPLACE_STAT])
++  REPLACE_UTIMENSAT=0;  AC_SUBST([REPLACE_UTIMENSAT])
++])
+diff --git a/m4/sys_time_h.m4 b/m4/sys_time_h.m4
+new file mode 100644
+index 00000000000..5c79300f8ec
+--- /dev/null
++++ b/m4/sys_time_h.m4
+@@ -0,0 +1,110 @@
++# Configure a replacement for <sys/time.h>.
++# serial 8
++
++# Copyright (C) 2007, 2009-2014 Free Software Foundation, Inc.
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# Written by Paul Eggert and Martin Lambers.
++
++AC_DEFUN([gl_HEADER_SYS_TIME_H],
++[
++  dnl Use AC_REQUIRE here, so that the REPLACE_GETTIMEOFDAY=0 statement
++  dnl below is expanded once only, before all REPLACE_GETTIMEOFDAY=1
++  dnl statements that occur in other macros.
++  AC_REQUIRE([gl_HEADER_SYS_TIME_H_BODY])
++])
++
++AC_DEFUN([gl_HEADER_SYS_TIME_H_BODY],
++[
++  AC_REQUIRE([AC_C_RESTRICT])
++  AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS])
++  AC_CHECK_HEADERS_ONCE([sys/time.h])
++  gl_CHECK_NEXT_HEADERS([sys/time.h])
++
++  if test $ac_cv_header_sys_time_h != yes; then
++    HAVE_SYS_TIME_H=0
++  fi
++
++  dnl On native Windows with MSVC, 'struct timeval' is defined in <winsock2.h>
++  dnl only. So include that header in the list.
++  gl_PREREQ_SYS_H_WINSOCK2
++  AC_CACHE_CHECK([for struct timeval], [gl_cv_sys_struct_timeval],
++    [AC_COMPILE_IFELSE(
++       [AC_LANG_PROGRAM(
++          [[#if HAVE_SYS_TIME_H
++             #include <sys/time.h>
++            #endif
++            #include <time.h>
++            #if HAVE_WINSOCK2_H
++            # include <winsock2.h>
++            #endif
++          ]],
++          [[static struct timeval x; x.tv_sec = x.tv_usec;]])],
++       [gl_cv_sys_struct_timeval=yes],
++       [gl_cv_sys_struct_timeval=no])
++    ])
++  if test $gl_cv_sys_struct_timeval != yes; then
++    HAVE_STRUCT_TIMEVAL=0
++  else
++    dnl On native Windows with a 64-bit 'time_t', 'struct timeval' is defined
++    dnl (in <sys/time.h> and <winsock2.h> for mingw64, in <winsock2.h> only
++    dnl for MSVC) with a tv_sec field of type 'long' (32-bit!), which is
++    dnl smaller than the 'time_t' type mandated by POSIX.
++    dnl On OpenBSD 5.1 amd64, tv_sec is 64 bits and time_t 32 bits, but
++    dnl that is good enough.
++    AC_CACHE_CHECK([for wide-enough struct timeval.tv_sec member],
++      [gl_cv_sys_struct_timeval_tv_sec],
++      [AC_COMPILE_IFELSE(
++         [AC_LANG_PROGRAM(
++            [[#if HAVE_SYS_TIME_H
++               #include <sys/time.h>
++              #endif
++              #include <time.h>
++              #if HAVE_WINSOCK2_H
++              # include <winsock2.h>
++              #endif
++            ]],
++            [[static struct timeval x;
++              typedef int verify_tv_sec_type[
++                sizeof (time_t) <= sizeof x.tv_sec ? 1 : -1
++              ];
++            ]])],
++         [gl_cv_sys_struct_timeval_tv_sec=yes],
++         [gl_cv_sys_struct_timeval_tv_sec=no])
++      ])
++    if test $gl_cv_sys_struct_timeval_tv_sec != yes; then
++      REPLACE_STRUCT_TIMEVAL=1
++    fi
++  fi
++
++  dnl Check for declarations of anything we want to poison if the
++  dnl corresponding gnulib module is not in use.
++  gl_WARN_ON_USE_PREPARE([[
++#if HAVE_SYS_TIME_H
++# include <sys/time.h>
++#endif
++#include <time.h>
++    ]], [gettimeofday])
++])
++
++AC_DEFUN([gl_SYS_TIME_MODULE_INDICATOR],
++[
++  dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
++  AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS])
++  gl_MODULE_INDICATOR_SET_VARIABLE([$1])
++  dnl Define it also as a C macro, for the benefit of the unit tests.
++  gl_MODULE_INDICATOR_FOR_TESTS([$1])
++])
++
++AC_DEFUN([gl_HEADER_SYS_TIME_H_DEFAULTS],
++[
++  GNULIB_GETTIMEOFDAY=0;     AC_SUBST([GNULIB_GETTIMEOFDAY])
++  dnl Assume POSIX behavior unless another module says otherwise.
++  HAVE_GETTIMEOFDAY=1;       AC_SUBST([HAVE_GETTIMEOFDAY])
++  HAVE_STRUCT_TIMEVAL=1;     AC_SUBST([HAVE_STRUCT_TIMEVAL])
++  HAVE_SYS_TIME_H=1;         AC_SUBST([HAVE_SYS_TIME_H])
++  REPLACE_GETTIMEOFDAY=0;    AC_SUBST([REPLACE_GETTIMEOFDAY])
++  REPLACE_STRUCT_TIMEVAL=0;  AC_SUBST([REPLACE_STRUCT_TIMEVAL])
++])
+diff --git a/m4/time_h.m4 b/m4/time_h.m4
+new file mode 100644
+index 00000000000..9852778f9a5
+--- /dev/null
++++ b/m4/time_h.m4
+@@ -0,0 +1,118 @@
++# Configure a more-standard replacement for <time.h>.
++
++# Copyright (C) 2000-2001, 2003-2007, 2009-2014 Free Software Foundation, Inc.
++
++# serial 8
++
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# Written by Paul Eggert and Jim Meyering.
++
++AC_DEFUN([gl_HEADER_TIME_H],
++[
++  dnl Use AC_REQUIRE here, so that the default behavior below is expanded
++  dnl once only, before all statements that occur in other macros.
++  AC_REQUIRE([gl_HEADER_TIME_H_BODY])
++])
++
++AC_DEFUN([gl_HEADER_TIME_H_BODY],
++[
++  AC_REQUIRE([AC_C_RESTRICT])
++  AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS])
++  gl_NEXT_HEADERS([time.h])
++  AC_REQUIRE([gl_CHECK_TYPE_STRUCT_TIMESPEC])
++])
++
++dnl Check whether 'struct timespec' is declared
++dnl in time.h, sys/time.h, or pthread.h.
++
++AC_DEFUN([gl_CHECK_TYPE_STRUCT_TIMESPEC],
++[
++  AC_CHECK_HEADERS_ONCE([sys/time.h])
++  AC_CACHE_CHECK([for struct timespec in <time.h>],
++    [gl_cv_sys_struct_timespec_in_time_h],
++    [AC_COMPILE_IFELSE(
++       [AC_LANG_PROGRAM(
++          [[#include <time.h>
++          ]],
++          [[static struct timespec x; x.tv_sec = x.tv_nsec;]])],
++       [gl_cv_sys_struct_timespec_in_time_h=yes],
++       [gl_cv_sys_struct_timespec_in_time_h=no])])
++
++  TIME_H_DEFINES_STRUCT_TIMESPEC=0
++  SYS_TIME_H_DEFINES_STRUCT_TIMESPEC=0
++  PTHREAD_H_DEFINES_STRUCT_TIMESPEC=0
++  if test $gl_cv_sys_struct_timespec_in_time_h = yes; then
++    TIME_H_DEFINES_STRUCT_TIMESPEC=1
++  else
++    AC_CACHE_CHECK([for struct timespec in <sys/time.h>],
++      [gl_cv_sys_struct_timespec_in_sys_time_h],
++      [AC_COMPILE_IFELSE(
++         [AC_LANG_PROGRAM(
++            [[#include <sys/time.h>
++            ]],
++            [[static struct timespec x; x.tv_sec = x.tv_nsec;]])],
++         [gl_cv_sys_struct_timespec_in_sys_time_h=yes],
++         [gl_cv_sys_struct_timespec_in_sys_time_h=no])])
++    if test $gl_cv_sys_struct_timespec_in_sys_time_h = yes; then
++      SYS_TIME_H_DEFINES_STRUCT_TIMESPEC=1
++    else
++      AC_CACHE_CHECK([for struct timespec in <pthread.h>],
++        [gl_cv_sys_struct_timespec_in_pthread_h],
++        [AC_COMPILE_IFELSE(
++           [AC_LANG_PROGRAM(
++              [[#include <pthread.h>
++              ]],
++              [[static struct timespec x; x.tv_sec = x.tv_nsec;]])],
++           [gl_cv_sys_struct_timespec_in_pthread_h=yes],
++           [gl_cv_sys_struct_timespec_in_pthread_h=no])])
++      if test $gl_cv_sys_struct_timespec_in_pthread_h = yes; then
++        PTHREAD_H_DEFINES_STRUCT_TIMESPEC=1
++      fi
++    fi
++  fi
++  AC_SUBST([TIME_H_DEFINES_STRUCT_TIMESPEC])
++  AC_SUBST([SYS_TIME_H_DEFINES_STRUCT_TIMESPEC])
++  AC_SUBST([PTHREAD_H_DEFINES_STRUCT_TIMESPEC])
++])
++
++AC_DEFUN([gl_TIME_MODULE_INDICATOR],
++[
++  dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
++  AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS])
++  gl_MODULE_INDICATOR_SET_VARIABLE([$1])
++  dnl Define it also as a C macro, for the benefit of the unit tests.
++  gl_MODULE_INDICATOR_FOR_TESTS([$1])
++])
++
++AC_DEFUN([gl_HEADER_TIME_H_DEFAULTS],
++[
++  GNULIB_MKTIME=0;                       AC_SUBST([GNULIB_MKTIME])
++  GNULIB_NANOSLEEP=0;                    AC_SUBST([GNULIB_NANOSLEEP])
++  GNULIB_STRPTIME=0;                     AC_SUBST([GNULIB_STRPTIME])
++  GNULIB_TIMEGM=0;                       AC_SUBST([GNULIB_TIMEGM])
++  GNULIB_TIME_R=0;                       AC_SUBST([GNULIB_TIME_R])
++  dnl Assume proper GNU behavior unless another module says otherwise.
++  HAVE_DECL_LOCALTIME_R=1;               AC_SUBST([HAVE_DECL_LOCALTIME_R])
++  HAVE_NANOSLEEP=1;                      AC_SUBST([HAVE_NANOSLEEP])
++  HAVE_STRPTIME=1;                       AC_SUBST([HAVE_STRPTIME])
++  HAVE_TIMEGM=1;                         AC_SUBST([HAVE_TIMEGM])
++  dnl If another module says to replace or to not replace, do that.
++  dnl Otherwise, replace only if someone compiles with -DGNULIB_PORTCHECK;
++  dnl this lets maintainers check for portability.
++  REPLACE_LOCALTIME_R=GNULIB_PORTCHECK;  AC_SUBST([REPLACE_LOCALTIME_R])
++  REPLACE_MKTIME=GNULIB_PORTCHECK;       AC_SUBST([REPLACE_MKTIME])
++  REPLACE_NANOSLEEP=GNULIB_PORTCHECK;    AC_SUBST([REPLACE_NANOSLEEP])
++  REPLACE_TIMEGM=GNULIB_PORTCHECK;       AC_SUBST([REPLACE_TIMEGM])
++
++  dnl Hack so that the time module doesn't depend on the sys_time module.
++  dnl First, default GNULIB_GETTIMEOFDAY to 0 if sys_time is absent.
++  : ${GNULIB_GETTIMEOFDAY=0};            AC_SUBST([GNULIB_GETTIMEOFDAY])
++  dnl Second, it's OK to not use GNULIB_PORTCHECK for REPLACE_GMTIME
++  dnl and REPLACE_LOCALTIME, as portability to Solaris 2.6 and earlier
++  dnl is no longer a big deal.
++  REPLACE_GMTIME=0;                      AC_SUBST([REPLACE_GMTIME])
++  REPLACE_LOCALTIME=0;                   AC_SUBST([REPLACE_LOCALTIME])
++])
diff --git a/SOURCES/0146-Make-editenv-chase-symlinks-including-those-across-d.patch b/SOURCES/0146-Make-editenv-chase-symlinks-including-those-across-d.patch
new file mode 100644
index 0000000..a76154a
--- /dev/null
+++ b/SOURCES/0146-Make-editenv-chase-symlinks-including-those-across-d.patch
@@ -0,0 +1,102 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 3 Sep 2014 10:38:00 -0400
+Subject: [PATCH] Make editenv chase symlinks including those across devices.
+
+This lets us make /boot/grub2/grubenv a symlink to
+/boot/efi/EFI/fedora/grubenv even though they're different mount points,
+which allows /usr/bin/grub2-editenv to be the same across platforms
+(i.e. UEFI vs BIOS).
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Reviewed-by: Adam Jackson <ajax@redhat.com>
+---
+ Makefile.util.def |  9 +++++++++
+ util/editenv.c    | 46 ++++++++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 53 insertions(+), 2 deletions(-)
+
+diff --git a/Makefile.util.def b/Makefile.util.def
+index 8f40e78332a..87029a10dfb 100644
+--- a/Makefile.util.def
++++ b/Makefile.util.def
+@@ -228,8 +228,17 @@ program = {
+ 
+   common = util/grub-editenv.c;
+   common = util/editenv.c;
++  common = util/grub-install-common.c;
+   common = grub-core/osdep/init.c;
++  common = grub-core/osdep/compress.c;
++  extra_dist = grub-core/osdep/unix/compress.c;
++  extra_dist = grub-core/osdep/basic/compress.c;
++  common = util/mkimage.c;
++  common = grub-core/osdep/config.c;
++  common = util/config.c;
++  common = util/resolve.c;
+ 
++  ldadd = '$(LIBLZMA)';
+   ldadd = libgrubmods.a;
+   ldadd = libgrubgcry.a;
+   ldadd = libgrubkern.a;
+diff --git a/util/editenv.c b/util/editenv.c
+index c6f8d2298c3..d8d1dad6ab9 100644
+--- a/util/editenv.c
++++ b/util/editenv.c
+@@ -37,6 +37,7 @@ grub_util_create_envblk_file (const char *name)
+   FILE *fp;
+   char *buf;
+   char *namenew;
++  char *rename_target = xstrdup(name);
+ 
+   buf = xmalloc (DEFAULT_ENVBLK_SIZE);
+ 
+@@ -59,7 +60,48 @@ grub_util_create_envblk_file (const char *name)
+   free (buf);
+   fclose (fp);
+ 
+-  if (grub_util_rename (namenew, name) < 0)
+-    grub_util_error (_("cannot rename the file %s to %s"), namenew, name);
++  ssize_t size = 1;
++  while (1)
++    {
++      char *linkbuf;
++      ssize_t retsize;
++
++      linkbuf = xmalloc(size+1);
++      retsize = grub_util_readlink (rename_target, linkbuf, size);
++      if (retsize < 0 && (errno == ENOENT || errno == EINVAL))
++	{
++	  free (linkbuf);
++	  break;
++	}
++      else if (retsize < 0)
++	{
++	  grub_util_error (_("cannot rename the file %s to %s: %m"), namenew, name);
++	  free (linkbuf);
++	  free (namenew);
++	  return;
++	}
++      else if (retsize == size)
++	{
++	  free(linkbuf);
++	  size += 128;
++	  continue;
++	}
++
++      free (rename_target);
++      linkbuf[retsize] = '\0';
++      rename_target = linkbuf;
++    }
++
++  int rc = grub_util_rename (namenew, rename_target);
++  if (rc < 0 && errno == EXDEV)
++    {
++      rc = grub_install_copy_file (namenew, rename_target, 1);
++      grub_util_unlink (namenew);
++    }
++
++  if (rc < 0)
++    grub_util_error (_("cannot rename the file %s to %s: %m"), namenew, name);
++
+   free (namenew);
++  free (rename_target);
+ }
diff --git a/SOURCES/0147-Generate-OS-and-CLASS-in-10_linux-from-etc-os-releas.patch b/SOURCES/0147-Generate-OS-and-CLASS-in-10_linux-from-etc-os-releas.patch
new file mode 100644
index 0000000..e30aa62
--- /dev/null
+++ b/SOURCES/0147-Generate-OS-and-CLASS-in-10_linux-from-etc-os-releas.patch
@@ -0,0 +1,29 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 4 Sep 2014 14:23:23 -0400
+Subject: [PATCH] Generate OS and CLASS in 10_linux from /etc/os-release
+
+This makes us use pretty names in the titles we generate in
+grub2-mkconfig when GRUB_DISTRIBUTOR isn't set.
+
+Resolves: rhbz#996794
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ util/grub.d/10_linux.in | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 8782d8c67cf..e8088a18160 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -29,7 +29,8 @@ export TEXTDOMAINDIR="@localedir@"
+ CLASS="--class gnu-linux --class gnu --class os --unrestricted"
+ 
+ if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
+-  OS="$(sed 's, release .*$,,g' /etc/system-release)"
++  OS="$(eval $(grep PRETTY_NAME /etc/os-release) ; echo ${PRETTY_NAME})"
++  CLASS="--class $(eval $(grep '^ID_LIKE=\|^ID=' /etc/os-release) ; [ -n "${ID_LIKE}" ] && echo ${ID_LIKE} || echo ${ID}) ${CLASS}"
+ else
+   OS="${GRUB_DISTRIBUTOR}"
+   CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}"
diff --git a/SOURCES/0148-Minimize-the-sort-ordering-for-.debug-and-rescue-ker.patch b/SOURCES/0148-Minimize-the-sort-ordering-for-.debug-and-rescue-ker.patch
new file mode 100644
index 0000000..717af81
--- /dev/null
+++ b/SOURCES/0148-Minimize-the-sort-ordering-for-.debug-and-rescue-ker.patch
@@ -0,0 +1,30 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 4 Sep 2014 15:52:08 -0400
+Subject: [PATCH] Minimize the sort ordering for .debug and -rescue- kernels.
+
+Resolves: rhbz#1065360
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ util/grub-mkconfig_lib.in | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
+index 14fadbcbbbd..7ac0bbed0d3 100644
+--- a/util/grub-mkconfig_lib.in
++++ b/util/grub-mkconfig_lib.in
+@@ -248,6 +248,14 @@ version_test_gt ()
+     *.old:*.old) ;;
+     *.old:*) version_test_gt_a="`echo -n "$version_test_gt_a" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=gt ;;
+     *:*.old) version_test_gt_b="`echo -n "$version_test_gt_b" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=ge ;;
++    *-rescue-*:*-rescue-*) ;;
++    *.debug:*.debug) ;;
++    *-rescue-*:*.debug) return 1 ;;
++    *.debug:*-rescue-*) return 0 ;;
++    *-rescue-*:*) return 1 ;;
++    *:*-rescue-*) return 0 ;;
++    *.debug:*) return 1 ;;
++    *:*.debug) return 0 ;;
+   esac
+   version_test_numeric "$version_test_gt_a" "$version_test_gt_cmp" "$version_test_gt_b"
+   return "$?"
diff --git a/SOURCES/0149-Add-GRUB_DISABLE_UUID.patch b/SOURCES/0149-Add-GRUB_DISABLE_UUID.patch
new file mode 100644
index 0000000..7804329
--- /dev/null
+++ b/SOURCES/0149-Add-GRUB_DISABLE_UUID.patch
@@ -0,0 +1,99 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 4 Sep 2014 16:49:25 -0400
+Subject: [PATCH] Add GRUB_DISABLE_UUID.
+
+This will cause "search --fs-uuid --set=root ..." not to be generated by
+grub2-mkconfig, and instead simply attempt to use the grub device name
+as it understands it.
+
+Good luck.
+
+Resolves: rhbz#1027833
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ docs/grub.texi            |  7 +++++++
+ util/grub-mkconfig.in     | 12 ++++++++++--
+ util/grub-mkconfig_lib.in |  4 ++--
+ 3 files changed, 19 insertions(+), 4 deletions(-)
+
+diff --git a/docs/grub.texi b/docs/grub.texi
+index 46b9e7f8e31..6b112c18804 100644
+--- a/docs/grub.texi
++++ b/docs/grub.texi
+@@ -1409,6 +1409,13 @@ disable the use of UUIDs, set this option to @samp{true}.
+ If this option is set to @samp{true}, disable the generation of recovery
+ mode menu entries.
+ 
++@item GRUB_DISABLE_UUID
++Normally, @command{grub-mkconfig} will generate menu entries that use
++universally-unique identifiers (UUIDs) to identify various filesystems to
++search for files.  This is usually more reliable, but in some cases it may
++not be appropriate.  To disable this use of UUIDs, set this option to
++@samp{true}.
++
+ @item GRUB_VIDEO_BACKEND
+ If graphical video support is required, either because the @samp{gfxterm}
+ graphical terminal is in use or because @samp{GRUB_GFXPAYLOAD_LINUX} is set,
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index beb22deee79..bc26e7c109e 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -130,11 +130,11 @@ fi
+ 
+ # Device containing our userland.  Typically used for root= parameter.
+ GRUB_DEVICE="`${grub_probe} --target=device /`"
+-GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true
++GRUB_DEVICE_UUID_GENERATED="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true
+ 
+ # Device containing our /boot partition.  Usually the same as GRUB_DEVICE.
+ GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`"
+-GRUB_DEVICE_BOOT_UUID="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_uuid 2> /dev/null`" || true
++GRUB_DEVICE_BOOT_UUID_GENERATED="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_uuid 2> /dev/null`" || true
+ 
+ # Filesystem for the device containing our userland.  Used for stuff like
+ # choosing Hurd filesystem module.
+@@ -148,6 +148,13 @@ if test -f ${sysconfdir}/default/grub ; then
+   . ${sysconfdir}/default/grub
+ fi
+ 
++if [ "x$GRUB_DISABLE_UUID" != "xtrue" -a -z "$GRUB_DEVICE_UUID" ]; then
++  GRUB_DEVICE_UUID="$GRUB_DEVICE_UUID_GENERATED"
++fi
++if [ "x$GRUB_DISABLE_UUID" != "xtrue" -a -z "$GRUB_DEVICE_BOOT_UUID" ]; then
++  GRUB_DEVICE_BOOT_UUID="$GRUB_DEVICE_BOOT_UUID_GENERATED"
++fi
++
+ # XXX: should this be deprecated at some point?
+ if [ "x${GRUB_TERMINAL}" != "x" ] ; then
+   GRUB_TERMINAL_INPUT="${GRUB_TERMINAL}"
+@@ -213,6 +220,7 @@ export GRUB_DEFAULT \
+   GRUB_SERIAL_COMMAND \
+   GRUB_DISABLE_LINUX_UUID \
+   GRUB_DISABLE_RECOVERY \
++  GRUB_DISABLE_UUID \
+   GRUB_VIDEO_BACKEND \
+   GRUB_GFXMODE \
+   GRUB_BACKGROUND \
+diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
+index 7ac0bbed0d3..5c9ed84a5e7 100644
+--- a/util/grub-mkconfig_lib.in
++++ b/util/grub-mkconfig_lib.in
+@@ -156,7 +156,7 @@ prepare_grub_to_access_device ()
+   if [ "x$fs_hint" != x ]; then
+     echo "set root='$fs_hint'"
+   fi
+-  if fs_uuid="`"${grub_probe}" --device $@ --target=fs_uuid 2> /dev/null`" ; then
++  if [ "x$GRUB_DISABLE_UUID" != "xtrue" ] && fs_uuid="`"${grub_probe}" --device $@ --target=fs_uuid 2> /dev/null`" ; then
+     hints="`"${grub_probe}" --device $@ --target=hints_string 2> /dev/null`" || hints=
+     echo "if [ x\$feature_platform_search_hint = xy ]; then"
+     echo "  search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}"
+@@ -173,7 +173,7 @@ grub_get_device_id ()
+   IFS='
+ '
+   device="$1"
+-  if fs_uuid="`"${grub_probe}" --device ${device} --target=fs_uuid 2> /dev/null`" ; then
++  if [ "x$GRUB_DISABLE_UUID" != "xtrue" ] && fs_uuid="`"${grub_probe}" --device ${device} --target=fs_uuid 2> /dev/null`" ; then
+     echo "$fs_uuid";
+   else
+     echo $device |sed 's, ,_,g'
diff --git a/SOURCES/0150-Allow-fallback-to-include-entries-by-title-not-just-.patch b/SOURCES/0150-Allow-fallback-to-include-entries-by-title-not-just-.patch
new file mode 100644
index 0000000..be4c654
--- /dev/null
+++ b/SOURCES/0150-Allow-fallback-to-include-entries-by-title-not-just-.patch
@@ -0,0 +1,128 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Fri, 5 Sep 2014 10:07:04 -0400
+Subject: [PATCH] Allow "fallback" to include entries by title, not just
+ number.
+
+Resolves: rhbz#1026084
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/normal/menu.c | 76 +++++++++++++++++++++++++++++++------------------
+ 1 file changed, 49 insertions(+), 27 deletions(-)
+
+diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
+index cc27c370776..a446d9ae746 100644
+--- a/grub-core/normal/menu.c
++++ b/grub-core/normal/menu.c
+@@ -163,12 +163,35 @@ grub_menu_set_timeout (int timeout)
+     }
+ }
+ 
++static int
++menuentry_eq (const char *id, const char *spec)
++{
++  const char *ptr1, *ptr2;
++  ptr1 = id;
++  ptr2 = spec;
++  while (1)
++    {
++      if (*ptr2 == '>' && ptr2[1] != '>' && *ptr1 == 0)
++	return 1;
++      if (*ptr2 == '>' && ptr2[1] != '>')
++	return 0;
++      if (*ptr2 == '>')
++	ptr2++;
++      if (*ptr1 != *ptr2)
++	return 0;
++      if (*ptr1 == 0)
++	return 1;
++      ptr1++;
++      ptr2++;
++    }
++}
++
+ /* Get the first entry number from the value of the environment variable NAME,
+    which is a space-separated list of non-negative integers.  The entry number
+    which is returned is stripped from the value of NAME.  If no entry number
+    can be found, -1 is returned.  */
+ static int
+-get_and_remove_first_entry_number (const char *name)
++get_and_remove_first_entry_number (grub_menu_t menu, const char *name)
+ {
+   const char *val;
+   char *tail;
+@@ -182,9 +205,32 @@ get_and_remove_first_entry_number (const char *name)
+ 
+   entry = (int) grub_strtoul (val, &tail, 0);
+ 
++  if (grub_errno == GRUB_ERR_BAD_NUMBER)
++    {
++      /* See if the variable matches the title of a menu entry.  */
++      grub_menu_entry_t e = menu->entry_list;
++      int i;
++
++      grub_errno = GRUB_ERR_NONE;
++
++      for (i = 0; e; i++)
++	{
++	  if (menuentry_eq (e->title, val)
++	      || menuentry_eq (e->id, val))
++	    {
++	      entry = i;
++	      break;
++	    }
++	  e = e->next;
++	}
++
++      if (! e)
++	entry = -1;
++    }
++
+   if (grub_errno == GRUB_ERR_NONE)
+     {
+-      /* Skip whitespace to find the next digit.  */
++      /* Skip whitespace to find the next entry.  */
+       while (*tail && grub_isspace (*tail))
+ 	tail++;
+       grub_env_set (name, tail);
+@@ -347,7 +393,7 @@ grub_menu_execute_with_fallback (grub_menu_t menu,
+   grub_menu_execute_entry (entry, 1);
+ 
+   /* Deal with fallback entries.  */
+-  while ((fallback_entry = get_and_remove_first_entry_number ("fallback"))
++  while ((fallback_entry = get_and_remove_first_entry_number (menu, "fallback"))
+ 	 >= 0)
+     {
+       grub_print_error ();
+@@ -465,30 +511,6 @@ grub_menu_register_viewer (struct grub_menu_viewer *viewer)
+   viewers = viewer;
+ }
+ 
+-static int
+-menuentry_eq (const char *id, const char *spec)
+-{
+-  const char *ptr1, *ptr2;
+-  ptr1 = id;
+-  ptr2 = spec;
+-  while (1)
+-    {
+-      if (*ptr2 == '>' && ptr2[1] != '>' && *ptr1 == 0)
+-	return 1;
+-      if (*ptr2 == '>' && ptr2[1] != '>')
+-	return 0;
+-      if (*ptr2 == '>')
+-	ptr2++;
+-      if (*ptr1 != *ptr2)
+-	return 0;
+-      if (*ptr1 == 0)
+-	return 1;
+-      ptr1++;
+-      ptr2++;
+-    }
+-}
+-
+-
+ /* Get the entry number from the variable NAME.  */
+ static int
+ get_entry_number (grub_menu_t menu, const char *name)
diff --git a/SOURCES/0151-Initialized-initrd_ctx-so-we-don-t-free-a-random-poi.patch b/SOURCES/0151-Initialized-initrd_ctx-so-we-don-t-free-a-random-poi.patch
new file mode 100644
index 0000000..da73645
--- /dev/null
+++ b/SOURCES/0151-Initialized-initrd_ctx-so-we-don-t-free-a-random-poi.patch
@@ -0,0 +1,131 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 17 Sep 2014 15:13:14 -0500
+Subject: [PATCH] Initialized initrd_ctx so we don't free a random pointer from
+ the stack.
+
+Currently, if "linux" fails, the "goto fail;" in grub_cmd_initrd sends us
+into grub_initrd_close() without grub_initrd_init() being called, and thus
+it never clears initrd_ctx->components.  grub_initrd_close() then frees that
+address, which is stale data from the stack.  If the stack happens to have a
+stale *address* there that matches a recent allocation, then you'll get a
+double free later.
+
+So initialize the memory up front.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/arm/linux.c              | 2 +-
+ grub-core/loader/arm64/linux.c            | 2 +-
+ grub-core/loader/i386/linux.c             | 2 +-
+ grub-core/loader/i386/pc/linux.c          | 2 +-
+ grub-core/loader/ia64/efi/linux.c         | 2 +-
+ grub-core/loader/mips/linux.c             | 2 +-
+ grub-core/loader/powerpc/ieee1275/linux.c | 2 +-
+ grub-core/loader/sparc64/ieee1275/linux.c | 2 +-
+ 8 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/loader/arm/linux.c b/grub-core/loader/arm/linux.c
+index e6770d96d29..62cbe75d34e 100644
+--- a/grub-core/loader/arm/linux.c
++++ b/grub-core/loader/arm/linux.c
+@@ -396,7 +396,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ {
+   grub_file_t file;
+   grub_size_t size = 0;
+-  struct grub_linux_initrd_context initrd_ctx;
++  struct grub_linux_initrd_context initrd_ctx = { 0, };
+ 
+   if (argc == 0)
+     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
+index f1d10a16492..0dc144e5da0 100644
+--- a/grub-core/loader/arm64/linux.c
++++ b/grub-core/loader/arm64/linux.c
+@@ -328,7 +328,7 @@ static grub_err_t
+ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ 		 int argc, char *argv[])
+ {
+-  struct grub_linux_initrd_context initrd_ctx;
++  struct grub_linux_initrd_context initrd_ctx = { 0, };
+   int initrd_size, initrd_pages;
+   void *initrd_mem = NULL;
+ 
+diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
+index 31fb91e2c73..2ae176315b6 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -1050,7 +1050,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   grub_addr_t addr_min, addr_max;
+   grub_addr_t addr;
+   grub_err_t err;
+-  struct grub_linux_initrd_context initrd_ctx;
++  struct grub_linux_initrd_context initrd_ctx = { 0, };
+ 
+   if (argc == 0)
+     {
+diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
+index 672c013e74d..b481e466846 100644
+--- a/grub-core/loader/i386/pc/linux.c
++++ b/grub-core/loader/i386/pc/linux.c
+@@ -388,7 +388,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   grub_uint8_t *initrd_chunk;
+   grub_addr_t initrd_addr;
+   grub_err_t err;
+-  struct grub_linux_initrd_context initrd_ctx;
++  struct grub_linux_initrd_context initrd_ctx = { 0, };
+ 
+   if (argc == 0)
+     {
+diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c
+index 87ac49f8c3b..eb78e6e626b 100644
+--- a/grub-core/loader/ia64/efi/linux.c
++++ b/grub-core/loader/ia64/efi/linux.c
+@@ -568,7 +568,7 @@ static grub_err_t
+ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ 		 int argc, char *argv[])
+ {
+-  struct grub_linux_initrd_context initrd_ctx;
++  struct grub_linux_initrd_context initrd_ctx = { 0, };
+ 
+   if (argc == 0)
+     {
+diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c
+index ef64a5b1d36..4a3e8c5dfa2 100644
+--- a/grub-core/loader/mips/linux.c
++++ b/grub-core/loader/mips/linux.c
+@@ -415,7 +415,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   void *initrd_src;
+   grub_addr_t initrd_dest;
+   grub_err_t err;
+-  struct grub_linux_initrd_context initrd_ctx;
++  struct grub_linux_initrd_context initrd_ctx = { 0, };
+ 
+   if (argc == 0)
+     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+diff --git a/grub-core/loader/powerpc/ieee1275/linux.c b/grub-core/loader/powerpc/ieee1275/linux.c
+index 4a14f66dee5..787d7dc2af3 100644
+--- a/grub-core/loader/powerpc/ieee1275/linux.c
++++ b/grub-core/loader/powerpc/ieee1275/linux.c
+@@ -333,7 +333,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   grub_size_t size = 0;
+   grub_addr_t first_addr;
+   grub_addr_t addr;
+-  struct grub_linux_initrd_context initrd_ctx;
++  struct grub_linux_initrd_context initrd_ctx = { 0, };
+ 
+   if (argc == 0)
+     {
+diff --git a/grub-core/loader/sparc64/ieee1275/linux.c b/grub-core/loader/sparc64/ieee1275/linux.c
+index de6ee2f75ed..c5e8dfab234 100644
+--- a/grub-core/loader/sparc64/ieee1275/linux.c
++++ b/grub-core/loader/sparc64/ieee1275/linux.c
+@@ -373,7 +373,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   grub_addr_t paddr;
+   grub_addr_t addr;
+   int ret;
+-  struct grub_linux_initrd_context initrd_ctx;
++  struct grub_linux_initrd_context initrd_ctx = { 0, };
+ 
+   if (argc == 0)
+     {
diff --git a/SOURCES/0152-Load-arm-with-SB-enabled.patch b/SOURCES/0152-Load-arm-with-SB-enabled.patch
new file mode 100644
index 0000000..cc0fa4c
--- /dev/null
+++ b/SOURCES/0152-Load-arm-with-SB-enabled.patch
@@ -0,0 +1,433 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 18 Sep 2014 11:26:14 -0400
+Subject: [PATCH] Load arm with SB enabled.
+
+Make sure we actually try to validate secure boot on this platform (even
+though we're not shipping it enabled by default.)
+
+This means giving the kernel grub's loaded image as the vehicle for the
+kernel command line, because we can't call systab->bs->LoadImage() if SB
+is enabled.
+---
+ grub-core/Makefile.core.def       |   2 +
+ grub-core/loader/arm64/linux.c    | 108 ++++++++++++++++++++------------------
+ grub-core/loader/efi/linux.c      |  65 +++++++++++++++++++++++
+ grub-core/loader/i386/efi/linux.c |  39 ++------------
+ include/grub/arm64/linux.h        |   8 +++
+ include/grub/efi/linux.h          |  31 +++++++++++
+ 6 files changed, 166 insertions(+), 87 deletions(-)
+ create mode 100644 grub-core/loader/efi/linux.c
+ create mode 100644 include/grub/efi/linux.h
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 9ff9ae5a311..9378c732981 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -1682,6 +1682,7 @@ module = {
+   ia64_efi = loader/ia64/efi/linux.c;
+   arm = loader/arm/linux.c;
+   arm64 = loader/arm64/linux.c;
++  arm64 = loader/efi/linux.c;
+   fdt = lib/fdt.c;
+   common = loader/linux.c;
+   common = lib/cmdline.c;
+@@ -1718,6 +1719,7 @@ module = {
+   name = linuxefi;
+   efi = loader/i386/efi/linux.c;
+   efi = lib/cmdline.c;
++  efi = loader/efi/linux.c;
+   enable = i386_efi;
+   enable = x86_64_efi;
+ };
+diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
+index 0dc144e5da0..bdd9c9b4968 100644
+--- a/grub-core/loader/arm64/linux.c
++++ b/grub-core/loader/arm64/linux.c
+@@ -27,6 +27,7 @@
+ #include <grub/types.h>
+ #include <grub/cpu/linux.h>
+ #include <grub/efi/efi.h>
++#include <grub/efi/linux.h>
+ #include <grub/efi/pe32.h>
+ #include <grub/i18n.h>
+ #include <grub/lib/cmdline.h>
+@@ -44,6 +45,7 @@ static int loaded;
+ 
+ static void *kernel_addr;
+ static grub_uint64_t kernel_size;
++static grub_uint32_t handover_offset;
+ 
+ static char *linux_args;
+ static grub_uint32_t cmdline_size;
+@@ -135,7 +137,9 @@ finalize_params (void)
+ {
+   grub_efi_boot_services_t *b;
+   grub_efi_status_t status;
++  grub_efi_loaded_image_t *loaded_image = NULL;
+   int node, retval;
++  int len;
+ 
+   get_fdt ();
+   if (!fdt)
+@@ -172,6 +176,23 @@ finalize_params (void)
+   grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
+ 		fdt);
+ 
++  /* Convert command line to UCS-2 */
++  loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
++  if (!loaded_image)
++    goto failure;
++
++  loaded_image->load_options_size = len =
++    (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t);
++  loaded_image->load_options =
++    grub_efi_allocate_pages (0,
++			     BYTES_TO_PAGES (loaded_image->load_options_size));
++  if (!loaded_image->load_options)
++    return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters");
++
++  loaded_image->load_options_size =
++    2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
++			    (grub_uint8_t *) linux_args, len, NULL);
++
+   return GRUB_ERR_NONE;
+ 
+ failure:
+@@ -181,6 +202,23 @@ failure:
+   return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
+ }
+ 
++static void
++free_params (void)
++{
++  grub_efi_loaded_image_t *loaded_image = NULL;
++
++  loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
++  if (loaded_image)
++    {
++      if (loaded_image->load_options)
++	grub_efi_free_pages ((grub_efi_physical_address_t)
++			      loaded_image->load_options,
++			     BYTES_TO_PAGES (loaded_image->load_options_size));
++      loaded_image->load_options = NULL;
++      loaded_image->load_options_size = 0;
++    }
++}
++
+ static grub_err_t
+ grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
+ 		     int argc, char *argv[])
+@@ -199,6 +237,10 @@ grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
+   if (argc != 1)
+     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+ 
++  if (grub_efi_secure_boot ())
++    return grub_error (GRUB_ERR_INVALID_COMMAND,
++		       N_("Not loading devicetree - Secure Boot is enabled"));
++
+   if (loaded_fdt)
+     grub_free (loaded_fdt);
+   loaded_fdt = NULL;
+@@ -243,65 +285,20 @@ out:
+ static grub_err_t
+ grub_linux_boot (void)
+ {
+-  grub_efi_memory_mapped_device_path_t *mempath;
+-  grub_efi_handle_t image_handle;
+-  grub_efi_boot_services_t *b;
+-  grub_efi_status_t status;
+   grub_err_t retval;
+-  grub_efi_loaded_image_t *loaded_image;
+-  int len;
+ 
+   retval = finalize_params();
+   if (retval != GRUB_ERR_NONE)
+     return retval;
+ 
+-  mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t));
+-  if (!mempath)
+-    return grub_errno;
+-
+-  mempath[0].header.type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE;
+-  mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE;
+-  mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath));
+-  mempath[0].memory_type = GRUB_EFI_LOADER_DATA;
+-  mempath[0].start_address = (grub_addr_t) kernel_addr;
+-  mempath[0].end_address = (grub_addr_t) kernel_addr + kernel_size;
+-
+-  mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+-  mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+-  mempath[1].header.length = sizeof (grub_efi_device_path_t);
+-
+-  b = grub_efi_system_table->boot_services;
+-  status = b->load_image (0, grub_efi_image_handle,
+-			  (grub_efi_device_path_t *) mempath,
+-                          kernel_addr, kernel_size, &image_handle);
+-  if (status != GRUB_EFI_SUCCESS)
+-    return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
+-
+   grub_dprintf ("linux", "linux command line: '%s'\n", linux_args);
+ 
+-  /* Convert command line to UCS-2 */
+-  loaded_image = grub_efi_get_loaded_image (image_handle);
+-  loaded_image->load_options_size = len =
+-    (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t);
+-  loaded_image->load_options =
+-    grub_efi_allocate_pages (0,
+-			     BYTES_TO_PAGES (loaded_image->load_options_size));
+-  if (!loaded_image->load_options)
+-    return grub_errno;
++  retval = grub_efi_linux_boot ((char *)kernel_addr, handover_offset,
++				kernel_addr);
+ 
+-  loaded_image->load_options_size =
+-    2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
+-			    (grub_uint8_t *) linux_args, len, NULL);
+-
+-  grub_dprintf("linux", "starting image %p\n", image_handle);
+-  status = b->start_image (image_handle, 0, NULL);
+-
+-  /* When successful, not reached */
+-  b->unload_image (image_handle);
+-  grub_efi_free_pages ((grub_efi_physical_address_t) loaded_image->load_options,
+-		       BYTES_TO_PAGES (loaded_image->load_options_size));
+-
+-  return grub_errno;
++  /* Never reached... */
++  free_params();
++  return retval;
+ }
+ 
+ static grub_err_t
+@@ -382,6 +379,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ {
+   grub_file_t file = 0;
+   struct grub_arm64_linux_kernel_header lh;
++  struct grub_arm64_linux_pe_header *pe;
+ 
+   grub_dl_ref (my_mod);
+ 
+@@ -426,6 +424,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+   grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
+ 
++  if (!grub_linuxefi_secure_validate (kernel_addr, kernel_size))
++    {
++      grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
++      goto fail;
++    }
++
++  pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
++  handover_offset = pe->opt.entry_addr;
++
+   cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
+   linux_args = grub_malloc (cmdline_size);
+   if (!linux_args)
+@@ -464,7 +471,6 @@ fail:
+   return grub_errno;
+ }
+ 
+-
+ static grub_command_t cmd_linux, cmd_initrd, cmd_devicetree;
+ 
+ GRUB_MOD_INIT (linux)
+diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
+new file mode 100644
+index 00000000000..aea378adf5c
+--- /dev/null
++++ b/grub-core/loader/efi/linux.c
+@@ -0,0 +1,65 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2014 Free Software Foundation, Inc.
++ *
++ *  GRUB 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 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <grub/err.h>
++#include <grub/mm.h>
++#include <grub/types.h>
++#include <grub/cpu/linux.h>
++#include <grub/efi/efi.h>
++#include <grub/efi/pe32.h>
++#include <grub/efi/linux.h>
++
++#define SHIM_LOCK_GUID \
++ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
++
++struct grub_efi_shim_lock
++{
++  grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
++};
++typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
++
++grub_efi_boolean_t
++grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
++{
++  grub_efi_guid_t guid = SHIM_LOCK_GUID;
++  grub_efi_shim_lock_t *shim_lock;
++
++  shim_lock = grub_efi_locate_protocol(&guid, NULL);
++
++  if (!shim_lock)
++    return 1;
++
++  if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS)
++    return 1;
++
++  return 0;
++}
++
++typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
++
++grub_err_t
++grub_efi_linux_boot (void *kernel_addr, grub_off_t offset,
++		     void *kernel_params)
++{
++  handover_func hf;
++
++  hf = (handover_func)((char *)kernel_addr + offset);
++  hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
++
++  return GRUB_ERR_BUG;
++}
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index b79e6320ba9..e5b778577f9 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -26,6 +26,7 @@
+ #include <grub/i18n.h>
+ #include <grub/lib/cmdline.h>
+ #include <grub/efi/efi.h>
++#include <grub/efi/linux.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -40,52 +41,18 @@ static char *linux_cmdline;
+ 
+ #define BYTES_TO_PAGES(bytes)   (((bytes) + 0xfff) >> 12)
+ 
+-#define SHIM_LOCK_GUID \
+-  { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
+-
+-struct grub_efi_shim_lock
+-{
+-  grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
+-};
+-typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
+-
+-static grub_efi_boolean_t
+-grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
+-{
+-  grub_efi_guid_t guid = SHIM_LOCK_GUID;
+-  grub_efi_shim_lock_t *shim_lock;
+-
+-  shim_lock = grub_efi_locate_protocol(&guid, NULL);
+-
+-  if (!shim_lock)
+-    return 1;
+-
+-  if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS)
+-    return 1;
+-
+-  return 0;
+-}
+-
+-typedef void(*handover_func)(void *, grub_efi_system_table_t *, struct linux_kernel_params *);
+-
+ static grub_err_t
+ grub_linuxefi_boot (void)
+ {
+-  handover_func hf;
+   int offset = 0;
+ 
+ #ifdef __x86_64__
+   offset = 512;
+ #endif
+-
+-  hf = (handover_func)((char *)kernel_mem + handover_offset + offset);
+-
+   asm volatile ("cli");
+ 
+-  hf (grub_efi_image_handle, grub_efi_system_table, params);
+-
+-  /* Not reached */
+-  return GRUB_ERR_NONE;
++  return grub_efi_linux_boot ((char *)kernel_mem, handover_offset + offset,
++			      params);
+ }
+ 
+ static grub_err_t
+diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h
+index 864e5dc363a..2cbd64f8c55 100644
+--- a/include/grub/arm64/linux.h
++++ b/include/grub/arm64/linux.h
+@@ -20,6 +20,7 @@
+ #define GRUB_LINUX_CPU_HEADER 1
+ 
+ #include <grub/efi/efi.h>
++#include <grub/efi/pe32.h>
+ 
+ #define GRUB_ARM64_LINUX_MAGIC 0x644d5241 /* 'ARM\x64' */
+ 
+@@ -38,4 +39,11 @@ struct grub_arm64_linux_kernel_header
+   grub_uint32_t hdr_offset;	/* Offset of PE/COFF header */
+ };
+ 
++struct grub_arm64_linux_pe_header
++{
++  grub_uint32_t magic;
++  struct grub_pe32_coff_header coff;
++  struct grub_pe64_optional_header opt;
++};
++
+ #endif /* ! GRUB_LINUX_CPU_HEADER */
+diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h
+new file mode 100644
+index 00000000000..d9ede36773b
+--- /dev/null
++++ b/include/grub/efi/linux.h
+@@ -0,0 +1,31 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2014  Free Software Foundation, Inc.
++ *
++ *  GRUB 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 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef GRUB_EFI_LINUX_HEADER
++#define GRUB_EFI_LINUX_HEADER	1
++
++#include <grub/efi/api.h>
++#include <grub/err.h>
++#include <grub/symbol.h>
++
++grub_efi_boolean_t
++EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size);
++grub_err_t
++EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
++				  void *kernel_param);
++
++#endif /* ! GRUB_EFI_LINUX_HEADER */
diff --git a/SOURCES/0153-Fix-up-some-man-pages-rpmdiff-noticed.patch b/SOURCES/0153-Fix-up-some-man-pages-rpmdiff-noticed.patch
new file mode 100644
index 0000000..258a63f
--- /dev/null
+++ b/SOURCES/0153-Fix-up-some-man-pages-rpmdiff-noticed.patch
@@ -0,0 +1,150 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 23 Sep 2014 09:58:49 -0400
+Subject: [PATCH] Fix up some man pages rpmdiff noticed.
+
+---
+ configure.ac             |  2 ++
+ util/grub-macbless.8     | 26 +++++++++++++++++++
+ util/grub-mkimage.1      |  2 +-
+ util/grub-syslinux2cfg.1 | 65 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 94 insertions(+), 1 deletion(-)
+ create mode 100644 util/grub-macbless.8
+ create mode 100644 util/grub-syslinux2cfg.1
+
+diff --git a/configure.ac b/configure.ac
+index 53fd7c73ee6..048ce7c89fa 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -76,6 +76,7 @@ grub_TRANSFORM([grub-fstest.3])
+ grub_TRANSFORM([grub-glue-efi.3])
+ grub_TRANSFORM([grub-install.1])
+ grub_TRANSFORM([grub-kbdcomp.3])
++grub_TRANSFORM([grub-macbless.8])
+ grub_TRANSFORM([grub-menulst2cfg.1])
+ grub_TRANSFORM([grub-mkconfig.1])
+ grub_TRANSFORM([grub-mkfont.3])
+@@ -93,6 +94,7 @@ grub_TRANSFORM([grub-render-label.3])
+ grub_TRANSFORM([grub-script-check.3])
+ grub_TRANSFORM([grub-set-default.1])
+ grub_TRANSFORM([grub-sparc64-setup.3])
++grub_TRANSFORM([grub-syslinux2cfg.1])
+ 
+ # Optimization flag.  Allow user to override.
+ if test "x$TARGET_CFLAGS" = x; then
+diff --git a/util/grub-macbless.8 b/util/grub-macbless.8
+new file mode 100644
+index 00000000000..ae842f3a606
+--- /dev/null
++++ b/util/grub-macbless.8
+@@ -0,0 +1,26 @@
++.TH GRUB-MACBLESS 1 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-macbless\fR \(em Mac-style bless utility for HFS or HFS+
++
++.SH SYNOPSIS
++\fBgrub-macbless\fR [-p | --ppc] [-v | --verbose] [-x | --x86] \fIFILE\fR
++
++.SH DESCRIPTION
++\fBgrub-mkimage\fR blesses a file on an HFS or HFS+ file system, so that it
++can be used to boot a Mac.
++
++.SH OPTIONS
++.TP
++--ppc
++Bless the file for use on PPC-based Macs.
++
++.TP
++--verbose
++Print verbose messages.
++
++.TP
++--x86
++Bless the file for use on x86-based Macs.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-mkimage.1 b/util/grub-mkimage.1
+index 4dea4f54597..0eaaafe505b 100644
+--- a/util/grub-mkimage.1
++++ b/util/grub-mkimage.1
+@@ -17,7 +17,7 @@
+ [-v | --verbose] \fIMODULES\fR
+ 
+ .SH DESCRIPTION
+-\fBgrub-mkimage\fI builds a bootable image of GRUB.
++\fBgrub-mkimage\fR builds a bootable image of GRUB.
+ 
+ .SH OPTIONS
+ .TP
+diff --git a/util/grub-syslinux2cfg.1 b/util/grub-syslinux2cfg.1
+new file mode 100644
+index 00000000000..85309482718
+--- /dev/null
++++ b/util/grub-syslinux2cfg.1
+@@ -0,0 +1,65 @@
++.TH GRUB-SYSLINUX2CFG 1 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-syslinux2cfg\fR \(em Transform a syslinux config file into a GRUB config.
++
++.SH SYNOPSIS
++\fBgrub-syslinux2cfg\fR [-c | --cwd=\fRDIR\fI] [-r | --root=\fIDIR\fR] [-v | --verbose]
++.RE
++.RS 25
++[-t | --target-root=\fIDIR\fR] [-T | --target-cwd=\fIDIR\fR]
++.RE
++.RS 25
++[-o | --output=\fIFILE\fR] [[-i | --isolinux] |
++.RE
++.RS 46
++ [-s | --syslinux] |
++.RE
++.RS 46
++ [-p | --pxelinux]] \fIFILE\fR
++
++.SH DESCRIPTION
++\fBgrub-syslinux2cfg\fR builds a GRUB configuration file out of an existing
++syslinux configuration file.
++
++.SH OPTIONS
++.TP
++--cwd=\fIDIR\fR
++Set \fIDIR\fR as syslinux's working directory.  The default is to use the
++parent directory of the input file.
++
++.TP
++--root=\fIDIR\fR
++Set \fIDIR\fR as the root directory of the syslinux disk.  The default value
++is "/".
++
++.TP
++--verbose
++Print verbose messages.
++
++.TP
++--target-root=\fIDIR\fR
++Root directory as it will be seen at runtime.  The default value is "/".
++
++.TP
++--target-cwd=\fIDIR\fR
++Working directory of syslinux as it will be seen at runtime.  The default
++value is the parent directory of the input file.
++
++.TP
++--output=\fIFILE\fR
++Write the new config file to \fIFILE\fR.  The default value is standard output.
++
++.TP
++--isolinux
++Assume that the input file is an isolinux configuration file.
++
++.TP
++--pxelinux
++Assume that the input file is a pxelinux configuration file.
++
++.TP
++--syslinux
++Assume that the input file is a syslinux configuration file.
++
++.SH SEE ALSO
++.BR "info grub"
diff --git a/SOURCES/0154-Try-prefix-if-fw_path-doesn-t-work.patch b/SOURCES/0154-Try-prefix-if-fw_path-doesn-t-work.patch
new file mode 100644
index 0000000..5a99a8e
--- /dev/null
+++ b/SOURCES/0154-Try-prefix-if-fw_path-doesn-t-work.patch
@@ -0,0 +1,208 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Fri, 3 Oct 2014 11:08:03 -0400
+Subject: [PATCH] Try $prefix if $fw_path doesn't work.
+
+Related: rhbz#1148652
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/kern/ieee1275/init.c |  28 +++++-----
+ grub-core/net/net.c            |   2 +-
+ grub-core/normal/main.c        | 120 ++++++++++++++++++++---------------------
+ 3 files changed, 75 insertions(+), 75 deletions(-)
+
+diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
+index 8191f8cd658..8ca4bf79f09 100644
+--- a/grub-core/kern/ieee1275/init.c
++++ b/grub-core/kern/ieee1275/init.c
+@@ -131,23 +131,25 @@ grub_machine_get_bootlocation (char **device, char **path)
+       grub_free (canon);
+     }
+   else
+-    *device = grub_ieee1275_encode_devname (bootpath);
+-  grub_free (type);
+-
+-  filename = grub_ieee1275_get_filename (bootpath);
+-  if (filename)
+     {
+-      char *lastslash = grub_strrchr (filename, '\\');
+-
+-      /* Truncate at last directory.  */
+-      if (lastslash)
++      filename = grub_ieee1275_get_filename (bootpath);
++      if (filename)
+         {
+-	  *lastslash = '\0';
+-	  grub_translate_ieee1275_path (filename);
++          char *lastslash = grub_strrchr (filename, '\\');
+ 
+-	  *path = filename;
+-	}
++          /* Truncate at last directory.  */
++          if (lastslash)
++            {
++              *lastslash = '\0';
++              grub_translate_ieee1275_path (filename);
++
++              *path = filename;
++            }
++        }
++      *device = grub_ieee1275_encode_devname (bootpath);
+     }
++
++  grub_free (type);
+   grub_free (bootpath);
+ }
+ 
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index 578e057e18f..10bfed31b2b 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -1817,7 +1817,7 @@ grub_net_search_configfile (char *config)
+   /* Remove the remaining minus sign at the end. */
+   config[config_len] = '\0';
+ 
+-  return GRUB_ERR_NONE;
++  return GRUB_ERR_FILE_NOT_FOUND;
+ }
+ 
+ static struct grub_preboot *fini_hnd;
+diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
+index 4190985ad37..aa14499996b 100644
+--- a/grub-core/normal/main.c
++++ b/grub-core/normal/main.c
+@@ -331,74 +331,72 @@ grub_enter_normal_mode (const char *config)
+   grub_boot_time ("Exiting normal mode");
+ }
+ 
++static grub_err_t
++grub_try_normal (const char *variable)
++{
++    char *config;
++    const char *prefix;
++    grub_err_t err = GRUB_ERR_FILE_NOT_FOUND;
++
++    prefix = grub_env_get (variable);
++    if (!prefix)
++      return GRUB_ERR_FILE_NOT_FOUND;
++
++    if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0)
++      {
++	grub_size_t config_len;
++	config_len = grub_strlen (prefix) +
++	  sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
++	config = grub_malloc (config_len);
++
++	if (! config)
++	  return GRUB_ERR_FILE_NOT_FOUND;
++
++	grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
++	err = grub_net_search_configfile (config);
++      }
++
++    if (err != GRUB_ERR_NONE)
++      {
++	config = grub_xasprintf ("%s/grub.cfg", prefix);
++	if (config)
++	  {
++	    grub_file_t file;
++	    file = grub_file_open (config);
++	    if (file)
++	      {
++		grub_file_close (file);
++		err = GRUB_ERR_NONE;
++	      }
++	  }
++      }
++
++    if (err == GRUB_ERR_NONE)
++      grub_enter_normal_mode (config);
++
++    grub_errno = 0;
++    grub_free (config);
++    return err;
++}
++
+ /* Enter normal mode from rescue mode.  */
+ static grub_err_t
+ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
+ 		 int argc, char *argv[])
+ {
+-  if (argc == 0)
+-    {
+-      /* Guess the config filename. It is necessary to make CONFIG static,
+-	 so that it won't get broken by longjmp.  */
+-      char *config;
+-      const char *prefix;
+-
+-      prefix = grub_env_get ("fw_path");
+-      if (! prefix)
+-	      prefix = grub_env_get ("prefix");
+-
+-      if (prefix)
+-	{
+-	  if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0)
+-	    {
+-	      grub_size_t config_len;
+-	      config_len = grub_strlen (prefix) +
+-		sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
+-	      config = grub_malloc (config_len);
+-
+-	      if (! config)
+-		goto quit;
+-
+-	      grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
+-
+-	      grub_net_search_configfile (config);
+-
+-	      grub_enter_normal_mode (config);
+-	      grub_free (config);
+-	      config = NULL;
+-	    }
+-
+-	  if (!config)
+-	    {
+-	      config = grub_xasprintf ("%s/grub.cfg", prefix);
+-	      if (config)
+-		{
+-		  grub_file_t file;
+-
+-		  file = grub_file_open (config);
+-		  if (file)
+-		    {
+-		      grub_file_close (file);
+-		      grub_enter_normal_mode (config);
+-		    }
+-		  else
+-		    {
+-		      /*  Ignore all errors.  */
+-		      grub_errno = 0;
+-		    }
+-		  grub_free (config);
+-		}
+-	    }
+-	}
+-      else
+-	{
+-	  grub_enter_normal_mode (0);
+-	}
+-    }
+-  else
++  if (argc)
+     grub_enter_normal_mode (argv[0]);
++  else
++    {
++      /* Guess the config filename. */
++      grub_err_t err;
++      err = grub_try_normal ("fw_path");
++      if (err == GRUB_ERR_FILE_NOT_FOUND)
++        err = grub_try_normal ("prefix");
++      if (err == GRUB_ERR_FILE_NOT_FOUND)
++        grub_enter_normal_mode (0);
++    }
+ 
+-quit:
+   return 0;
+ }
+ 
diff --git a/SOURCES/0155-Update-info-with-grub.cfg-netboot-selection-order-11.patch b/SOURCES/0155-Update-info-with-grub.cfg-netboot-selection-order-11.patch
new file mode 100644
index 0000000..b621d5a
--- /dev/null
+++ b/SOURCES/0155-Update-info-with-grub.cfg-netboot-selection-order-11.patch
@@ -0,0 +1,66 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Mon, 16 Mar 2015 16:34:51 -0400
+Subject: [PATCH] Update info with grub.cfg netboot selection order (#1148650)
+
+Added documentation to the grub info page that specifies the order
+netboot clients will use to select a grub configuration file.
+
+Resolves rhbz#1148650
+---
+ docs/grub.texi | 42 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 42 insertions(+)
+
+diff --git a/docs/grub.texi b/docs/grub.texi
+index 6b112c18804..ef09c832482 100644
+--- a/docs/grub.texi
++++ b/docs/grub.texi
+@@ -2414,6 +2414,48 @@ grub-mknetdir --net-directory=/srv/tftp --subdir=/boot/grub -d /usr/lib/grub/i38
+ Then follow instructions printed out by grub-mknetdir on configuring your DHCP
+ server.
+ 
++The grub.cfg file is placed in the same directory as the path output by
++grub-mknetdir hereafter referred to as FWPATH. GRUB will search for its 
++configuration files in order using the following rules where the appended
++value corresponds to a value on the client machine.
++
++@example
++@group
++@samp{(FWPATH)}/grub.cfg-@samp{(UUID OF NIC)}
++@samp{(FWPATH)}/grub.cfg-@samp{(MAC ADDRESS OF NIC)}
++@samp{(FWPATH)}/grub.cfg-@samp{(IPv4 OR IPv6 ADDRESS)}
++@samp{(FWPATH)}/grub.cfg
++@end group
++@end example
++
++The client will only attempt to look up an IPv6 address config once, however,
++it will try the IPv4 multiple times. The concrete example below shows what
++would happen under the IPv4 case.
++
++@example
++@group
++UUID: 7726a678-7fc0-4853-a4f6-c85ac36a120a
++MAC:  52:54:00:ec:33:81
++IPV4: 10.0.0.130 (0A000082)
++@end group
++@end example
++
++@example
++@group
++@samp{(FWPATH)}/grub.cfg-7726a678-7fc0-4853-a4f6-c85ac36a120a
++@samp{(FWPATH)}/grub.cfg-52-54-00-ec-33-81
++@samp{(FWPATH)}/grub.cfg-0A000082
++@samp{(FWPATH)}/grub.cfg-0A00008
++@samp{(FWPATH)}/grub.cfg-0A0000
++@samp{(FWPATH)}/grub.cfg-0A000
++@samp{(FWPATH)}/grub.cfg-0A00
++@samp{(FWPATH)}/grub.cfg-0A0
++@samp{(FWPATH)}/grub.cfg-0A
++@samp{(FWPATH)}/grub.cfg-0
++@samp{(FWPATH)}/grub.cfg
++@end group
++@end example
++
+ After GRUB has started, files on the TFTP server will be accessible via the
+ @samp{(tftp)} device.
+ 
diff --git a/SOURCES/0156-Use-Distribution-Package-Sort-for-grub2-mkconfig-112.patch b/SOURCES/0156-Use-Distribution-Package-Sort-for-grub2-mkconfig-112.patch
new file mode 100644
index 0000000..5406f63
--- /dev/null
+++ b/SOURCES/0156-Use-Distribution-Package-Sort-for-grub2-mkconfig-112.patch
@@ -0,0 +1,446 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Mon, 16 Mar 2015 14:14:19 -0400
+Subject: [PATCH] Use Distribution Package Sort for grub2-mkconfig (#1124074)
+
+Users reported that newly installed kernels on their systems installed
+with grub-mkconfig would not appear on the grub boot list in order
+starting with the most recent. Added an option for rpm-based systems to
+use the rpm-sort library to sort kernels instead.
+
+Resolves rhbz#1124074
+---
+ configure.ac              |  29 +++++
+ Makefile.util.def         |  16 +++
+ util/grub-rpm-sort.c      | 281 ++++++++++++++++++++++++++++++++++++++++++++++
+ .gitignore                |   1 +
+ util/grub-mkconfig_lib.in |   8 +-
+ util/grub-rpm-sort.8      |  12 ++
+ 6 files changed, 346 insertions(+), 1 deletion(-)
+ create mode 100644 util/grub-rpm-sort.c
+ create mode 100644 util/grub-rpm-sort.8
+
+diff --git a/configure.ac b/configure.ac
+index 048ce7c89fa..de17e65c4b7 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -65,6 +65,7 @@ grub_TRANSFORM([grub-mkrelpath])
+ grub_TRANSFORM([grub-mkrescue])
+ grub_TRANSFORM([grub-probe])
+ grub_TRANSFORM([grub-reboot])
++grub_TRANSFORM([grub-rpm-sort])
+ grub_TRANSFORM([grub-script-check])
+ grub_TRANSFORM([grub-set-default])
+ grub_TRANSFORM([grub-sparc64-setup])
+@@ -89,6 +90,7 @@ grub_TRANSFORM([grub-mkrescue.1])
+ grub_TRANSFORM([grub-mkstandalone.3])
+ grub_TRANSFORM([grub-ofpathname.3])
+ grub_TRANSFORM([grub-probe.3])
++grub_TRANSFORM([grub-rpm-sort.8])
+ grub_TRANSFORM([grub-reboot.3])
+ grub_TRANSFORM([grub-render-label.3])
+ grub_TRANSFORM([grub-script-check.3])
+@@ -1543,6 +1545,33 @@ fi
+ 
+ AC_SUBST([LIBDEVMAPPER])
+ 
++AC_ARG_ENABLE([rpm-sort],
++              [AS_HELP_STRING([--enable-rpm-sort],
++                              [enable native rpm sorting of kernels in grub (default=guessed)])])
++if test x"$enable_rpm-sort" = xno ; then
++  rpm_sort_excuse="explicitly disabled"
++fi
++
++if test x"$rpm_sort_excuse" = x ; then
++  # Check for rpmlib header.
++  AC_CHECK_HEADER([rpm/rpmlib.h], [],
++               [rpm_sort_excuse="need rpm/rpmlib header"])
++fi
++
++if test x"$rpm_sort_excuse" = x ; then
++  # Check for rpm library.
++  AC_CHECK_LIB([rpm], [rpmvercmp], [],
++               [rpm_sort_excuse="rpmlib missing rpmvercmp"])
++fi
++
++if test x"$rpm_sort_excuse" = x ; then
++   LIBRPM="-lrpm";
++   AC_DEFINE([HAVE_RPM], [1],
++             [Define to 1 if you have the rpm library.])
++fi
++
++AC_SUBST([LIBRPM])
++
+ LIBGEOM=
+ if test x$host_kernel = xkfreebsd; then
+   AC_CHECK_LIB([geom], [geom_gettree], [],
+diff --git a/Makefile.util.def b/Makefile.util.def
+index 87029a10dfb..3ac75720466 100644
+--- a/Makefile.util.def
++++ b/Makefile.util.def
+@@ -675,6 +675,22 @@ program = {
+   ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
+ };
+ 
++program = {
++  name = grub-rpm-sort;
++  mansection = 8;
++  installdir = sbin;
++
++  common = grub-core/kern/emu/misc.c;
++  common = grub-core/kern/emu/argp_common.c;
++  common = grub-core/osdep/init.c;
++  common = util/misc.c;
++  common = util/grub-rpm-sort.c;
++
++  ldadd = grub-core/gnulib/libgnu.a;
++  ldadd = libgrubkern.a;
++  ldadd = '$(LIBDEVMAPPER) $(LIBRPM)';
++};
++
+ script = {
+   name = grub-mkconfig;
+   common = util/grub-mkconfig.in;
+diff --git a/util/grub-rpm-sort.c b/util/grub-rpm-sort.c
+new file mode 100644
+index 00000000000..f33bd1ed568
+--- /dev/null
++++ b/util/grub-rpm-sort.c
+@@ -0,0 +1,281 @@
++#include <config.h>
++#include <grub/types.h>
++#include <grub/util/misc.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <errno.h>
++#include <assert.h>
++#include <argp.h>
++#include <rpm/rpmlib.h>
++
++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 = grub_util_fopen(input, "r");
++
++  text = xmalloc (sz);
++
++  if (!in)
++    grub_util_error (_("cannot open `%s': %s"), input, strerror (errno));
++
++  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;
++    }
++}
++
++/*
++ * 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;
++
++  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 = rpmvercmp ((lhs_name == NULL ? "" : lhs_name),
++                          (rhs_name == NULL ? "" : rhs_name));
++  if (vercmpflag != 0)
++    return vercmpflag;
++
++  /* Check version and return if unequal */
++  vercmpflag = rpmvercmp ((lhs_version == NULL ? "" : lhs_version),
++                          (rhs_version == NULL ? "" : rhs_version));
++  if (vercmpflag != 0)
++    return vercmpflag;
++
++  /* Check release and return the version compare value */
++  vercmpflag = rpmvercmp ((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[] = {
++  { 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 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, N_("[INPUT_FILES]"),
++  N_("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;
++
++  grub_util_host_init (&argc, &argv);
++
++  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)
++    grub_util_error ("%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)
++    grub_util_error ("%s", _("Invalid input\n"));
++
++  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/.gitignore b/.gitignore
+index 18ab8e81278..b6c45776a4d 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -237,6 +237,7 @@ po/POTFILES.in
+ po/POTFILES-shell.in
+ /grub-glue-efi
+ /grub-render-label
++grub-rpm-sort
+ /grub-glue-efi.exe
+ /grub-render-label.exe
+ grub-core/gnulib/locale.h
+diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
+index 5c9ed84a5e7..e85b60c322a 100644
+--- a/util/grub-mkconfig_lib.in
++++ b/util/grub-mkconfig_lib.in
+@@ -213,6 +213,12 @@ version_sort ()
+    esac
+ }
+ 
++if [ "x$RPMLIB" = x ]; then
++  kernel_sort=version_sort
++else
++  kernel_sort="${sbindir}/grub-rpm-sort"
++fi
++
+ version_test_numeric ()
+ {
+   version_test_numeric_a="$1"
+@@ -229,7 +235,7 @@ version_test_numeric ()
+     version_test_numeric_a="$version_test_numeric_b"
+     version_test_numeric_b="$version_test_numeric_c"
+   fi
+-  if (echo "$version_test_numeric_a" ; echo "$version_test_numeric_b") | version_sort | head -n 1 | grep -qx "$version_test_numeric_b" ; then
++  if (echo "$version_test_numeric_a" ; echo "$version_test_numeric_b") | "$kernel_sort" | head -n 1 | grep -qx "$version_test_numeric_b" ; then
+     return 0
+   else
+     return 1
+diff --git a/util/grub-rpm-sort.8 b/util/grub-rpm-sort.8
+new file mode 100644
+index 00000000000..8ce21488448
+--- /dev/null
++++ b/util/grub-rpm-sort.8
+@@ -0,0 +1,12 @@
++.TH GRUB-RPM-SORT 8 "Wed Feb 26 2014"
++.SH NAME
++\fBgrub-rpm-sort\fR \(em Sort input according to RPM version compare.
++
++.SH SYNOPSIS
++\fBgrub-rpm-sort\fR [OPTIONS].
++
++.SH DESCRIPTION
++You should not normally run this program directly.  Use grub-mkconfig instead.
++
++.SH SEE ALSO
++.BR "info grub"
diff --git a/SOURCES/0157-efidisk-move-device-path-helpers-in-core-for-efinet.patch b/SOURCES/0157-efidisk-move-device-path-helpers-in-core-for-efinet.patch
new file mode 100644
index 0000000..e57c685
--- /dev/null
+++ b/SOURCES/0157-efidisk-move-device-path-helpers-in-core-for-efinet.patch
@@ -0,0 +1,204 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Thu, 7 May 2015 20:37:16 +0300
+Subject: [PATCH] efidisk: move device path helpers in core for efinet
+
+---
+ grub-core/disk/efi/efidisk.c | 61 ++++++++------------------------------------
+ grub-core/kern/efi/efi.c     | 41 +++++++++++++++++++++++++++++
+ include/grub/efi/efi.h       |  4 +++
+ 3 files changed, 55 insertions(+), 51 deletions(-)
+
+diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c
+index 3b12c349923..845c66fa9ab 100644
+--- a/grub-core/disk/efi/efidisk.c
++++ b/grub-core/disk/efi/efidisk.c
+@@ -43,47 +43,6 @@ static struct grub_efidisk_data *fd_devices;
+ static struct grub_efidisk_data *hd_devices;
+ static struct grub_efidisk_data *cd_devices;
+ 
+-/* Duplicate a device path.  */
+-static grub_efi_device_path_t *
+-duplicate_device_path (const grub_efi_device_path_t *dp)
+-{
+-  grub_efi_device_path_t *p;
+-  grub_size_t total_size = 0;
+-
+-  for (p = (grub_efi_device_path_t *) dp;
+-       ;
+-       p = GRUB_EFI_NEXT_DEVICE_PATH (p))
+-    {
+-      total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
+-      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
+-	break;
+-    }
+-
+-  p = grub_malloc (total_size);
+-  if (! p)
+-    return 0;
+-
+-  grub_memcpy (p, dp, total_size);
+-  return p;
+-}
+-
+-/* Return the device path node right before the end node.  */
+-static grub_efi_device_path_t *
+-find_last_device_path (const grub_efi_device_path_t *dp)
+-{
+-  grub_efi_device_path_t *next, *p;
+-
+-  if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
+-    return 0;
+-
+-  for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p);
+-       ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
+-       p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
+-    ;
+-
+-  return p;
+-}
+-
+ static struct grub_efidisk_data *
+ make_devices (void)
+ {
+@@ -110,7 +69,7 @@ make_devices (void)
+       if (! dp)
+ 	continue;
+ 
+-      ldp = find_last_device_path (dp);
++      ldp = grub_efi_find_last_device_path (dp);
+       if (! ldp)
+ 	/* This is empty. Why?  */
+ 	continue;
+@@ -150,11 +109,11 @@ find_parent_device (struct grub_efidisk_data *devices,
+   grub_efi_device_path_t *dp, *ldp;
+   struct grub_efidisk_data *parent;
+ 
+-  dp = duplicate_device_path (d->device_path);
++  dp = grub_efi_duplicate_device_path (d->device_path);
+   if (! dp)
+     return 0;
+ 
+-  ldp = find_last_device_path (dp);
++  ldp = grub_efi_find_last_device_path (dp);
+   ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+   ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+   ldp->length = sizeof (*ldp);
+@@ -180,11 +139,11 @@ is_child (struct grub_efidisk_data *child,
+   grub_efi_device_path_t *dp, *ldp;
+   int ret;
+ 
+-  dp = duplicate_device_path (child->device_path);
++  dp = grub_efi_duplicate_device_path (child->device_path);
+   if (! dp)
+     return 0;
+ 
+-  ldp = find_last_device_path (dp);
++  ldp = grub_efi_find_last_device_path (dp);
+   ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+   ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+   ldp->length = sizeof (*ldp);
+@@ -207,8 +166,8 @@ add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d)
+     {
+       int ret;
+ 
+-      ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path),
+-					   find_last_device_path (d->device_path));
++      ret = grub_efi_compare_device_paths (grub_efi_find_last_device_path ((*p)->device_path),
++					   grub_efi_find_last_device_path (d->device_path));
+       if (ret == 0)
+ 	ret = grub_efi_compare_device_paths ((*p)->device_path,
+ 					     d->device_path);
+@@ -795,7 +754,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
+   if (! dp)
+     return 0;
+ 
+-  ldp = find_last_device_path (dp);
++  ldp = grub_efi_find_last_device_path (dp);
+   if (! ldp)
+     return 0;
+ 
+@@ -811,14 +770,14 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
+ 
+       /* It is necessary to duplicate the device path so that GRUB
+ 	 can overwrite it.  */
+-      dup_dp = duplicate_device_path (dp);
++      dup_dp = grub_efi_duplicate_device_path (dp);
+       if (! dup_dp)
+ 	return 0;
+ 
+       while (1)
+ 	{
+ 	  grub_efi_device_path_t *dup_ldp;
+-	  dup_ldp = find_last_device_path (dup_dp);
++	  dup_ldp = grub_efi_find_last_device_path (dup_dp);
+ 	  if (!(GRUB_EFI_DEVICE_PATH_TYPE (dup_ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
+ 		&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE
+ 		    || GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)))
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index d99a6fbdf0d..c80d85b677e 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -423,6 +423,47 @@ grub_efi_get_device_path (grub_efi_handle_t handle)
+ 				 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ }
+ 
++/* Return the device path node right before the end node.  */
++grub_efi_device_path_t *
++grub_efi_find_last_device_path (const grub_efi_device_path_t *dp)
++{
++  grub_efi_device_path_t *next, *p;
++
++  if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
++    return 0;
++
++  for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p);
++       ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
++       p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
++    ;
++
++  return p;
++}
++
++/* Duplicate a device path.  */
++grub_efi_device_path_t *
++grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp)
++{
++  grub_efi_device_path_t *p;
++  grub_size_t total_size = 0;
++
++  for (p = (grub_efi_device_path_t *) dp;
++       ;
++       p = GRUB_EFI_NEXT_DEVICE_PATH (p))
++    {
++      total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
++      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
++	break;
++    }
++
++  p = grub_malloc (total_size);
++  if (! p)
++    return 0;
++
++  grub_memcpy (p, dp, total_size);
++  return p;
++}
++
+ static void
+ dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor)
+ {
+diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
+index a000c383e81..22456327e13 100644
+--- a/include/grub/efi/efi.h
++++ b/include/grub/efi/efi.h
+@@ -56,6 +56,10 @@ void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp);
+ char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp);
+ grub_efi_device_path_t *
+ EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle);
++grub_efi_device_path_t *
++EXPORT_FUNC(grub_efi_find_last_device_path) (const grub_efi_device_path_t *dp);
++grub_efi_device_path_t *
++EXPORT_FUNC(grub_efi_duplicate_device_path) (const grub_efi_device_path_t *dp);
+ grub_err_t EXPORT_FUNC (grub_efi_finish_boot_services) (grub_efi_uintn_t *outbuf_size, void *outbuf,
+ 							grub_efi_uintn_t *map_key,
+ 							grub_efi_uintn_t *efi_desc_size,
diff --git a/SOURCES/0158-efinet-Check-for-immediate-completition.patch b/SOURCES/0158-efinet-Check-for-immediate-completition.patch
new file mode 100644
index 0000000..b337ffc
--- /dev/null
+++ b/SOURCES/0158-efinet-Check-for-immediate-completition.patch
@@ -0,0 +1,48 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Martin Wilck <martin.wilck@ts.fujitsu.com>
+Date: Fri, 27 Mar 2015 14:27:56 +0100
+Subject: [PATCH] efinet: Check for immediate completition.
+
+This both speeds GRUB up and workarounds unexpected EFI behaviour.
+---
+ grub-core/net/drivers/efi/efinet.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index a6e4c7992f7..78df215be12 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -37,11 +37,12 @@ send_card_buffer (struct grub_net_card *dev,
+   grub_efi_status_t st;
+   grub_efi_simple_network_t *net = dev->efi_net;
+   grub_uint64_t limit_time = grub_get_time_ms () + 4000;
++  void *txbuf;
+ 
+   if (dev->txbusy)
+     while (1)
+       {
+-	void *txbuf = NULL;
++	txbuf = NULL;
+ 	st = efi_call_3 (net->get_status, net, 0, &txbuf);
+ 	if (st != GRUB_EFI_SUCCESS)
+ 	  return grub_error (GRUB_ERR_IO,
+@@ -74,7 +75,18 @@ send_card_buffer (struct grub_net_card *dev,
+ 		   dev->txbuf, NULL, NULL, NULL);
+   if (st != GRUB_EFI_SUCCESS)
+     return grub_error (GRUB_ERR_IO, N_("couldn't send network packet"));
+-  dev->txbusy = 1;
++
++  /*
++     The card may have sent out the packet immediately - set txbusy
++     to 0 in this case.
++     Cases were observed where checking txbuf at the next call
++     of send_card_buffer() is too late: 0 is returned in txbuf and
++     we run in the GRUB_ERR_TIMEOUT case above.
++     Perhaps a timeout in the FW has discarded the recycle buffer.
++   */
++  st = efi_call_3 (net->get_status, net, 0, &txbuf);
++  dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf == dev->txbuf);
++
+   return GRUB_ERR_NONE;
+ }
+ 
diff --git a/SOURCES/0159-efinet-memory-leak-on-module-removal.patch b/SOURCES/0159-efinet-memory-leak-on-module-removal.patch
new file mode 100644
index 0000000..022222a
--- /dev/null
+++ b/SOURCES/0159-efinet-memory-leak-on-module-removal.patch
@@ -0,0 +1,27 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Mon, 4 May 2015 08:08:57 +0300
+Subject: [PATCH] efinet: memory leak on module removal
+
+---
+ grub-core/net/drivers/efi/efinet.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 78df215be12..810adf38fe6 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -294,6 +294,12 @@ GRUB_MOD_FINI(efinet)
+ 
+   FOR_NET_CARDS_SAFE (card, next) 
+     if (card->driver == &efidriver)
+-      grub_net_card_unregister (card);
++      {
++	grub_net_card_unregister (card);
++	grub_free (card->txbuf);
++	grub_free (card->rcvbuf);
++	grub_free (card->name);
++	grub_free (card);
++      }
+ }
+ 
diff --git a/SOURCES/0160-efinet-cannot-free-const-char-pointer.patch b/SOURCES/0160-efinet-cannot-free-const-char-pointer.patch
new file mode 100644
index 0000000..865ccd9
--- /dev/null
+++ b/SOURCES/0160-efinet-cannot-free-const-char-pointer.patch
@@ -0,0 +1,22 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Mon, 4 May 2015 08:39:29 +0300
+Subject: [PATCH] efinet: cannot free const char * pointer
+
+---
+ grub-core/net/drivers/efi/efinet.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 810adf38fe6..bb863e65a38 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -298,7 +298,7 @@ GRUB_MOD_FINI(efinet)
+ 	grub_net_card_unregister (card);
+ 	grub_free (card->txbuf);
+ 	grub_free (card->rcvbuf);
+-	grub_free (card->name);
++	grub_free ((char *)card->name);
+ 	grub_free (card);
+       }
+ }
diff --git a/SOURCES/0161-Revert-efinet-memory-leak-on-module-removal.patch b/SOURCES/0161-Revert-efinet-memory-leak-on-module-removal.patch
new file mode 100644
index 0000000..f1cf7e0
--- /dev/null
+++ b/SOURCES/0161-Revert-efinet-memory-leak-on-module-removal.patch
@@ -0,0 +1,31 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Mon, 4 May 2015 09:13:53 +0300
+Subject: [PATCH] Revert "efinet: memory leak on module removal"
+
+This reverts commits 47b2bee3ef0ea60fc3f5bfc37f3784e559385297
+and 8d3c4544ffdd0289a4b0bdeb0cdc6355f801a4b3. It is not safe
+to free allocated cards, dangling pointers main remain. Such
+cleanup requires more changes in net core.
+---
+ grub-core/net/drivers/efi/efinet.c | 8 +-------
+ 1 file changed, 1 insertion(+), 7 deletions(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index bb863e65a38..78df215be12 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -294,12 +294,6 @@ GRUB_MOD_FINI(efinet)
+ 
+   FOR_NET_CARDS_SAFE (card, next) 
+     if (card->driver == &efidriver)
+-      {
+-	grub_net_card_unregister (card);
+-	grub_free (card->txbuf);
+-	grub_free (card->rcvbuf);
+-	grub_free ((char *)card->name);
+-	grub_free (card);
+-      }
++      grub_net_card_unregister (card);
+ }
+ 
diff --git a/SOURCES/0162-efinet-skip-virtual-IPv4-and-IPv6-devices-when-enume.patch b/SOURCES/0162-efinet-skip-virtual-IPv4-and-IPv6-devices-when-enume.patch
new file mode 100644
index 0000000..f21a921
--- /dev/null
+++ b/SOURCES/0162-efinet-skip-virtual-IPv4-and-IPv6-devices-when-enume.patch
@@ -0,0 +1,94 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Thu, 7 May 2015 20:37:17 +0300
+Subject: [PATCH] efinet: skip virtual IPv4 and IPv6 devices when enumerating
+ cards
+
+EDK2 PXE driver creates two child devices - IPv4 and IPv6 - with
+bound SNP instance. This means we get three cards for every physical
+adapter when enumerating. Not only is this confusing, this may result
+in grub ignoring packets that come in via the "wrong" card.
+
+Example of device hierarchy is
+
+ Ctrl[91] PciRoot(0x0)/Pci(0x3,0x0)
+   Ctrl[95] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)
+     Ctrl[B4] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)/IPv4(0.0.0.0)
+     Ctrl[BC] PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400123456,0x1)/IPv6(0000:0000:0000:0000:0000:0000:0000:0000)
+
+Skip PXE created virtual devices when enumerating cards. Make sure to
+find real card when applying initial autoconfiguration during PXE boot,
+this information is associated with one of child devices.
+---
+ grub-core/net/drivers/efi/efinet.c | 51 +++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 50 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 78df215be12..caa7b50228b 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -174,6 +174,29 @@ grub_efinet_findcards (void)
+     {
+       grub_efi_simple_network_t *net;
+       struct grub_net_card *card;
++      grub_efi_device_path_t *dp, *parent = NULL, *child = NULL;
++
++      /* EDK2 UEFI PXE driver creates IPv4 and IPv6 messaging devices as
++	 children of main MAC messaging device. We only need one device with
++	 bound SNP per physical card, otherwise they compete with each other
++	 when polling for incoming packets.
++       */
++      dp = grub_efi_get_device_path (*handle);
++      if (!dp)
++	continue;
++      for (; ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp); dp = GRUB_EFI_NEXT_DEVICE_PATH (dp))
++	{
++	  parent = child;
++	  child = dp;
++	}
++      if (child
++	  && GRUB_EFI_DEVICE_PATH_TYPE (child) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
++	  && (GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
++	      || GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)
++	  && parent
++	  && GRUB_EFI_DEVICE_PATH_TYPE (parent) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
++	  && GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)
++	continue;
+ 
+       net = grub_efi_open_protocol (*handle, &net_io_guid,
+ 				    GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+@@ -252,7 +275,33 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+     if (! cdp)
+       continue;
+     if (grub_efi_compare_device_paths (dp, cdp) != 0)
+-      continue;
++      {
++	grub_efi_device_path_t *ldp, *dup_dp, *dup_ldp;
++	int match;
++
++	/* EDK2 UEFI PXE driver creates pseudo devices with type IPv4/IPv6
++	   as children of Ethernet card and binds PXE and Load File protocols
++	   to it. Loaded Image Device Path protocol will point to these pseudo
++	   devices. We skip them when enumerating cards, so here we need to
++	   find matching MAC device.
++         */
++	ldp = grub_efi_find_last_device_path (dp);
++	if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
++	    || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
++		&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
++	  continue;
++	dup_dp = grub_efi_duplicate_device_path (dp);
++	if (!dup_dp)
++	  continue;
++	dup_ldp = grub_efi_find_last_device_path (dup_dp);
++	dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++	dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++	dup_ldp->length = sizeof (*dup_ldp);
++	match = grub_efi_compare_device_paths (dup_dp, cdp) == 0;
++	grub_free (dup_dp);
++	if (!match)
++	  continue;
++      }
+     pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
+ 				  GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+     if (! pxe)
diff --git a/SOURCES/0163-efinet-open-Simple-Network-Protocol-exclusively.patch b/SOURCES/0163-efinet-open-Simple-Network-Protocol-exclusively.patch
new file mode 100644
index 0000000..c26954d
--- /dev/null
+++ b/SOURCES/0163-efinet-open-Simple-Network-Protocol-exclusively.patch
@@ -0,0 +1,86 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Thu, 7 May 2015 20:37:17 +0300
+Subject: [PATCH] efinet: open Simple Network Protocol exclusively
+
+EDK2 network stack is based on Managed Network Protocol which is layered
+on top of Simple Management Protocol and does background polling. This
+polling races with grub for received (and probably trasmitted) packets
+which causes either serious slowdown or complete failure to load files.
+
+Open SNP device exclusively.  This destroys all child MNP instances and
+stops background polling.
+
+Exclusive open cannot be done when enumerating cards, as it would destroy
+PXE information we need to autoconfigure interface; and it cannot be done
+during autoconfiguration as we need to do it for non-PXE boot as well. So
+move SNP open to card ->open method and add matching ->close to clean up.
+
+Based on patch from Mark Salter <msalter@redhat.com>
+
+Also-By: Mark Salter <msalter@redhat.com>
+Closes: 41731
+---
+ grub-core/net/drivers/efi/efinet.c | 46 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 46 insertions(+)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index caa7b50228b..6a1dd1f9dff 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -142,9 +142,55 @@ get_card_packet (struct grub_net_card *dev)
+   return nb;
+ }
+ 
++static grub_err_t
++open_card (struct grub_net_card *dev)
++{
++  grub_efi_simple_network_t *net;
++
++  /* Try to reopen SNP exlusively to close any active MNP protocol instance
++     that may compete for packet polling
++   */
++  net = grub_efi_open_protocol (dev->efi_handle, &net_io_guid,
++				GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE);
++  if (net)
++    {
++      if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
++	  && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS)
++	return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net start failed",
++			   dev->name);
++
++      if (net->mode->state == GRUB_EFI_NETWORK_STOPPED)
++	return grub_error (GRUB_ERR_NET_NO_CARD, "%s: card stopped",
++			   dev->name);
++
++      if (net->mode->state == GRUB_EFI_NETWORK_STARTED
++	  && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS)
++	return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize failed",
++			   dev->name);
++
++      efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
++		  dev->efi_net, &net_io_guid,
++		  grub_efi_image_handle, dev->efi_handle);
++      dev->efi_net = net;
++    }
++
++  /* If it failed we just try to run as best as we can */
++  return GRUB_ERR_NONE;
++}
++
++static void
++close_card (struct grub_net_card *dev)
++{
++  efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
++	      dev->efi_net, &net_io_guid,
++	      grub_efi_image_handle, dev->efi_handle);
++}
++
+ static struct grub_net_card_driver efidriver =
+   {
+     .name = "efinet",
++    .open = open_card,
++    .close = close_card,
+     .send = send_card_buffer,
+     .recv = get_card_packet
+   };
diff --git a/SOURCES/0164-efinet-enable-hardware-filters-when-opening-interfac.patch b/SOURCES/0164-efinet-enable-hardware-filters-when-opening-interfac.patch
new file mode 100644
index 0000000..e914ac4
--- /dev/null
+++ b/SOURCES/0164-efinet-enable-hardware-filters-when-opening-interfac.patch
@@ -0,0 +1,104 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Tue, 16 Jun 2015 19:52:45 +0300
+Subject: [PATCH] efinet: enable hardware filters when opening interface
+
+Exclusive open on SNP will close all existing protocol instances which
+may disable all receive filters on interface. Reinstall them after we
+opened protocol exclusively.
+
+Also follow UEFI specification recommendation and stop interfaces when
+closing them:
+
+Unexpected system errors, reboots and hangs can occur if an OS is loaded
+and the network devices are not Shutdown() and Stopped().
+
+Also by: Mark Salter <msalter@redhat.com>
+Closes: 45204
+---
+ grub-core/net/drivers/efi/efinet.c | 25 +++++++++++++++++++++++++
+ include/grub/efi/api.h             | 20 +++++++++++++++++---
+ 2 files changed, 42 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 6a1dd1f9dff..7b8c4a59d10 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -168,6 +168,29 @@ open_card (struct grub_net_card *dev)
+ 	return grub_error (GRUB_ERR_NET_NO_CARD, "%s: net initialize failed",
+ 			   dev->name);
+ 
++      /* Enable hardware receive filters if driver declares support for it.
++	 We need unicast and broadcast and additionaly all nodes and
++	 solicited multicast for IPv6. Solicited multicast is per-IPv6
++	 address and we currently do not have API to do it so simply
++	 try to enable receive of all multicast packets or evertyhing in
++	 the worst case (i386 PXE driver always enables promiscuous too).
++
++	 This does trust firmware to do what it claims to do.
++       */
++      if (net->mode->receive_filter_mask)
++	{
++	  grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST   |
++				  GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
++				  GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
++
++	  filters &= net->mode->receive_filter_mask;
++	  if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST))
++	    filters |= (net->mode->receive_filter_mask &
++			GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS);
++
++	  efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL);
++	}
++
+       efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
+ 		  dev->efi_net, &net_io_guid,
+ 		  grub_efi_image_handle, dev->efi_handle);
+@@ -181,6 +204,8 @@ open_card (struct grub_net_card *dev)
+ static void
+ close_card (struct grub_net_card *dev)
+ {
++  efi_call_1 (dev->efi_net->shutdown, dev->efi_net);
++  efi_call_1 (dev->efi_net->stop, dev->efi_net);
+   efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
+ 	      dev->efi_net, &net_io_guid,
+ 	      grub_efi_image_handle, dev->efi_handle);
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 142340372e1..029ee92f5d0 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -1564,17 +1564,31 @@ enum
+     GRUB_EFI_NETWORK_INITIALIZED,
+   };
+ 
++enum
++  {
++    GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST		  = 0x01,
++    GRUB_EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST		  = 0x02,
++    GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST		  = 0x04,
++    GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS		  = 0x08,
++    GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST = 0x10,
++  };
++
+ struct grub_efi_simple_network
+ {
+   grub_uint64_t revision;
+   grub_efi_status_t (*start) (struct grub_efi_simple_network *this);
+-  void (*stop) (void);
++  grub_efi_status_t (*stop) (struct grub_efi_simple_network *this);
+   grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this,
+ 				   grub_efi_uintn_t extra_rx,
+ 				   grub_efi_uintn_t extra_tx);
+   void (*reset) (void);
+-  void (*shutdown) (void);
+-  void (*receive_filters) (void);
++  grub_efi_status_t (*shutdown) (struct grub_efi_simple_network *this);
++  grub_efi_status_t (*receive_filters) (struct grub_efi_simple_network *this,
++					grub_uint32_t enable,
++					grub_uint32_t disable,
++					grub_efi_boolean_t reset_mcast_filter,
++					grub_efi_uintn_t mcast_filter_count,
++					grub_efi_mac_address_t *mcast_filter);
+   void (*station_address) (void);
+   void (*statistics) (void);
+   void (*mcastiptomac) (void);
diff --git a/SOURCES/0165-efinet-handle-get_status-on-buggy-firmware-properly.patch b/SOURCES/0165-efinet-handle-get_status-on-buggy-firmware-properly.patch
new file mode 100644
index 0000000..22e2bcc
--- /dev/null
+++ b/SOURCES/0165-efinet-handle-get_status-on-buggy-firmware-properly.patch
@@ -0,0 +1,63 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fb.com>
+Date: Thu, 6 Aug 2015 10:49:46 -0700
+Subject: [PATCH] efinet: handle get_status() on buggy firmware properly
+
+The EFI spec indicates that get_status() should return the address of the buffer
+we passed into transmit to indicate the the buffer was transmitted.  However we
+have boxes where the firmware returns some arbitrary address instead, which
+makes grub think that we've not sent anything.  So since we have the SNP stuff
+opened in exclusive mode just assume any non-NULL txbuf means that our transmit
+occurred properly.  This makes grub able to do its networking stuff properly on
+our broken firmware.  Thanks,
+
+cc: Peter Jones <pjones@redhat.com>
+Signed-off-by: Josef Bacik <jbacik@fb.com>
+---
+ grub-core/net/drivers/efi/efinet.c | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 7b8c4a59d10..ea0e0ca360e 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -47,19 +47,19 @@ send_card_buffer (struct grub_net_card *dev,
+ 	if (st != GRUB_EFI_SUCCESS)
+ 	  return grub_error (GRUB_ERR_IO,
+ 			     N_("couldn't send network packet"));
+-	if (txbuf == dev->txbuf)
++	/*
++	   Some buggy firmware could return an arbitrary address instead of the
++	   txbuf address we trasmitted, so just check that txbuf is non NULL
++	   for success.  This is ok because we open the SNP protocol in
++	   exclusive mode so we know we're the only ones transmitting on this
++	   box and since we only transmit one packet at a time we know our
++	   transmit was successfull.
++	 */
++	if (txbuf)
+ 	  {
+ 	    dev->txbusy = 0;
+ 	    break;
+ 	  }
+-	if (txbuf)
+-	  {
+-	    st = efi_call_7 (net->transmit, net, 0, dev->last_pkt_size,
+-			     dev->txbuf, NULL, NULL, NULL);
+-	    if (st != GRUB_EFI_SUCCESS)
+-	      return grub_error (GRUB_ERR_IO,
+-				 N_("couldn't send network packet"));
+-	  }
+ 	if (limit_time < grub_get_time_ms ())
+ 	  return grub_error (GRUB_ERR_TIMEOUT,
+ 			     N_("couldn't send network packet"));
+@@ -84,8 +84,9 @@ send_card_buffer (struct grub_net_card *dev,
+      we run in the GRUB_ERR_TIMEOUT case above.
+      Perhaps a timeout in the FW has discarded the recycle buffer.
+    */
++  txbuf = NULL;
+   st = efi_call_3 (net->get_status, net, 0, &txbuf);
+-  dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf == dev->txbuf);
++  dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf);
+ 
+   return GRUB_ERR_NONE;
+ }
diff --git a/SOURCES/0166-Handle-rssd-storage-devices.patch b/SOURCES/0166-Handle-rssd-storage-devices.patch
new file mode 100644
index 0000000..cc012e0
--- /dev/null
+++ b/SOURCES/0166-Handle-rssd-storage-devices.patch
@@ -0,0 +1,36 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 30 Jun 2015 15:50:41 -0400
+Subject: [PATCH] Handle rssd storage devices.
+
+Resolves: rhbz#1087962
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/osdep/linux/getroot.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
+index 7007193d9c7..5987d078a2f 100644
+--- a/grub-core/osdep/linux/getroot.c
++++ b/grub-core/osdep/linux/getroot.c
+@@ -884,6 +884,19 @@ grub_util_part_to_disk (const char *os_dev, struct stat *st,
+ 	  return path;
+ 	}
+ 
++      /* If this is an rssd device. */
++      if ((strncmp ("rssd", p, 4) == 0) && p[4] >= 'a' && p[4] <= 'z')
++	{
++	  char *pp = p + 4;
++	  while (*pp >= 'a' && *pp <= 'z')
++	    pp++;
++	  if (*pp)
++	    *is_part = 1;
++	  /* /dev/rssd[a-z]+[0-9]* */
++	  *pp = '\0';
++	  return path;
++	}
++
+       /* If this is a loop device */
+       if ((strncmp ("loop", p, 4) == 0) && p[4] >= '0' && p[4] <= '9')
+ 	{
diff --git a/SOURCES/0167-xfs-Fix-termination-loop-for-directory-iteration.patch b/SOURCES/0167-xfs-Fix-termination-loop-for-directory-iteration.patch
new file mode 100644
index 0000000..a8476c2
--- /dev/null
+++ b/SOURCES/0167-xfs-Fix-termination-loop-for-directory-iteration.patch
@@ -0,0 +1,29 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Mon, 14 Jul 2014 17:21:29 +0200
+Subject: [PATCH] xfs: Fix termination loop for directory iteration
+
+Directory iteration used wrong position (sizeof wrong structure) for
+termination of iteration inside a directory block. Luckily the position
+ended up being wrong by just 1 byte and directory entries are larger so
+things worked out fine in practice. But fix the problem anyway.
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+---
+ grub-core/fs/xfs.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
+index 16ffd3f1ebd..4bd52d1e081 100644
+--- a/grub-core/fs/xfs.c
++++ b/grub-core/fs/xfs.c
+@@ -603,8 +603,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
+ 		       - grub_be_to_cpu32 (tail->leaf_stale));
+ 
+ 	    /* Iterate over all entries within this block.  */
+-	    while (pos < (dirblk_size
+-			  - (int) sizeof (struct grub_xfs_dir2_entry)))
++	    while (pos < tail_start)
+ 	      {
+ 		struct grub_xfs_dir2_entry *direntry;
+ 		grub_uint8_t *freetag;
diff --git a/SOURCES/0168-xfs-Convert-inode-numbers-to-cpu-endianity-immediate.patch b/SOURCES/0168-xfs-Convert-inode-numbers-to-cpu-endianity-immediate.patch
new file mode 100644
index 0000000..f381d9b
--- /dev/null
+++ b/SOURCES/0168-xfs-Convert-inode-numbers-to-cpu-endianity-immediate.patch
@@ -0,0 +1,79 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Mon, 14 Jul 2014 17:21:30 +0200
+Subject: [PATCH] xfs: Convert inode numbers to cpu endianity immediately after
+ reading
+
+Currently XFS driver converted inode numbers to native endianity only
+when using them to compute inode position. Although this works, it is
+somewhat confusing. So convert inode numbers when reading them from disk
+structures as every other field.
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+---
+ grub-core/fs/xfs.c | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
+index 4bd52d1e081..0d704e9a4d4 100644
+--- a/grub-core/fs/xfs.c
++++ b/grub-core/fs/xfs.c
+@@ -180,14 +180,14 @@ static inline grub_uint64_t
+ GRUB_XFS_INO_INOINAG (struct grub_xfs_data *data,
+ 		      grub_uint64_t ino)
+ {
+-  return (grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1));
++  return (ino & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1));
+ }
+ 
+ static inline grub_uint64_t
+ GRUB_XFS_INO_AG (struct grub_xfs_data *data,
+ 		 grub_uint64_t ino)
+ {
+-  return (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data));
++  return (ino >> GRUB_XFS_INO_AGBITS (data));
+ }
+ 
+ static inline grub_disk_addr_t
+@@ -506,13 +506,12 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
+ 	if (smallino)
+ 	  {
+ 	    parent = grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4);
+-	    parent = grub_cpu_to_be64 (parent);
+ 	    /* The header is a bit smaller than usual.  */
+ 	    de = (struct grub_xfs_dir_entry *) ((char *) de - 4);
+ 	  }
+ 	else
+ 	  {
+-	    parent = diro->inode.data.dir.dirhead.parent.i8;
++	    parent = grub_be_to_cpu64(diro->inode.data.dir.dirhead.parent.i8);
+ 	  }
+ 
+ 	/* Synthesize the direntries for `.' and `..'.  */
+@@ -545,7 +544,6 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
+ 		| (((grub_uint64_t) inopos[5]) << 16)
+ 		| (((grub_uint64_t) inopos[6]) << 8)
+ 		| (((grub_uint64_t) inopos[7]) << 0);
+-	    ino = grub_cpu_to_be64 (ino);
+ 
+ 	    c = de->name[de->len];
+ 	    de->name[de->len] = '\0';
+@@ -627,7 +625,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
+ 		   is not used by GRUB.  So it can be overwritten.  */
+ 		filename[direntry->len] = '\0';
+ 
+-		if (iterate_dir_call_hook (direntry->inode, filename, &ctx))
++		if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode), 
++					   filename, &ctx))
+ 		  {
+ 		    grub_free (dirblock);
+ 		    return 1;
+@@ -689,7 +688,7 @@ grub_xfs_mount (grub_disk_t disk)
+     goto fail;
+ 
+   data->diropen.data = data;
+-  data->diropen.ino = data->sblock.rootino;
++  data->diropen.ino = grub_be_to_cpu64(data->sblock.rootino);
+   data->diropen.inode_read = 1;
+   data->bsize = grub_be_to_cpu32 (data->sblock.bsize);
+   data->agsize = grub_be_to_cpu32 (data->sblock.agsize);
diff --git a/SOURCES/0169-xfs-Add-helpers-for-inode-size.patch b/SOURCES/0169-xfs-Add-helpers-for-inode-size.patch
new file mode 100644
index 0000000..ea3f241
--- /dev/null
+++ b/SOURCES/0169-xfs-Add-helpers-for-inode-size.patch
@@ -0,0 +1,94 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Mon, 1 Jun 2015 14:28:45 +0200
+Subject: [PATCH] xfs: Add helpers for inode size
+
+Add helpers to return size of XFS inode on disk and when loaded in
+memory.
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+---
+ grub-core/fs/xfs.c | 35 ++++++++++++++++++++++++-----------
+ 1 file changed, 24 insertions(+), 11 deletions(-)
+
+diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
+index 0d704e9a4d4..26d8147a92e 100644
+--- a/grub-core/fs/xfs.c
++++ b/grub-core/fs/xfs.c
+@@ -255,6 +255,24 @@ grub_xfs_inode_offset (struct grub_xfs_data *data,
+ 	  data->sblock.log2_inode);
+ }
+ 
++static inline grub_size_t
++grub_xfs_inode_size(struct grub_xfs_data *data)
++{
++  return 1 << data->sblock.log2_inode;
++}
++
++/*
++ * Returns size occupied by XFS inode stored in memory - we store struct
++ * grub_fshelp_node there but on disk inode size may be actually larger than
++ * struct grub_xfs_inode so we need to account for that so that we can read
++ * from disk directly into in-memory structure.
++ */
++static inline grub_size_t
++grub_xfs_fshelp_size(struct grub_xfs_data *data)
++{
++  return sizeof (struct grub_fshelp_node) - sizeof (struct grub_xfs_inode)
++	       + grub_xfs_inode_size(data);
++}
+ 
+ static grub_err_t
+ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
+@@ -264,8 +282,8 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
+   int offset = grub_xfs_inode_offset (data, ino);
+ 
+   /* Read the inode.  */
+-  if (grub_disk_read (data->disk, block, offset,
+-		      1 << data->sblock.log2_inode, inode))
++  if (grub_disk_read (data->disk, block, offset, grub_xfs_inode_size(data),
++		      inode))
+     return grub_errno;
+ 
+   if (grub_strncmp ((char *) inode->magic, "IN", 2))
+@@ -297,7 +315,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
+       if (node->inode.fork_offset)
+ 	recoffset = (node->inode.fork_offset - 1) / 2;
+       else
+-	recoffset = ((1 << node->data->sblock.log2_inode)
++	recoffset = (grub_xfs_inode_size(node->data)
+ 		     - ((char *) &node->inode.data.btree.keys
+ 			- (char *) &node->inode))
+ 	  / (2 * sizeof (grub_uint64_t));
+@@ -456,9 +474,7 @@ static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename,
+   struct grub_fshelp_node *fdiro;
+   grub_err_t err;
+ 
+-  fdiro = grub_malloc (sizeof (struct grub_fshelp_node)
+-		       - sizeof (struct grub_xfs_inode)
+-		       + (1 << ctx->diro->data->sblock.log2_inode) + 1);
++  fdiro = grub_malloc (grub_xfs_fshelp_size(ctx->diro->data) + 1);
+   if (!fdiro)
+     {
+       grub_print_error ();
+@@ -682,7 +698,7 @@ grub_xfs_mount (grub_disk_t disk)
+   data = grub_realloc (data,
+ 		       sizeof (struct grub_xfs_data)
+ 		       - sizeof (struct grub_xfs_inode)
+-		       + (1 << data->sblock.log2_inode) + 1);
++		       + grub_xfs_inode_size(data) + 1);
+ 
+   if (! data)
+     goto fail;
+@@ -797,10 +813,7 @@ grub_xfs_open (struct grub_file *file, const char *name)
+ 
+   if (fdiro != &data->diropen)
+     {
+-      grub_memcpy (&data->diropen, fdiro,
+-		   sizeof (struct grub_fshelp_node)
+-		   - sizeof (struct grub_xfs_inode)
+-		   + (1 << data->sblock.log2_inode));
++      grub_memcpy (&data->diropen, fdiro, grub_xfs_fshelp_size(data));
+       grub_free (fdiro);
+     }
+ 
diff --git a/SOURCES/0170-xfs-V5-filesystem-format-support.patch b/SOURCES/0170-xfs-V5-filesystem-format-support.patch
new file mode 100644
index 0000000..2d80632
--- /dev/null
+++ b/SOURCES/0170-xfs-V5-filesystem-format-support.patch
@@ -0,0 +1,576 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Mon, 1 Jun 2015 14:28:46 +0200
+Subject: [PATCH] xfs: V5 filesystem format support
+
+Add support for new XFS on disk format. We have to handle optional
+filetype fields in directory entries, additional CRC, LSN, UUID entries
+in some structures, etc.
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+---
+ grub-core/fs/xfs.c | 332 ++++++++++++++++++++++++++++++++++++++++-------------
+ 1 file changed, 252 insertions(+), 80 deletions(-)
+
+diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
+index 26d8147a92e..f00e43e7dc3 100644
+--- a/grub-core/fs/xfs.c
++++ b/grub-core/fs/xfs.c
+@@ -34,6 +34,50 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ #define XFS_INODE_FORMAT_EXT	2
+ #define XFS_INODE_FORMAT_BTREE	3
+ 
++/* Superblock version field flags */
++#define XFS_SB_VERSION_NUMBITS		0x000f
++#define	XFS_SB_VERSION_ATTRBIT		0x0010
++#define	XFS_SB_VERSION_NLINKBIT		0x0020
++#define	XFS_SB_VERSION_QUOTABIT		0x0040
++#define	XFS_SB_VERSION_ALIGNBIT		0x0080
++#define	XFS_SB_VERSION_DALIGNBIT	0x0100
++#define	XFS_SB_VERSION_LOGV2BIT		0x0400
++#define	XFS_SB_VERSION_SECTORBIT	0x0800
++#define	XFS_SB_VERSION_EXTFLGBIT	0x1000
++#define	XFS_SB_VERSION_DIRV2BIT		0x2000
++#define XFS_SB_VERSION_MOREBITSBIT	0x8000
++#define XFS_SB_VERSION_BITS_SUPPORTED \
++	(XFS_SB_VERSION_NUMBITS | \
++	 XFS_SB_VERSION_ATTRBIT | \
++	 XFS_SB_VERSION_NLINKBIT | \
++	 XFS_SB_VERSION_QUOTABIT | \
++	 XFS_SB_VERSION_ALIGNBIT | \
++	 XFS_SB_VERSION_DALIGNBIT | \
++	 XFS_SB_VERSION_LOGV2BIT | \
++	 XFS_SB_VERSION_SECTORBIT | \
++	 XFS_SB_VERSION_EXTFLGBIT | \
++	 XFS_SB_VERSION_DIRV2BIT | \
++	 XFS_SB_VERSION_MOREBITSBIT)
++
++/* Recognized xfs format versions */
++#define XFS_SB_VERSION_4		4	/* Good old XFS filesystem */
++#define XFS_SB_VERSION_5		5	/* CRC enabled filesystem */
++
++/* features2 field flags */
++#define XFS_SB_VERSION2_LAZYSBCOUNTBIT	0x00000002	/* Superblk counters */
++#define XFS_SB_VERSION2_ATTR2BIT	0x00000008	/* Inline attr rework */
++#define XFS_SB_VERSION2_PROJID32BIT	0x00000080	/* 32-bit project ids */
++#define XFS_SB_VERSION2_FTYPE		0x00000200	/* inode type in dir */
++#define XFS_SB_VERSION2_BITS_SUPPORTED \
++	(XFS_SB_VERSION2_LAZYSBCOUNTBIT | \
++	 XFS_SB_VERSION2_ATTR2BIT | \
++	 XFS_SB_VERSION2_PROJID32BIT | \
++	 XFS_SB_VERSION2_FTYPE)
++
++/* incompat feature flags */
++#define XFS_SB_FEAT_INCOMPAT_FTYPE      (1 << 0)        /* filetype in dirent */
++#define XFS_SB_FEAT_INCOMPAT_SUPPORTED \
++	(XFS_SB_FEAT_INCOMPAT_FTYPE)
+ 
+ struct grub_xfs_sblock
+ {
+@@ -45,7 +89,9 @@ struct grub_xfs_sblock
+   grub_uint64_t rootino;
+   grub_uint8_t unused3[20];
+   grub_uint32_t agsize;
+-  grub_uint8_t unused4[20];
++  grub_uint8_t unused4[12];
++  grub_uint16_t version;
++  grub_uint8_t unused5[6];
+   grub_uint8_t label[12];
+   grub_uint8_t log2_bsize;
+   grub_uint8_t log2_sect;
+@@ -54,12 +100,19 @@ struct grub_xfs_sblock
+   grub_uint8_t log2_agblk;
+   grub_uint8_t unused6[67];
+   grub_uint8_t log2_dirblk;
++  grub_uint8_t unused7[7];
++  grub_uint32_t features2;
++  grub_uint8_t unused8[4];
++  grub_uint32_t sb_features_compat;
++  grub_uint32_t sb_features_ro_compat;
++  grub_uint32_t sb_features_incompat;
++  grub_uint32_t sb_features_log_incompat;
+ } GRUB_PACKED;
+ 
+ struct grub_xfs_dir_header
+ {
+   grub_uint8_t count;
+-  grub_uint8_t smallino;
++  grub_uint8_t largeino;
+   union
+   {
+     grub_uint32_t i4;
+@@ -67,14 +120,16 @@ struct grub_xfs_dir_header
+   } GRUB_PACKED parent;
+ } GRUB_PACKED;
+ 
++/* Structure for directory entry inlined in the inode */
+ struct grub_xfs_dir_entry
+ {
+   grub_uint8_t len;
+   grub_uint16_t offset;
+   char name[1];
+-  /* Inode number follows, 32 bits.  */
++  /* Inode number follows, 32 / 64 bits.  */
+ } GRUB_PACKED;
+ 
++/* Structure for directory entry in a block */
+ struct grub_xfs_dir2_entry
+ {
+   grub_uint64_t inode;
+@@ -90,7 +145,8 @@ struct grub_xfs_btree_node
+   grub_uint16_t numrecs;
+   grub_uint64_t left;
+   grub_uint64_t right;
+-  grub_uint64_t keys[1];
++  /* In V5 here follow crc, uuid, etc. */
++  /* Then follow keys and block pointers */
+ }  GRUB_PACKED;
+ 
+ struct grub_xfs_btree_root
+@@ -123,19 +179,11 @@ struct grub_xfs_inode
+   grub_uint16_t unused3;
+   grub_uint8_t fork_offset;
+   grub_uint8_t unused4[17];
+-  union
+-  {
+-    char raw[156];
+-    struct dir
+-    {
+-      struct grub_xfs_dir_header dirhead;
+-      struct grub_xfs_dir_entry direntry[1];
+-    } dir;
+-    grub_xfs_extent extents[XFS_INODE_EXTENTS];
+-    struct grub_xfs_btree_root btree;
+-  } GRUB_PACKED data;
+ } GRUB_PACKED;
+ 
++#define XFS_V2_INODE_SIZE sizeof(struct grub_xfs_inode)
++#define XFS_V3_INODE_SIZE (XFS_V2_INODE_SIZE + 76)
++
+ struct grub_xfs_dirblock_tail
+ {
+   grub_uint32_t leaf_count;
+@@ -157,6 +205,8 @@ struct grub_xfs_data
+   int pos;
+   int bsize;
+   grub_uint32_t agsize;
++  unsigned int hasftype:1;
++  unsigned int hascrc:1;
+   struct grub_fshelp_node diropen;
+ };
+ 
+@@ -164,6 +214,71 @@ static grub_dl_t my_mod;
+ 
+ 
+ 
++static int grub_xfs_sb_hascrc(struct grub_xfs_data *data)
++{
++  return (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) ==
++	  grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5);
++}
++
++static int grub_xfs_sb_hasftype(struct grub_xfs_data *data)
++{
++  if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) ==
++	grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5) &&
++      data->sblock.sb_features_incompat & grub_cpu_to_be32_compile_time(XFS_SB_FEAT_INCOMPAT_FTYPE))
++    return 1;
++  if (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_MOREBITSBIT) &&
++      data->sblock.features2 & grub_cpu_to_be32_compile_time(XFS_SB_VERSION2_FTYPE))
++    return 1;
++  return 0;
++}
++
++static int grub_xfs_sb_valid(struct grub_xfs_data *data)
++{
++  grub_dprintf("xfs", "Validating superblock\n");
++  if (grub_strncmp ((char *) (data->sblock.magic), "XFSB", 4)
++      || data->sblock.log2_bsize < GRUB_DISK_SECTOR_BITS
++      || ((int) data->sblock.log2_bsize
++	  + (int) data->sblock.log2_dirblk) >= 27)
++    {
++      grub_error (GRUB_ERR_BAD_FS, "not a XFS filesystem");
++      return 0;
++    }
++  if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) ==
++       grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5))
++    {
++      grub_dprintf("xfs", "XFS v5 superblock detected\n");
++      if (data->sblock.sb_features_incompat &
++          grub_cpu_to_be32_compile_time(~XFS_SB_FEAT_INCOMPAT_SUPPORTED))
++        {
++	  grub_error (GRUB_ERR_BAD_FS, "XFS filesystem has unsupported "
++		      "incompatible features");
++	  return 0;
++        }
++      return 1;
++    }
++  else if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) ==
++	   grub_cpu_to_be16_compile_time(XFS_SB_VERSION_4))
++    {
++      grub_dprintf("xfs", "XFS v4 superblock detected\n");
++      if (!(data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_DIRV2BIT)))
++	{
++	  grub_error (GRUB_ERR_BAD_FS, "XFS filesystem without V2 directories "
++		      "is unsupported");
++	  return 0;
++	}
++      if (data->sblock.version & grub_cpu_to_be16_compile_time(~XFS_SB_VERSION_BITS_SUPPORTED) ||
++	  (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_MOREBITSBIT) &&
++	   data->sblock.features2 & grub_cpu_to_be16_compile_time(~XFS_SB_VERSION2_BITS_SUPPORTED)))
++	{
++	  grub_error (GRUB_ERR_BAD_FS, "XFS filesystem has unsupported version "
++		      "bits");
++	  return 0;
++	}
++      return 1;
++    }
++  return 0;
++}
++
+ /* Filetype information as used in inodes.  */
+ #define FILETYPE_INO_MASK	0170000
+ #define FILETYPE_INO_REG	0100000
+@@ -219,18 +334,6 @@ GRUB_XFS_EXTENT_SIZE (grub_xfs_extent *exts, int ex)
+   return (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 21) - 1));
+ }
+ 
+-static inline int
+-GRUB_XFS_ROUND_TO_DIRENT (int pos)
+-{
+-  return ((((pos) + 8 - 1) / 8) * 8);
+-}
+-
+-static inline int
+-GRUB_XFS_NEXT_DIRENT (int pos, int len)
+-{
+-  return (pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2);
+-}
+-
+ 
+ static inline grub_uint64_t
+ grub_xfs_inode_block (struct grub_xfs_data *data,
+@@ -274,6 +377,85 @@ grub_xfs_fshelp_size(struct grub_xfs_data *data)
+ 	       + grub_xfs_inode_size(data);
+ }
+ 
++static void *
++grub_xfs_inode_data(struct grub_xfs_inode *inode)
++{
++	if (inode->version <= 2)
++		return ((char *)inode) + XFS_V2_INODE_SIZE;
++	return ((char *)inode) + XFS_V3_INODE_SIZE;
++}
++
++static struct grub_xfs_dir_entry *
++grub_xfs_inline_de(struct grub_xfs_dir_header *head)
++{
++	/*
++	 * With small inode numbers the header is 4 bytes smaller because of
++	 * smaller parent pointer
++	 */
++	return (void *)(((char *)head) + sizeof(struct grub_xfs_dir_header) -
++		(head->largeino ? 0 : sizeof(grub_uint32_t)));
++}
++
++static grub_uint8_t *
++grub_xfs_inline_de_inopos(struct grub_xfs_data *data,
++			  struct grub_xfs_dir_entry *de)
++{
++	return ((grub_uint8_t *)(de + 1)) + de->len - 1 +
++		 (data->hasftype ? 1 : 0);
++}
++
++static struct grub_xfs_dir_entry *
++grub_xfs_inline_next_de(struct grub_xfs_data *data,
++			struct grub_xfs_dir_header *head,
++			struct grub_xfs_dir_entry *de)
++{
++  char *p = (char *)de + sizeof(struct grub_xfs_dir_entry) - 1 + de->len;
++
++  p += head->largeino ? sizeof(grub_uint64_t) : sizeof(grub_uint32_t);
++  if (data->hasftype)
++    p++;
++
++  return (struct grub_xfs_dir_entry *)p;
++}
++
++static struct grub_xfs_dirblock_tail *
++grub_xfs_dir_tail(struct grub_xfs_data *data, void *dirblock)
++{
++  int dirblksize = 1 << (data->sblock.log2_bsize + data->sblock.log2_dirblk);
++
++  return (struct grub_xfs_dirblock_tail *)
++    ((char *)dirblock + dirblksize - sizeof (struct grub_xfs_dirblock_tail));
++}
++
++static struct grub_xfs_dir2_entry *
++grub_xfs_first_de(struct grub_xfs_data *data, void *dirblock)
++{
++  if (data->hascrc)
++    return (struct grub_xfs_dir2_entry *)((char *)dirblock + 64);
++  return (struct grub_xfs_dir2_entry *)((char *)dirblock + 16);
++}
++
++static struct grub_xfs_dir2_entry *
++grub_xfs_next_de(struct grub_xfs_data *data, struct grub_xfs_dir2_entry *de)
++{
++  int size = sizeof (struct grub_xfs_dir2_entry) + de->len + 2 /* Tag */;
++
++  if (data->hasftype)
++    size++;		/* File type */
++  return (struct grub_xfs_dir2_entry *)(((char *)de) + ALIGN_UP(size, 8));
++}
++
++static grub_uint64_t *
++grub_xfs_btree_keys(struct grub_xfs_data *data,
++		    struct grub_xfs_btree_node *leaf)
++{
++  grub_uint64_t *keys = (grub_uint64_t *)(leaf + 1);
++
++  if (data->hascrc)
++    keys += 6;	/* skip crc, uuid, ... */
++  return keys;
++}
++
+ static grub_err_t
+ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
+ 		     struct grub_xfs_inode *inode)
+@@ -281,6 +463,8 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
+   grub_uint64_t block = grub_xfs_inode_block (data, ino);
+   int offset = grub_xfs_inode_offset (data, ino);
+ 
++  grub_dprintf("xfs", "Reading inode (%"PRIuGRUB_UINT64_T") - %"PRIuGRUB_UINT64_T", %d\n",
++	       ino, block, offset);
+   /* Read the inode.  */
+   if (grub_disk_read (data->disk, block, offset, grub_xfs_inode_size(data),
+ 		      inode))
+@@ -303,6 +487,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
+ 
+   if (node->inode.format == XFS_INODE_FORMAT_BTREE)
+     {
++      struct grub_xfs_btree_root *root;
+       const grub_uint64_t *keys;
+       int recoffset;
+ 
+@@ -310,15 +495,15 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
+       if (leaf == 0)
+         return 0;
+ 
+-      nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs);
+-      keys = &node->inode.data.btree.keys[0];
++      root = grub_xfs_inode_data(&node->inode);
++      nrec = grub_be_to_cpu16 (root->numrecs);
++      keys = &root->keys[0];
+       if (node->inode.fork_offset)
+ 	recoffset = (node->inode.fork_offset - 1) / 2;
+       else
+ 	recoffset = (grub_xfs_inode_size(node->data)
+-		     - ((char *) &node->inode.data.btree.keys
+-			- (char *) &node->inode))
+-	  / (2 * sizeof (grub_uint64_t));
++		     - ((char *) keys - (char *) &node->inode))
++				/ (2 * sizeof (grub_uint64_t));
+       do
+         {
+           int i;
+@@ -340,7 +525,10 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
+                               0, node->data->bsize, leaf))
+             return 0;
+ 
+-          if (grub_strncmp ((char *) leaf->magic, "BMAP", 4))
++	  if ((!node->data->hascrc &&
++	       grub_strncmp ((char *) leaf->magic, "BMAP", 4)) ||
++	      (node->data->hascrc &&
++	       grub_strncmp ((char *) leaf->magic, "BMA3", 4)))
+             {
+               grub_free (leaf);
+               grub_error (GRUB_ERR_BAD_FS, "not a correct XFS BMAP node");
+@@ -348,8 +536,8 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
+             }
+ 
+           nrec = grub_be_to_cpu16 (leaf->numrecs);
+-          keys = &leaf->keys[0];
+-	  recoffset = ((node->data->bsize - ((char *) &leaf->keys
++          keys = grub_xfs_btree_keys(node->data, leaf);
++	  recoffset = ((node->data->bsize - ((char *) keys
+ 					     - (char *) leaf))
+ 		       / (2 * sizeof (grub_uint64_t)));
+ 	}
+@@ -359,7 +547,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
+   else if (node->inode.format == XFS_INODE_FORMAT_EXT)
+     {
+       nrec = grub_be_to_cpu32 (node->inode.nextents);
+-      exts = &node->inode.data.extents[0];
++      exts = grub_xfs_inode_data(&node->inode);
+     }
+   else
+     {
+@@ -417,7 +605,7 @@ grub_xfs_read_symlink (grub_fshelp_node_t node)
+   switch (node->inode.format)
+     {
+     case XFS_INODE_FORMAT_INO:
+-      return grub_strndup (node->inode.data.raw, size);
++      return grub_strndup (grub_xfs_inode_data(&node->inode), size);
+ 
+     case XFS_INODE_FORMAT_EXT:
+       {
+@@ -512,23 +700,18 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
+     {
+     case XFS_INODE_FORMAT_INO:
+       {
+-	struct grub_xfs_dir_entry *de = &diro->inode.data.dir.direntry[0];
+-	int smallino = !diro->inode.data.dir.dirhead.smallino;
++	struct grub_xfs_dir_header *head = grub_xfs_inode_data(&diro->inode);
++	struct grub_xfs_dir_entry *de = grub_xfs_inline_de(head);
++	int smallino = !head->largeino;
+ 	int i;
+ 	grub_uint64_t parent;
+ 
+ 	/* If small inode numbers are used to pack the direntry, the
+ 	   parent inode number is small too.  */
+ 	if (smallino)
+-	  {
+-	    parent = grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4);
+-	    /* The header is a bit smaller than usual.  */
+-	    de = (struct grub_xfs_dir_entry *) ((char *) de - 4);
+-	  }
++	  parent = grub_be_to_cpu32 (head->parent.i4);
+ 	else
+-	  {
+-	    parent = grub_be_to_cpu64(diro->inode.data.dir.dirhead.parent.i8);
+-	  }
++	  parent = grub_be_to_cpu64 (head->parent.i8);
+ 
+ 	/* Synthesize the direntries for `.' and `..'.  */
+ 	if (iterate_dir_call_hook (diro->ino, ".", &ctx))
+@@ -537,12 +720,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
+ 	if (iterate_dir_call_hook (parent, "..", &ctx))
+ 	  return 1;
+ 
+-	for (i = 0; i < diro->inode.data.dir.dirhead.count; i++)
++	for (i = 0; i < head->count; i++)
+ 	  {
+ 	    grub_uint64_t ino;
+-	    grub_uint8_t *inopos = (((grub_uint8_t *) de)
+-			    + sizeof (struct grub_xfs_dir_entry)
+-			    + de->len - 1);
++	    grub_uint8_t *inopos = grub_xfs_inline_de_inopos(dir->data, de);
+ 	    grub_uint8_t c;
+ 
+ 	    /* inopos might be unaligned.  */
+@@ -567,10 +748,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
+ 	      return 1;
+ 	    de->name[de->len] = c;
+ 
+-	    de = ((struct grub_xfs_dir_entry *)
+-		  (((char *) de)+ sizeof (struct grub_xfs_dir_entry) + de->len
+-		   + ((smallino ? sizeof (grub_uint32_t)
+-		       : sizeof (grub_uint64_t))) - 1));
++	    de = grub_xfs_inline_next_de(dir->data, head, de);
+ 	  }
+ 	break;
+       }
+@@ -597,15 +775,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
+ 		    >> dirblk_log2);
+ 	     blk++)
+ 	  {
+-	    /* The header is skipped, the first direntry is stored
+-	       from byte 16.  */
+-	    int pos = 16;
++	    struct grub_xfs_dir2_entry *direntry =
++					grub_xfs_first_de(dir->data, dirblock);
+ 	    int entries;
+-	    int tail_start = (dirblk_size
+-			      - sizeof (struct grub_xfs_dirblock_tail));
+-
+-	    struct grub_xfs_dirblock_tail *tail;
+-	    tail = (struct grub_xfs_dirblock_tail *) &dirblock[tail_start];
++	    struct grub_xfs_dirblock_tail *tail =
++					grub_xfs_dir_tail(dir->data, dirblock);
+ 
+ 	    numread = grub_xfs_read_file (dir, 0, 0,
+ 					  blk << dirblk_log2,
+@@ -617,13 +791,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
+ 		       - grub_be_to_cpu32 (tail->leaf_stale));
+ 
+ 	    /* Iterate over all entries within this block.  */
+-	    while (pos < tail_start)
++	    while ((char *)direntry < (char *)tail)
+ 	      {
+-		struct grub_xfs_dir2_entry *direntry;
+ 		grub_uint8_t *freetag;
+ 		char *filename;
+ 
+-		direntry = (struct grub_xfs_dir2_entry *) &dirblock[pos];
+ 		freetag = (grub_uint8_t *) direntry;
+ 
+ 		if (grub_get_unaligned16 (freetag) == 0XFFFF)
+@@ -631,14 +803,16 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
+ 		    grub_uint8_t *skip = (freetag + sizeof (grub_uint16_t));
+ 
+ 		    /* This entry is not used, go to the next one.  */
+-		    pos += grub_be_to_cpu16 (grub_get_unaligned16 (skip));
++		    direntry = (struct grub_xfs_dir2_entry *)
++				(((char *)direntry) +
++				grub_be_to_cpu16 (grub_get_unaligned16 (skip)));
+ 
+ 		    continue;
+ 		  }
+ 
+-		filename = &dirblock[pos + sizeof (*direntry)];
+-		/* The byte after the filename is for the tag, which
+-		   is not used by GRUB.  So it can be overwritten.  */
++		filename = (char *)(direntry + 1);
++		/* The byte after the filename is for the filetype, padding, or
++		   tag, which is not used by GRUB.  So it can be overwritten. */
+ 		filename[direntry->len] = '\0';
+ 
+ 		if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode), 
+@@ -655,8 +829,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
+ 		  break;
+ 
+ 		/* Select the next directory entry.  */
+-		pos = GRUB_XFS_NEXT_DIRENT (pos, direntry->len);
+-		pos = GRUB_XFS_ROUND_TO_DIRENT (pos);
++		direntry = grub_xfs_next_de(dir->data, direntry);
+ 	      }
+ 	  }
+ 	grub_free (dirblock);
+@@ -681,19 +854,14 @@ grub_xfs_mount (grub_disk_t disk)
+   if (!data)
+     return 0;
+ 
++  grub_dprintf("xfs", "Reading sb\n");
+   /* Read the superblock.  */
+   if (grub_disk_read (disk, 0, 0,
+ 		      sizeof (struct grub_xfs_sblock), &data->sblock))
+     goto fail;
+ 
+-  if (grub_strncmp ((char *) (data->sblock.magic), "XFSB", 4)
+-      || data->sblock.log2_bsize < GRUB_DISK_SECTOR_BITS
+-      || ((int) data->sblock.log2_bsize
+-	  + (int) data->sblock.log2_dirblk) >= 27)
+-    {
+-      grub_error (GRUB_ERR_BAD_FS, "not a XFS filesystem");
+-      goto fail;
+-    }
++  if (!grub_xfs_sb_valid(data))
++    goto fail;
+ 
+   data = grub_realloc (data,
+ 		       sizeof (struct grub_xfs_data)
+@@ -708,9 +876,13 @@ grub_xfs_mount (grub_disk_t disk)
+   data->diropen.inode_read = 1;
+   data->bsize = grub_be_to_cpu32 (data->sblock.bsize);
+   data->agsize = grub_be_to_cpu32 (data->sblock.agsize);
++  data->hasftype = grub_xfs_sb_hasftype(data);
++  data->hascrc = grub_xfs_sb_hascrc(data);
+ 
+   data->disk = disk;
+   data->pos = 0;
++  grub_dprintf("xfs", "Reading root ino %"PRIuGRUB_UINT64_T"\n",
++	       grub_cpu_to_be64(data->sblock.rootino));
+ 
+   grub_xfs_read_inode (data, data->diropen.ino, &data->diropen.inode);
+ 
diff --git a/SOURCES/0171-xfs-silence-Coverity-overflow-warning.patch b/SOURCES/0171-xfs-silence-Coverity-overflow-warning.patch
new file mode 100644
index 0000000..b65a692
--- /dev/null
+++ b/SOURCES/0171-xfs-silence-Coverity-overflow-warning.patch
@@ -0,0 +1,24 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Fri, 19 Jun 2015 18:38:25 +0300
+Subject: [PATCH] xfs: silence Coverity overflow warning
+
+inode size cannot really overflow integer, but Coverity does not know it.
+CID: 96602
+---
+ grub-core/fs/xfs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
+index f00e43e7dc3..72492915533 100644
+--- a/grub-core/fs/xfs.c
++++ b/grub-core/fs/xfs.c
+@@ -361,7 +361,7 @@ grub_xfs_inode_offset (struct grub_xfs_data *data,
+ static inline grub_size_t
+ grub_xfs_inode_size(struct grub_xfs_data *data)
+ {
+-  return 1 << data->sblock.log2_inode;
++  return (grub_size_t)1 << data->sblock.log2_inode;
+ }
+ 
+ /*
diff --git a/SOURCES/0172-send-router-solicitation-for-ipv6-address-autoconf-v.patch b/SOURCES/0172-send-router-solicitation-for-ipv6-address-autoconf-v.patch
new file mode 100644
index 0000000..332a464
--- /dev/null
+++ b/SOURCES/0172-send-router-solicitation-for-ipv6-address-autoconf-v.patch
@@ -0,0 +1,160 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Tue, 18 Nov 2014 16:03:08 +0800
+Subject: [PATCH] send router solicitation for ipv6 address autoconf v2
+
+Many routers have long router advertisment interval configured by
+default. The Neighbor Discovery protocol (RFC4861) has defined default
+MaxRtrAdvInterval value as 600 seconds and
+MinRtrAdvInterval as 0.33*MaxRtrAdvInterval. This makes
+net_ipv6_autoconf fails more often than not as currently it passively
+listens the RA message to perfom address autoconfiguration.
+
+This patch tries to send router solicitation to overcome the problem of
+long RA interval.
+
+v2:
+use cpu_to_be macro for network byte order conversion
+add missing error handling
+---
+ grub-core/net/icmp6.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ grub-core/net/net.c   |  4 ++-
+ include/grub/net/ip.h |  2 ++
+ 3 files changed, 88 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c
+index bbc902014fe..0843a15afda 100644
+--- a/grub-core/net/icmp6.c
++++ b/grub-core/net/icmp6.c
+@@ -72,6 +72,11 @@ struct neighbour_advertise
+   grub_uint64_t target[2];
+ } GRUB_PACKED;
+ 
++struct router_solicit
++{
++  grub_uint32_t reserved;
++} GRUB_PACKED;
++
+ enum
+   {
+     FLAG_SLAAC = 0x40
+@@ -81,6 +86,7 @@ enum
+   {
+     ICMP6_ECHO = 128,
+     ICMP6_ECHO_REPLY = 129,
++    ICMP6_ROUTER_SOLICIT = 133,
+     ICMP6_ROUTER_ADVERTISE = 134,
+     ICMP6_NEIGHBOUR_SOLICIT = 135,
+     ICMP6_NEIGHBOUR_ADVERTISE = 136,
+@@ -533,3 +539,80 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf,
+   grub_netbuff_free (nb);
+   return err;
+ }
++
++grub_err_t
++grub_net_icmp6_send_router_solicit (struct grub_net_network_level_interface *inf)
++{
++  struct grub_net_buff *nb;
++  grub_err_t err = GRUB_ERR_NONE;
++  grub_net_network_level_address_t multicast;
++  grub_net_link_level_address_t ll_multicast;
++  struct option_header *ohdr;
++  struct router_solicit *sol;
++  struct icmp_header *icmphr;
++
++  multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
++  multicast.ipv6[0] = grub_cpu_to_be64 (0xff02ULL << 48);
++  multicast.ipv6[1] = grub_cpu_to_be64 (0x02ULL);
++
++  err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast);
++  if (err)
++    return err;
++
++  nb = grub_netbuff_alloc (sizeof (struct router_solicit)
++			   + sizeof (struct option_header)
++			   + 6
++			   + sizeof (struct icmp_header)
++			   + GRUB_NET_OUR_IPV6_HEADER_SIZE
++			   + GRUB_NET_MAX_LINK_HEADER_SIZE);
++  if (!nb)
++    return grub_errno;
++  err = grub_netbuff_reserve (nb,
++			      sizeof (struct router_solicit)
++			      + sizeof (struct option_header)
++			      + 6
++			      + sizeof (struct icmp_header)
++			      + GRUB_NET_OUR_IPV6_HEADER_SIZE
++			      + GRUB_NET_MAX_LINK_HEADER_SIZE);
++  if (err)
++    goto fail;
++
++  err = grub_netbuff_push (nb, 6);
++  if (err)
++    goto fail;
++
++  grub_memcpy (nb->data, inf->hwaddress.mac, 6);
++
++  err = grub_netbuff_push (nb, sizeof (*ohdr));
++  if (err)
++    goto fail;
++
++  ohdr = (struct option_header *) nb->data;
++  ohdr->type = OPTION_SOURCE_LINK_LAYER_ADDRESS;
++  ohdr->len = 1;
++
++  err = grub_netbuff_push (nb, sizeof (*sol));
++  if (err)
++    goto fail;
++
++  sol = (struct router_solicit *) nb->data;
++  sol->reserved = 0;
++
++  err = grub_netbuff_push (nb, sizeof (*icmphr));
++  if (err)
++    goto fail;
++
++  icmphr = (struct icmp_header *) nb->data;
++  icmphr->type = ICMP6_ROUTER_SOLICIT;
++  icmphr->code = 0;
++  icmphr->checksum = 0;
++  icmphr->checksum = grub_net_ip_transport_checksum (nb,
++						     GRUB_NET_IP_ICMPV6,
++						     &inf->address,
++						     &multicast);
++  err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb,
++				 GRUB_NET_IP_ICMPV6);
++ fail:
++  grub_netbuff_free (nb);
++  return err;
++}
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index 10bfed31b2b..b10addbe27b 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -380,12 +380,14 @@ grub_cmd_ipv6_autoconf (struct grub_command *cmd __attribute__ ((unused)),
+ 
+   for (interval = 200; interval < 10000; interval *= 2)
+     {
+-      /* FIXME: send router solicitation.  */
+       int done = 1;
+       for (j = 0; j < ncards; j++)
+ 	{
+ 	  if (slaacs[j]->slaac_counter)
+ 	    continue;
++	  err = grub_net_icmp6_send_router_solicit (ifaces[j]);
++	  if (err)
++	    err = GRUB_ERR_NONE;
+ 	  done = 0;
+ 	}
+       if (done)
+diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h
+index 7a8e614794d..dcceaa56894 100644
+--- a/include/grub/net/ip.h
++++ b/include/grub/net/ip.h
+@@ -92,4 +92,6 @@ grub_err_t
+ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf,
+ 			     const grub_net_network_level_address_t *proto_addr);
+ 
++grub_err_t
++grub_net_icmp6_send_router_solicit (struct grub_net_network_level_interface *inf);
+ #endif 
diff --git a/SOURCES/0173-icmp6-fix-no-respond-to-neighbor-solicit-message.patch b/SOURCES/0173-icmp6-fix-no-respond-to-neighbor-solicit-message.patch
new file mode 100644
index 0000000..0968619
--- /dev/null
+++ b/SOURCES/0173-icmp6-fix-no-respond-to-neighbor-solicit-message.patch
@@ -0,0 +1,26 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Mon, 3 Nov 2014 16:27:45 +0800
+Subject: [PATCH] icmp6 fix no respond to neighbor solicit message
+
+The structure size used in grub_netbuff_pull to get the pointer to
+option header is apparently wrong, which leads to subsequent range check
+failed and therefore not responding to any neighbor solicit message in my
+testing.
+---
+ grub-core/net/icmp6.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c
+index 0843a15afda..78223946031 100644
+--- a/grub-core/net/icmp6.c
++++ b/grub-core/net/icmp6.c
+@@ -211,7 +211,7 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
+ 	if (ttl != 0xff)
+ 	  break;
+ 	nbh = (struct neighbour_solicit *) nb->data;
+-	err = grub_netbuff_pull (nb, sizeof (struct router_adv));
++	err = grub_netbuff_pull (nb, sizeof (*nbh));
+ 	if (err)
+ 	  {
+ 	    grub_netbuff_free (nb);
diff --git a/SOURCES/0174-calibrate_tsc-use-the-Stall-EFI-boot-service-on-GRUB.patch b/SOURCES/0174-calibrate_tsc-use-the-Stall-EFI-boot-service-on-GRUB.patch
new file mode 100644
index 0000000..defe185
--- /dev/null
+++ b/SOURCES/0174-calibrate_tsc-use-the-Stall-EFI-boot-service-on-GRUB.patch
@@ -0,0 +1,70 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Fri, 10 Oct 2014 11:11:09 +0200
+Subject: [PATCH] calibrate_tsc(): use the Stall() EFI boot service on
+ GRUB_MACHINE_EFI
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1150698
+
+HyperV Gen2 virtual machines have no PIT; guest code should rely on UEFI
+services instead.
+
+Signed-off-by: RHEL Ninjas <example@example.com>
+---
+ grub-core/kern/i386/tsc.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/kern/i386/tsc.c b/grub-core/kern/i386/tsc.c
+index 3a4cae601d0..e49964833ca 100644
+--- a/grub-core/kern/i386/tsc.c
++++ b/grub-core/kern/i386/tsc.c
+@@ -26,9 +26,14 @@
+ #include <grub/i386/tsc.h>
+ #include <grub/i386/cpuid.h>
+ #ifdef GRUB_MACHINE_XEN
+-#include <grub/xen.h>
++# include <grub/xen.h>
+ #else
+-#include <grub/i386/pit.h>
++# ifdef GRUB_MACHINE_EFI
++#  include <grub/efi/efi.h>
++#  include <grub/efi/api.h>
++# else
++#  include <grub/i386/pit.h>
++# endif
+ #endif
+ #include <grub/cpu/io.h>
+ 
+@@ -72,8 +77,14 @@ grub_cpu_is_tsc_supported (void)
+ #ifndef GRUB_MACHINE_XEN
+ 
+ static void
+-grub_pit_wait (grub_uint16_t tics)
++grub_stall (grub_uint16_t tics)
+ {
++# ifdef GRUB_MACHINE_EFI
++  grub_uint64_t microseconds;
++
++  microseconds = (grub_uint64_t)tics * 1000 * 1000 * 3 / 3579545;
++  efi_call_1 (grub_efi_system_table->boot_services->stall, microseconds);
++# else
+   /* Disable timer2 gate and speaker.  */
+   grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT)
+ 	     & ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2),
+@@ -97,6 +108,7 @@ grub_pit_wait (grub_uint16_t tics)
+   grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT)
+ 	     & ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2),
+              GRUB_PIT_SPEAKER_PORT);
++# endif
+ }
+ #endif
+ 
+@@ -119,7 +131,7 @@ calibrate_tsc (void)
+   grub_uint64_t end_tsc;
+ 
+   tsc_boot_time = grub_get_tsc ();
+-  grub_pit_wait (0xffff);
++  grub_stall (0xffff);
+   end_tsc = grub_get_tsc ();
+ 
+   grub_tsc_rate = grub_divmod64 ((55ULL << 32), end_tsc - tsc_boot_time, 0);
diff --git a/SOURCES/0175-fix-memory-corruption-in-pubkey-filter-over-network.patch b/SOURCES/0175-fix-memory-corruption-in-pubkey-filter-over-network.patch
new file mode 100644
index 0000000..0b95ffe
--- /dev/null
+++ b/SOURCES/0175-fix-memory-corruption-in-pubkey-filter-over-network.patch
@@ -0,0 +1,164 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Fri, 5 Dec 2014 21:17:08 +0300
+Subject: [PATCH] fix memory corruption in pubkey filter over network
+
+grub_pubkey_open closed original file after it was read; it set
+io->device to NULL to prevent grub_file_close from trying to close device.
+But network device itself is stacked (net -> bufio); and bufio preserved
+original netfs file which hold reference to device. grub_file_close(io)
+called grub_bufio_close which called grub_file_close for original file.
+grub_file_close(netfs-file) now also called grub_device_close which
+freed file->device->net. So file structure returned by grub_pubkey_open
+now had device->net pointed to freed memory. When later file was closed,
+it was attempted to be freed again.
+
+Change grub_pubkey_open to behave like other filters - preserve original
+parent file and pass grub_file_close down to parent. In this way only the
+original file will close device. We really need to move this logic into
+core instead.
+
+Also plug memory leaks in error paths on the way.
+
+Reported-By: Robert Kliewer <robert.kliewer@gmail.com>
+Closes: bug #43601
+---
+ grub-core/commands/verify.c | 72 +++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 60 insertions(+), 12 deletions(-)
+
+diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c
+index 525bdd18737..d5995766b4c 100644
+--- a/grub-core/commands/verify.c
++++ b/grub-core/commands/verify.c
+@@ -33,6 +33,13 @@
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
++struct grub_verified
++{
++  grub_file_t file;
++  void *buf;
++};
++typedef struct grub_verified *grub_verified_t;
++
+ enum
+   {
+     OPTION_SKIP_SIG = 0
+@@ -802,19 +809,39 @@ grub_cmd_verify_signature (grub_extcmd_context_t ctxt,
+ 
+ static int sec = 0;
+ 
++static void
++verified_free (grub_verified_t verified)
++{
++  if (verified)
++    {
++      grub_free (verified->buf);
++      grub_free (verified);
++    }
++}
++
+ static grub_ssize_t
+ verified_read (struct grub_file *file, char *buf, grub_size_t len)
+ {
+-  grub_memcpy (buf, (char *) file->data + file->offset, len);
++  grub_verified_t verified = file->data;
++
++  grub_memcpy (buf, (char *) verified->buf + file->offset, len);
+   return len;
+ }
+ 
+ static grub_err_t
+ verified_close (struct grub_file *file)
+ {
+-  grub_free (file->data);
++  grub_verified_t verified = file->data;
++
++  grub_file_close (verified->file);
++  verified_free (verified);
+   file->data = 0;
+-  return GRUB_ERR_NONE;
++
++  /* device and name are freed by parent */
++  file->device = 0;
++  file->name = 0;
++
++  return grub_errno;
+ }
+ 
+ struct grub_fs verified_fs =
+@@ -832,6 +859,7 @@ grub_pubkey_open (grub_file_t io, const char *filename)
+   grub_err_t err;
+   grub_file_filter_t curfilt[GRUB_FILE_FILTER_MAX];
+   grub_file_t ret;
++  grub_verified_t verified;
+ 
+   if (!sec)
+     return io;
+@@ -857,7 +885,10 @@ grub_pubkey_open (grub_file_t io, const char *filename)
+ 
+   ret = grub_malloc (sizeof (*ret));
+   if (!ret)
+-    return NULL;
++    {
++      grub_file_close (sig);
++      return NULL;
++    }
+   *ret = *io;
+ 
+   ret->fs = &verified_fs;
+@@ -866,29 +897,46 @@ grub_pubkey_open (grub_file_t io, const char *filename)
+     {
+       grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ 		  "big file signature isn't implemented yet");
++      grub_file_close (sig);
++      grub_free (ret);
++      return NULL;
++    }
++  verified = grub_malloc (sizeof (*verified));
++  if (!verified)
++    {
++      grub_file_close (sig);
++      grub_free (ret);
+       return NULL;
+     }
+-  ret->data = grub_malloc (ret->size);
+-  if (!ret->data)
++  verified->buf = grub_malloc (ret->size);
++  if (!verified->buf)
+     {
++      grub_file_close (sig);
++      grub_free (verified);
+       grub_free (ret);
+       return NULL;
+     }
+-  if (grub_file_read (io, ret->data, ret->size) != (grub_ssize_t) ret->size)
++  if (grub_file_read (io, verified->buf, ret->size) != (grub_ssize_t) ret->size)
+     {
+       if (!grub_errno)
+ 	grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
+ 		    filename);
++      grub_file_close (sig);
++      verified_free (verified);
++      grub_free (ret);
+       return NULL;
+     }
+ 
+-  err = grub_verify_signature_real (ret->data, ret->size, 0, sig, NULL);
++  err = grub_verify_signature_real (verified->buf, ret->size, 0, sig, NULL);
+   grub_file_close (sig);
+   if (err)
+-    return NULL;
+-  io->device = 0;
+-  io->name = 0;
+-  grub_file_close (io);
++    {
++      verified_free (verified);
++      grub_free (ret);
++      return NULL;
++    }
++  verified->file = io;
++  ret->data = verified;
+   return ret;
+ }
+ 
diff --git a/SOURCES/0176-Make-grub2-mkconfig-construct-titles-that-look-like-.patch b/SOURCES/0176-Make-grub2-mkconfig-construct-titles-that-look-like-.patch
new file mode 100644
index 0000000..1c5edf2
--- /dev/null
+++ b/SOURCES/0176-Make-grub2-mkconfig-construct-titles-that-look-like-.patch
@@ -0,0 +1,69 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 28 Apr 2015 11:15:03 -0400
+Subject: [PATCH] Make grub2-mkconfig construct titles that look like the ones
+ we want elsewhere.
+
+Resolves: rhbz#1215839
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ util/grub.d/10_linux.in | 34 +++++++++++++++++++++++++++-------
+ 1 file changed, 27 insertions(+), 7 deletions(-)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index e8088a18160..b3c460cb266 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -66,6 +66,32 @@ case x"$GRUB_FS" in
+ 	;;
+ esac
+ 
++mktitle ()
++{
++  local title_type
++  local version
++  local OS_NAME
++  local OS_VERS
++
++  title_type=$1 && shift
++  version=$1 && shift
++
++  OS_NAME="$(eval $(grep ^NAME= /etc/os-release) ; echo ${NAME})"
++  OS_VERS="$(eval $(grep ^VERSION= /etc/os-release) ; echo ${VERSION})"
++
++  case $title_type in
++    recovery)
++      title=$(printf '%s (%s) %s (recovery mode)' \
++                     "${OS_NAME}" "${version}" "${OS_VERS}")
++      ;;
++    *)
++      title=$(printf '%s (%s) %s' \
++                     "${OS_NAME}" "${version}" "${OS_VERS}")
++      ;;
++  esac
++  echo -n ${title}
++}
++
+ title_correction_code=
+ 
+ linux_entry ()
+@@ -94,17 +120,11 @@ linux_entry ()
+       boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
+   fi
+   if [ x$type != xsimple ] ; then
+-      case $type in
+-	  recovery)
+-	      title="$(gettext_printf "%s, with Linux %s (recovery mode)" "${os}" "${version}")" ;;
+-	  *)
+-	      title="$(gettext_printf "%s, with Linux %s" "${os}" "${version}")" ;;
+-      esac
++      title=$(mktitle "$type" "$version")
+       if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then
+ 	  replacement_title="$(echo "Advanced options for ${OS}" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')"
+ 	  quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"
+ 	  title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
+-	  grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")"
+       fi
+       echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+   else
diff --git a/SOURCES/0177-don-t-strip-fw_path-twice-for-EFI-network-boot.patch b/SOURCES/0177-don-t-strip-fw_path-twice-for-EFI-network-boot.patch
new file mode 100644
index 0000000..622955e
--- /dev/null
+++ b/SOURCES/0177-don-t-strip-fw_path-twice-for-EFI-network-boot.patch
@@ -0,0 +1,27 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: RHEL Ninjas <example@example.com>
+Date: Mon, 13 Apr 2015 12:42:53 +1000
+Subject: [PATCH] don't strip fw_path twice for EFI network boot
+
+---
+ grub-core/kern/efi/init.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
+index 942ab0256b9..c391df48236 100644
+--- a/grub-core/kern/efi/init.c
++++ b/grub-core/kern/efi/init.c
+@@ -61,7 +61,12 @@ grub_machine_get_bootlocation (char **device, char **path)
+   *device = grub_efidisk_get_device_name (image->device_handle);
+   *path = grub_efi_get_filename (image->file_path);
+   if (!*device && grub_efi_net_config)
+-    grub_efi_net_config (image->device_handle, device, path);
++    {
++      grub_efi_net_config (image->device_handle, device, path);
++      /* grub_efi_net_config returns the directory path, not the boot filename,
++         so don't strip any further. */
++      return;
++    }
+ 
+   /* Get the directory.  */
+   p = grub_strrchr (*path, '/');
diff --git a/SOURCES/0178-Add-friendly-grub2-password-config-tool-985962.patch b/SOURCES/0178-Add-friendly-grub2-password-config-tool-985962.patch
new file mode 100644
index 0000000..d53e093
--- /dev/null
+++ b/SOURCES/0178-Add-friendly-grub2-password-config-tool-985962.patch
@@ -0,0 +1,279 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Thu, 25 Jun 2015 11:13:11 -0400
+Subject: [PATCH] Add friendly grub2 password config tool (#985962)
+
+Provided a tool for users to reset the grub2 root user password
+without having to alter the grub.cfg. The hashed password now
+lives in a root-only-readable configuration file.
+
+Resolves: rhbz#985962
+---
+ configure.ac             |   1 +
+ Makefile.util.def        |  13 +++++
+ .gitignore               |  12 ++---
+ util/grub-mkconfig.in    |   2 +
+ util/grub-setpassword.8  |  28 +++++++++++
+ util/grub-setpassword.in | 123 +++++++++++++++++++++++++++++++++++++++++++++++
+ util/grub.d/01_users.in  |  11 +++++
+ 7 files changed, 182 insertions(+), 8 deletions(-)
+ create mode 100644 util/grub-setpassword.8
+ create mode 100755 util/grub-setpassword.in
+ create mode 100644 util/grub.d/01_users.in
+
+diff --git a/configure.ac b/configure.ac
+index de17e65c4b7..273da6cb906 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -65,6 +65,7 @@ grub_TRANSFORM([grub-mkrelpath])
+ grub_TRANSFORM([grub-mkrescue])
+ grub_TRANSFORM([grub-probe])
+ grub_TRANSFORM([grub-reboot])
++grub_TRANSFORM([grub-setpassword])
+ grub_TRANSFORM([grub-rpm-sort])
+ grub_TRANSFORM([grub-script-check])
+ grub_TRANSFORM([grub-set-default])
+diff --git a/Makefile.util.def b/Makefile.util.def
+index 3ac75720466..e2821a2f3a5 100644
+--- a/Makefile.util.def
++++ b/Makefile.util.def
+@@ -437,6 +437,12 @@ script = {
+   installdir = grubconf;
+ };
+ 
++script = {
++  name = '01_users';
++  common = util/grub.d/01_users.in;
++  installdir = grubconf;
++};
++
+ script = {
+   name = '10_windows';
+   common = util/grub.d/10_windows.in;
+@@ -712,6 +718,13 @@ script = {
+   installdir = sbin;
+ };
+ 
++script = {
++  name = grub-setpassword;
++  common = util/grub-setpassword.in;
++  mansection = 8;
++  installdir = sbin;
++};
++
+ script = {
+   name = grub-mkconfig_lib;
+   common = util/grub-mkconfig_lib.in;
+diff --git a/.gitignore b/.gitignore
+index b6c45776a4d..e49f76b114a 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -1,11 +1,7 @@
+-00_header
+-10_*
+-20_linux_xen
+-30_os-prober
+-40_custom
+-41_custom
+-*.1
+-*.8
++[[:digit:]][[:digit:]]_*
++!util/[[:digit:]][[:digit:]]_*.in
++*.[[:digit:]]
++!util/*.[[:digit:]]
+ aclocal.m4
+ ahci_test
+ ascii.bitmaps
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index bc26e7c109e..e029d0d5ea9 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -260,6 +260,8 @@ for i in "${grub_mkconfig_dir}"/* ; do
+     *~) ;;
+     # emacsen autosave files. FIXME: support other editors
+     */\#*\#) ;;
++    # rpm config files of yore.
++    *.rpmsave|*.rpmnew|*.rpmorig) ;;
+     *)
+       if grub_file_is_not_garbage "$i" && test -x "$i" ; then
+         echo
+diff --git a/util/grub-setpassword.8 b/util/grub-setpassword.8
+new file mode 100644
+index 00000000000..5973abef4ab
+--- /dev/null
++++ b/util/grub-setpassword.8
+@@ -0,0 +1,28 @@
++.TH GRUB-SETPASSWORD 3 "Thu Jun 25 2015"
++.SH NAME
++\fBgrub-setpassword\fR \(em Generate the user.cfg file containing the hashed grub bootloader password.
++
++.SH SYNOPSIS
++\fBgrub-setpassword\fR [OPTION]
++
++.SH DESCRIPTION
++\fBgrub-setpassword\fR outputs the user.cfg file which contains the hashed GRUB bootloader password. This utility only supports configurations where there is a single root user.
++
++The file has the format:
++GRUB_2PASSWORD=<\fIhashed password\fR>.
++
++.SH OPTIONS
++.TP
++-h, --help
++Display program usage and exit.
++.TP
++-v, --version
++Display the current version.
++.TP
++-o, --output[=\fIDIRECTORY PATH\fR]
++Choose the file path to which user.cfg will be written.
++
++.SH SEE ALSO
++.BR "info grub"
++
++.BR "info grub2-mkpasswd-pbkdf2"
+diff --git a/util/grub-setpassword.in b/util/grub-setpassword.in
+new file mode 100755
+index 00000000000..dd76f00fc0e
+--- /dev/null
++++ b/util/grub-setpassword.in
+@@ -0,0 +1,123 @@
++#!/bin/sh -e
++
++if [ -d /sys/firmware/efi/efivars/ ]; then
++    grubdir=`echo "/@bootdirname@/efi/EFI/redhat/" | sed 's,//*,/,g'`
++else
++    grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`
++fi
++
++PACKAGE_VERSION="@PACKAGE_VERSION@"
++PACKAGE_NAME="@PACKAGE_NAME@"
++self=`basename $0`
++bindir="@bindir@"
++grub_mkpasswd="${bindir}/@grub_mkpasswd_pbkdf2@"
++
++# Usage: usage
++# Print the usage.
++usage () {
++    cat <<EOF
++Usage: $0 [OPTION] [SOURCE]
++Run GRUB script in a Qemu instance.
++
++  -h, --help              print this message and exit
++  -v, --version           print the version information and exit
++  -o, --output_path       choose a custom output path for user.cfg
++
++$0 prompts the user to set a password on the grub bootloader. The password
++is written to a file named user.cfg.
++
++Report bugs at https://bugzilla.redhat.com.
++EOF
++}
++
++argument () {
++    opt=$1
++    shift
++
++    if test $# -eq 0; then
++        gettext_printf "%s: option requires an argument -- \`%s'\n" "$self" "$opt" 1>&2
++        exit 1
++    fi
++    echo $1
++}
++
++# Ensure that it's the root user running this script
++if [ "${EUID}" -ne 0 ]; then
++    echo "The grub bootloader password may only be set by root."
++    usage
++    exit 2
++fi
++
++# Check the arguments.
++while test $# -gt 0
++do
++    option=$1
++    shift
++
++    case "$option" in
++    -h | --help)
++	usage
++	exit 0 ;;
++    -v | --version)
++	echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
++	exit 0 ;;
++    -o | --output)
++        OUTPUT_PATH=`argument $option "$@"`; shift ;;
++    --output=*)
++        OUTPUT_PATH=`echo "$option" | sed 's/--output=//'` ;;
++    -o=*)
++        OUTPUT_PATH=`echo "$option" | sed 's/-o=//'` ;;
++    esac
++done
++
++# set user input or default path for user.cfg file
++if [ -z "${OUTPUT_PATH}" ]; then
++    OUTPUT_PATH="${grubdir}"
++fi
++
++if [ ! -d "${OUTPUT_PATH}" ]; then
++    echo "${OUTPUT_PATH} does not exist."
++    usage
++    exit 2;
++fi
++
++ttyopt=$(stty -g)
++fixtty() {
++      stty ${ttyopt}
++}
++
++trap fixtty EXIT
++stty -echo
++
++# prompt & confirm new grub2 root user password
++echo -n "Enter password: "
++read PASSWORD
++echo
++echo -n "Confirm password: "
++read PASSWORD_CONFIRM
++echo
++stty ${ttyopt}
++
++getpass() {
++    local P0
++    local P1
++    P0="$1" && shift
++    P1="$1" && shift
++
++    ( echo ${P0} ; echo ${P1} ) | \
++        ${grub_mkpasswd} | \
++        grep -v '[eE]nter password:' | \
++        sed -e "s/PBKDF2 hash of your password is //"
++}
++
++MYPASS="$(getpass "${PASSWORD}" "${PASSWORD_CONFIRM}")"
++if [ -z "${MYPASS}" ]; then
++      echo "${self}: error: empty password" 1>&2
++      exit 1
++fi
++
++# on the ESP, these will fail to set the permissions, but it's okay because
++# the directory is protected.
++install -m 0600 /dev/null "${grubdir}/user.cfg" 2>/dev/null || :
++chmod 0600 "${grubdir}/user.cfg" 2>/dev/null || :
++echo "GRUB2_PASSWORD=${MYPASS}" > "${grubdir}/user.cfg"
+diff --git a/util/grub.d/01_users.in b/util/grub.d/01_users.in
+new file mode 100644
+index 00000000000..facd409e722
+--- /dev/null
++++ b/util/grub.d/01_users.in
+@@ -0,0 +1,11 @@
++#!/bin/sh -e
++cat << EOF
++if [ -f \${prefix}/user.cfg ]; then
++  source \${prefix}/user.cfg
++  if [ -n \${GRUB2_PASSWORD} ]; then
++    set superusers="root"
++    export superusers
++    password_pbkdf2 root \${GRUB2_PASSWORD}
++  fi
++fi
++EOF
diff --git a/SOURCES/0179-Try-to-make-sure-configure.ac-and-grub-rpm-sort-play.patch b/SOURCES/0179-Try-to-make-sure-configure.ac-and-grub-rpm-sort-play.patch
new file mode 100644
index 0000000..eba3892
--- /dev/null
+++ b/SOURCES/0179-Try-to-make-sure-configure.ac-and-grub-rpm-sort-play.patch
@@ -0,0 +1,57 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 3 Aug 2015 11:46:42 -0400
+Subject: [PATCH] Try to make sure configure.ac and grub-rpm-sort play nice.
+
+Apparently the test for whether to use grub-rpm-sort and also the
+renaming of it to grub2-rpm-sort on the runtime side weren't right.
+
+Related: rhbz#1124074
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ configure.ac              | 2 +-
+ util/grub-mkconfig_lib.in | 9 ++++++---
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 273da6cb906..04c052dc610 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1549,7 +1549,7 @@ AC_SUBST([LIBDEVMAPPER])
+ AC_ARG_ENABLE([rpm-sort],
+               [AS_HELP_STRING([--enable-rpm-sort],
+                               [enable native rpm sorting of kernels in grub (default=guessed)])])
+-if test x"$enable_rpm-sort" = xno ; then
++if test x"$enable_rpm_sort" = xno ; then
+   rpm_sort_excuse="explicitly disabled"
+ fi
+ 
+diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
+index e85b60c322a..c67a319916a 100644
+--- a/util/grub-mkconfig_lib.in
++++ b/util/grub-mkconfig_lib.in
+@@ -33,6 +33,9 @@ fi
+ if test "x$grub_mkrelpath" = x; then
+   grub_mkrelpath="${bindir}/@grub_mkrelpath@"
+ fi
++if test "x$grub_rpm_sort" = x; then
++  grub_rpm_sort="${sbindir}/@grub_rpm_sort@"
++fi
+ 
+ if which gettext >/dev/null 2>/dev/null; then
+   :
+@@ -213,10 +216,10 @@ version_sort ()
+    esac
+ }
+ 
+-if [ "x$RPMLIB" = x ]; then
++if [ "x$grub_rpm_sort" != x -a -x "$grub_rpm_sort" ]; then
++  kernel_sort="$grub_rpm_sort"
++else
+   kernel_sort=version_sort
+-else
+-  kernel_sort="${sbindir}/grub-rpm-sort"
+ fi
+ 
+ version_test_numeric ()
diff --git a/SOURCES/0180-ppc64le-sync-mkconfig-to-disk-1212114.patch b/SOURCES/0180-ppc64le-sync-mkconfig-to-disk-1212114.patch
new file mode 100644
index 0000000..27a337b
--- /dev/null
+++ b/SOURCES/0180-ppc64le-sync-mkconfig-to-disk-1212114.patch
@@ -0,0 +1,39 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Don Zickus <dzickus@redhat.com>
+Date: Wed, 22 Jul 2015 13:59:55 -0400
+Subject: [PATCH] ppc64le sync mkconfig to disk (#1212114)
+
+If creating a new grub2 entry using grub2-mkconfig, the entry is not
+immediately sync'd to disk.  If a crash happens before the writeback,
+the subsequent reboot fails because the grub2.cfg is corrupted.
+
+Address this by forcing all the changes (mainly the fs meta data) to disk
+before finishing the grub2 conf changes.
+
+Tested by 'grub2-mkconfig -o /etc/grub22.cfg; echo c > /proc/sysrq-trigger'.
+
+Before, the machine would panic and on reboot be stuck without a grub.cfg
+to read.  After, works as expected.
+
+Resolves: rhbz#1212114
+---
+ util/grub-mkconfig.in | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index e029d0d5ea9..cf315e241f6 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -290,3 +290,12 @@ fi
+ 
+ gettext "done" >&2
+ echo >&2
++
++# make sure changes make it to the disk.
++# if /boot is a mountpoint, force the meta data on disk
++# to by-pass writeback delay.
++# PPC64LE-only to deal with Petitboot issues
++ARCH=$(uname -m)
++if [ "${ARCH}" = "ppc64le" ]; then
++    sync && mountpoint -q /boot &&fsfreeze -f /boot && fsfreeze -u /boot
++fi
diff --git a/SOURCES/0181-tcp-ack-when-we-get-an-OOO-lost-packet.patch b/SOURCES/0181-tcp-ack-when-we-get-an-OOO-lost-packet.patch
new file mode 100644
index 0000000..071bcbe
--- /dev/null
+++ b/SOURCES/0181-tcp-ack-when-we-get-an-OOO-lost-packet.patch
@@ -0,0 +1,34 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fb.com>
+Date: Wed, 12 Aug 2015 08:16:22 -0700
+Subject: [PATCH] tcp: ack when we get an OOO/lost packet
+
+While adding tcp window scaling support I was finding that I'd get some packet
+loss or reordering when transferring from large distances and grub would just
+timeout.  This is because we weren't ack'ing when we got our OOO packet, so the
+sender didn't know it needed to retransmit anything, so eventually it would fill
+the window and stop transmitting, and we'd time out.  Fix this by ACK'ing when
+we don't find our next sequence numbered packet.  With this fix I no longer time
+out.  Thanks,
+
+Signed-off-by: Josef Bacik <jbacik@fb.com>
+---
+ grub-core/net/tcp.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c
+index 2077f5519b2..fa29a2afc6c 100644
+--- a/grub-core/net/tcp.c
++++ b/grub-core/net/tcp.c
+@@ -882,7 +882,10 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb,
+ 	  grub_priority_queue_pop (sock->pq);
+ 	}
+       if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq)
+-	return GRUB_ERR_NONE;
++	{
++	  ack (sock);
++	  return GRUB_ERR_NONE;
++	}
+       while (1)
+ 	{
+ 	  nb_top_p = grub_priority_queue_top (sock->pq);
diff --git a/SOURCES/0182-tcp-add-window-scaling-support.patch b/SOURCES/0182-tcp-add-window-scaling-support.patch
new file mode 100644
index 0000000..4455fce
--- /dev/null
+++ b/SOURCES/0182-tcp-add-window-scaling-support.patch
@@ -0,0 +1,87 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fb.com>
+Date: Wed, 12 Aug 2015 08:57:55 -0700
+Subject: [PATCH] tcp: add window scaling support
+
+Sometimes we have to provision boxes across regions, such as California to
+Sweden.  The http server has a 10 minute timeout, so if we can't get our 250mb
+image transferred fast enough our provisioning fails, which is not ideal.  So
+add tcp window scaling on open connections and set the window size to 1mb.  With
+this change we're able to get higher sustained transfers between regions and can
+transfer our image in well below 10 minutes.  Without this patch we'd time out
+every time halfway through the transfer.  Thanks,
+
+Signed-off-by: Josef Bacik <jbacik@fb.com>
+---
+ grub-core/net/tcp.c | 42 +++++++++++++++++++++++++++++-------------
+ 1 file changed, 29 insertions(+), 13 deletions(-)
+
+diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c
+index fa29a2afc6c..c22ef033d6e 100644
+--- a/grub-core/net/tcp.c
++++ b/grub-core/net/tcp.c
+@@ -106,6 +106,18 @@ struct tcphdr
+   grub_uint16_t urgent;
+ } GRUB_PACKED;
+ 
++struct tcp_scale_opt {
++  grub_uint8_t kind;
++  grub_uint8_t length;
++  grub_uint8_t scale;
++} GRUB_PACKED;
++
++struct tcp_synhdr {
++  struct tcphdr tcphdr;
++  struct tcp_scale_opt scale_opt;
++  grub_uint8_t padding;
++};
++
+ struct tcp_pseudohdr
+ {
+   grub_uint32_t src;
+@@ -555,7 +567,7 @@ grub_net_tcp_open (char *server,
+   grub_net_tcp_socket_t socket;
+   static grub_uint16_t in_port = 21550;
+   struct grub_net_buff *nb;
+-  struct tcphdr *tcph;
++  struct tcp_synhdr *tcph;
+   int i;
+   grub_uint8_t *nbd;
+   grub_net_link_level_address_t ll_target_addr;
+@@ -617,20 +629,24 @@ grub_net_tcp_open (char *server,
+     }
+ 
+   tcph = (void *) nb->data;
++  grub_memset(tcph, 0, sizeof (*tcph));
+   socket->my_start_seq = grub_get_time_ms ();
+   socket->my_cur_seq = socket->my_start_seq + 1;
+-  socket->my_window = 8192;
+-  tcph->seqnr = grub_cpu_to_be32 (socket->my_start_seq);
+-  tcph->ack = grub_cpu_to_be32_compile_time (0);
+-  tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN);
+-  tcph->window = grub_cpu_to_be16 (socket->my_window);
+-  tcph->urgent = 0;
+-  tcph->src = grub_cpu_to_be16 (socket->in_port);
+-  tcph->dst = grub_cpu_to_be16 (socket->out_port);
+-  tcph->checksum = 0;
+-  tcph->checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP,
+-						   &socket->inf->address,
+-						   &socket->out_nla);
++  socket->my_window = 32768;
++  tcph->tcphdr.seqnr = grub_cpu_to_be32 (socket->my_start_seq);
++  tcph->tcphdr.ack = grub_cpu_to_be32_compile_time (0);
++  tcph->tcphdr.flags = grub_cpu_to_be16_compile_time ((6 << 12) | TCP_SYN);
++  tcph->tcphdr.window = grub_cpu_to_be16 (socket->my_window);
++  tcph->tcphdr.urgent = 0;
++  tcph->tcphdr.src = grub_cpu_to_be16 (socket->in_port);
++  tcph->tcphdr.dst = grub_cpu_to_be16 (socket->out_port);
++  tcph->tcphdr.checksum = 0;
++  tcph->scale_opt.kind = 3;
++  tcph->scale_opt.length = 3;
++  tcph->scale_opt.scale = 5;
++  tcph->tcphdr.checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP,
++							  &socket->inf->address,
++							  &socket->out_nla);
+ 
+   tcp_socket_register (socket);
+ 
diff --git a/SOURCES/0183-efinet-retransmit-if-our-device-is-busy.patch b/SOURCES/0183-efinet-retransmit-if-our-device-is-busy.patch
new file mode 100644
index 0000000..f932d7d
--- /dev/null
+++ b/SOURCES/0183-efinet-retransmit-if-our-device-is-busy.patch
@@ -0,0 +1,45 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fb.com>
+Date: Mon, 31 Aug 2015 13:34:35 -0400
+Subject: [PATCH] efinet: retransmit if our device is busy
+
+When I fixed the txbuf handling I ripped out the retransmission code since it
+was flooding our network when we had the buggy behavior.  Turns out this was too
+heavy handed as we can still have transient tx timeouts.  So instead make sure
+we retry our transmission once per timeout.  This way we can deal with transient
+transmission problems without flooding the box.  This fixes an issue we were
+seeing in production.  Thanks,
+
+Signed-off-by: Josef Bacik <jbacik@fb.com>
+---
+ grub-core/net/drivers/efi/efinet.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index ea0e0ca360e..c3a128cd1dc 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -38,6 +38,7 @@ send_card_buffer (struct grub_net_card *dev,
+   grub_efi_simple_network_t *net = dev->efi_net;
+   grub_uint64_t limit_time = grub_get_time_ms () + 4000;
+   void *txbuf;
++  int retry = 0;
+ 
+   if (dev->txbusy)
+     while (1)
+@@ -60,6 +61,15 @@ send_card_buffer (struct grub_net_card *dev,
+ 	    dev->txbusy = 0;
+ 	    break;
+ 	  }
++	if (!retry)
++	  {
++	    st = efi_call_7 (net->transmit, net, 0, dev->last_pkt_size,
++			     dev->txbuf, NULL, NULL, NULL);
++	    if (st != GRUB_EFI_SUCCESS)
++	      return grub_error (GRUB_ERR_IO,
++				 N_("couldn't send network packet"));
++	    retry = 1;
++	  }
+ 	if (limit_time < grub_get_time_ms ())
+ 	  return grub_error (GRUB_ERR_TIMEOUT,
+ 			     N_("couldn't send network packet"));
diff --git a/SOURCES/0184-efinet-add-filter-for-the-first-exclusive-reopen-of-.patch b/SOURCES/0184-efinet-add-filter-for-the-first-exclusive-reopen-of-.patch
new file mode 100644
index 0000000..8078da6
--- /dev/null
+++ b/SOURCES/0184-efinet-add-filter-for-the-first-exclusive-reopen-of-.patch
@@ -0,0 +1,44 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: RHEL Ninjas <example@example.com>
+Date: Fri, 25 Sep 2015 16:24:23 +0900
+Subject: [PATCH] efinet: add filter for the first exclusive reopen of SNP
+
+---
+ grub-core/net/drivers/efi/efinet.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index c3a128cd1dc..d8099a59855 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -407,6 +407,30 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+       if (net->mode->state == GRUB_EFI_NETWORK_STARTED
+ 	  && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS)
+ 	continue;
++
++      /* Enable hardware receive filters if driver declares support for it.
++	 We need unicast and broadcast and additionaly all nodes and
++	 solicited multicast for IPv6. Solicited multicast is per-IPv6
++	 address and we currently do not have API to do it so simply
++	 try to enable receive of all multicast packets or evertyhing in
++	 the worst case (i386 PXE driver always enables promiscuous too).
++
++	 This does trust firmware to do what it claims to do.
++       */
++      if (net->mode->receive_filter_mask)
++	{
++	  grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST   |
++				  GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
++				  GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
++
++	  filters &= net->mode->receive_filter_mask;
++	  if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST))
++	    filters |= (net->mode->receive_filter_mask &
++			GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS);
++
++	  efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL);
++	}
++
+       card->efi_net = net;
+     }
+     return;
diff --git a/SOURCES/0185-Fix-security-issue-when-reading-username-and-passwor.patch b/SOURCES/0185-Fix-security-issue-when-reading-username-and-passwor.patch
new file mode 100644
index 0000000..d000899
--- /dev/null
+++ b/SOURCES/0185-Fix-security-issue-when-reading-username-and-passwor.patch
@@ -0,0 +1,44 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Hector Marco-Gisbert <hecmargi@upv.es>
+Date: Fri, 13 Nov 2015 16:21:09 +0100
+Subject: [PATCH] Fix security issue when reading username and password
+
+  This patch fixes two integer underflows at:
+    * grub-core/lib/crypto.c
+    * grub-core/normal/auth.c
+
+Resolves: CVE-2015-8370
+
+Signed-off-by: Hector Marco-Gisbert <hecmargi@upv.es>
+Signed-off-by: Ismael Ripoll-Ripoll <iripoll@disca.upv.es>
+---
+ grub-core/lib/crypto.c  | 2 +-
+ grub-core/normal/auth.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c
+index 8e8426c4ab4..a23519cb3bd 100644
+--- a/grub-core/lib/crypto.c
++++ b/grub-core/lib/crypto.c
+@@ -456,7 +456,7 @@ grub_password_get (char buf[], unsigned buf_size)
+ 	  break;
+ 	}
+ 
+-      if (key == '\b')
++      if (key == '\b' && cur_len)
+ 	{
+ 	  cur_len--;
+ 	  continue;
+diff --git a/grub-core/normal/auth.c b/grub-core/normal/auth.c
+index c6bd96e28ec..5782ec5a940 100644
+--- a/grub-core/normal/auth.c
++++ b/grub-core/normal/auth.c
+@@ -172,7 +172,7 @@ grub_username_get (char buf[], unsigned buf_size)
+ 	  break;
+ 	}
+ 
+-      if (key == '\b')
++      if (key == '\b' && cur_len)
+ 	{
+ 	  cur_len--;
+ 	  grub_printf ("\b");
diff --git a/SOURCES/0186-01_users-Handle-GRUB_PASSWORD-better.patch b/SOURCES/0186-01_users-Handle-GRUB_PASSWORD-better.patch
new file mode 100644
index 0000000..88ef564
--- /dev/null
+++ b/SOURCES/0186-01_users-Handle-GRUB_PASSWORD-better.patch
@@ -0,0 +1,42 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Fri, 4 Dec 2015 09:28:38 -0500
+Subject: [PATCH] 01_users: Handle GRUB_PASSWORD better.
+
+Only handle GRUB_PASSWORD not GRUB2_PASSWORD (as that's more likely to
+be acceptable upstream).
+
+Related: rhbz#1284370
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ util/grub-setpassword.8 | 2 +-
+ util/grub.d/01_users.in | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/util/grub-setpassword.8 b/util/grub-setpassword.8
+index 5973abef4ab..49200a848b7 100644
+--- a/util/grub-setpassword.8
++++ b/util/grub-setpassword.8
+@@ -9,7 +9,7 @@
+ \fBgrub-setpassword\fR outputs the user.cfg file which contains the hashed GRUB bootloader password. This utility only supports configurations where there is a single root user.
+ 
+ The file has the format:
+-GRUB_2PASSWORD=<\fIhashed password\fR>.
++GRUB2_PASSWORD=<\fIhashed password\fR>.
+ 
+ .SH OPTIONS
+ .TP
+diff --git a/util/grub.d/01_users.in b/util/grub.d/01_users.in
+index facd409e722..db2f44bfb78 100644
+--- a/util/grub.d/01_users.in
++++ b/util/grub.d/01_users.in
+@@ -2,7 +2,7 @@
+ cat << EOF
+ if [ -f \${prefix}/user.cfg ]; then
+   source \${prefix}/user.cfg
+-  if [ -n \${GRUB2_PASSWORD} ]; then
++  if [ -n "\${GRUB2_PASSWORD}" ]; then
+     set superusers="root"
+     export superusers
+     password_pbkdf2 root \${GRUB2_PASSWORD}
diff --git a/SOURCES/0187-Failed-config-now-returns-exit-code-1252311.patch b/SOURCES/0187-Failed-config-now-returns-exit-code-1252311.patch
new file mode 100644
index 0000000..f82c897
--- /dev/null
+++ b/SOURCES/0187-Failed-config-now-returns-exit-code-1252311.patch
@@ -0,0 +1,25 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Fri, 29 Jan 2016 14:49:24 -0500
+Subject: [PATCH] Failed config now returns exit code (#1252311)
+
+Grub would notify the user if the new config was invalid, however, it
+did not exit properly with exit code 1. Added the proper exit code.
+
+Resolves: rhbz#1252311
+---
+ util/grub-mkconfig.in | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index cf315e241f6..7db89499949 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -281,6 +281,7 @@ Ensure that there are no errors in /etc/default/grub
+ and /etc/grub.d/* files or please file a bug report with
+ %s file attached." "${grub_cfg}.new" >&2
+     echo >&2
++    exit 1
+   else
+     # none of the children aborted with error, install the new grub.cfg
+     cat ${grub_cfg}.new > ${grub_cfg}
diff --git a/SOURCES/0188-Warn-if-grub-password-will-not-be-read-1290803.patch b/SOURCES/0188-Warn-if-grub-password-will-not-be-read-1290803.patch
new file mode 100644
index 0000000..4baf91a
--- /dev/null
+++ b/SOURCES/0188-Warn-if-grub-password-will-not-be-read-1290803.patch
@@ -0,0 +1,28 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Mon, 22 Feb 2016 15:30:05 -0500
+Subject: [PATCH] Warn if grub password will not be read (#1290803)
+
+It is possible for a system to have never run grub-mkconfig and add the
+section that reads the user.cfg file which contains a user set GRUB
+password. Users in that scenario will now be warned that grub-mkconfig
+must be run prior to their newly set password taking effect.
+
+Resolves: rhbz#1290803
+---
+ util/grub-setpassword.in | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/util/grub-setpassword.in b/util/grub-setpassword.in
+index dd76f00fc0e..fb9d3a3b6f9 100755
+--- a/util/grub-setpassword.in
++++ b/util/grub-setpassword.in
+@@ -121,3 +121,8 @@ fi
+ install -m 0600 /dev/null "${grubdir}/user.cfg" 2>/dev/null || :
+ chmod 0600 "${grubdir}/user.cfg" 2>/dev/null || :
+ echo "GRUB2_PASSWORD=${MYPASS}" > "${grubdir}/user.cfg"
++
++if ! grep -q "^### BEGIN /etc/grub.d/01_users ###$" "${grubdir}/grub.cfg"; then
++    echo "WARNING: The current configuration lacks password support!"
++    echo "Update your configuration with @grub_mkconfig@ to support this feature."
++fi
diff --git a/SOURCES/0189-Clean-up-grub-setpassword-documentation-1290799.patch b/SOURCES/0189-Clean-up-grub-setpassword-documentation-1290799.patch
new file mode 100644
index 0000000..b5ad6ec
--- /dev/null
+++ b/SOURCES/0189-Clean-up-grub-setpassword-documentation-1290799.patch
@@ -0,0 +1,55 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Tue, 26 Jan 2016 10:28:35 -0500
+Subject: [PATCH] Clean up grub-setpassword documentation (#1290799)
+
+The output for --help had some errors. Corrected those and polished the
+text to be a little easier to follow. Carried verbage over to man page
+to maintain internal consistency.
+
+Resolves: rhbz#1290799
+---
+ util/grub-setpassword.8  |  2 +-
+ util/grub-setpassword.in | 15 +++++++--------
+ 2 files changed, 8 insertions(+), 9 deletions(-)
+
+diff --git a/util/grub-setpassword.8 b/util/grub-setpassword.8
+index 49200a848b7..dc91dd6697b 100644
+--- a/util/grub-setpassword.8
++++ b/util/grub-setpassword.8
+@@ -19,7 +19,7 @@ Display program usage and exit.
+ -v, --version
+ Display the current version.
+ .TP
+--o, --output[=\fIDIRECTORY PATH\fR]
++-o, --output=<\fIDIRECTORY\fR>
+ Choose the file path to which user.cfg will be written.
+ 
+ .SH SEE ALSO
+diff --git a/util/grub-setpassword.in b/util/grub-setpassword.in
+index fb9d3a3b6f9..c8c0fa4199d 100755
+--- a/util/grub-setpassword.in
++++ b/util/grub-setpassword.in
+@@ -16,15 +16,14 @@ grub_mkpasswd="${bindir}/@grub_mkpasswd_pbkdf2@"
+ # Print the usage.
+ usage () {
+     cat <<EOF
+-Usage: $0 [OPTION] [SOURCE]
+-Run GRUB script in a Qemu instance.
+-
+-  -h, --help              print this message and exit
+-  -v, --version           print the version information and exit
+-  -o, --output_path       choose a custom output path for user.cfg
+-
++Usage: $0 [OPTION]
+ $0 prompts the user to set a password on the grub bootloader. The password
+-is written to a file named user.cfg.
++is written to a file named user.cfg which lives in the GRUB directory
++located by default at ${grubdir}.
++
++  -h, --help                     print this message and exit
++  -v, --version                  print the version information and exit
++  -o, --output_path <DIRECTORY>  put user.cfg in a user-selected directory
+ 
+ Report bugs at https://bugzilla.redhat.com.
+ EOF
diff --git a/SOURCES/0190-Fix-locale-issue-in-grub-setpassword-1294243.patch b/SOURCES/0190-Fix-locale-issue-in-grub-setpassword-1294243.patch
new file mode 100644
index 0000000..4ab663d
--- /dev/null
+++ b/SOURCES/0190-Fix-locale-issue-in-grub-setpassword-1294243.patch
@@ -0,0 +1,27 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Fri, 29 Jan 2016 16:56:11 -0500
+Subject: [PATCH] Fix locale issue in grub-setpassword (#1294243)
+
+A shell substitution was expecting non-translated output to grab the
+hashed password and put it in the user.cfg file. Modified code to force
+the generic C locale when this particular piece of code is run.
+
+Resolves: rhbz#1294243
+---
+ util/grub-setpassword.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/util/grub-setpassword.in b/util/grub-setpassword.in
+index c8c0fa4199d..d7924af5192 100755
+--- a/util/grub-setpassword.in
++++ b/util/grub-setpassword.in
+@@ -104,7 +104,7 @@ getpass() {
+     P1="$1" && shift
+ 
+     ( echo ${P0} ; echo ${P1} ) | \
+-        ${grub_mkpasswd} | \
++        LC_ALL=C ${grub_mkpasswd} | \
+         grep -v '[eE]nter password:' | \
+         sed -e "s/PBKDF2 hash of your password is //"
+ }
diff --git a/SOURCES/0191-efi-really-mark-memory-of-unknown-type-as-reserved.patch b/SOURCES/0191-efi-really-mark-memory-of-unknown-type-as-reserved.patch
new file mode 100644
index 0000000..70dfa71
--- /dev/null
+++ b/SOURCES/0191-efi-really-mark-memory-of-unknown-type-as-reserved.patch
@@ -0,0 +1,66 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Thu, 26 Nov 2015 19:50:42 +0300
+Subject: [PATCH] efi: really mark memory of unknown type as reserved
+
+9be4c45dbe3c877d1f4856e99ee15133c6cd2261 added switch case between
+fall through cases, causing all memory regions of unknown type to be
+marked as available.
+
+Move default case into its own block and add explicit FALLTHROUGH
+annotation.
+
+Reported by Elliott, Robert (Persistent Memory) <elliott@hpe.com>
+
+(cherry picked from commit 3d2c8048da7db334fd6d57b27304ac765fd4cd67)
+
+Resolves: rhbz#1288608
+---
+ grub-core/mmap/efi/mmap.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/mmap/efi/mmap.c b/grub-core/mmap/efi/mmap.c
+index a77efe81d0c..900a4d6598c 100644
+--- a/grub-core/mmap/efi/mmap.c
++++ b/grub-core/mmap/efi/mmap.c
+@@ -73,6 +73,7 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data,
+ 		    GRUB_MEMORY_AVAILABLE, hook_data);
+ 	      break;
+ 	    }
++	  /* FALLTHROUGH */
+ 	case GRUB_EFI_RUNTIME_SERVICES_CODE:
+ 	  hook (desc->physical_start, desc->num_pages * 4096,
+ 		GRUB_MEMORY_CODE, hook_data);
+@@ -83,10 +84,6 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data,
+ 		GRUB_MEMORY_BADRAM, hook_data);
+ 	  break;
+ 
+-	default:
+-	  grub_printf ("Unknown memory type %d, considering reserved\n",
+-		       desc->type);
+-
+ 	case GRUB_EFI_BOOT_SERVICES_DATA:
+ 	  if (!avoid_efi_boot_services)
+ 	    {
+@@ -94,6 +91,7 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data,
+ 		    GRUB_MEMORY_AVAILABLE, hook_data);
+ 	      break;
+ 	    }
++	  /* FALLTHROUGH */
+ 	case GRUB_EFI_RESERVED_MEMORY_TYPE:
+ 	case GRUB_EFI_RUNTIME_SERVICES_DATA:
+ 	case GRUB_EFI_MEMORY_MAPPED_IO:
+@@ -119,6 +117,13 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data,
+ 	  hook (desc->physical_start, desc->num_pages * 4096,
+ 		GRUB_MEMORY_NVS, hook_data);
+ 	  break;
++
++	default:
++	  grub_printf ("Unknown memory type %d, considering reserved\n",
++		       desc->type);
++	  hook (desc->physical_start, desc->num_pages * 4096,
++		GRUB_MEMORY_RESERVED, hook_data);
++	  break;
+ 	}
+     }
+ 
diff --git a/SOURCES/0192-Translate-UEFI-persistent-memory-type.patch b/SOURCES/0192-Translate-UEFI-persistent-memory-type.patch
new file mode 100644
index 0000000..20d2adc
--- /dev/null
+++ b/SOURCES/0192-Translate-UEFI-persistent-memory-type.patch
@@ -0,0 +1,100 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Elliott <elliott@hpe.com>
+Date: Thu, 3 Dec 2015 11:38:36 -0600
+Subject: [PATCH] Translate UEFI persistent memory type
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Define
+* GRUB_EFI_PERSISTENT_MEMORY (UEFI memory map type 14) per UEFI 2.5
+* GRUB_MEMORY_PERSISTENT (E820 type 7) per ACPI 3.0
+* GRUB_MEMORY_PERSISTENT_LEGACY (E820 unofficial type 12) per ACPI 3.0
+
+and translate GRUB_EFI_PERSISTENT_MEMORY to GRUB_MEMORY_PERSISTENT in
+grub_efi_mmap_iterate().
+
+Includes
+* adding the E820 names to lsmmap
+* handling the E820 types in make_efi_memtype()
+
+Suggested-by: Vladimir 'φ-coder/phcoder' Serbinenko <phcoder@gmail.com>
+Suggested-by: Andrei Borzenkov <arvidjaar@gmail.com>
+(cherry picked from commit 76ce1de740f202985ffd7b2e980cf34c75a2dac3)
+
+Resolves: rhbz#1288608
+---
+ grub-core/commands/lsmmap.c |  2 ++
+ grub-core/mmap/efi/mmap.c   | 12 ++++++++++++
+ include/grub/efi/api.h      |  1 +
+ include/grub/memory.h       |  2 ++
+ 4 files changed, 17 insertions(+)
+
+diff --git a/grub-core/commands/lsmmap.c b/grub-core/commands/lsmmap.c
+index 4b504fd28f8..816ee47d1ed 100644
+--- a/grub-core/commands/lsmmap.c
++++ b/grub-core/commands/lsmmap.c
+@@ -37,6 +37,8 @@ static const char *names[] =
+        is required to save accross hibernations.  */
+     [GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage RAM"),
+     [GRUB_MEMORY_BADRAM] = N_("faulty RAM (BadRAM)"),
++    [GRUB_MEMORY_PERSISTENT] = N_("persistent RAM"),
++    [GRUB_MEMORY_PERSISTENT_LEGACY] = N_("persistent RAM (legacy)"),
+     [GRUB_MEMORY_COREBOOT_TABLES] = N_("RAM holding coreboot tables"),
+     [GRUB_MEMORY_CODE] = N_("RAM holding firmware code")
+   };
+diff --git a/grub-core/mmap/efi/mmap.c b/grub-core/mmap/efi/mmap.c
+index 900a4d6598c..bd495a18481 100644
+--- a/grub-core/mmap/efi/mmap.c
++++ b/grub-core/mmap/efi/mmap.c
+@@ -118,6 +118,11 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data,
+ 		GRUB_MEMORY_NVS, hook_data);
+ 	  break;
+ 
++	case GRUB_EFI_PERSISTENT_MEMORY:
++	  hook (desc->physical_start, desc->num_pages * 4096,
++		GRUB_MEMORY_PERSISTENT, hook_data);
++	break;
++
+ 	default:
+ 	  grub_printf ("Unknown memory type %d, considering reserved\n",
+ 		       desc->type);
+@@ -147,6 +152,13 @@ make_efi_memtype (int type)
+       /* No way to remove a chunk of memory from EFI mmap.
+ 	 So mark it as unusable. */
+     case GRUB_MEMORY_HOLE:
++    /*
++     * AllocatePages() does not support GRUB_EFI_PERSISTENT_MEMORY,
++     * so no translation for GRUB_MEMORY_PERSISTENT or
++     * GRUB_MEMORY_PERSISTENT_LEGACY.
++     */
++    case GRUB_MEMORY_PERSISTENT:
++    case GRUB_MEMORY_PERSISTENT_LEGACY:
+     case GRUB_MEMORY_RESERVED:
+       return GRUB_EFI_UNUSABLE_MEMORY;
+ 
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 029ee92f5d0..551d93e50a3 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -431,6 +431,7 @@ enum grub_efi_memory_type
+     GRUB_EFI_MEMORY_MAPPED_IO,
+     GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE,
+     GRUB_EFI_PAL_CODE,
++    GRUB_EFI_PERSISTENT_MEMORY,
+     GRUB_EFI_MAX_MEMORY_TYPE
+   };
+ typedef enum grub_efi_memory_type grub_efi_memory_type_t;
+diff --git a/include/grub/memory.h b/include/grub/memory.h
+index 083cfb6802e..6da114a1bdc 100644
+--- a/include/grub/memory.h
++++ b/include/grub/memory.h
+@@ -30,6 +30,8 @@ typedef enum grub_memory_type
+     GRUB_MEMORY_ACPI = 3,
+     GRUB_MEMORY_NVS = 4,
+     GRUB_MEMORY_BADRAM = 5,
++    GRUB_MEMORY_PERSISTENT = 7,
++    GRUB_MEMORY_PERSISTENT_LEGACY = 12,
+     GRUB_MEMORY_COREBOOT_TABLES = 16,
+     GRUB_MEMORY_CODE = 20,
+     /* This one is special: it's used internally but is never reported
diff --git a/SOURCES/0193-lsefimmap-support-persistent-memory-and-other-UEFI-2.patch b/SOURCES/0193-lsefimmap-support-persistent-memory-and-other-UEFI-2.patch
new file mode 100644
index 0000000..0d4791d
--- /dev/null
+++ b/SOURCES/0193-lsefimmap-support-persistent-memory-and-other-UEFI-2.patch
@@ -0,0 +1,181 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Elliott <elliott@hpe.com>
+Date: Thu, 17 Dec 2015 10:53:32 -0600
+Subject: [PATCH] lsefimmap: support persistent memory and other UEFI 2.5
+ features
+
+This should accompany
+	76ce1de740 Translate UEFI persistent memory type
+
+1. Add a string for the EfiPersistentMemory type 14 that was
+added in UEFI 2.5.
+
+2. Decode the memory attributes that were added in UEFI 2.5:
+* NV (non-volatile)
+* MORE_RELIABLE (higher reliable, e.g., mirrored memory in a system
+  with partial memory mirroring)
+* RO (read-only)
+
+3. Use proper IEC binary units (KiB, MiB, etc.) for power-of-two
+values rather than misusing SI power-of-ten units (KB, MB, etc.)
+
+4. The lsmmap command only decodes memory ranges sizes up to GiB scale
+units.  Persistent memory ranges will reach into the TiB scale.
+Since 64-bit size field supports TiB, PiB, and EiB, decode all of
+them for completeness.
+
+5. In the lsefimmap command, rewrite the print statements to
+* avoid rounding
+* avoid a big nested if/else tree.
+
+For example: In the sixth entry below, the value of 309MB implies
+316416KB but is really reporting 316436KB.
+
+Widen the size column to 6 digits to accommodate typical cases.
+The worst case value would require 14 digits; if that happens,
+let the columns get out of sync.
+
+Old format:
+Type      Physical start  - end             #Pages     Size Attributes
+conv-mem  0000000000000000-0000000000092fff 00000093  588KB UC WC WT WB
+reserved  0000000000093000-0000000000093fff 00000001    4KB UC WC WT WB
+conv-mem  0000000000094000-000000000009ffff 0000000c   48KB UC WC WT WB
+conv-mem  0000000000100000-000000000fffffff 0000ff00  255MB UC WC WT WB
+BS-code   0000000010000000-0000000010048fff 00000049  292KB UC WC WT WB
+conv-mem  0000000010049000-000000002354dfff 00013505  309MB UC WC WT WB
+ldr-data  000000002354e000-000000003ecfffff 0001b7b2  439MB UC WC WT WB
+BS-data   000000003ed00000-000000003ed7ffff 00000080  512KB UC WC WT WB
+conv-mem  000000003ed80000-000000006af5ffff 0002c1e0  705MB UC WC WT WB
+reserved  000000006af60000-000000006b55ffff 00000600    6MB UC WC WT WB
+BS-data   000000006b560000-000000006b560fff 00000001    4KB UC WC WT WB
+RT-data   000000006b561000-000000006b5e1fff 00000081  516KB RT UC WC WT WB
+BS-data   000000006b5e2000-000000006ecfafff 00003719   55MB UC WC WT WB
+BS-code   000000006ecfb000-000000006ecfbfff 00000001    4KB UC WC WT WB
+conv-mem  000000006ecfc000-00000000711fafff 000024ff   36MB UC WC WT WB
+BS-data   00000000711fb000-000000007128dfff 00000093  588KB UC WC WT WB
+Unk 0d    0000000880000000-0000000e7fffffff 00600000   24GB UC WC WT WB NV
+reserved  0000001680000000-0000001c7fffffff 00600000   24GB UC WC WT WB NV
+
+New format:
+Type      Physical start  - end             #Pages        Size Attributes
+conv-mem  0000000000000000-0000000000092fff 00000093    588KiB UC WC WT WB
+reserved  0000000000093000-0000000000093fff 00000001      4KiB UC WC WT WB
+conv-mem  0000000000094000-000000000009ffff 0000000c     48KiB UC WC WT WB
+conv-mem  0000000000100000-000000000fffffff 0000ff00    255MiB UC WC WT WB
+BS-code   0000000010000000-0000000010048fff 00000049    292KiB UC WC WT WB
+conv-mem  0000000010049000-000000002354dfff 00013505 316436KiB UC WC WT WB
+ldr-data  000000002354e000-000000003ecfffff 0001b7b2 450248KiB UC WC WT WB
+BS-data   000000003ed00000-000000003ed7ffff 00000080    512KiB UC WC WT WB
+conv-mem  000000003ed80000-000000006af5ffff 0002c1e0 722816KiB UC WC WT WB
+reserved  000000006af60000-000000006b55ffff 00000600      6MiB UC WC WT WB
+BS-data   000000006b560000-000000006b560fff 00000001      4KiB UC WC WT WB
+RT-data   000000006b561000-000000006b5e1fff 00000081    516KiB RT UC WC WT WB
+BS-data   000000006b5e2000-000000006ecfafff 00003719  56420KiB UC WC WT WB
+BS-code   000000006ecfb000-000000006ecfbfff 00000001      4KiB UC WC WT WB
+conv-mem  000000006ecfc000-0000000071222fff 00002527  38044KiB UC WC WT WB
+BS-data   0000000071223000-00000000712ddfff 000000bb    748KiB UC WC WT WB
+persist   0000000880000000-0000000e7fffffff 00600000     24GiB UC WC WT WB NV
+reserved  0000001680000000-0000001c7fffffff 00600000     24GiB UC WC WT WB NV
+
+(cherry picked from commit c79c59f1295df8ea660f8a858f9532d76a5f67b7)
+
+Resolves: rhbz#1288608
+---
+ grub-core/commands/efi/lsefimmap.c | 47 +++++++++++++++++++++++++-------------
+ include/grub/efi/api.h             |  3 +++
+ 2 files changed, 34 insertions(+), 16 deletions(-)
+
+diff --git a/grub-core/commands/efi/lsefimmap.c b/grub-core/commands/efi/lsefimmap.c
+index 215b45bff80..c85ff7f366d 100644
+--- a/grub-core/commands/efi/lsefimmap.c
++++ b/grub-core/commands/efi/lsefimmap.c
+@@ -51,7 +51,7 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
+ 
+   grub_printf
+     ("Type      Physical start  - end             #Pages   "
+-     "  Size Attributes\n");
++     "     Size Attributes\n");
+   memory_map_end = ADD_MEMORY_DESCRIPTOR (memory_map, map_size);
+   for (desc = memory_map;
+        desc < memory_map_end;
+@@ -74,7 +74,8 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
+ 	  "ACPI-nvs",
+ 	  "MMIO    ",
+ 	  "IO-ports",
+-	  "PAL-code"
++	  "PAL-code",
++	  "persist ",
+ 	};
+       if (desc->type < ARRAY_SIZE (types_str))
+ 	grub_printf ("%s ", types_str[desc->type]);
+@@ -87,21 +88,29 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
+ 		   desc->physical_start + (desc->num_pages << 12) - 1,
+ 		   desc->num_pages);
+ 
+-      size = desc->num_pages;
+-      size <<= (12 - 10);
+-      if (size < 1024)
+-	grub_printf (" %4" PRIuGRUB_UINT64_T "KB", size);
++      size = desc->num_pages << 12;	/* 4 KiB page size */
++      /*
++       * Since size is a multiple of 4 KiB, no need to handle units
++       * of just Bytes (which would use a mask of 0x3ff).
++       *
++       * 14 characters would support the largest possible number of 4 KiB
++       * pages that are not a multiple of larger units (e.g., MiB):
++       * 17592186044415 (0xffffff_fffff000), but that uses a lot of
++       * whitespace for a rare case.  6 characters usually suffices;
++       * columns will be off if not, but this is preferable to rounding.
++       */
++      if (size & 0xfffff)
++	grub_printf (" %6" PRIuGRUB_UINT64_T "KiB", size >> 10);
++      else if (size & 0x3fffffff)
++	grub_printf (" %6" PRIuGRUB_UINT64_T "MiB", size >> 20);
++      else if (size & 0xffffffffff)
++	grub_printf (" %6" PRIuGRUB_UINT64_T "GiB", size >> 30);
++      else if (size & 0x3ffffffffffff)
++	grub_printf (" %6" PRIuGRUB_UINT64_T "TiB", size >> 40);
++      else if (size & 0xfffffffffffffff)
++	grub_printf (" %6" PRIuGRUB_UINT64_T "PiB", size >> 50);
+       else
+-	{
+-	  size /= 1024;
+-	  if (size < 1024)
+-	    grub_printf (" %4" PRIuGRUB_UINT64_T "MB", size);
+-	  else
+-	    {
+-	      size /= 1024;
+-	      grub_printf (" %4" PRIuGRUB_UINT64_T "GB", size);
+-	    }
+-	}
++	grub_printf (" %6" PRIuGRUB_UINT64_T "EiB", size >> 60);
+ 
+       attr = desc->attribute;
+       if (attr & GRUB_EFI_MEMORY_RUNTIME)
+@@ -122,6 +131,12 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
+ 	grub_printf (" RP");
+       if (attr & GRUB_EFI_MEMORY_XP)
+ 	grub_printf (" XP");
++      if (attr & GRUB_EFI_MEMORY_NV)
++	grub_printf (" NV");
++      if (attr & GRUB_EFI_MEMORY_MORE_RELIABLE)
++	grub_printf (" MR");
++      if (attr & GRUB_EFI_MEMORY_RO)
++	grub_printf (" RO");
+ 
+       grub_printf ("\n");
+     }
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 551d93e50a3..a6cce6e3395 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -49,6 +49,9 @@
+ #define GRUB_EFI_MEMORY_WP	0x0000000000001000LL
+ #define GRUB_EFI_MEMORY_RP	0x0000000000002000LL
+ #define GRUB_EFI_MEMORY_XP	0x0000000000004000LL
++#define GRUB_EFI_MEMORY_NV	0x0000000000008000LL
++#define GRUB_EFI_MEMORY_MORE_RELIABLE	0x0000000000010000LL
++#define GRUB_EFI_MEMORY_RO	0x0000000000020000LL
+ #define GRUB_EFI_MEMORY_RUNTIME	0x8000000000000000LL
+ 
+ #define GRUB_EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL	0x00000001
diff --git a/SOURCES/0194-efiemu-Handle-persistent-RAM-and-unknown-possible-fu.patch b/SOURCES/0194-efiemu-Handle-persistent-RAM-and-unknown-possible-fu.patch
new file mode 100644
index 0000000..4f4b7f9
--- /dev/null
+++ b/SOURCES/0194-efiemu-Handle-persistent-RAM-and-unknown-possible-fu.patch
@@ -0,0 +1,84 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Elliott <elliott@hpe.com>
+Date: Fri, 22 Jan 2016 13:32:30 +0100
+Subject: [PATCH] efiemu: Handle persistent RAM and unknown possible future
+ additions.
+
+(cherry picked from commit ae3b83a4d4df75a01198a2fed7542391e7c449e0)
+
+Resolves: rhbz#1288608
+---
+ grub-core/efiemu/mm.c | 25 ++++++++++++++++++++++---
+ 1 file changed, 22 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c
+index d4a4f3aad6d..13af4ad0dd8 100644
+--- a/grub-core/efiemu/mm.c
++++ b/grub-core/efiemu/mm.c
+@@ -99,7 +99,8 @@ grub_efiemu_request_memalign (grub_size_t align, grub_size_t size,
+   grub_size_t align_overhead;
+   struct grub_efiemu_memrequest *ret, *cur, *prev;
+   /* Check that the request is correct */
+-  if (type >= GRUB_EFI_MAX_MEMORY_TYPE || type <= GRUB_EFI_LOADER_CODE)
++  if (type <= GRUB_EFI_LOADER_CODE || type == GRUB_EFI_PERSISTENT_MEMORY ||
++	type >= GRUB_EFI_MAX_MEMORY_TYPE)
+     return -2;
+ 
+   /* Add new size to requested size */
+@@ -166,6 +167,13 @@ efiemu_alloc_requests (void)
+       GRUB_EFI_MEMORY_MAPPED_IO,
+       GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE,
+       GRUB_EFI_PAL_CODE
++
++      /*
++       * These are not allocatable:
++       * GRUB_EFI_RESERVED_MEMORY_TYPE
++       * GRUB_EFI_PERSISTENT_MEMORY
++       * >= GRUB_EFI_MAX_MEMORY_TYPE
++       */
+     };
+ 
+   /* Compute total memory needed */
+@@ -402,6 +410,10 @@ fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
+ 	return grub_efiemu_add_to_mmap (addr, size,
+ 					GRUB_EFI_ACPI_MEMORY_NVS);
+ 
++      case GRUB_MEMORY_PRAM:
++      case GRUB_MEMORY_PMEM:
++	return grub_efiemu_add_to_mmap (addr, size,
++					GRUB_EFI_PERSISTENT_MEMORY);
+       default:
+ 	grub_dprintf ("efiemu",
+ 		      "Unknown memory type %d. Assuming unusable\n", type);
+@@ -445,7 +457,7 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
+       case GRUB_EFI_MEMORY_MAPPED_IO:
+       case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE:
+       case GRUB_EFI_PAL_CODE:
+-      case GRUB_EFI_MAX_MEMORY_TYPE:
++      default:
+ 	hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
+ 	      GRUB_MEMORY_RESERVED, hook_data);
+ 	break;
+@@ -468,6 +480,12 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
+ 	hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
+ 	      GRUB_MEMORY_NVS, hook_data);
+ 	break;
++
++      case GRUB_EFI_PERSISTENT_MEMORY:
++	hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
++	      GRUB_MEMORY_PMEM, hook_data);
++	break;
++
+       }
+ 
+   return 0;
+@@ -503,7 +521,8 @@ grub_efiemu_mmap_sort_and_uniq (void)
+       [GRUB_EFI_ACPI_MEMORY_NVS] = 3,
+       [GRUB_EFI_MEMORY_MAPPED_IO] = 4,
+       [GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE] = 4,
+-      [GRUB_EFI_PAL_CODE] = 4
++      [GRUB_EFI_PAL_CODE] = 4,
++      [GRUB_EFI_PERSISTENT_MEMORY] = 4
+     };
+ 
+   int i, j, k, done;
diff --git a/SOURCES/0195-efiemu-Fix-compilation-failure.patch b/SOURCES/0195-efiemu-Fix-compilation-failure.patch
new file mode 100644
index 0000000..40d83ed
--- /dev/null
+++ b/SOURCES/0195-efiemu-Fix-compilation-failure.patch
@@ -0,0 +1,36 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 22 Jan 2016 14:10:30 +0100
+Subject: [PATCH] efiemu: Fix compilation failure
+
+(cherry picked from commit b6a03dfd327489d53ee07c6d7d593b99c7b7cb62)
+
+Resolves: rhbz#1288608
+---
+ grub-core/efiemu/mm.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c
+index 13af4ad0dd8..e606dbffc92 100644
+--- a/grub-core/efiemu/mm.c
++++ b/grub-core/efiemu/mm.c
+@@ -410,8 +410,8 @@ fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
+ 	return grub_efiemu_add_to_mmap (addr, size,
+ 					GRUB_EFI_ACPI_MEMORY_NVS);
+ 
+-      case GRUB_MEMORY_PRAM:
+-      case GRUB_MEMORY_PMEM:
++      case GRUB_MEMORY_PERSISTENT:
++      case GRUB_MEMORY_PERSISTENT_LEGACY:
+ 	return grub_efiemu_add_to_mmap (addr, size,
+ 					GRUB_EFI_PERSISTENT_MEMORY);
+       default:
+@@ -483,7 +483,7 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
+ 
+       case GRUB_EFI_PERSISTENT_MEMORY:
+ 	hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
+-	      GRUB_MEMORY_PMEM, hook_data);
++	      GRUB_MEMORY_PERSISTENT, hook_data);
+ 	break;
+ 
+       }
diff --git a/SOURCES/0196-devmapper-getroot-use-makedev-instead-of-direct-shif.patch b/SOURCES/0196-devmapper-getroot-use-makedev-instead-of-direct-shif.patch
new file mode 100644
index 0000000..fe265df
--- /dev/null
+++ b/SOURCES/0196-devmapper-getroot-use-makedev-instead-of-direct-shif.patch
@@ -0,0 +1,30 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Sat, 7 Nov 2015 09:46:46 +0300
+Subject: [PATCH] devmapper/getroot: use makedev instead of direct shift
+
+Fixes device detection with large number of devices.
+
+Reported by Tim Wallberg <twalberg@comcast.net>
+
+(cherry picked from commit 349a381df0ce2e809506f7b166bf952f97407330)
+
+Resolves: rhbz#1279599
+---
+ grub-core/osdep/devmapper/getroot.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/grub-core/osdep/devmapper/getroot.c b/grub-core/osdep/devmapper/getroot.c
+index d02386b3498..de32102322b 100644
+--- a/grub-core/osdep/devmapper/getroot.c
++++ b/grub-core/osdep/devmapper/getroot.c
+@@ -204,8 +204,7 @@ grub_util_devmapper_part_to_disk (struct stat *st,
+ 					 &major, &minor, 0))
+     {
+       *is_part = 1;
+-      return grub_find_device ("/dev",
+-			       (major << 8) | minor);
++      return grub_find_device ("/dev", makedev (major, minor));
+     }
+   *is_part = 0;
+   return xstrdup (path);
diff --git a/SOURCES/0197-loader-linux-do-not-pad-initrd-with-zeroes-at-the-en.patch b/SOURCES/0197-loader-linux-do-not-pad-initrd-with-zeroes-at-the-en.patch
new file mode 100644
index 0000000..429a49c
--- /dev/null
+++ b/SOURCES/0197-loader-linux-do-not-pad-initrd-with-zeroes-at-the-en.patch
@@ -0,0 +1,69 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Thu, 7 May 2015 20:24:24 +0300
+Subject: [PATCH] loader/linux: do not pad initrd with zeroes at the end
+
+Syslinux memdisk is using initrd image and needs to know uncompressed
+size in advance. For gzip uncompressed size is at the end of compressed
+stream. Grub padded each input file to 4 bytes at the end, which means
+syslinux got wrong size.
+
+Linux initramfs loader apparently does not care about trailing alignment.
+So change code to align beginning of each file instead which atomatically
+gives us the correct size for single file.
+
+Reported-By: David Shaw <dshaw@jabberwocky.com>
+
+(cherry picked from commit a8c473288d3f0a5e17a903a5121dea1a695dda3b)
+
+Resolves: rhbz#1219864
+---
+ grub-core/loader/linux.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
+index 117232f0c95..d2cd591f604 100644
+--- a/grub-core/loader/linux.c
++++ b/grub-core/loader/linux.c
+@@ -161,6 +161,9 @@ grub_initrd_init (int argc, char *argv[],
+   for (i = 0; i < argc; i++)
+     {
+       const char *fname = argv[i];
++
++      initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4);
++
+       if (grub_memcmp (argv[i], "newc:", 5) == 0)
+ 	{
+ 	  const char *ptr, *eptr;
+@@ -205,7 +208,7 @@ grub_initrd_init (int argc, char *argv[],
+       initrd_ctx->nfiles++;
+       initrd_ctx->components[i].size
+ 	= grub_file_size (initrd_ctx->components[i].file);
+-      initrd_ctx->size += ALIGN_UP (initrd_ctx->components[i].size, 4);
++      initrd_ctx->size += initrd_ctx->components[i].size;
+     }
+ 
+   if (newc)
+@@ -248,10 +251,12 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
+   int i;
+   int newc = 0;
+   struct dir *root = 0;
++  grub_ssize_t cursize = 0;
+ 
+   for (i = 0; i < initrd_ctx->nfiles; i++)
+     {
+-      grub_ssize_t cursize;
++      grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
++      ptr += ALIGN_UP_OVERHEAD (cursize, 4);
+ 
+       if (initrd_ctx->components[i].newc_name)
+ 	{
+@@ -283,8 +288,6 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
+ 	  return grub_errno;
+ 	}
+       ptr += cursize;
+-      grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
+-      ptr += ALIGN_UP_OVERHEAD (cursize, 4);
+     }
+   if (newc)
+     ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0);
diff --git a/SOURCES/0198-Revert-reopen-SNP-protocol-for-exclusive-use-by-grub.patch b/SOURCES/0198-Revert-reopen-SNP-protocol-for-exclusive-use-by-grub.patch
new file mode 100644
index 0000000..11ffa6d
--- /dev/null
+++ b/SOURCES/0198-Revert-reopen-SNP-protocol-for-exclusive-use-by-grub.patch
@@ -0,0 +1,73 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 7 Apr 2016 10:58:06 -0400
+Subject: [PATCH] Revert "reopen SNP protocol for exclusive use by grub"
+
+I *think* this should have been replaced by upstream's
+49426e9fd2e562c73a4f1206f32eff9e424a1a73, so I'm reverting for now.
+
+May resolve rhbz#1273974.
+
+This reverts commit 147daeab22db793978f952b6f0d832919a1b0081.
+---
+ grub-core/net/drivers/efi/efinet.c | 40 --------------------------------------
+ 1 file changed, 40 deletions(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index d8099a59855..3f112438a93 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -340,7 +340,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ {
+   struct grub_net_card *card;
+   grub_efi_device_path_t *dp;
+-  grub_efi_simple_network_t *net;
+ 
+   dp = grub_efi_get_device_path (hnd);
+   if (! dp)
+@@ -394,45 +393,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 				    &pxe_mode->dhcp_ack,
+ 				    sizeof (pxe_mode->dhcp_ack),
+ 				    1, device, path);
+-    net = grub_efi_open_protocol (card->efi_handle, &net_io_guid,
+-				  GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE);
+-    if (net) {
+-      if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
+-	  && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS)
+-	continue;
+-
+-      if (net->mode->state == GRUB_EFI_NETWORK_STOPPED)
+-	continue;
+-
+-      if (net->mode->state == GRUB_EFI_NETWORK_STARTED
+-	  && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS)
+-	continue;
+-
+-      /* Enable hardware receive filters if driver declares support for it.
+-	 We need unicast and broadcast and additionaly all nodes and
+-	 solicited multicast for IPv6. Solicited multicast is per-IPv6
+-	 address and we currently do not have API to do it so simply
+-	 try to enable receive of all multicast packets or evertyhing in
+-	 the worst case (i386 PXE driver always enables promiscuous too).
+-
+-	 This does trust firmware to do what it claims to do.
+-       */
+-      if (net->mode->receive_filter_mask)
+-	{
+-	  grub_uint32_t filters = GRUB_EFI_SIMPLE_NETWORK_RECEIVE_UNICAST   |
+-				  GRUB_EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
+-				  GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
+-
+-	  filters &= net->mode->receive_filter_mask;
+-	  if (!(filters & GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST))
+-	    filters |= (net->mode->receive_filter_mask &
+-			GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS);
+-
+-	  efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL);
+-	}
+-
+-      card->efi_net = net;
+-    }
+     return;
+   }
+ }
diff --git a/SOURCES/0199-Add-a-url-parser.patch b/SOURCES/0199-Add-a-url-parser.patch
new file mode 100644
index 0000000..f04ab41
--- /dev/null
+++ b/SOURCES/0199-Add-a-url-parser.patch
@@ -0,0 +1,1016 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 14 Jun 2016 16:18:44 -0400
+Subject: [PATCH] Add a url parser.
+
+This patch adds a url parser that can parse http, https, tftp, and tftps
+urls, and is easily extensible to handle more types.
+
+It's a little ugly in terms of the arguments it takes.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/Makefile.core.def |   1 +
+ grub-core/kern/misc.c       |  13 +
+ grub-core/net/url.c         | 856 ++++++++++++++++++++++++++++++++++++++++++++
+ include/grub/misc.h         |  45 +++
+ include/grub/net/url.h      |  28 ++
+ 5 files changed, 943 insertions(+)
+ create mode 100644 grub-core/net/url.c
+ create mode 100644 include/grub/net/url.h
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 9378c732981..d73ea6f6c51 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -2103,6 +2103,7 @@ module = {
+   common = net/ethernet.c;
+   common = net/arp.c;
+   common = net/netbuff.c;
++  common = net/url.c;
+ };
+ 
+ module = {
+diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
+index a3e5056db3f..392c697db03 100644
+--- a/grub-core/kern/misc.c
++++ b/grub-core/kern/misc.c
+@@ -325,6 +325,19 @@ grub_strrchr (const char *s, int c)
+   return p;
+ }
+ 
++char *
++grub_strchrnul (const char *s, int c)
++{
++  do
++    {
++      if (*s == c)
++	break;
++    }
++  while (*s++);
++
++  return (char *) s;
++}
++
+ int
+ grub_strword (const char *haystack, const char *needle)
+ {
+diff --git a/grub-core/net/url.c b/grub-core/net/url.c
+new file mode 100644
+index 00000000000..537019f2c78
+--- /dev/null
++++ b/grub-core/net/url.c
+@@ -0,0 +1,856 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2016  Free Software Foundation, Inc.
++ *
++ *  GRUB 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 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifdef URL_TEST
++
++#define _GNU_SOURCE 1
++
++#include <errno.h>
++#include <limits.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++#include <unistd.h>
++
++#define N_(x) x
++
++#define grub_malloc(x) malloc(x)
++#define grub_free(x) ({if (x) free(x);})
++#define grub_error(a, fmt, args...) printf(fmt "\n", ## args)
++#define grub_dprintf(a, fmt, args...) printf(a ": " fmt, ## args)
++#define grub_strlen(x) strlen(x)
++#define grub_strdup(x) strdup(x)
++#define grub_strstr(x,y) strstr(x,y)
++#define grub_memcpy(x,y,z) memcpy(x,y,z)
++#define grub_strcmp(x,y) strcmp(x,y)
++#define grub_strncmp(x,y,z) strncmp(x,y,z)
++#define grub_strcasecmp(x,y) strcasecmp(x,y)
++#define grub_strchrnul(x,y) strchrnul(x,y)
++#define grub_strchr(x,y) strchr(x,y)
++#define grub_strndup(x,y) strndup(x,y)
++#define grub_strtoul(x,y,z) strtoul(x,y,z)
++#define grub_memmove(x,y,z) memmove(x,y,z)
++#define grub_size_t size_t
++#define grub_errno errno
++
++#else
++#include <grub/types.h>
++#include <grub/mm.h>
++#include <grub/misc.h>
++#include <grub/net/url.h>
++#endif
++
++static char *
++translate_slashes(char *str)
++{
++  int i, j;
++  if (str == NULL)
++    return str;
++
++  for (i = 0, j = 0; str[i] != '\0'; i++, j++)
++    {
++      if (str[i] == '\\')
++	{
++	  str[j] = '/';
++	  if (str[i+1] == '\\')
++	    i++;
++	}
++    }
++
++  return str;
++}
++
++static inline int
++hex2int (char c)
++{
++  if (c >= '0' && c <= '9')
++    return c - '0';
++  c |= 0x20;
++  if (c >= 'a' && c <= 'f')
++    return c - 'a' + 10;
++  return -1;
++}
++
++static int
++url_unescape (char *buf, grub_size_t len)
++{
++  int c, rc;
++  unsigned int i;
++
++
++  if (len < 3)
++    {
++      for (i = 0; i < len; i++)
++	if (buf[i] == '%')
++	  return -1;
++      return 0;
++    }
++
++  for (i = 0; len > 2 && i < len - 2; i++)
++    {
++      if (buf[i] == '%')
++	{
++	  unsigned int j;
++	  for (j = i+1; j < i+3; j++)
++	    {
++	      if (!(buf[j] >= '0' && buf[j] <= '9') &&
++		  !(buf[j] >= 'a' && buf[j] <= 'f') &&
++		  !(buf[j] >= 'A' && buf[j] <= 'F'))
++		return -1;
++	    }
++	  i += 2;
++	}
++    }
++  if (i == len - 2)
++    {
++      if (buf[i+1] == '%' || buf[i+2] == '%')
++	return -1;
++    }
++  for (i = 0; i < len - 2; i++)
++    {
++      if (buf[i] == '%')
++	{
++	  rc = hex2int (buf[i+1]);
++	  if (rc < 0)
++	    return -1;
++	  c = (rc & 0xf) << 4;
++	  rc = hex2int (buf[i+2]);
++	  if (rc < 0)
++	    return -1;
++	  c |= (rc & 0xf);
++
++	  buf[i] = c;
++	  grub_memmove (buf+i+1, buf+i+3, len-(i+2));
++	  len -= 2;
++	}
++    }
++  return 0;
++}
++
++static int
++extract_http_url_info (char *url, int ssl,
++		       char **userinfo, char **host, int *port,
++		       char **file)
++{
++  char *colon, *slash, *query, *at = NULL, *separator, *auth_end;
++
++  char *userinfo_off = NULL;
++  char *userinfo_end;
++  char *host_off = NULL;
++  char *host_end;
++  char *port_off = NULL;
++  char *port_end;
++  char *file_off = NULL;
++
++  grub_size_t l;
++  int c;
++
++  if (!url || !userinfo || !host || !port || !file)
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument");
++
++  *userinfo = *host = *file = NULL;
++  *port = -1;
++
++  userinfo_off = url;
++
++  slash = grub_strchrnul (userinfo_off, '/');
++  query = grub_strchrnul (userinfo_off, '?');
++  auth_end = slash < query ? slash : query;
++  /* auth_end here is one /past/ the last character in the auth section, i.e.
++   * it's the : or / or NUL */
++
++  separator = grub_strchrnul (userinfo_off, '@');
++  if (separator > auth_end)
++    {
++      host_off = userinfo_off;
++      userinfo_off = NULL;
++      userinfo_end = NULL;
++    }
++  else
++    {
++      at = separator;
++      *separator = '\0';
++      userinfo_end = separator;
++      host_off = separator + 1;
++    }
++
++  if (*host_off == '[')
++    {
++      separator = grub_strchrnul (host_off, ']');
++      if (separator >= auth_end)
++	goto fail;
++
++      separator += 1;
++      host_end = separator;
++    }
++  else
++    {
++      host_end = separator = colon = grub_strchrnul (host_off, ':');
++
++      if (colon > auth_end)
++	{
++	  separator = NULL;
++	  host_end = auth_end;
++	}
++    }
++
++  if (separator && separator < auth_end)
++    {
++      if (*separator == ':')
++	{
++	  port_off = separator + 1;
++	  port_end = auth_end;
++
++	  if (auth_end - port_end > 0)
++	    goto fail;
++	  if (port_end - port_off < 1)
++	    goto fail;
++	}
++      else
++	goto fail;
++    }
++
++  file_off = auth_end;
++  if (port_off)
++    {
++      unsigned long portul;
++
++      separator = NULL;
++      c = *port_end;
++      *port_end = '\0';
++
++      portul = grub_strtoul (port_off, &separator, 10);
++      *port_end = c;
++#ifdef URL_TEST
++      if (portul == ULONG_MAX && errno == ERANGE)
++	goto fail;
++#else
++      if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
++	goto fail;
++#endif
++      if (portul & ~0xfffful)
++	goto fail;
++      if (separator != port_end)
++	goto fail;
++
++      *port = portul & 0xfffful;
++    }
++  else if (ssl)
++    *port = 443;
++  else
++    *port = 80;
++
++  if (userinfo_off && *userinfo_off)
++    {
++      l = userinfo_end - userinfo_off + 1;
++
++      *userinfo = grub_strndup (userinfo_off, l);
++      if (!*userinfo)
++	goto fail;
++      (*userinfo)[l-1]= '\0';
++    }
++
++  l = host_end - host_off;
++  c = *host_end;
++  *host_end = '\0';
++  *host = grub_strndup (host_off, l);
++  *host_end = c;
++  if (!*host)
++    goto fail;
++  (*host)[l] = '\0';
++
++  *file = grub_strdup (file_off);
++  if (!*file)
++    goto fail;
++
++  if (at)
++    *at = '@';
++  return 0;
++fail:
++  if (at)
++    *at = '@';
++  grub_free (*userinfo);
++  grub_free (*host);
++  grub_free (*file);
++
++  return -1;
++}
++
++static int
++extract_tftp_url_info (char *url, int ssl, char **host, char **file, int *port)
++{
++  char *slash, *semi;
++
++  char *host_off = url;
++  char *host_end;
++  char *file_off;
++
++  int c;
++
++  if (!url || !host || !file || !port)
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument");
++
++  if (ssl)
++    *port = 3713;
++  else
++    *port = 69;
++
++  slash = grub_strchr (url, '/');
++  if (!slash)
++    return -1;
++
++  host_end = file_off = slash;
++
++  semi = grub_strchrnul (slash, ';');
++  if (!grub_strncmp (semi, ";mode=", 6) && grub_strcmp (semi+6, "octet"))
++    {
++      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
++		  N_("TFTP mode `%s' is not implemented."), semi+6);
++      return -1;
++    }
++
++  /*
++   * Maybe somebody added a new method, I dunno.  Anyway, semi is a reserved
++   * character, so if it's there, it's the start of the mode block or it's
++   * invalid.  So set it to \0 unconditionally, not just for ;mode=octet
++   */
++  *semi = '\0';
++
++  c = *host_end;
++  *host_end = '\0';
++  *host = grub_strdup (host_off);
++  *host_end = c;
++
++  *file = grub_strdup (file_off);
++
++  if (!*file || !*host)
++    {
++      grub_free (*file);
++      grub_free (*host);
++      return -1;
++    }
++
++  return 0;
++}
++
++int
++extract_url_info (const char *urlbuf, grub_size_t buflen,
++		  char **scheme, char **userinfo,
++		  char **host, int *port, char **file)
++{
++  char *url;
++  char *colon;
++
++  char *scheme_off;
++  char *specific_off;
++
++  int rc;
++  int c;
++
++  int https;
++
++  if (!urlbuf || !buflen || !scheme || !userinfo || !host || !port || !file)
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument");
++
++  *scheme = *userinfo = *host = *file = NULL;
++  *port = -1;
++
++  /* make sure we have our own coherent grub_string. */
++  url = grub_malloc (buflen + 1);
++  if (!url)
++    return -1;
++
++  grub_memcpy (url, urlbuf, buflen);
++  url[buflen] = '\0';
++
++  grub_dprintf ("net", "dhcpv6 boot-file-url: `%s'\n", url);
++
++  /* get rid of any backslashes */
++  url = translate_slashes (url);
++
++  /* find the constituent parts */
++  colon = grub_strstr (url, "://");
++  if (!colon)
++    goto fail;
++
++  scheme_off = url;
++  c = *colon;
++  *colon = '\0';
++  specific_off = colon + 3;
++
++  https = !grub_strcasecmp (scheme_off, "https");
++
++  rc = 0;
++  if (!grub_strcasecmp (scheme_off, "tftp"))
++    {
++      rc = extract_tftp_url_info (specific_off, 0, host, file, port);
++    }
++#ifdef URL_TEST
++  else if (!grub_strcasecmp (scheme_off, "http") || https)
++#else
++  else if (!grub_strcasecmp (scheme_off, "http"))
++#endif
++    {
++      rc = extract_http_url_info (specific_off,
++				  https, userinfo, host, port, file);
++    }
++#ifdef URL_TEST
++  else if (!grub_strcasecmp (scheme_off, "iscsi"))
++    {
++      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
++		  N_("Unimplemented URL scheme `%s'"), scheme_off);
++      *colon = c;
++      goto fail;
++    }
++  else if (!grub_strcasecmp (scheme_off, "tftps"))
++    {
++      rc = extract_tftp_url_info (specific_off, 1, host, file, port);
++    }
++#endif
++  else
++    {
++      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
++		  N_("Unimplemented URL scheme `%s'"), scheme_off);
++      *colon = c;
++      goto fail;
++    }
++
++  if (rc < 0)
++    {
++      *colon = c;
++      goto fail;
++    }
++
++  *scheme = grub_strdup (scheme_off);
++  *colon = c;
++  if (!*scheme)
++    goto fail;
++
++  if (*userinfo)
++    {
++      rc = url_unescape (*userinfo, grub_strlen (*userinfo));
++      if (rc < 0)
++	goto fail;
++    }
++
++  if (*host)
++    {
++      rc = url_unescape (*host, grub_strlen (*host));
++      if (rc < 0)
++	goto fail;
++    }
++
++  if (*file)
++    {
++      rc = url_unescape (*file, grub_strlen (*file));
++      if (rc < 0)
++	goto fail;
++    }
++
++  grub_free (url);
++  return 0;
++fail:
++  grub_free (*scheme);
++  grub_free (*userinfo);
++  grub_free (*host);
++  grub_free (*file);
++
++  if (!grub_errno)
++    grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("Invalid boot-file-url `%s'"),
++		url);
++  grub_free (url);
++  return -1;
++}
++
++#ifdef URL_TEST
++
++struct test {
++    char *url;
++    int rc;
++    char *scheme;
++    char *userinfo;
++    char *host;
++    int port;
++    char *file;
++} tests[] = {
++  {.url = "http://foo.example.com/",
++   .rc = 0,
++   .scheme = "http",
++   .host = "foo.example.com",
++   .port = 80,
++   .file = "/",
++  },
++  {.url = "http://foo.example.com/?foobar",
++   .rc = 0,
++   .scheme = "http",
++   .host = "foo.example.com",
++   .port = 80,
++   .file = "/?foobar",
++  },
++  {.url = "http://[foo.example.com/",
++   .rc = -1,
++  },
++  {.url = "http://[foo.example.com/?foobar",
++   .rc = -1,
++  },
++  {.url = "http://foo.example.com:/",
++   .rc = -1,
++  },
++  {.url = "http://foo.example.com:81/",
++   .rc = 0,
++   .scheme = "http",
++   .host = "foo.example.com",
++   .port = 81,
++   .file = "/",
++  },
++  {.url = "http://foo.example.com:81/?foobar",
++   .rc = 0,
++   .scheme = "http",
++   .host = "foo.example.com",
++   .port = 81,
++   .file = "/?foobar",
++  },
++  {.url = "http://[1234::1]/",
++   .rc = 0,
++   .scheme = "http",
++   .host = "[1234::1]",
++   .port = 80,
++   .file = "/",
++  },
++  {.url = "http://[1234::1]/?foobar",
++   .rc = 0,
++   .scheme = "http",
++   .host = "[1234::1]",
++   .port = 80,
++   .file = "/?foobar",
++  },
++  {.url = "http://[1234::1]:81/",
++   .rc = 0,
++   .scheme = "http",
++   .host = "[1234::1]",
++   .port = 81,
++   .file = "/",
++  },
++  {.url = "http://[1234::1]:81/?foobar",
++   .rc = 0,
++   .scheme = "http",
++   .host = "[1234::1]",
++   .port = 81,
++   .file = "/?foobar",
++  },
++  {.url = "http://foo@foo.example.com/",
++   .rc = 0,
++   .scheme = "http",
++   .userinfo = "foo",
++   .host = "foo.example.com",
++   .port = 80,
++   .file = "/",
++  },
++  {.url = "http://foo@foo.example.com/?foobar",
++   .rc = 0,
++   .scheme = "http",
++   .userinfo = "foo",
++   .host = "foo.example.com",
++   .port = 80,
++   .file = "/?foobar",
++  },
++  {.url = "http://foo@[foo.example.com/",
++   .rc = -1,
++  },
++  {.url = "http://foo@[foo.example.com/?foobar",
++   .rc = -1,
++  },
++  {.url = "http://foo@foo.example.com:81/",
++   .rc = 0,
++   .scheme = "http",
++   .userinfo = "foo",
++   .host = "foo.example.com",
++   .port = 81,
++   .file = "/",
++  },
++  {.url = "http://foo@foo.example.com:81/?foobar",
++   .rc = 0,
++   .scheme = "http",
++   .userinfo = "foo",
++   .host = "foo.example.com",
++   .port = 81,
++   .file = "/?foobar",
++  },
++  {.url = "http://foo@[1234::1]/",
++   .rc = 0,
++   .scheme = "http",
++   .userinfo = "foo",
++   .host = "[1234::1]",
++   .port = 80,
++   .file = "/",
++  },
++  {.url = "http://foo@[1234::1]/?foobar",
++   .rc = 0,
++   .scheme = "http",
++   .userinfo = "foo",
++   .host = "[1234::1]",
++   .port = 80,
++   .file = "/?foobar",
++  },
++  {.url = "http://foo@[1234::1]:81/",
++   .rc = 0,
++   .scheme = "http",
++   .userinfo = "foo",
++   .host = "[1234::1]",
++   .port = 81,
++   .file = "/",
++  },
++  {.url = "http://foo@[1234::1]:81/?foobar",
++   .rc = 0,
++   .scheme = "http",
++   .userinfo = "foo",
++   .host = "[1234::1]",
++   .port = 81,
++   .file = "/?foobar",
++  },
++  {.url = "https://foo.example.com/",
++   .rc = 0,
++   .scheme = "https",
++   .host = "foo.example.com",
++   .port = 443,
++   .file = "/",
++  },
++  {.url = "https://foo.example.com/?foobar",
++   .rc = 0,
++   .scheme = "https",
++   .host = "foo.example.com",
++   .port = 443,
++   .file = "/?foobar",
++  },
++  {.url = "https://[foo.example.com/",
++   .rc = -1,
++  },
++  {.url = "https://[foo.example.com/?foobar",
++   .rc = -1,
++  },
++  {.url = "https://foo.example.com:81/",
++   .rc = 0,
++   .scheme = "https",
++   .host = "foo.example.com",
++   .port = 81,
++   .file = "/",
++  },
++  {.url = "https://foo.example.com:81/?foobar",
++   .rc = 0,
++   .scheme = "https",
++   .host = "foo.example.com",
++   .port = 81,
++   .file = "/?foobar",
++  },
++  {.url = "https://[1234::1]/",
++   .rc = 0,
++   .scheme = "https",
++   .host = "[1234::1]",
++   .port = 443,
++   .file = "/",
++  },
++  {.url = "https://[1234::1]/?foobar",
++   .rc = 0,
++   .scheme = "https",
++   .host = "[1234::1]",
++   .port = 443,
++   .file = "/?foobar",
++  },
++  {.url = "https://[1234::1]:81/",
++   .rc = 0,
++   .scheme = "https",
++   .host = "[1234::1]",
++   .port = 81,
++   .file = "/",
++  },
++  {.url = "https://[1234::1]:81/?foobar",
++   .rc = 0,
++   .scheme = "https",
++   .host = "[1234::1]",
++   .port = 81,
++   .file = "/?foobar",
++  },
++  {.url = "https://foo@foo.example.com/",
++   .rc = 0,
++   .scheme = "https",
++   .userinfo = "foo",
++   .host = "foo.example.com",
++   .port = 443,
++   .file = "/",
++  },
++  {.url = "https://foo@foo.example.com/?foobar",
++   .rc = 0,
++   .scheme = "https",
++   .userinfo = "foo",
++   .host = "foo.example.com",
++   .port = 443,
++   .file = "/?foobar",
++  },
++  {.url = "https://foo@[foo.example.com/",
++   .rc = -1,
++  },
++  {.url = "https://f%6fo@[foo.example.com/?fooba%72",
++   .rc = -1,
++  },
++  {.url = "https://foo@foo.example.com:81/",
++   .rc = 0,
++   .scheme = "https",
++   .userinfo = "foo",
++   .host = "foo.example.com",
++   .port = 81,
++   .file = "/",
++  },
++  {.url = "https://foo@foo.example.com:81/?foobar",
++   .rc = 0,
++   .scheme = "https",
++   .userinfo = "foo",
++   .host = "foo.example.com",
++   .port = 81,
++   .file = "/?foobar",
++  },
++  {.url = "https://foo@[1234::1]/",
++   .rc = 0,
++   .scheme = "https",
++   .userinfo = "foo",
++   .host = "[1234::1]",
++   .port = 443,
++   .file = "/",
++  },
++  {.url = "https://foo@[1234::1]/?foobar",
++   .rc = 0,
++   .scheme = "https",
++   .userinfo = "foo",
++   .host = "[1234::1]",
++   .port = 443,
++   .file = "/?foobar",
++  },
++  {.url = "https://f%6fo@[12%334::1]:81/",
++   .rc = 0,
++   .scheme = "https",
++   .userinfo = "foo",
++   .host = "[1234::1]",
++   .port = 81,
++   .file = "/",
++  },
++  {.url = "https://foo@[1234::1]:81/?foobar",
++   .rc = 0,
++   .scheme = "https",
++   .userinfo = "foo",
++   .host = "[1234::1]",
++   .port = 81,
++   .file = "/?foobar",
++  },
++  {.url = "tftp://foo.e%78ample.com/foo/bar/b%61%7a",
++   .rc = 0,
++   .scheme = "tftp",
++   .host = "foo.example.com",
++   .port = 69,
++   .file = "/foo/bar/baz",
++  },
++  {.url = "tftp://foo.example.com/foo/bar/baz",
++   .rc = 0,
++   .scheme = "tftp",
++   .host = "foo.example.com",
++   .port = 69,
++   .file = "/foo/bar/baz",
++  },
++  {.url = "tftps://foo.example.com/foo/bar/baz",
++   .rc = 0,
++   .scheme = "tftps",
++   .host = "foo.example.com",
++   .port = 3713,
++   .file = "/foo/bar/baz",
++  },
++  {.url = "tftps://foo.example.com/foo/bar/baz;mode=netascii",
++   .rc = -1,
++  },
++  {.url = "tftps://foo.example.com/foo/bar/baz;mode=octet",
++   .rc = 0,
++   .scheme = "tftps",
++   .host = "foo.example.com",
++   .port = 3713,
++   .file = "/foo/bar/baz",
++  },
++  {.url = "tftps://foo.example.com/foo/bar/baz;mode=invalid",
++   .rc = -1,
++  },
++  {.url = "",
++  },
++};
++
++static int
++string_test (char *name, char *a, char *b)
++{
++  if ((a && !b) || (!a && b))
++    {
++      printf("expected %s \"%s\", got \"%s\"\n", name, a, b);
++      return -1;
++    }
++  if (a && b && strcmp(a, b))
++    {
++      printf("expected %s \"%s\", got \"%s\"\n", name, a, b);
++      return -1;
++    }
++  return 0;
++}
++
++int
++main(void)
++{
++	unsigned int i;
++	int rc;
++
++	for (i = 0; tests[i].url[0] != '\0'; i++)
++	{
++		char *scheme, *userinfo, *host, *file;
++		int port;
++
++		printf("======= url: \"%s\"\n", tests[i].url);
++		rc = extract_url_info(tests[i].url, strlen(tests[i].url) + 1,
++				      &scheme, &userinfo, &host, &port, &file);
++		if (tests[i].rc != rc)
++		  {
++		    printf("  extract_url_info(...) = %d\n", rc);
++		    exit(1);
++		  }
++		else if (rc >= 0)
++		  {
++		    if (string_test("scheme", tests[i].scheme, scheme) < 0)
++		      exit(1);
++		    if (string_test("userinfo", tests[i].userinfo, userinfo) < 0)
++		      exit(1);
++		    if (string_test("host", tests[i].host, host) < 0)
++		      exit(1);
++		    if (port != tests[i].port)
++		      {
++			printf("  bad port \"%d\" should have been \"%d\"\n",
++			       port, tests[i].port);
++			exit(1);
++		      }
++		    if (string_test("file", tests[i].file, file) < 0)
++		      exit(1);
++		  }
++		free(scheme);
++		free(userinfo);
++		free(host);
++		free(file);
++	}
++	printf("everything worked?!?\n");
++}
++#endif
+diff --git a/include/grub/misc.h b/include/grub/misc.h
+index c6cd4564d86..34250291908 100644
+--- a/include/grub/misc.h
++++ b/include/grub/misc.h
+@@ -104,6 +104,7 @@ int EXPORT_FUNC(grub_strncmp) (const char *s1, const char *s2, grub_size_t n);
+ 
+ char *EXPORT_FUNC(grub_strchr) (const char *s, int c);
+ char *EXPORT_FUNC(grub_strrchr) (const char *s, int c);
++char *EXPORT_FUNC(grub_strchrnul) (const char *s, int c);
+ int EXPORT_FUNC(grub_strword) (const char *s, const char *w);
+ 
+ /* Copied from gnulib.
+@@ -226,6 +227,50 @@ grub_toupper (int c)
+   return c;
+ }
+ 
++static inline char *
++grub_strcasestr (const char *haystack, const char *needle)
++{
++  /* Be careful not to look at the entire extent of haystack or needle
++     until needed.  This is useful because of these two cases:
++       - haystack may be very long, and a match of needle found early,
++       - needle may be very long, and not even a short initial segment of
++       needle may be found in haystack.  */
++  if (*needle != '\0')
++    {
++      /* Speed up the following searches of needle by caching its first
++	 character.  */
++      char b = *needle++;
++
++      for (;; haystack++)
++	{
++	  if (*haystack == '\0')
++	    /* No match.  */
++	    return 0;
++	  if (grub_tolower(*haystack) == grub_tolower(b))
++	    /* The first character matches.  */
++	    {
++	      const char *rhaystack = haystack + 1;
++	      const char *rneedle = needle;
++
++	      for (;; rhaystack++, rneedle++)
++		{
++		  if (*rneedle == '\0')
++		    /* Found a match.  */
++		    return (char *) haystack;
++		  if (*rhaystack == '\0')
++		    /* No match.  */
++		    return 0;
++		  if (grub_tolower(*rhaystack) != grub_tolower(*rneedle))
++		    /* Nothing in this round.  */
++		    break;
++		}
++	    }
++	}
++    }
++  else
++    return (char *) haystack;
++}
++
+ static inline int
+ grub_strcasecmp (const char *s1, const char *s2)
+ {
+diff --git a/include/grub/net/url.h b/include/grub/net/url.h
+new file mode 100644
+index 00000000000..a215fa27d0a
+--- /dev/null
++++ b/include/grub/net/url.h
+@@ -0,0 +1,28 @@
++/* url.h - prototypes for url parsing functions */
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2016  Free Software Foundation, Inc.
++ *
++ *  GRUB 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 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef GRUB_URL_HEADER
++#define GRUB_URL_HEADER	1
++
++int
++EXPORT_FUNC(extract_url_info) (const char *urlbuf, grub_size_t buflen,
++			       char **scheme, char **userinfo,
++			       char **host, int *port, char **file);
++
++#endif /* GRUB_URL_HEADER */
diff --git a/SOURCES/0200-efinet-and-bootp-add-support-for-dhcpv6.patch b/SOURCES/0200-efinet-and-bootp-add-support-for-dhcpv6.patch
new file mode 100644
index 0000000..b2a0d52
--- /dev/null
+++ b/SOURCES/0200-efinet-and-bootp-add-support-for-dhcpv6.patch
@@ -0,0 +1,652 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 8 Jun 2016 21:03:37 -0400
+Subject: [PATCH] efinet and bootp: add support for dhcpv6
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/net/bootp.c              | 173 +++++++++++++++++++++++++++++++++++++
+ grub-core/net/drivers/efi/efinet.c |  52 +++++++++--
+ grub-core/net/net.c                |  67 ++++++++++++++
+ grub-core/net/tftp.c               |   4 +
+ include/grub/efi/api.h             | 129 +++++++++++++++++++++++++--
+ include/grub/net.h                 |  60 +++++++++++++
+ 6 files changed, 471 insertions(+), 14 deletions(-)
+
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index 88f20568914..4793ebc434e 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -23,6 +23,7 @@
+ #include <grub/net/ip.h>
+ #include <grub/net/netbuff.h>
+ #include <grub/net/udp.h>
++#include <grub/net/url.h>
+ #include <grub/datetime.h>
+ 
+ static char *
+@@ -335,6 +336,178 @@ grub_net_configure_by_dhcp_ack (const char *name,
+   return inter;
+ }
+ 
++struct grub_net_network_level_interface *
++grub_net_configure_by_dhcpv6_ack (const char *name,
++				  struct grub_net_card *card,
++				  grub_net_interface_flags_t flags
++				    __attribute__((__unused__)),
++				  const grub_net_link_level_address_t *hwaddr,
++				  const struct grub_net_dhcpv6_packet *packet,
++				  int is_def, char **device, char **path)
++{
++  struct grub_net_network_level_interface *inter = NULL;
++  struct grub_net_network_level_address addr;
++  int mask = -1;
++
++  if (device)
++    *device = 0;
++  if (path)
++    *path = 0;
++
++  grub_dprintf ("net", "mac address is %02x:%02x:%02x:%02x:%02x:%02x\n",
++		hwaddr->mac[0], hwaddr->mac[1], hwaddr->mac[2],
++		hwaddr->mac[3], hwaddr->mac[4], hwaddr->mac[5]);
++
++  if (is_def)
++    grub_net_default_server = 0;
++
++  if (is_def && !grub_net_default_server && packet)
++    {
++      const grub_uint8_t *options = packet->dhcp_options;
++      unsigned int option_max = 1024 - OFFSET_OF (dhcp_options, packet);
++      unsigned int i;
++
++      for (i = 0; i < option_max - sizeof (grub_net_dhcpv6_option_t); )
++	{
++	  grub_uint16_t num, len;
++	  grub_net_dhcpv6_option_t *opt =
++	    (grub_net_dhcpv6_option_t *)(options + i);
++
++	  num = grub_be_to_cpu16(opt->option_num);
++	  len = grub_be_to_cpu16(opt->option_len);
++
++	  grub_dprintf ("net", "got dhcpv6 option %d len %d\n", num, len);
++
++	  if (len == 0)
++	    break;
++
++	  if (len + i > 1024)
++	    break;
++
++	  if (num == GRUB_NET_DHCP6_BOOTFILE_URL)
++	    {
++	      char *scheme, *userinfo, *host, *file;
++	      char *tmp;
++	      int hostlen;
++	      int port;
++	      int rc = extract_url_info ((const char *)opt->option_data,
++					 (grub_size_t)len,
++					 &scheme, &userinfo, &host, &port,
++					 &file);
++	      if (rc < 0)
++		continue;
++
++	      /* right now this only handles tftp. */
++	      if (grub_strcmp("tftp", scheme))
++		{
++		  grub_free (scheme);
++		  grub_free (userinfo);
++		  grub_free (host);
++		  grub_free (file);
++		  continue;
++		}
++	      grub_free (userinfo);
++
++	      hostlen = grub_strlen (host);
++	      if (hostlen > 2 && host[0] == '[' && host[hostlen-1] == ']')
++		{
++		  tmp = host+1;
++		  host[hostlen-1] = '\0';
++		}
++	      else
++		tmp = host;
++
++	      *device = grub_xasprintf ("%s,%s", scheme, tmp);
++	      grub_free (scheme);
++	      grub_free (host);
++
++	      if (file && *file)
++		{
++		  tmp = grub_strrchr (file, '/');
++		  if (tmp)
++		    *(tmp+1) = '\0';
++		  else
++		    file[0] = '\0';
++		}
++	      else if (!file)
++		file = grub_strdup ("");
++
++	      if (file[0] == '/')
++		{
++		  *path = grub_strdup (file+1);
++		  grub_free (file);
++		}
++	      else
++		*path = file;
++	    }
++	  else if (num == GRUB_NET_DHCP6_IA_NA)
++	    {
++	      const grub_net_dhcpv6_option_t *ia_na_opt;
++	      const grub_net_dhcpv6_opt_ia_na_t *ia_na =
++		(const grub_net_dhcpv6_opt_ia_na_t *)opt;
++	      unsigned int left = len - OFFSET_OF (options, ia_na);
++	      unsigned int j;
++
++	      if ((grub_uint8_t *)ia_na + left >
++		  (grub_uint8_t *)options + option_max)
++		left -= ((grub_uint8_t *)ia_na + left)
++		        - ((grub_uint8_t *)options + option_max);
++
++	      if (len < OFFSET_OF (option_data, opt)
++			+ sizeof (grub_net_dhcpv6_option_t))
++		{
++		  grub_dprintf ("net",
++				"found dhcpv6 ia_na option with no address\n");
++		  continue;
++		}
++
++	      for (j = 0; left > sizeof (grub_net_dhcpv6_option_t); )
++		{
++		  ia_na_opt = (const grub_net_dhcpv6_option_t *)
++			       (ia_na->options + j);
++		  grub_uint16_t ia_na_opt_num, ia_na_opt_len;
++
++		  ia_na_opt_num = grub_be_to_cpu16 (ia_na_opt->option_num);
++		  ia_na_opt_len = grub_be_to_cpu16 (ia_na_opt->option_len);
++		  if (ia_na_opt_len == 0)
++		    break;
++		  if (j + ia_na_opt_len > left)
++		    break;
++		  if (ia_na_opt_num == GRUB_NET_DHCP6_IA_ADDRESS)
++		    {
++		      const grub_net_dhcpv6_opt_ia_address_t *ia_addr;
++
++		      ia_addr = (const grub_net_dhcpv6_opt_ia_address_t *)
++				 ia_na_opt;
++		      addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
++		      grub_memcpy(addr.ipv6, ia_addr->ipv6_address,
++				  sizeof (ia_addr->ipv6_address));
++		      inter = grub_net_add_addr (name, card, &addr, hwaddr, 0);
++		    }
++
++		  j += ia_na_opt_len;
++		  left -= ia_na_opt_len;
++		}
++	    }
++
++	  i += len + 4;
++	}
++
++      grub_print_error ();
++    }
++
++  if (is_def)
++    {
++      grub_env_set ("net_default_interface", name);
++      grub_env_export ("net_default_interface");
++    }
++
++    if (inter)
++      grub_net_add_ipv6_local (inter, mask);
++    return inter;
++}
++
++
+ void
+ grub_net_process_dhcp (struct grub_net_buff *nb,
+ 		       struct grub_net_card *card)
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 3f112438a93..d7befb2ba9b 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -18,11 +18,15 @@
+ 
+ #include <grub/net/netbuff.h>
+ #include <grub/dl.h>
++#include <grub/env.h>
+ #include <grub/net.h>
++#include <grub/net/url.h>
+ #include <grub/time.h>
+ #include <grub/efi/api.h>
+ #include <grub/efi/efi.h>
+ #include <grub/i18n.h>
++#include <grub/lib/hexdump.h>
++#include <grub/types.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -339,7 +343,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 			  char **path)
+ {
+   struct grub_net_card *card;
+-  grub_efi_device_path_t *dp;
++  grub_efi_device_path_t *dp, *ldp = NULL;
+ 
+   dp = grub_efi_get_device_path (hnd);
+   if (! dp)
+@@ -350,14 +354,19 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+     grub_efi_device_path_t *cdp;
+     struct grub_efi_pxe *pxe;
+     struct grub_efi_pxe_mode *pxe_mode;
++
+     if (card->driver != &efidriver)
+       continue;
++
+     cdp = grub_efi_get_device_path (card->efi_handle);
+     if (! cdp)
+       continue;
++
++    ldp = grub_efi_find_last_device_path (dp);
++
+     if (grub_efi_compare_device_paths (dp, cdp) != 0)
+       {
+-	grub_efi_device_path_t *ldp, *dup_dp, *dup_ldp;
++	grub_efi_device_path_t *dup_dp, *dup_ldp;
+ 	int match;
+ 
+ 	/* EDK2 UEFI PXE driver creates pseudo devices with type IPv4/IPv6
+@@ -366,7 +375,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 	   devices. We skip them when enumerating cards, so here we need to
+ 	   find matching MAC device.
+          */
+-	ldp = grub_efi_find_last_device_path (dp);
+ 	if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
+ 	    || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
+ 		&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
+@@ -383,16 +391,44 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 	if (!match)
+ 	  continue;
+       }
++
+     pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
+ 				  GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+     if (! pxe)
+       continue;
++
+     pxe_mode = pxe->mode;
+-    grub_net_configure_by_dhcp_ack (card->name, card, 0,
+-				    (struct grub_net_bootp_packet *)
+-				    &pxe_mode->dhcp_ack,
+-				    sizeof (pxe_mode->dhcp_ack),
+-				    1, device, path);
++    if (pxe_mode->using_ipv6)
++      {
++	grub_net_link_level_address_t hwaddr;
++
++	grub_dprintf ("efinet", "using ipv6 and dhcpv6\n");
++	grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n",
++		      pxe_mode->dhcp_ack_received ? "yes" : "no",
++		      pxe_mode->dhcp_ack_received ? "" : " cannot continue");
++	if (!pxe_mode->dhcp_ack_received)
++	  continue;
++
++	hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
++	grub_memcpy (hwaddr.mac,
++		     card->efi_net->mode->current_address,
++		     sizeof (hwaddr.mac));
++
++	grub_net_configure_by_dhcpv6_ack (card->name, card, 0,
++					  &hwaddr, &pxe_mode->dhcp_ack,
++					  1, device, path);
++	grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
++      }
++    else
++      {
++	grub_dprintf ("efinet", "using ipv4 and dhcp\n");
++	grub_net_configure_by_dhcp_ack (card->name, card, 0,
++					(struct grub_net_bootp_packet *)
++					&pxe_mode->dhcp_ack,
++					sizeof (pxe_mode->dhcp_ack),
++					1, device, path);
++	grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
++      }
+     return;
+   }
+ }
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index b10addbe27b..81d3b6208cb 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -969,6 +969,73 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa
+   grub_net_network_level_interfaces = inter;
+ }
+ 
++int
++grub_ipv6_get_masksize(grub_uint8_t *be_mask)
++{
++  grub_uint8_t *mask;
++  grub_uint16_t mask16[8];
++  unsigned int x;
++  int ret = 0;
++
++  grub_memcpy (mask16, be_mask, sizeof(mask16));
++  for (x = 0; x < 8; x++)
++    mask16[x] = grub_be_to_cpu16 (mask16[x]);
++
++  mask = (grub_uint8_t *)mask16;
++
++  for (x = 15; x > 0; x++)
++    {
++      grub_uint8_t octet = mask[x];
++      while (octet & 0x80)
++	{
++	  ret++;
++	  octet <<= 1;
++	}
++      if (ret)
++	ret += 8 * (15 - x);
++      break;
++    }
++
++  return ret;
++}
++
++grub_err_t
++grub_net_add_ipv6_local (struct grub_net_network_level_interface *inter,
++			 int mask)
++{
++  struct grub_net_route *route;
++
++  if (inter->address.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6)
++    return 0;
++
++  if (mask == -1)
++      mask = grub_ipv6_get_masksize ((grub_uint8_t *)inter->address.ipv6);
++
++  if (mask == -1)
++    return 0;
++
++  route = grub_zalloc (sizeof (*route));
++  if (!route)
++    return grub_errno;
++
++  route->name = grub_xasprintf ("%s:local", inter->name);
++  if (!route->name)
++    {
++      grub_free (route);
++      return grub_errno;
++    }
++
++  route->target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
++  grub_memcpy (route->target.ipv6.base, inter->address.ipv6,
++	       sizeof (inter->address.ipv6));
++  route->target.ipv6.masksize = mask;
++  route->is_gateway = 0;
++  route->interface = inter;
++
++  grub_net_route_register (route);
++
++  return 0;
++}
+ 
+ grub_err_t
+ grub_net_add_ipv4_local (struct grub_net_network_level_interface *inter,
+diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
+index 51736142764..22a4debdcd4 100644
+--- a/grub-core/net/tftp.c
++++ b/grub-core/net/tftp.c
+@@ -370,18 +370,22 @@ tftp_open (struct grub_file *file, const char *filename)
+   if (!data->pq)
+     return grub_errno;
+ 
++  grub_dprintf("tftp", "resolving address for %s\n", file->device->net->server);
+   err = grub_net_resolve_address (file->device->net->server, &addr);
+   if (err)
+     {
++      grub_dprintf("tftp", "Address resolution failed: %d\n", err);
+       destroy_pq (data);
+       return err;
+     }
+ 
++  grub_dprintf("tftp", "opening connection\n");
+   data->sock = grub_net_udp_open (addr,
+ 				  TFTP_SERVER_PORT, tftp_receive,
+ 				  file);
+   if (!data->sock)
+     {
++      grub_dprintf("tftp", "connection failed\n");
+       destroy_pq (data);
+       return grub_errno;
+     }
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index a6cce6e3395..9422ba9a9db 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -527,10 +527,16 @@ typedef void *grub_efi_handle_t;
+ typedef void *grub_efi_event_t;
+ typedef grub_efi_uint64_t grub_efi_lba_t;
+ typedef grub_efi_uintn_t grub_efi_tpl_t;
+-typedef grub_uint8_t grub_efi_mac_address_t[32];
+-typedef grub_uint8_t grub_efi_ipv4_address_t[4];
+-typedef grub_uint16_t grub_efi_ipv6_address_t[8];
+-typedef grub_uint8_t grub_efi_ip_address_t[8] __attribute__ ((aligned(4)));
++typedef grub_efi_uint8_t grub_efi_mac_address_t[32];
++typedef grub_efi_uint8_t grub_efi_ipv4_address_t[4];
++typedef grub_efi_uint8_t grub_efi_ipv6_address_t[16];
++typedef union
++{
++  grub_efi_uint32_t addr[4];
++  grub_efi_ipv4_address_t v4;
++  grub_efi_ipv6_address_t v6;
++} grub_efi_ip_address_t __attribute__ ((aligned(4)));
++
+ typedef grub_efi_uint64_t grub_efi_physical_address_t;
+ typedef grub_efi_uint64_t grub_efi_virtual_address_t;
+ 
+@@ -1405,16 +1411,127 @@ struct grub_efi_simple_text_output_interface
+ };
+ typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output_interface_t;
+ 
+-typedef grub_uint8_t grub_efi_pxe_packet_t[1472];
++typedef struct grub_efi_pxe_dhcpv4_packet
++{
++  grub_efi_uint8_t bootp_opcode;
++  grub_efi_uint8_t bootp_hwtype;
++  grub_efi_uint8_t bootp_hwaddr_len;
++  grub_efi_uint8_t bootp_gate_hops;
++  grub_efi_uint32_t bootp_ident;
++  grub_efi_uint16_t bootp_seconds;
++  grub_efi_uint16_t bootp_flags;
++  grub_efi_uint8_t bootp_ci_addr[4];
++  grub_efi_uint8_t bootp_yi_addr[4];
++  grub_efi_uint8_t bootp_si_addr[4];
++  grub_efi_uint8_t bootp_gi_addr[4];
++  grub_efi_uint8_t bootp_hw_addr[16];
++  grub_efi_uint8_t bootp_srv_name[64];
++  grub_efi_uint8_t bootp_boot_file[128];
++  grub_efi_uint32_t dhcp_magik;
++  grub_efi_uint8_t dhcp_options[56];
++} grub_efi_pxe_dhcpv4_packet_t;
++
++struct grub_efi_pxe_dhcpv6_packet
++{
++  grub_efi_uint32_t message_type:8;
++  grub_efi_uint32_t transaction_id:24;
++  grub_efi_uint8_t dhcp_options[1024];
++} GRUB_PACKED;
++typedef struct grub_efi_pxe_dhcpv6_packet grub_efi_pxe_dhcpv6_packet_t;
++
++typedef union
++{
++  grub_efi_uint8_t raw[1472];
++  grub_efi_pxe_dhcpv4_packet_t dhcpv4;
++  grub_efi_pxe_dhcpv6_packet_t dhcpv6;
++} grub_efi_pxe_packet_t;
++
++#define GRUB_EFI_PXE_MAX_IPCNT 8
++#define GRUB_EFI_PXE_MAX_ARP_ENTRIES 8
++#define GRUB_EFI_PXE_MAX_ROUTE_ENTRIES 8
++
++typedef struct grub_efi_pxe_ip_filter
++{
++  grub_efi_uint8_t filters;
++  grub_efi_uint8_t ip_count;
++  grub_efi_uint8_t reserved;
++  grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_MAX_IPCNT];
++} grub_efi_pxe_ip_filter_t;
++
++typedef struct grub_efi_pxe_arp_entry
++{
++  grub_efi_ip_address_t ip_addr;
++  grub_efi_mac_address_t mac_addr;
++} grub_efi_pxe_arp_entry_t;
++
++typedef struct grub_efi_pxe_route_entry
++{
++  grub_efi_ip_address_t ip_addr;
++  grub_efi_ip_address_t subnet_mask;
++  grub_efi_ip_address_t gateway_addr;
++} grub_efi_pxe_route_entry_t;
++
++typedef struct grub_efi_pxe_icmp_error
++{
++  grub_efi_uint8_t type;
++  grub_efi_uint8_t code;
++  grub_efi_uint16_t checksum;
++  union
++    {
++      grub_efi_uint32_t reserved;
++      grub_efi_uint32_t mtu;
++      grub_efi_uint32_t pointer;
++      struct
++	{
++	  grub_efi_uint16_t identifier;
++	  grub_efi_uint16_t sequence;
++	} echo;
++    } u;
++  grub_efi_uint8_t data[494];
++} grub_efi_pxe_icmp_error_t;
++
++typedef struct grub_efi_pxe_tftp_error
++{
++  grub_efi_uint8_t error_code;
++  grub_efi_char8_t error_string[127];
++} grub_efi_pxe_tftp_error_t;
+ 
+ typedef struct grub_efi_pxe_mode
+ {
+-  grub_uint8_t unused[52];
++  grub_efi_boolean_t started;
++  grub_efi_boolean_t ipv6_available;
++  grub_efi_boolean_t ipv6_supported;
++  grub_efi_boolean_t using_ipv6;
++  grub_efi_boolean_t bis_supported;
++  grub_efi_boolean_t bis_detected;
++  grub_efi_boolean_t auto_arp;
++  grub_efi_boolean_t send_guid;
++  grub_efi_boolean_t dhcp_discover_valid;
++  grub_efi_boolean_t dhcp_ack_received;
++  grub_efi_boolean_t proxy_offer_received;
++  grub_efi_boolean_t pxe_discover_valid;
++  grub_efi_boolean_t pxe_reply_received;
++  grub_efi_boolean_t pxe_bis_reply_received;
++  grub_efi_boolean_t icmp_error_received;
++  grub_efi_boolean_t tftp_error_received;
++  grub_efi_boolean_t make_callbacks;
++  grub_efi_uint8_t ttl;
++  grub_efi_uint8_t tos;
++  grub_efi_ip_address_t station_ip;
++  grub_efi_ip_address_t subnet_mask;
+   grub_efi_pxe_packet_t dhcp_discover;
+   grub_efi_pxe_packet_t dhcp_ack;
+   grub_efi_pxe_packet_t proxy_offer;
+   grub_efi_pxe_packet_t pxe_discover;
+   grub_efi_pxe_packet_t pxe_reply;
++  grub_efi_pxe_packet_t pxe_bis_reply;
++  grub_efi_pxe_ip_filter_t ip_filter;
++  grub_efi_uint32_t arp_cache_entries;
++  grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_MAX_ARP_ENTRIES];
++  grub_efi_uint32_t route_table_entries;
++  grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_MAX_ROUTE_ENTRIES];
++  grub_efi_pxe_icmp_error_t icmp_error;
++  grub_efi_pxe_tftp_error_t tftp_error;
+ } grub_efi_pxe_mode_t;
+ 
+ typedef struct grub_efi_pxe
+diff --git a/include/grub/net.h b/include/grub/net.h
+index 88fc71ceffe..c7b8e2ac885 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -418,6 +418,51 @@ struct grub_net_bootp_packet
+   grub_uint8_t vendor[0];
+ } GRUB_PACKED;
+ 
++enum
++  {
++    GRUB_NET_DHCP6_IA_NA = 3,
++    GRUB_NET_DHCP6_IA_ADDRESS = 5,
++    GRUB_NET_DHCP6_BOOTFILE_URL = 59,
++  };
++
++struct grub_net_dhcpv6_option
++{
++  grub_uint16_t option_num;
++  grub_uint16_t option_len;
++  grub_uint8_t option_data[];
++} GRUB_PACKED;
++typedef struct grub_net_dhcpv6_option grub_net_dhcpv6_option_t;
++
++struct grub_net_dhcpv6_opt_ia_na
++{
++  grub_uint16_t option_num;
++  grub_uint16_t option_len;
++  grub_uint32_t iaid;
++  grub_uint32_t t1;
++  grub_uint32_t t2;
++  grub_uint8_t options[];
++} GRUB_PACKED;
++typedef struct grub_net_dhcpv6_opt_ia_na grub_net_dhcpv6_opt_ia_na_t;
++
++struct grub_net_dhcpv6_opt_ia_address
++{
++  grub_uint16_t option_num;
++  grub_uint16_t option_len;
++  grub_uint64_t ipv6_address[2];
++  grub_uint32_t preferred_lifetime;
++  grub_uint32_t valid_lifetime;
++  grub_uint8_t options[];
++} GRUB_PACKED;
++typedef struct grub_net_dhcpv6_opt_ia_address grub_net_dhcpv6_opt_ia_address_t;
++
++struct grub_net_dhcpv6_packet
++{
++  grub_uint32_t message_type:8;
++  grub_uint32_t transaction_id:24;
++  grub_uint8_t dhcp_options[1024];
++} GRUB_PACKED;
++typedef struct grub_net_dhcpv6_packet grub_net_dhcpv6_packet_t;
++
+ #define	GRUB_NET_BOOTP_RFC1048_MAGIC_0	0x63
+ #define	GRUB_NET_BOOTP_RFC1048_MAGIC_1	0x82
+ #define	GRUB_NET_BOOTP_RFC1048_MAGIC_2	0x53
+@@ -446,6 +491,21 @@ grub_net_configure_by_dhcp_ack (const char *name,
+ 				grub_size_t size,
+ 				int is_def, char **device, char **path);
+ 
++struct grub_net_network_level_interface *
++grub_net_configure_by_dhcpv6_ack (const char *name,
++				 struct grub_net_card *card,
++				 grub_net_interface_flags_t flags,
++				 const grub_net_link_level_address_t *hwaddr,
++				 const struct grub_net_dhcpv6_packet *packet,
++				 int is_def, char **device, char **path);
++
++int
++grub_ipv6_get_masksize(grub_uint8_t *mask);
++
++grub_err_t
++grub_net_add_ipv6_local (struct grub_net_network_level_interface *inf,
++			 int mask);
++
+ grub_err_t
+ grub_net_add_ipv4_local (struct grub_net_network_level_interface *inf,
+ 			 int mask);
diff --git a/SOURCES/0201-ppc64le-has-no-separate-boot-mount-1261926.patch b/SOURCES/0201-ppc64le-has-no-separate-boot-mount-1261926.patch
new file mode 100644
index 0000000..10cf282
--- /dev/null
+++ b/SOURCES/0201-ppc64le-has-no-separate-boot-mount-1261926.patch
@@ -0,0 +1,41 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Fri, 17 Jun 2016 11:47:34 -0400
+Subject: [PATCH] ppc64le has no separate /boot mount (#1261926)
+
+The patch for rhbz#1212114 ensures that ppc64le systems sync grub config
+changes to disk prior to grub-mkconfig completion and a reboot.
+
+This patch required checking for /boot as its own mount point because
+issuing fsfreeze to a root partition is unwise. For administrators who
+configured a ppc64le system with no separate /boot partition, the failed
+check results in an error message. The file is written and would work
+most of the time, however, it also introduces a corner case where the
+behavior manifested in rhbz#1212114 could re-appear on these systems.
+
+The system call issued by fsfreeeze is being issued by methods within
+the anaconda installer and can be removed from GRUB proper.
+
+Related: rhbz#1315468
+Resolves: rhbz#1261926
+---
+ util/grub-mkconfig.in | 9 ---------
+ 1 file changed, 9 deletions(-)
+
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index 7db89499949..0cfe6047539 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -291,12 +291,3 @@ fi
+ 
+ gettext "done" >&2
+ echo >&2
+-
+-# make sure changes make it to the disk.
+-# if /boot is a mountpoint, force the meta data on disk
+-# to by-pass writeback delay.
+-# PPC64LE-only to deal with Petitboot issues
+-ARCH=$(uname -m)
+-if [ "${ARCH}" = "ppc64le" ]; then
+-    sync && mountpoint -q /boot &&fsfreeze -f /boot && fsfreeze -u /boot
+-fi
diff --git a/SOURCES/0202-Add-grub-get-kernel-settings-and-use-it-in-10_linux.patch b/SOURCES/0202-Add-grub-get-kernel-settings-and-use-it-in-10_linux.patch
new file mode 100644
index 0000000..b9c7b05
--- /dev/null
+++ b/SOURCES/0202-Add-grub-get-kernel-settings-and-use-it-in-10_linux.patch
@@ -0,0 +1,312 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 23 Jun 2016 11:01:39 -0400
+Subject: [PATCH] Add grub-get-kernel-settings and use it in 10_linux
+
+This patch adds grub-get-kernel-settings, which reads the system kernel
+installation configuration from /etc/sysconfig/kernel, and outputs
+${GRUB_...} variables suitable for evaluation by grub-mkconfig.  Those
+variables are then used by 10_linux to choose whether or not to create
+debug stanzas.
+
+Resolves: rhbz#1226325
+---
+ configure.ac                                   |  2 +
+ Makefile.util.def                              |  7 ++
+ .gitignore                                     |  1 +
+ util/bash-completion.d/grub-completion.bash.in | 22 +++++++
+ util/grub-get-kernel-settings.3                | 20 ++++++
+ util/grub-get-kernel-settings.in               | 91 ++++++++++++++++++++++++++
+ util/grub-mkconfig.in                          |  3 +
+ util/grub.d/10_linux.in                        | 23 +++++--
+ 8 files changed, 164 insertions(+), 5 deletions(-)
+ create mode 100644 util/grub-get-kernel-settings.3
+ create mode 100644 util/grub-get-kernel-settings.in
+
+diff --git a/configure.ac b/configure.ac
+index 04c052dc610..8b10a93cb56 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -58,6 +58,7 @@ grub_TRANSFORM([grub-install])
+ grub_TRANSFORM([grub-mkconfig])
+ grub_TRANSFORM([grub-mkfont])
+ grub_TRANSFORM([grub-mkimage])
++grub_TRANSFORM([grub-get-kernel-settings])
+ grub_TRANSFORM([grub-glue-efi])
+ grub_TRANSFORM([grub-mklayout])
+ grub_TRANSFORM([grub-mkpasswd-pbkdf2])
+@@ -75,6 +76,7 @@ grub_TRANSFORM([grub-file])
+ grub_TRANSFORM([grub-bios-setup.3])
+ grub_TRANSFORM([grub-editenv.1])
+ grub_TRANSFORM([grub-fstest.3])
++grub_TRANSFORM([grub-get-kernel-settings.3])
+ grub_TRANSFORM([grub-glue-efi.3])
+ grub_TRANSFORM([grub-install.1])
+ grub_TRANSFORM([grub-kbdcomp.3])
+diff --git a/Makefile.util.def b/Makefile.util.def
+index e2821a2f3a5..3918e3b5292 100644
+--- a/Makefile.util.def
++++ b/Makefile.util.def
+@@ -704,6 +704,13 @@ script = {
+   installdir = sbin;
+ };
+ 
++script = {
++  name = grub-get-kernel-settings;
++  common = util/grub-get-kernel-settings.in;
++  mansection = 3;
++  installdir = sbin;
++};
++
+ script = {
+   name = grub-set-default;
+   common = util/grub-set-default.in;
+diff --git a/.gitignore b/.gitignore
+index e49f76b114a..547ef0bcff0 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -61,6 +61,7 @@ grub-fstest.exe
+ grub_fstest_init.c
+ grub_fstest_init.h
+ grub_func_test
++grub-get-kernel-settings
+ grub-install
+ grub-install.exe
+ grub-kbdcomp
+diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in
+index 44bf135b9f8..5c4acd496d4 100644
+--- a/util/bash-completion.d/grub-completion.bash.in
++++ b/util/bash-completion.d/grub-completion.bash.in
+@@ -264,6 +264,28 @@ have ${__grub_sparc64_setup_program} && \
+ unset __grub_sparc64_setup_program
+ 
+ 
++#
++# grub-get-kernel-settings
++#
++_grub_get_kernel_settings () {
++    local cur
++
++    COMPREPLY=()
++    cur=`_get_cword`
++
++    if [[ "$cur" == -* ]]; then
++        __grubcomp "$(__grub_get_options_from_help)"
++    else
++        # Default complete with a filename
++        _filedir
++    fi
++}
++__grub_get_kernel_settings_program="@grub_get_kernel_settings@"
++have ${__grub_get_kernel_settings_program} && \
++ complete -F _grub_get_kernel_settings -o filenames ${__grub_get_kernel_settings_program}
++unset __grub_get_kernel_settings_program
++
++
+ #
+ # grub-install
+ #
+diff --git a/util/grub-get-kernel-settings.3 b/util/grub-get-kernel-settings.3
+new file mode 100644
+index 00000000000..ba33330e28d
+--- /dev/null
++++ b/util/grub-get-kernel-settings.3
+@@ -0,0 +1,20 @@
++.TH GRUB-GET-KERNEL-SETTINGS 3 "Thu Jun 25 2015"
++.SH NAME
++\fBgrub-get-kernel-settings\fR \(em Evaluate the system's kernel installation settings for use while making a grub configuration file.
++
++.SH SYNOPSIS
++\fBgrub-get-kernel-settings\fR [OPTION]
++
++.SH DESCRIPTION
++\fBgrub-get-kernel-settings\fR reads the kernel installation settings on the host system, and emits a set of grub settings suitable for use when creating a grub configuration file.
++
++.SH OPTIONS
++.TP
++-h, --help
++Display program usage and exit.
++.TP
++-v, --version
++Display the current version.
++
++.SH SEE ALSO
++.BR "info grub"
+diff --git a/util/grub-get-kernel-settings.in b/util/grub-get-kernel-settings.in
+new file mode 100644
+index 00000000000..ae0b4696d49
+--- /dev/null
++++ b/util/grub-get-kernel-settings.in
+@@ -0,0 +1,91 @@
++#!/bin/sh
++set -e
++
++# Evaluate new-kernel-pkg's configuration file.
++# Copyright (C) 2016 Free Software Foundation, Inc.
++#
++# GRUB 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 3 of the License, or
++# (at your option) any later version.
++#
++# GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
++
++prefix="@prefix@"
++exec_prefix="@exec_prefix@"
++datarootdir="@datarootdir@"
++
++prefix="@prefix@"
++exec_prefix="@exec_prefix@"
++sbindir="@sbindir@"
++bindir="@bindir@"
++sysconfdir="@sysconfdir@"
++PACKAGE_NAME=@PACKAGE_NAME@
++PACKAGE_VERSION=@PACKAGE_VERSION@
++host_os=@host_os@
++datadir="@datadir@"
++if [ "x$pkgdatadir" = x ]; then
++    pkgdatadir="${datadir}/@PACKAGE@"
++fi
++grub_cfg=""
++
++self=`basename $0`
++
++grub_probe="${sbindir}/@grub_probe@"
++grub_file="${bindir}/@grub_file@"
++grub_editenv="${bindir}/@grub_editenv@"
++grub_script_check="${bindir}/@grub_script_check@"
++
++export TEXTDOMAIN=@PACKAGE@
++export TEXTDOMAINDIR="@localedir@"
++
++. "${pkgdatadir}/grub-mkconfig_lib"
++
++# Usage: usage
++# Print the usage.
++usage () {
++    gettext_printf "Usage: %s [OPTION]\n" "$self"
++    gettext "Evaluate new-kernel-pkg configuration"; echo
++    echo
++    print_option_help "-h, --help" "$(gettext "print this message and exit")"
++    print_option_help "-v, --version" "$(gettext "print the version information and exit")"
++    echo
++}
++
++# Check the arguments.
++while test $# -gt 0
++do
++    option=$1
++    shift
++
++    case "$option" in
++    -h | --help)
++	usage
++	exit 0 ;;
++    -v | --version)
++	echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
++	exit 0 ;;
++    -*)
++	gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2
++	usage
++	exit 1
++	;;
++    # Explicitly ignore non-option arguments, for compatibility.
++    esac
++done
++
++if test -f /etc/sysconfig/kernel ; then
++    . /etc/sysconfig/kernel
++fi
++
++if [ "$MAKEDEBUG" = "yes" ]; then
++    echo GRUB_LINUX_MAKE_DEBUG=true
++    echo GRUB_CMDLINE_LINUX_DEBUG=\"systemd.log_level=debug systemd.log_target=kmsg\"
++    echo GRUB_LINUX_DEBUG_TITLE_POSTFIX=\" with debugging\"
++fi
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index 0cfe6047539..aa4fdb8a3b2 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -42,6 +42,7 @@ grub_probe="${sbindir}/@grub_probe@"
+ grub_file="${bindir}/@grub_file@"
+ grub_editenv="${bindir}/@grub_editenv@"
+ grub_script_check="${bindir}/@grub_script_check@"
++grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@"
+ 
+ export TEXTDOMAIN=@PACKAGE@
+ export TEXTDOMAINDIR="@localedir@"
+@@ -148,6 +149,8 @@ if test -f ${sysconfdir}/default/grub ; then
+   . ${sysconfdir}/default/grub
+ fi
+ 
++eval `${grub_get_kernel_settings}` || true
++
+ if [ "x$GRUB_DISABLE_UUID" != "xtrue" -a -z "$GRUB_DEVICE_UUID" ]; then
+   GRUB_DEVICE_UUID="$GRUB_DEVICE_UUID_GENERATED"
+ fi
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index b3c460cb266..0d0086d3b6a 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -99,7 +99,8 @@ linux_entry ()
+   os="$1"
+   version="$2"
+   type="$3"
+-  args="$4"
++  isdebug="$4"
++  args="$5"
+ 
+   sixteenbit=""
+   linuxefi="linux"
+@@ -130,6 +131,9 @@ linux_entry ()
+   else
+       echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+   fi      
++  if [ x$isdebug = xdebug ]; then
++      title="$title${GRUB_LINUX_DEBUG_TITLE_POSTFIX}"
++  fi
+   if [ x$type != xrecovery ] ; then
+       save_default_entry | grub_add_tab
+   fi
+@@ -281,11 +285,15 @@ while [ "x$list" != "x" ] ; do
+   fi
+ 
+   if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then
+-    linux_entry "${OS}" "${version}" simple \
++    linux_entry "${OS}" "${version}" simple standard \
+     "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
++    if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then
++      linux_entry "${OS}" "${version}" simple debug \
++        "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX_DEBUG}"
++    fi
+ 
+     submenu_indentation="$grub_tab"
+-    
++
+     if [ -z "$boot_device_id" ]; then
+ 	boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
+     fi
+@@ -294,10 +302,15 @@ while [ "x$list" != "x" ] ; do
+     is_top_level=false
+   fi
+ 
+-  linux_entry "${OS}" "${version}" advanced \
++  linux_entry "${OS}" "${version}" advanced standard \
+               "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
++  if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then
++    linux_entry "${OS}" "${version}" advanced debug \
++                "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX_DEBUG}"
++  fi
++
+   if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
+-    linux_entry "${OS}" "${version}" recovery \
++    linux_entry "${OS}" "${version}" recovery standard \
+                 "single ${GRUB_CMDLINE_LINUX}"
+   fi
+ 
diff --git a/SOURCES/0203-Fix-coverity-issues-in-shell-scripts-1226325.patch b/SOURCES/0203-Fix-coverity-issues-in-shell-scripts-1226325.patch
new file mode 100644
index 0000000..7ebed51
--- /dev/null
+++ b/SOURCES/0203-Fix-coverity-issues-in-shell-scripts-1226325.patch
@@ -0,0 +1,59 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Thu, 7 Jul 2016 15:05:26 -0400
+Subject: [PATCH] Fix coverity issues in shell scripts (#1226325)
+
+Remove unused variables called out by coverity. Convert a non-quoted
+variable to a quoted variable without use of deprecated backticks.
+
+Related: rhbz#1226325
+---
+ util/grub-get-kernel-settings.in | 9 ---------
+ util/grub-mkconfig.in            | 2 +-
+ 2 files changed, 1 insertion(+), 10 deletions(-)
+
+diff --git a/util/grub-get-kernel-settings.in b/util/grub-get-kernel-settings.in
+index ae0b4696d49..cee8c209650 100644
+--- a/util/grub-get-kernel-settings.in
++++ b/util/grub-get-kernel-settings.in
+@@ -21,27 +21,18 @@ prefix="@prefix@"
+ exec_prefix="@exec_prefix@"
+ datarootdir="@datarootdir@"
+ 
+-prefix="@prefix@"
+ exec_prefix="@exec_prefix@"
+ sbindir="@sbindir@"
+ bindir="@bindir@"
+-sysconfdir="@sysconfdir@"
+ PACKAGE_NAME=@PACKAGE_NAME@
+ PACKAGE_VERSION=@PACKAGE_VERSION@
+-host_os=@host_os@
+ datadir="@datadir@"
+ if [ "x$pkgdatadir" = x ]; then
+     pkgdatadir="${datadir}/@PACKAGE@"
+ fi
+-grub_cfg=""
+ 
+ self=`basename $0`
+ 
+-grub_probe="${sbindir}/@grub_probe@"
+-grub_file="${bindir}/@grub_file@"
+-grub_editenv="${bindir}/@grub_editenv@"
+-grub_script_check="${bindir}/@grub_script_check@"
+-
+ export TEXTDOMAIN=@PACKAGE@
+ export TEXTDOMAINDIR="@localedir@"
+ 
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index aa4fdb8a3b2..86801aa4e5c 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -149,7 +149,7 @@ if test -f ${sysconfdir}/default/grub ; then
+   . ${sysconfdir}/default/grub
+ fi
+ 
+-eval `${grub_get_kernel_settings}` || true
++eval "$("${grub_get_kernel_settings}")" || true
+ 
+ if [ "x$GRUB_DISABLE_UUID" != "xtrue" -a -z "$GRUB_DEVICE_UUID" ]; then
+   GRUB_DEVICE_UUID="$GRUB_DEVICE_UUID_GENERATED"
diff --git a/SOURCES/0204-Fix-compiler-warning-1154226.patch b/SOURCES/0204-Fix-compiler-warning-1154226.patch
new file mode 100644
index 0000000..bbc07f5
--- /dev/null
+++ b/SOURCES/0204-Fix-compiler-warning-1154226.patch
@@ -0,0 +1,27 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Thu, 7 Jul 2016 16:30:32 -0400
+Subject: [PATCH] Fix compiler warning (#1154226)
+
+Coverity threw a compiler warning for an incompatible pointer type when
+referencing a union. Converted the argument to pass the exact member of the
+union instead of just the union itself.
+
+Related: rhbz#1154226
+---
+ grub-core/net/drivers/efi/efinet.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index d7befb2ba9b..ed103df7a80 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -415,7 +415,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 		     sizeof (hwaddr.mac));
+ 
+ 	grub_net_configure_by_dhcpv6_ack (card->name, card, 0,
+-					  &hwaddr, &pxe_mode->dhcp_ack,
++					  &hwaddr, &pxe_mode->dhcp_ack.dhcpv6,
+ 					  1, device, path);
+ 	grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
+       }
diff --git a/SOURCES/0205-Fix-CLANG-error-from-Coverity-1154226.patch b/SOURCES/0205-Fix-CLANG-error-from-Coverity-1154226.patch
new file mode 100644
index 0000000..9144313
--- /dev/null
+++ b/SOURCES/0205-Fix-CLANG-error-from-Coverity-1154226.patch
@@ -0,0 +1,30 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Mon, 11 Jul 2016 10:59:48 -0400
+Subject: [PATCH] Fix CLANG error from Coverity (#1154226)
+
+Resolved a null pointer deference warning from coverity.
+
+Related: rhbz#1154226
+---
+ grub-core/net/url.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/net/url.c b/grub-core/net/url.c
+index 537019f2c78..146858284cd 100644
+--- a/grub-core/net/url.c
++++ b/grub-core/net/url.c
+@@ -267,7 +267,12 @@ extract_http_url_info (char *url, int ssl,
+     }
+ 
+   l = host_end - host_off;
+-  c = *host_end;
++
++  if (host_end == NULL)
++    goto fail;
++  else
++    c = *host_end;
++
+   *host_end = '\0';
+   *host = grub_strndup (host_off, l);
+   *host_end = c;
diff --git a/SOURCES/0206-grub_ipv6_get_masksize-fix-loop-iteration-error.patch b/SOURCES/0206-grub_ipv6_get_masksize-fix-loop-iteration-error.patch
new file mode 100644
index 0000000..9220c3d
--- /dev/null
+++ b/SOURCES/0206-grub_ipv6_get_masksize-fix-loop-iteration-error.patch
@@ -0,0 +1,25 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 11 Jul 2016 15:43:01 -0400
+Subject: [PATCH] grub_ipv6_get_masksize: fix loop iteration error
+
+Related: rhbz#1154226
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/net/net.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index 81d3b6208cb..19a81bc9e78 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -983,7 +983,7 @@ grub_ipv6_get_masksize(grub_uint8_t *be_mask)
+ 
+   mask = (grub_uint8_t *)mask16;
+ 
+-  for (x = 15; x > 0; x++)
++  for (x = 15; x > 0; x--)
+     {
+       grub_uint8_t octet = mask[x];
+       while (octet & 0x80)
diff --git a/SOURCES/0207-efinet-fix-some-coverity-gripes.patch b/SOURCES/0207-efinet-fix-some-coverity-gripes.patch
new file mode 100644
index 0000000..170cb6a
--- /dev/null
+++ b/SOURCES/0207-efinet-fix-some-coverity-gripes.patch
@@ -0,0 +1,62 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 11 Jul 2016 15:57:28 -0400
+Subject: [PATCH] efinet: fix some coverity gripes.
+
+Related: rhbz#1154226
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/net/bootp.c              |  9 +++++----
+ grub-core/net/drivers/efi/efinet.c | 11 +++++++----
+ 2 files changed, 12 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index 4793ebc434e..46ce8135ac5 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -349,10 +349,11 @@ grub_net_configure_by_dhcpv6_ack (const char *name,
+   struct grub_net_network_level_address addr;
+   int mask = -1;
+ 
+-  if (device)
+-    *device = 0;
+-  if (path)
+-    *path = 0;
++  if (!device || !path)
++    return NULL;
++
++  *device = 0;
++  *path = 0;
+ 
+   grub_dprintf ("net", "mac address is %02x:%02x:%02x:%02x:%02x:%02x\n",
+ 		hwaddr->mac[0], hwaddr->mac[1], hwaddr->mac[2],
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index ed103df7a80..2244f14030f 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -401,6 +401,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+     if (pxe_mode->using_ipv6)
+       {
+ 	grub_net_link_level_address_t hwaddr;
++	struct grub_net_network_level_interface *intf;
+ 
+ 	grub_dprintf ("efinet", "using ipv6 and dhcpv6\n");
+ 	grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n",
+@@ -414,10 +415,12 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 		     card->efi_net->mode->current_address,
+ 		     sizeof (hwaddr.mac));
+ 
+-	grub_net_configure_by_dhcpv6_ack (card->name, card, 0,
+-					  &hwaddr, &pxe_mode->dhcp_ack.dhcpv6,
+-					  1, device, path);
+-	grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
++	intf = grub_net_configure_by_dhcpv6_ack (card->name, card, 0,
++						 &hwaddr,
++						 &pxe_mode->dhcp_ack.dhcpv6,
++						 1, device, path);
++	if (intf && device && path)
++	  grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
+       }
+     else
+       {
diff --git a/SOURCES/0208-Fix-another-coverity-gripe-about-a-missing-typecast.patch b/SOURCES/0208-Fix-another-coverity-gripe-about-a-missing-typecast.patch
new file mode 100644
index 0000000..91f2f30
--- /dev/null
+++ b/SOURCES/0208-Fix-another-coverity-gripe-about-a-missing-typecast.patch
@@ -0,0 +1,30 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 12 Jul 2016 10:23:42 -0400
+Subject: [PATCH] Fix another coverity gripe about a missing typecast.
+
+Related: rhbz#1154226
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/net/drivers/efi/efinet.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 2244f14030f..69b0fc7a8fe 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -415,10 +415,9 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 		     card->efi_net->mode->current_address,
+ 		     sizeof (hwaddr.mac));
+ 
+-	intf = grub_net_configure_by_dhcpv6_ack (card->name, card, 0,
+-						 &hwaddr,
+-						 &pxe_mode->dhcp_ack.dhcpv6,
+-						 1, device, path);
++	intf = grub_net_configure_by_dhcpv6_ack (card->name, card, 0, &hwaddr,
++	      (const struct grub_net_dhcpv6_packet *)&pxe_mode->dhcp_ack.dhcpv6,
++	      1, device, path);
+ 	if (intf && device && path)
+ 	  grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
+       }
diff --git a/SOURCES/0209-Fix-duplicate-shell-entries-1226325.patch b/SOURCES/0209-Fix-duplicate-shell-entries-1226325.patch
new file mode 100644
index 0000000..2b036af
--- /dev/null
+++ b/SOURCES/0209-Fix-duplicate-shell-entries-1226325.patch
@@ -0,0 +1,31 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Robert Marshall <rmarshall@redhat.com>
+Date: Tue, 12 Jul 2016 10:25:16 -0400
+Subject: [PATCH] Fix duplicate shell entries (#1226325)
+
+Coverity discovered more of the same non-used shell variables that had
+appeared more than once in the file.
+
+Related: rhbz#1226325
+---
+ util/grub-get-kernel-settings.in | 7 -------
+ 1 file changed, 7 deletions(-)
+
+diff --git a/util/grub-get-kernel-settings.in b/util/grub-get-kernel-settings.in
+index cee8c209650..6a68a0ef664 100644
+--- a/util/grub-get-kernel-settings.in
++++ b/util/grub-get-kernel-settings.in
+@@ -17,13 +17,6 @@ set -e
+ # You should have received a copy of the GNU General Public License
+ # along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ 
+-prefix="@prefix@"
+-exec_prefix="@exec_prefix@"
+-datarootdir="@datarootdir@"
+-
+-exec_prefix="@exec_prefix@"
+-sbindir="@sbindir@"
+-bindir="@bindir@"
+ PACKAGE_NAME=@PACKAGE_NAME@
+ PACKAGE_VERSION=@PACKAGE_VERSION@
+ datadir="@datadir@"
diff --git a/SOURCES/0210-Coverity-rightly-noticed-that-grub_ipv6_get_masksize.patch b/SOURCES/0210-Coverity-rightly-noticed-that-grub_ipv6_get_masksize.patch
new file mode 100644
index 0000000..5936422
--- /dev/null
+++ b/SOURCES/0210-Coverity-rightly-noticed-that-grub_ipv6_get_masksize.patch
@@ -0,0 +1,87 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 12 Jul 2016 11:59:39 -0400
+Subject: [PATCH] Coverity rightly noticed that grub_ipv6_get_masksize() was
+ broken.
+
+This fixes it with a version that even seems to work.
+
+Related: rhbz#1154226
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/net/net.c | 27 ++++++++++++++++-----------
+ include/grub/net.h  |  2 +-
+ 2 files changed, 17 insertions(+), 12 deletions(-)
+
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index 19a81bc9e78..36fc0d8b2e8 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -970,29 +970,34 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa
+ }
+ 
+ int
+-grub_ipv6_get_masksize(grub_uint8_t *be_mask)
++grub_ipv6_get_masksize (grub_uint16_t be_mask[8])
+ {
+   grub_uint8_t *mask;
+   grub_uint16_t mask16[8];
+-  unsigned int x;
+-  int ret = 0;
++  int x, y;
++  int ret = 128;
+ 
+-  grub_memcpy (mask16, be_mask, sizeof(mask16));
++  grub_memcpy (mask16, be_mask, sizeof (mask16));
+   for (x = 0; x < 8; x++)
+     mask16[x] = grub_be_to_cpu16 (mask16[x]);
+ 
+   mask = (grub_uint8_t *)mask16;
+ 
+-  for (x = 15; x > 0; x--)
++  for (x = 15; x >= 0; x--)
+     {
+       grub_uint8_t octet = mask[x];
+-      while (octet & 0x80)
++      if (!octet)
+ 	{
+-	  ret++;
+-	  octet <<= 1;
++	  ret -= 8;
++	  continue;
++	}
++      for (y = 0; y < 8; y++)
++	{
++	  if (octet & (1 << y))
++	    break;
++	  else
++	    ret--;
+ 	}
+-      if (ret)
+-	ret += 8 * (15 - x);
+       break;
+     }
+ 
+@@ -1009,7 +1014,7 @@ grub_net_add_ipv6_local (struct grub_net_network_level_interface *inter,
+     return 0;
+ 
+   if (mask == -1)
+-      mask = grub_ipv6_get_masksize ((grub_uint8_t *)inter->address.ipv6);
++      mask = grub_ipv6_get_masksize ((grub_uint16_t *)inter->address.ipv6);
+ 
+   if (mask == -1)
+     return 0;
+diff --git a/include/grub/net.h b/include/grub/net.h
+index c7b8e2ac885..bd930f4dd8c 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -500,7 +500,7 @@ grub_net_configure_by_dhcpv6_ack (const char *name,
+ 				 int is_def, char **device, char **path);
+ 
+ int
+-grub_ipv6_get_masksize(grub_uint8_t *mask);
++grub_ipv6_get_masksize(grub_uint16_t *mask);
+ 
+ grub_err_t
+ grub_net_add_ipv6_local (struct grub_net_network_level_interface *inf,
diff --git a/SOURCES/0211-Export-grub-get-kernel-settings-variables.patch b/SOURCES/0211-Export-grub-get-kernel-settings-variables.patch
new file mode 100644
index 0000000..a2420d7
--- /dev/null
+++ b/SOURCES/0211-Export-grub-get-kernel-settings-variables.patch
@@ -0,0 +1,51 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 25 Aug 2016 14:15:29 -0400
+Subject: [PATCH] Export grub-get-kernel-settings variables
+
+Without this export, the generators for various configs never get the
+setting.
+
+Related: rhbz#1226325
+
+Signed-off-by: Peter Jones <example@example.com>
+---
+ util/grub-get-kernel-settings.in | 3 +++
+ util/grub.d/10_linux.in          | 6 +++---
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/util/grub-get-kernel-settings.in b/util/grub-get-kernel-settings.in
+index 6a68a0ef664..12046219878 100644
+--- a/util/grub-get-kernel-settings.in
++++ b/util/grub-get-kernel-settings.in
+@@ -70,6 +70,9 @@ fi
+ 
+ if [ "$MAKEDEBUG" = "yes" ]; then
+     echo GRUB_LINUX_MAKE_DEBUG=true
++    echo export GRUB_LINUX_MAKE_DEBUG
+     echo GRUB_CMDLINE_LINUX_DEBUG=\"systemd.log_level=debug systemd.log_target=kmsg\"
++    echo export GRUB_CMDLINE_LINUX_DEBUG
+     echo GRUB_LINUX_DEBUG_TITLE_POSTFIX=\" with debugging\"
++    echo export GRUB_LINUX_DEBUG_TITLE_POSTFIX
+ fi
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 0d0086d3b6a..bf0fb727bcd 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -127,13 +127,13 @@ linux_entry ()
+ 	  quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"
+ 	  title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
+       fi
++      if [ x$isdebug = xdebug ]; then
++	  title="$title${GRUB_LINUX_DEBUG_TITLE_POSTFIX}"
++      fi
+       echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+   else
+       echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+   fi      
+-  if [ x$isdebug = xdebug ]; then
+-      title="$title${GRUB_LINUX_DEBUG_TITLE_POSTFIX}"
+-  fi
+   if [ x$type != xrecovery ] ; then
+       save_default_entry | grub_add_tab
+   fi
diff --git a/SOURCES/0212-Normalize-slashes-in-tftp-paths.patch b/SOURCES/0212-Normalize-slashes-in-tftp-paths.patch
new file mode 100644
index 0000000..b89abf9
--- /dev/null
+++ b/SOURCES/0212-Normalize-slashes-in-tftp-paths.patch
@@ -0,0 +1,59 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Lenny Szubowicz <lszubowi@redhat.com>
+Date: Mon, 29 Aug 2016 11:04:48 -0400
+Subject: [PATCH] Normalize slashes in tftp paths.
+
+Some tftp servers do not handle multiple consecutive slashes correctly;
+this patch avoids sending tftp requests with non-normalized paths.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/net/tftp.c | 28 +++++++++++++++++++++++++---
+ 1 file changed, 25 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
+index 22a4debdcd4..8632339de97 100644
+--- a/grub-core/net/tftp.c
++++ b/grub-core/net/tftp.c
+@@ -300,6 +300,25 @@ destroy_pq (tftp_data_t data)
+   grub_priority_queue_destroy (data->pq);
+ }
+ 
++/* Create a normalized copy of the filename.
++   Compress any string of consecutive forward slashes to a single forward
++   slash. */
++static void
++grub_normalize_filename (char *normalized, const char *filename)
++{
++  char *dest = normalized;
++  char *src = filename;
++
++  while (*src != '\0')
++    {
++      if (src[0] == '/' && src[1] == '/')
++	src++;
++      else
++	*dest++ = *src++;
++    }
++  *dest = '\0';
++}
++
+ static grub_err_t
+ tftp_open (struct grub_file *file, const char *filename)
+ {
+@@ -334,9 +353,12 @@ tftp_open (struct grub_file *file, const char *filename)
+   rrqlen = 0;
+ 
+   tftph->opcode = grub_cpu_to_be16 (TFTP_RRQ);
+-  grub_strcpy (rrq, filename);
+-  rrqlen += grub_strlen (filename) + 1;
+-  rrq += grub_strlen (filename) + 1;
++
++  /* Copy and normalize the filename to work-around issues on some tftp
++     servers when file names are being matched for remapping. */
++  grub_normalize_filename (rrq, filename);
++  rrqlen += grub_strlen (rrq) + 1;
++  rrq += grub_strlen (rrq) + 1;
+ 
+   grub_strcpy (rrq, "octet");
+   rrqlen += grub_strlen ("octet") + 1;
diff --git a/SOURCES/0213-bz1374141-fix-incorrect-mask-for-ppc64.patch b/SOURCES/0213-bz1374141-fix-incorrect-mask-for-ppc64.patch
new file mode 100644
index 0000000..a0b1016
--- /dev/null
+++ b/SOURCES/0213-bz1374141-fix-incorrect-mask-for-ppc64.patch
@@ -0,0 +1,44 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Masahiro Matsuya <mmatsuya@redhat.com>
+Date: Sat, 29 Oct 2016 08:35:26 +0900
+Subject: [PATCH] bz1374141 fix incorrect mask for ppc64
+
+The netmask configured in firmware is not respected on ppc64 (big endian).
+When 255.255.252.0 is set as netmask in firmware, the following is the value of bootpath string in grub_ieee1275_parse_bootpath().
+
+ /vdevice/l-lan@30000002:speed=auto,duplex=auto,192.168.88.10,,192.168.89.113,192.168.88.1,5,5,255.255.252.0,512
+
+The netmask in this bootpath is no problem, since it's a value specified in firmware. But,
+The value of 'subnet_mask.ipv4' was set with 0xfffffc00, and __builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4)) returned 16 (not 22).
+As a result, 16 was used for netmask wrongly.
+
+1111 1111 1111 1111 1111 1100 0000 0000 # subnet_mask.ipv4 (=0xfffffc00)
+0000 0000 1111 1100 1111 1111 1111 1111 # grub_le_to_cpu32 (subnet_mask.ipv4)
+1111 1111 0000 0011 0000 0000 0000 0000 # ~grub_le_to_cpu32 (subnet_mask.ipv4)
+
+And, the count of zero with __builtin_ctz can be 16.
+This patch changes it as below.
+
+1111 1111 1111 1111 1111 1100 0000 0000 # subnet_mask.ipv4 (=0xfffffc00)
+0000 0000 1111 1100 1111 1111 1111 1111 # grub_le_to_cpu32 (subnet_mask.ipv4)
+1111 1111 1111 1111 1111 1100 0000 0000 # grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4))
+0000 0000 0000 0000 0000 0011 1111 1111 # ~grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4))
+
+The count of zero with __builtin_clz can be 22. (clz counts the number of one bits preceding the most significant zero bit)
+---
+ grub-core/net/drivers/ieee1275/ofnet.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c
+index eea8e71d300..cd24ddc99c5 100644
+--- a/grub-core/net/drivers/ieee1275/ofnet.c
++++ b/grub-core/net/drivers/ieee1275/ofnet.c
+@@ -208,7 +208,7 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
+       inter = grub_net_add_addr ((*card)->name, *card, &client_addr, &hw_addr,
+                                  flags);
+       grub_net_add_ipv4_local (inter,
+-                          __builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4)));
++                          __builtin_clz (~grub_swap_bytes32(grub_le_to_cpu32 (subnet_mask.ipv4))));
+     }
+ 
+   if (gateway_addr.ipv4 != 0)
diff --git a/SOURCES/0214-Make-efi-machines-load-an-env-block-from-a-variable.patch b/SOURCES/0214-Make-efi-machines-load-an-env-block-from-a-variable.patch
new file mode 100644
index 0000000..9f253ca
--- /dev/null
+++ b/SOURCES/0214-Make-efi-machines-load-an-env-block-from-a-variable.patch
@@ -0,0 +1,81 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 7 Dec 2015 14:20:49 -0500
+Subject: [PATCH] Make efi machines load an env block from a variable
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/Makefile.core.def |  1 +
+ grub-core/kern/efi/init.c   | 34 +++++++++++++++++++++++++++++++++-
+ 2 files changed, 34 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index d73ea6f6c51..4fc74393335 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -173,6 +173,7 @@ kernel = {
+   efi = kern/efi/init.c;
+   efi = kern/efi/mm.c;
+   efi = term/efi/console.c;
++  efi = lib/envblk.c;
+ 
+   x86 = kern/i386/tsc.c;
+ 
+diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
+index c391df48236..c5d8a76144a 100644
+--- a/grub-core/kern/efi/init.c
++++ b/grub-core/kern/efi/init.c
+@@ -25,9 +25,40 @@
+ #include <grub/env.h>
+ #include <grub/mm.h>
+ #include <grub/kernel.h>
++#include <grub/lib/envblk.h>
+ 
+ grub_addr_t grub_modbase;
+ 
++#define GRUB_EFI_GRUB_VARIABLE_GUID \
++  { 0x91376aff, 0xcba6, 0x42be, \
++    { 0x94, 0x9d, 0x06, 0xfd, 0xe8, 0x11, 0x28, 0xe8 } \
++  }
++
++/* Helper for grub_efi_env_init */
++static int
++set_var (const char *name, const char *value,
++	 void *whitelist __attribute__((__unused__)))
++{
++  grub_env_set (name, value);
++  return 0;
++}
++
++static void
++grub_efi_env_init (void)
++{
++  grub_efi_guid_t efi_grub_guid = GRUB_EFI_GRUB_VARIABLE_GUID;
++  struct grub_envblk envblk_s = { NULL, 0 };
++  grub_envblk_t envblk = &envblk_s;
++
++  envblk_s.buf = grub_efi_get_variable ("GRUB_ENV", &efi_grub_guid,
++					&envblk_s.size);
++  if (!envblk_s.buf || envblk_s.size < 1)
++    return;
++
++  grub_envblk_iterate (envblk, NULL, set_var);
++  grub_free (envblk_s.buf);
++}
++
+ void
+ grub_efi_init (void)
+ {
+@@ -42,10 +73,11 @@ grub_efi_init (void)
+   efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer,
+ 	      0, 0, 0, NULL);
+ 
++  grub_efi_env_init ();
+   grub_efidisk_init ();
+ }
+ 
+-void (*grub_efi_net_config) (grub_efi_handle_t hnd, 
++void (*grub_efi_net_config) (grub_efi_handle_t hnd,
+ 			     char **device,
+ 			     char **path);
+ 
diff --git a/SOURCES/0215-Fix-race-in-EFI-validation.patch b/SOURCES/0215-Fix-race-in-EFI-validation.patch
new file mode 100644
index 0000000..ce42a83
--- /dev/null
+++ b/SOURCES/0215-Fix-race-in-EFI-validation.patch
@@ -0,0 +1,94 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Matthew Garrett <mjg59@coreos.com>
+Date: Tue, 14 Jul 2015 16:58:51 -0700
+Subject: [PATCH] Fix race in EFI validation
+
+---
+ grub-core/loader/i386/efi/linux.c | 44 ++++++++++-----------------------------
+ 1 file changed, 11 insertions(+), 33 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index e5b778577f9..7ccf32d9d45 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -154,7 +154,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_file_t file = 0;
+   struct linux_kernel_header lh;
+   grub_ssize_t len, start, filelen;
+-  void *kernel;
++  void *kernel = NULL;
+ 
+   grub_dl_ref (my_mod);
+ 
+@@ -191,10 +191,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-  grub_file_seek (file, 0);
+-
+-  grub_free(kernel);
+-
+   params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
+ 
+   if (! params)
+@@ -203,15 +199,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-  memset (params, 0, 16384);
++  grub_memset (params, 0, 16384);
+ 
+-  if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
+-    {
+-      if (!grub_errno)
+-	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+-		    argv[0]);
+-      goto fail;
+-    }
++  grub_memcpy (&lh, kernel, sizeof (lh));
+ 
+   if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
+     {
+@@ -271,27 +261,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-  if (grub_file_seek (file, start) == (grub_off_t) -1)
+-    {
+-      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+-		  argv[0]);
+-      goto fail;
+-    }
++  grub_memcpy (kernel_mem, (char *)kernel + start, len);
++  grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
++  loaded=1;
+ 
+-  if (grub_file_read (file, kernel_mem, len) != len && !grub_errno)
+-    {
+-      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+-		  argv[0]);
+-    }
+-
+-  if (grub_errno == GRUB_ERR_NONE)
+-    {
+-      grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
+-      loaded = 1;
+-      lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
+-    }
+-
+-  memcpy(params, &lh, 2 * 512);
++  lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
++  grub_memcpy (params, &lh, 2 * 512);
+ 
+   params->type_of_loader = 0x21;
+ 
+@@ -300,6 +275,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   if (file)
+     grub_file_close (file);
+ 
++  if (kernel)
++    grub_free (kernel);
++
+   if (grub_errno != GRUB_ERR_NONE)
+     {
+       grub_dl_unref (my_mod);
diff --git a/SOURCES/0216-efi-chainloader-fix-use-after-free.patch b/SOURCES/0216-efi-chainloader-fix-use-after-free.patch
new file mode 100644
index 0000000..6bbc6d5
--- /dev/null
+++ b/SOURCES/0216-efi-chainloader-fix-use-after-free.patch
@@ -0,0 +1,23 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Sat, 20 Jun 2015 23:38:17 +0300
+Subject: [PATCH] efi/chainloader: fix use after free
+
+Found by: Coverity scan.
+CID: 96714
+---
+ grub-core/loader/efi/chainloader.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 233237018b5..ec23cf4ed66 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -351,6 +351,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   loaded_image->device_handle = dev_handle;
+ 
+   grub_file_close (file);
++  file = NULL;
+ 
+   if (argc > 1)
+     {
diff --git a/SOURCES/0217-chainloader-fix-resoource-leak.patch b/SOURCES/0217-chainloader-fix-resoource-leak.patch
new file mode 100644
index 0000000..e078f02
--- /dev/null
+++ b/SOURCES/0217-chainloader-fix-resoource-leak.patch
@@ -0,0 +1,35 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Fri, 26 Jun 2015 09:25:30 +0300
+Subject: [PATCH] chainloader: fix resoource leak
+
+Found by: Coverity scan.
+CID: 96651
+---
+ grub-core/loader/efi/chainloader.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index ec23cf4ed66..522a716e37d 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -350,9 +350,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+     }
+   loaded_image->device_handle = dev_handle;
+ 
+-  grub_file_close (file);
+-  file = NULL;
+-
+   if (argc > 1)
+     {
+       int i, len;
+@@ -382,6 +379,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+       loaded_image->load_options_size = len;
+     }
+ 
++  grub_file_close (file);
++  grub_device_close (dev);
++
+   grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
+   return 0;
+ 
diff --git a/SOURCES/0218-efi-properly-terminate-filepath-with-NULL-in-chainlo.patch b/SOURCES/0218-efi-properly-terminate-filepath-with-NULL-in-chainlo.patch
new file mode 100644
index 0000000..ff187f2
--- /dev/null
+++ b/SOURCES/0218-efi-properly-terminate-filepath-with-NULL-in-chainlo.patch
@@ -0,0 +1,41 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Thu, 15 Dec 2016 16:07:00 +0300
+Subject: [PATCH] efi: properly terminate filepath with NULL in chainloader
+
+EFI File Path Media Device Path is defined as NULL terminated string;
+but chainloader built file paths without final NULL. This caused error
+with Secure Boot and Linux Foundation PreLoader on Acer with InsydeH20 BIOS.
+Apparently firmware failed verification with EFI_INVALID_PARAMETER which is
+considered fatal error by PreLoader.
+
+Reported and tested by Giovanni Santini <itachi.sama.amaterasu@gmail.com>
+---
+ grub-core/loader/efi/chainloader.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 522a716e37d..adc85636633 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -122,6 +122,8 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
+     if (*p == '/')
+       *p = '\\';
+ 
++  /* File Path is NULL terminated */
++  fp->path_name[size++] = '\0';
+   fp->header.length = size * sizeof (grub_efi_char16_t) + sizeof (*fp);
+ }
+ 
+@@ -156,8 +158,10 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
+       d = GRUB_EFI_NEXT_DEVICE_PATH (d);
+     }
+ 
++  /* File Path is NULL terminated. Allocate space for 2 extra characters */
++  /* FIXME why we split path in two components? */
+   file_path = grub_malloc (size
+-			   + ((grub_strlen (dir_start) + 1)
++			   + ((grub_strlen (dir_start) + 2)
+ 			      * GRUB_MAX_UTF16_PER_UTF8
+ 			      * sizeof (grub_efi_char16_t))
+ 			   + sizeof (grub_efi_file_path_device_path_t) * 2);
diff --git a/SOURCES/0219-Use-device-part-of-chainloader-target-if-present.patch b/SOURCES/0219-Use-device-part-of-chainloader-target-if-present.patch
new file mode 100644
index 0000000..28efeb0
--- /dev/null
+++ b/SOURCES/0219-Use-device-part-of-chainloader-target-if-present.patch
@@ -0,0 +1,34 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Raymund Will <rw@suse.com>
+Date: Fri, 10 Apr 2015 01:45:02 -0400
+Subject: [PATCH] Use device part of chainloader target, if present.
+
+Otherwise chainloading is restricted to '$root', which might not even
+be readable by EFI!
+
+v1. use grub_file_get_device_name() to get device name
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/efi/chainloader.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index adc85636633..14ce6ddd7ad 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -223,8 +223,11 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   if (! file)
+     goto fail;
+ 
+-  /* Get the root device's device path.  */
+-  dev = grub_device_open (0);
++  /* Get the device path from filename. */
++  char *devname = grub_file_get_device_name (filename);
++  dev = grub_device_open (devname);
++  if (devname)
++    grub_free (devname);
+   if (! dev)
+     goto fail;
+ 
diff --git a/SOURCES/0220-Add-secureboot-support-on-efi-chainloader.patch b/SOURCES/0220-Add-secureboot-support-on-efi-chainloader.patch
new file mode 100644
index 0000000..15f2968
--- /dev/null
+++ b/SOURCES/0220-Add-secureboot-support-on-efi-chainloader.patch
@@ -0,0 +1,797 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 6 Oct 2015 13:04:37 -0400
+Subject: [PATCH] Add secureboot support on efi chainloader
+
+Expand the chainloader to be able to verify the image by means of shim
+lock protocol. The PE/COFF image is loaded and relocated by the
+chainloader instead of calling LoadImage and StartImage UEFI boot
+Service as they require positive verification result from keys enrolled
+in KEK or DB. The shim will use MOK in addition to firmware enrolled
+keys to verify the image.
+
+The chainloader module could be used to load other UEFI bootloaders,
+such as xen.efi, and could be signed by any of MOK, KEK or DB.
+
+Based on https://build.opensuse.org/package/view_file/openSUSE:Factory/grub2/grub2-secureboot-chainloader.patch
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/efi/chainloader.c | 612 ++++++++++++++++++++++++++++++++++---
+ include/grub/efi/pe32.h            |  20 +-
+ 2 files changed, 595 insertions(+), 37 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 14ce6ddd7ad..87a91e16f17 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -32,6 +32,8 @@
+ #include <grub/efi/api.h>
+ #include <grub/efi/efi.h>
+ #include <grub/efi/disk.h>
++#include <grub/efi/pe32.h>
++#include <grub/efi/linux.h>
+ #include <grub/command.h>
+ #include <grub/i18n.h>
+ #include <grub/net.h>
+@@ -46,9 +48,14 @@ static grub_dl_t my_mod;
+ 
+ static grub_efi_physical_address_t address;
+ static grub_efi_uintn_t pages;
++static grub_ssize_t fsize;
+ static grub_efi_device_path_t *file_path;
+ static grub_efi_handle_t image_handle;
+ static grub_efi_char16_t *cmdline;
++static grub_ssize_t cmdline_len;
++static grub_efi_handle_t dev_handle;
++
++static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table);
+ 
+ static grub_err_t
+ grub_chainloader_unload (void)
+@@ -63,6 +70,7 @@ grub_chainloader_unload (void)
+   grub_free (cmdline);
+   cmdline = 0;
+   file_path = 0;
++  dev_handle = 0;
+ 
+   grub_dl_unref (my_mod);
+   return GRUB_ERR_NONE;
+@@ -191,12 +199,523 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
+   return file_path;
+ }
+ 
++#define SHIM_LOCK_GUID \
++  { 0x605dab50, 0xe046, 0x4300, { 0xab,0xb6,0x3d,0xd8,0x10,0xdd,0x8b,0x23 } }
++
++typedef union
++{
++  struct grub_pe32_header_32 pe32;
++  struct grub_pe32_header_64 pe32plus;
++} grub_pe_header_t;
++
++struct pe_coff_loader_image_context
++{
++  grub_efi_uint64_t image_address;
++  grub_efi_uint64_t image_size;
++  grub_efi_uint64_t entry_point;
++  grub_efi_uintn_t size_of_headers;
++  grub_efi_uint16_t image_type;
++  grub_efi_uint16_t number_of_sections;
++  grub_efi_uint32_t section_alignment;
++  struct grub_pe32_section_table *first_section;
++  struct grub_pe32_data_directory *reloc_dir;
++  struct grub_pe32_data_directory *sec_dir;
++  grub_efi_uint64_t number_of_rva_and_sizes;
++  grub_pe_header_t *pe_hdr;
++};
++
++typedef struct pe_coff_loader_image_context pe_coff_loader_image_context_t;
++
++struct grub_efi_shim_lock
++{
++  grub_efi_status_t (*verify)(void *buffer,
++                              grub_efi_uint32_t size);
++  grub_efi_status_t (*hash)(void *data,
++                            grub_efi_int32_t datasize,
++                            pe_coff_loader_image_context_t *context,
++                            grub_efi_uint8_t *sha256hash,
++                            grub_efi_uint8_t *sha1hash);
++  grub_efi_status_t (*context)(void *data,
++                               grub_efi_uint32_t size,
++                               pe_coff_loader_image_context_t *context);
++};
++
++typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
++
++static grub_efi_boolean_t
++read_header (void *data, grub_efi_uint32_t size,
++	     pe_coff_loader_image_context_t *context)
++{
++  grub_efi_guid_t guid = SHIM_LOCK_GUID;
++  grub_efi_shim_lock_t *shim_lock;
++  grub_efi_status_t status;
++
++  shim_lock = grub_efi_locate_protocol (&guid, NULL);
++
++  if (!shim_lock)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "no shim lock protocol");
++      return 0;
++    }
++
++  status = shim_lock->context (data, size, context);
++
++  if (status == GRUB_EFI_SUCCESS)
++    {
++      grub_dprintf ("chain", "context success\n");
++      return 1;
++    }
++
++  switch (status)
++    {
++      case GRUB_EFI_UNSUPPORTED:
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "context error unsupported");
++      break;
++      case GRUB_EFI_INVALID_PARAMETER:
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "context error invalid parameter");
++      break;
++      default:
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "context error code");
++      break;
++    }
++
++  return 0;
++}
++
++static void*
++image_address (void *image, grub_efi_uint64_t sz, grub_efi_uint64_t adr)
++{
++  if (adr > sz)
++    return NULL;
++
++  return ((grub_uint8_t*)image + adr);
++}
++
++static int
++image_is_64_bit (grub_pe_header_t *pe_hdr)
++{
++  /* .Magic is the same offset in all cases */
++  if (pe_hdr->pe32plus.optional_header.magic == GRUB_PE32_PE64_MAGIC)
++    return 1;
++  return 0;
++}
++
++static const grub_uint16_t machine_type =
++#if defined(__x86_64__)
++  GRUB_PE32_MACHINE_X86_64;
++#elif defined(__aarch64__)
++  GRUB_PE32_MACHINE_ARM64;
++#elif defined(__arm__)
++  GRUB_PE32_MACHINE_ARMTHUMB_MIXED;
++#elif defined(__i386__) || defined(__i486__) || defined(__i686__)
++  GRUB_PE32_MACHINE_I386;
++#elif defined(__ia64__)
++  GRUB_PE32_MACHINE_IA64;
++#else
++#error this architecture is not supported by grub2
++#endif
++
++static grub_efi_status_t
++relocate_coff (pe_coff_loader_image_context_t *context,
++	       struct grub_pe32_section_table *section,
++	       void *orig, void *data)
++{
++  struct grub_pe32_data_directory *reloc_base, *reloc_base_end;
++  grub_efi_uint64_t adjust;
++  struct grub_pe32_fixup_block *reloc, *reloc_end;
++  char *fixup, *fixup_base, *fixup_data = NULL;
++  grub_efi_uint16_t *fixup_16;
++  grub_efi_uint32_t *fixup_32;
++  grub_efi_uint64_t *fixup_64;
++  grub_efi_uint64_t size = context->image_size;
++  void *image_end = (char *)orig + size;
++  int n = 0;
++
++  if (image_is_64_bit (context->pe_hdr))
++    context->pe_hdr->pe32plus.optional_header.image_base =
++      (grub_uint64_t)(unsigned long)data;
++  else
++    context->pe_hdr->pe32.optional_header.image_base =
++      (grub_uint32_t)(unsigned long)data;
++
++  /* Alright, so here's how this works:
++   *
++   * context->reloc_dir gives us two things:
++   * - the VA the table of base relocation blocks are (maybe) to be
++   *   mapped at (reloc_dir->rva)
++   * - the virtual size (reloc_dir->size)
++   *
++   * The .reloc section (section here) gives us some other things:
++   * - the name! kind of. (section->name)
++   * - the virtual size (section->virtual_size), which should be the same
++   *   as RelocDir->Size
++   * - the virtual address (section->virtual_address)
++   * - the file section size (section->raw_data_size), which is
++   *   a multiple of optional_header->file_alignment.  Only useful for image
++   *   validation, not really useful for iteration bounds.
++   * - the file address (section->raw_data_offset)
++   * - a bunch of stuff we don't use that's 0 in our binaries usually
++   * - Flags (section->characteristics)
++   *
++   * and then the thing that's actually at the file address is an array
++   * of struct grub_pe32_fixup_block structs with some values packed behind
++   * them.  The block_size field of this structure includes the
++   * structure itself, and adding it to that structure's address will
++   * yield the next entry in the array.
++   */
++
++  reloc_base = image_address (orig, size, section->raw_data_offset);
++  reloc_base_end = image_address (orig, size, section->raw_data_offset
++				  + section->virtual_size - 1);
++
++  grub_dprintf ("chain", "reloc_base %p reloc_base_end %p\n", reloc_base,
++		reloc_base_end);
++
++  if (!reloc_base && !reloc_base_end)
++    return GRUB_EFI_SUCCESS;
++
++  if (!reloc_base || !reloc_base_end)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc table overflows binary");
++      return GRUB_EFI_UNSUPPORTED;
++    }
++
++  adjust = (grub_uint64_t)data - context->image_address;
++  if (adjust == 0)
++    return GRUB_EFI_SUCCESS;
++
++  while (reloc_base < reloc_base_end)
++    {
++      grub_uint16_t *entry;
++      reloc = (struct grub_pe32_fixup_block *)((char*)reloc_base);
++
++      if ((reloc_base->size == 0) ||
++	  (reloc_base->size > context->reloc_dir->size))
++	{
++	  grub_error (GRUB_ERR_BAD_ARGUMENT,
++		      "Reloc %d block size %d is invalid\n", n,
++		      reloc_base->size);
++	  return GRUB_EFI_UNSUPPORTED;
++	}
++
++      entry = &reloc->entries[0];
++      reloc_end = (struct grub_pe32_fixup_block *)
++	((char *)reloc_base + reloc_base->size);
++
++      if ((void *)reloc_end < data || (void *)reloc_end > image_end)
++        {
++          grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc entry %d overflows binary",
++		      n);
++          return GRUB_EFI_UNSUPPORTED;
++        }
++
++      fixup_base = image_address(data, size, reloc_base->rva);
++
++      if (!fixup_base)
++        {
++          grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc %d Invalid fixupbase", n);
++          return GRUB_EFI_UNSUPPORTED;
++        }
++
++      while ((void *)entry < (void *)reloc_end)
++        {
++          fixup = fixup_base + (*entry & 0xFFF);
++          switch ((*entry) >> 12)
++            {
++              case GRUB_PE32_REL_BASED_ABSOLUTE:
++                break;
++              case GRUB_PE32_REL_BASED_HIGH:
++                fixup_16 = (grub_uint16_t *)fixup;
++                *fixup_16 = (grub_uint16_t)
++		  (*fixup_16 + ((grub_uint16_t)((grub_uint32_t)adjust >> 16)));
++                if (fixup_data != NULL)
++                  {
++                    *(grub_uint16_t *) fixup_data = *fixup_16;
++                    fixup_data = fixup_data + sizeof (grub_uint16_t);
++                  }
++                break;
++              case GRUB_PE32_REL_BASED_LOW:
++                fixup_16 = (grub_uint16_t *)fixup;
++                *fixup_16 = (grub_uint16_t) (*fixup_16 + (grub_uint16_t)adjust);
++                if (fixup_data != NULL)
++                  {
++                    *(grub_uint16_t *) fixup_data = *fixup_16;
++                    fixup_data = fixup_data + sizeof (grub_uint16_t);
++                  }
++                break;
++              case GRUB_PE32_REL_BASED_HIGHLOW:
++                fixup_32 = (grub_uint32_t *)fixup;
++                *fixup_32 = *fixup_32 + (grub_uint32_t)adjust;
++                if (fixup_data != NULL)
++                  {
++                    fixup_data = (char *)ALIGN_UP ((grub_addr_t)fixup_data, sizeof (grub_uint32_t));
++                    *(grub_uint32_t *) fixup_data = *fixup_32;
++                    fixup_data += sizeof (grub_uint32_t);
++                  }
++                break;
++              case GRUB_PE32_REL_BASED_DIR64:
++                fixup_64 = (grub_uint64_t *)fixup;
++                *fixup_64 = *fixup_64 + (grub_uint64_t)adjust;
++                if (fixup_data != NULL)
++                  {
++                    fixup_data = (char *)ALIGN_UP ((grub_addr_t)fixup_data, sizeof (grub_uint64_t));
++                    *(grub_uint64_t *) fixup_data = *fixup_64;
++                    fixup_data += sizeof (grub_uint64_t);
++                  }
++                break;
++              default:
++                grub_error (GRUB_ERR_BAD_ARGUMENT,
++			    "Reloc %d unknown relocation type %d",
++			    n, (*entry) >> 12);
++                return GRUB_EFI_UNSUPPORTED;
++            }
++          entry += 1;
++        }
++      reloc_base = (struct grub_pe32_data_directory *)reloc_end;
++      n++;
++    }
++
++  return GRUB_EFI_SUCCESS;
++}
++
++static grub_efi_device_path_t *
++grub_efi_get_media_file_path (grub_efi_device_path_t *dp)
++{
++  while (1)
++    {
++      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
++      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
++
++      if (type == GRUB_EFI_END_DEVICE_PATH_TYPE)
++        break;
++      else if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
++            && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
++      return dp;
++
++      dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
++    }
++
++    return NULL;
++}
++
++static grub_efi_boolean_t
++handle_image (void *data, grub_efi_uint32_t datasize)
++{
++  grub_efi_boot_services_t *b;
++  grub_efi_loaded_image_t *li, li_bak;
++  grub_efi_status_t efi_status;
++  char *buffer = NULL;
++  char *buffer_aligned = NULL;
++  grub_efi_uint32_t i, size;
++  struct grub_pe32_section_table *section;
++  char *base, *end;
++  pe_coff_loader_image_context_t context;
++  grub_uint32_t section_alignment;
++  grub_uint32_t buffer_size;
++
++  b = grub_efi_system_table->boot_services;
++
++  if (read_header (data, datasize, &context))
++    {
++      grub_dprintf ("chain", "Succeed to read header\n");
++    }
++  else
++    {
++      grub_dprintf ("chain", "Failed to read header\n");
++      goto error_exit;
++    }
++
++  section_alignment = context.section_alignment;
++  buffer_size = context.image_size + section_alignment;
++
++  efi_status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA,
++			   buffer_size, &buffer);
++
++  if (efi_status != GRUB_EFI_SUCCESS)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++      goto error_exit;
++    }
++
++  buffer_aligned = (char *)ALIGN_UP ((grub_addr_t)buffer, section_alignment);
++
++  if (!buffer_aligned)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++      goto error_exit;
++    }
++
++  grub_memcpy (buffer_aligned, data, context.size_of_headers);
++
++  char *reloc_base, *reloc_base_end;
++  reloc_base = image_address (buffer_aligned, datasize,
++			      context.reloc_dir->rva);
++  /* RelocBaseEnd here is the address of the last byte of the table */
++  reloc_base_end = image_address (buffer_aligned, datasize,
++				  context.reloc_dir->rva
++				  + context.reloc_dir->size - 1);
++  struct grub_pe32_section_table *reloc_section = NULL;
++
++  section = context.first_section;
++  for (i = 0; i < context.number_of_sections; i++, section++)
++    {
++      size = section->virtual_size;
++      if (size > section->raw_data_size)
++        size = section->raw_data_size;
++
++      base = image_address (buffer_aligned, context.image_size,
++			    section->virtual_address);
++      end = image_address (buffer_aligned, context.image_size,
++			   section->virtual_address + size - 1);
++
++
++      /* We do want to process .reloc, but it's often marked
++       * discardable, so we don't want to memcpy it. */
++      if (grub_memcmp (section->name, ".reloc\0\0", 8) == 0)
++	{
++	  if (reloc_section)
++	    {
++	      grub_error (GRUB_ERR_BAD_ARGUMENT,
++			  "Image has multiple relocation sections");
++	      goto error_exit;
++	    }
++
++	  /* If it has nonzero sizes, and our bounds check
++	   * made sense, and the VA and size match RelocDir's
++	   * versions, then we believe in this section table. */
++	  if (section->raw_data_size && section->virtual_size &&
++	      base && end && reloc_base == base && reloc_base_end == end)
++	    {
++	      reloc_section = section;
++	    }
++	}
++
++      if (section->characteristics && GRUB_PE32_SCN_MEM_DISCARDABLE)
++	continue;
++
++      if (!base || !end)
++        {
++          grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid section size");
++          goto error_exit;
++        }
++
++      if (section->virtual_address < context.size_of_headers ||
++	  section->raw_data_offset < context.size_of_headers)
++	{
++	  grub_error (GRUB_ERR_BAD_ARGUMENT,
++		      "Section %d is inside image headers", i);
++	  goto error_exit;
++	}
++
++      if (section->raw_data_size > 0)
++        grub_memcpy (base, (grub_efi_uint8_t*)data + section->raw_data_offset,
++		     size);
++
++      if (size < section->virtual_size)
++        grub_memset (base + size, 0, section->virtual_size - size);
++
++      grub_dprintf ("chain", "copied section %s\n", section->name);
++    }
++
++  /* 5 == EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC */
++  if (context.number_of_rva_and_sizes <= 5)
++    {
++      grub_dprintf ("chain", "image has no relocation entry\n");
++      goto error_exit;
++    }
++
++  if (context.reloc_dir->size && reloc_section)
++    {
++      /* run the relocation fixups */
++      efi_status = relocate_coff (&context, reloc_section, data,
++				  buffer_aligned);
++
++      if (efi_status != GRUB_EFI_SUCCESS)
++	{
++	  grub_error (GRUB_ERR_BAD_ARGUMENT, "relocation failed");
++	  goto error_exit;
++	}
++    }
++
++  entry_point = image_address (buffer_aligned, context.image_size,
++			       context.entry_point);
++
++  if (!entry_point)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid entry point");
++      goto error_exit;
++    }
++
++  li = grub_efi_get_loaded_image (grub_efi_image_handle);
++  if (!li)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "no loaded image available");
++      goto error_exit;
++    }
++
++  grub_memcpy (&li_bak, li, sizeof (grub_efi_loaded_image_t));
++  li->image_base = buffer_aligned;
++  li->image_size = context.image_size;
++  li->load_options = cmdline;
++  li->load_options_size = cmdline_len;
++  li->file_path = grub_efi_get_media_file_path (file_path);
++  li->device_handle = dev_handle;
++  if (li->file_path)
++    {
++      grub_printf ("file path: ");
++      grub_efi_print_device_path (li->file_path);
++    }
++  else
++    {
++      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found");
++      goto error_exit;
++    }
++
++  efi_status = efi_call_2 (entry_point, grub_efi_image_handle,
++			   grub_efi_system_table);
++
++  grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t));
++  efi_status = efi_call_1 (b->free_pool, buffer);
++
++  return 1;
++
++error_exit:
++  if (buffer)
++      efi_call_1 (b->free_pool, buffer);
++
++  return 0;
++}
++
++static grub_err_t
++grub_secureboot_chainloader_unload (void)
++{
++  grub_efi_boot_services_t *b;
++
++  b = grub_efi_system_table->boot_services;
++  efi_call_2 (b->free_pages, address, pages);
++  grub_free (file_path);
++  grub_free (cmdline);
++  cmdline = 0;
++  file_path = 0;
++  dev_handle = 0;
++
++  grub_dl_unref (my_mod);
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_secureboot_chainloader_boot (void)
++{
++  handle_image ((void *)address, fsize);
++  grub_loader_unset ();
++  return grub_errno;
++}
++
+ static grub_err_t
+ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ 		      int argc, char *argv[])
+ {
+   grub_file_t file = 0;
+-  grub_ssize_t size;
+   grub_efi_status_t status;
+   grub_efi_boot_services_t *b;
+   grub_device_t dev = 0;
+@@ -204,7 +723,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   grub_efi_loaded_image_t *loaded_image;
+   char *filename;
+   void *boot_image = 0;
+-  grub_efi_handle_t dev_handle = 0;
+ 
+   if (argc == 0)
+     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+@@ -216,9 +734,36 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   address = 0;
+   image_handle = 0;
+   file_path = 0;
++  dev_handle = 0;
+ 
+   b = grub_efi_system_table->boot_services;
+ 
++  if (argc > 1)
++    {
++      int i;
++      grub_efi_char16_t *p16;
++
++      for (i = 1, cmdline_len = 0; i < argc; i++)
++        cmdline_len += grub_strlen (argv[i]) + 1;
++
++      cmdline_len *= sizeof (grub_efi_char16_t);
++      cmdline = p16 = grub_malloc (cmdline_len);
++      if (! cmdline)
++        goto fail;
++
++      for (i = 1; i < argc; i++)
++        {
++          char *p8;
++
++          p8 = argv[i];
++          while (*p8)
++            *(p16++) = *(p8++);
++
++          *(p16++) = ' ';
++        }
++      *(--p16) = 0;
++    }
++
+   file = grub_file_open (filename);
+   if (! file)
+     goto fail;
+@@ -267,14 +812,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   grub_printf ("file path: ");
+   grub_efi_print_device_path (file_path);
+ 
+-  size = grub_file_size (file);
+-  if (!size)
++  fsize = grub_file_size (file);
++  if (!fsize)
+     {
+       grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+ 		  filename);
+       goto fail;
+     }
+-  pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12);
++  pages = (((grub_efi_uintn_t) fsize + ((1 << 12) - 1)) >> 12);
+ 
+   status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES,
+ 			      GRUB_EFI_LOADER_CODE,
+@@ -288,7 +833,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+     }
+ 
+   boot_image = (void *) ((grub_addr_t) address);
+-  if (grub_file_read (file, boot_image, size) != size)
++  if (grub_file_read (file, boot_image, fsize) != fsize)
+     {
+       if (grub_errno == GRUB_ERR_NONE)
+ 	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+@@ -298,7 +843,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+     }
+ 
+ #if defined (__i386__) || defined (__x86_64__)
+-  if (size >= (grub_ssize_t) sizeof (struct grub_macho_fat_header))
++  if (fsize >= (grub_ssize_t) sizeof (struct grub_macho_fat_header))
+     {
+       struct grub_macho_fat_header *head = boot_image;
+       if (head->magic
+@@ -307,6 +852,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ 	  grub_uint32_t i;
+ 	  struct grub_macho_fat_arch *archs
+ 	    = (struct grub_macho_fat_arch *) (head + 1);
++
++	  if (grub_efi_secure_boot())
++	    {
++	      grub_error (GRUB_ERR_BAD_OS,
++			  "MACHO binaries are forbidden with Secure Boot");
++	      goto fail;
++	    }
++
+ 	  for (i = 0; i < grub_cpu_to_le32 (head->nfat_arch); i++)
+ 	    {
+ 	      if (GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT (archs[i].cputype))
+@@ -321,21 +874,28 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ 	      > ~grub_cpu_to_le32 (archs[i].size)
+ 	      || grub_cpu_to_le32 (archs[i].offset)
+ 	      + grub_cpu_to_le32 (archs[i].size)
+-	      > (grub_size_t) size)
++	      > (grub_size_t) fsize)
+ 	    {
+ 	      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+ 			  filename);
+ 	      goto fail;
+ 	    }
+ 	  boot_image = (char *) boot_image + grub_cpu_to_le32 (archs[i].offset);
+-	  size = grub_cpu_to_le32 (archs[i].size);
++	  fsize = grub_cpu_to_le32 (archs[i].size);
+ 	}
+     }
+ #endif
+ 
++  if (grub_linuxefi_secure_validate((void *)address, fsize))
++    {
++      grub_file_close (file);
++      grub_loader_set (grub_secureboot_chainloader_boot,
++		       grub_secureboot_chainloader_unload, 0);
++      return 0;
++    }
++
+   status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
+-		       boot_image, size,
+-		       &image_handle);
++		       boot_image, fsize, &image_handle);
+   if (status != GRUB_EFI_SUCCESS)
+     {
+       if (status == GRUB_EFI_OUT_OF_RESOURCES)
+@@ -357,33 +917,10 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+     }
+   loaded_image->device_handle = dev_handle;
+ 
+-  if (argc > 1)
++  if (cmdline)
+     {
+-      int i, len;
+-      grub_efi_char16_t *p16;
+-
+-      for (i = 1, len = 0; i < argc; i++)
+-        len += grub_strlen (argv[i]) + 1;
+-
+-      len *= sizeof (grub_efi_char16_t);
+-      cmdline = p16 = grub_malloc (len);
+-      if (! cmdline)
+-        goto fail;
+-
+-      for (i = 1; i < argc; i++)
+-        {
+-          char *p8;
+-
+-          p8 = argv[i];
+-          while (*p8)
+-            *(p16++) = *(p8++);
+-
+-          *(p16++) = ' ';
+-        }
+-      *(--p16) = 0;
+-
+       loaded_image->load_options = cmdline;
+-      loaded_image->load_options_size = len;
++      loaded_image->load_options_size = cmdline_len;
+     }
+ 
+   grub_file_close (file);
+@@ -405,6 +942,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   if (address)
+     efi_call_2 (b->free_pages, address, pages);
+ 
++  if (cmdline)
++    grub_free (cmdline);
++
+   grub_dl_unref (my_mod);
+ 
+   return grub_errno;
+diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
+index f79c36c026e..f79782e1bde 100644
+--- a/include/grub/efi/pe32.h
++++ b/include/grub/efi/pe32.h
+@@ -212,7 +212,11 @@ struct grub_pe64_optional_header
+ struct grub_pe32_section_table
+ {
+   char name[8];
+-  grub_uint32_t virtual_size;
++  union
++    {
++      grub_uint32_t physical_address;
++      grub_uint32_t virtual_size;
++    };
+   grub_uint32_t virtual_address;
+   grub_uint32_t raw_data_size;
+   grub_uint32_t raw_data_offset;
+@@ -263,6 +267,20 @@ struct grub_pe32_header
+ #endif
+ };
+ 
++struct grub_pe32_header_32
++{
++  char signature[GRUB_PE32_SIGNATURE_SIZE];
++  struct grub_pe32_coff_header coff_header;
++  struct grub_pe32_optional_header optional_header;
++};
++
++struct grub_pe32_header_64
++{
++  char signature[GRUB_PE32_SIGNATURE_SIZE];
++  struct grub_pe32_coff_header coff_header;
++  struct grub_pe64_optional_header optional_header;
++};
++
+ struct grub_pe32_fixup_block
+ {
+   grub_uint32_t page_rva;
diff --git a/SOURCES/0221-Make-any-of-the-loaders-that-link-in-efi-mode-honor-.patch b/SOURCES/0221-Make-any-of-the-loaders-that-link-in-efi-mode-honor-.patch
new file mode 100644
index 0000000..7b98145
--- /dev/null
+++ b/SOURCES/0221-Make-any-of-the-loaders-that-link-in-efi-mode-honor-.patch
@@ -0,0 +1,492 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 6 Oct 2015 16:09:25 -0400
+Subject: [PATCH] Make any of the loaders that link in efi mode honor secure
+ boot.
+
+And in this case "honor" means "even if somebody does link this in, they
+won't register commands if SB is enabled."
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/Makefile.core.def        |  2 ++
+ grub-core/commands/iorw.c          |  7 +++++
+ grub-core/commands/memrw.c         |  7 +++++
+ grub-core/kern/efi/efi.c           | 28 ------------------
+ grub-core/kern/efi/sb.c            | 58 ++++++++++++++++++++++++++++++++++++++
+ grub-core/loader/efi/appleloader.c |  7 +++++
+ grub-core/loader/efi/chainloader.c |  1 +
+ grub-core/loader/i386/bsd.c        |  7 +++++
+ grub-core/loader/i386/linux.c      |  7 +++++
+ grub-core/loader/i386/pc/linux.c   |  7 +++++
+ grub-core/loader/multiboot.c       |  7 +++++
+ grub-core/loader/xnu.c             |  7 +++++
+ include/grub/efi/efi.h             |  1 -
+ include/grub/efi/sb.h              | 29 +++++++++++++++++++
+ include/grub/ia64/linux.h          |  0
+ include/grub/mips/linux.h          |  0
+ include/grub/powerpc/linux.h       |  0
+ include/grub/sparc64/linux.h       |  0
+ grub-core/Makefile.am              |  1 +
+ 19 files changed, 147 insertions(+), 29 deletions(-)
+ create mode 100644 grub-core/kern/efi/sb.c
+ create mode 100644 include/grub/efi/sb.h
+ create mode 100644 include/grub/ia64/linux.h
+ create mode 100644 include/grub/mips/linux.h
+ create mode 100644 include/grub/powerpc/linux.h
+ create mode 100644 include/grub/sparc64/linux.h
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 4fc74393335..b340ceeec7f 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -175,6 +175,8 @@ kernel = {
+   efi = term/efi/console.c;
+   efi = lib/envblk.c;
+ 
++  common = kern/efi/sb.c;
++
+   x86 = kern/i386/tsc.c;
+ 
+   i386_efi = kern/i386/efi/init.c;
+diff --git a/grub-core/commands/iorw.c b/grub-core/commands/iorw.c
+index a0c164e54f0..41a7f3f0466 100644
+--- a/grub-core/commands/iorw.c
++++ b/grub-core/commands/iorw.c
+@@ -23,6 +23,7 @@
+ #include <grub/env.h>
+ #include <grub/cpu/io.h>
+ #include <grub/i18n.h>
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -118,6 +119,9 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv)
+ 
+ GRUB_MOD_INIT(memrw)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   cmd_read_byte =
+     grub_register_extcmd ("inb", grub_cmd_read, 0,
+ 			  N_("PORT"), N_("Read 8-bit value from PORT."),
+@@ -146,6 +150,9 @@ GRUB_MOD_INIT(memrw)
+ 
+ GRUB_MOD_FINI(memrw)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   grub_unregister_extcmd (cmd_read_byte);
+   grub_unregister_extcmd (cmd_read_word);
+   grub_unregister_extcmd (cmd_read_dword);
+diff --git a/grub-core/commands/memrw.c b/grub-core/commands/memrw.c
+index 98769eadb34..088cbe9e2bc 100644
+--- a/grub-core/commands/memrw.c
++++ b/grub-core/commands/memrw.c
+@@ -22,6 +22,7 @@
+ #include <grub/extcmd.h>
+ #include <grub/env.h>
+ #include <grub/i18n.h>
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -120,6 +121,9 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv)
+ 
+ GRUB_MOD_INIT(memrw)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   cmd_read_byte =
+     grub_register_extcmd ("read_byte", grub_cmd_read, 0,
+ 			  N_("ADDR"), N_("Read 8-bit value from ADDR."),
+@@ -148,6 +152,9 @@ GRUB_MOD_INIT(memrw)
+ 
+ GRUB_MOD_FINI(memrw)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   grub_unregister_extcmd (cmd_read_byte);
+   grub_unregister_extcmd (cmd_read_word);
+   grub_unregister_extcmd (cmd_read_dword);
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index c80d85b677e..7dfe2ef1455 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -260,34 +260,6 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
+   return NULL;
+ }
+ 
+-grub_efi_boolean_t
+-grub_efi_secure_boot (void)
+-{
+-  grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
+-  grub_size_t datasize;
+-  char *secure_boot = NULL;
+-  char *setup_mode = NULL;
+-  grub_efi_boolean_t ret = 0;
+-
+-  secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
+-
+-  if (datasize != 1 || !secure_boot)
+-    goto out;
+-
+-  setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
+-
+-  if (datasize != 1 || !setup_mode)
+-    goto out;
+-
+-  if (*secure_boot && !*setup_mode)
+-    ret = 1;
+-
+- out:
+-  grub_free (secure_boot);
+-  grub_free (setup_mode);
+-  return ret;
+-}
+-
+ #pragma GCC diagnostic ignored "-Wcast-align"
+ 
+ /* Search the mods section from the PE32/PE32+ image. This code uses
+diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
+new file mode 100644
+index 00000000000..a41b6c5b851
+--- /dev/null
++++ b/grub-core/kern/efi/sb.c
+@@ -0,0 +1,58 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2014 Free Software Foundation, Inc.
++ *
++ *  GRUB 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 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <grub/err.h>
++#include <grub/mm.h>
++#include <grub/types.h>
++#include <grub/cpu/linux.h>
++#include <grub/efi/efi.h>
++#include <grub/efi/pe32.h>
++#include <grub/efi/linux.h>
++#include <grub/efi/sb.h>
++
++int
++grub_efi_secure_boot (void)
++{
++#ifdef GRUB_MACHINE_EFI
++  grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
++  grub_size_t datasize;
++  char *secure_boot = NULL;
++  char *setup_mode = NULL;
++  grub_efi_boolean_t ret = 0;
++
++  secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
++
++  if (datasize != 1 || !secure_boot)
++    goto out;
++
++  setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
++
++  if (datasize != 1 || !setup_mode)
++    goto out;
++
++  if (*secure_boot && !*setup_mode)
++    ret = 1;
++
++ out:
++  grub_free (secure_boot);
++  grub_free (setup_mode);
++  return ret;
++#else
++  return 0;
++#endif
++}
+diff --git a/grub-core/loader/efi/appleloader.c b/grub-core/loader/efi/appleloader.c
+index 74888c463ba..69c2a10d351 100644
+--- a/grub-core/loader/efi/appleloader.c
++++ b/grub-core/loader/efi/appleloader.c
+@@ -24,6 +24,7 @@
+ #include <grub/misc.h>
+ #include <grub/efi/api.h>
+ #include <grub/efi/efi.h>
++#include <grub/efi/sb.h>
+ #include <grub/command.h>
+ #include <grub/i18n.h>
+ 
+@@ -227,6 +228,9 @@ static grub_command_t cmd;
+ 
+ GRUB_MOD_INIT(appleloader)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   cmd = grub_register_command ("appleloader", grub_cmd_appleloader,
+ 			       N_("[OPTS]"),
+ 			       /* TRANSLATORS: This command is used on EFI to
+@@ -238,5 +242,8 @@ GRUB_MOD_INIT(appleloader)
+ 
+ GRUB_MOD_FINI(appleloader)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   grub_unregister_command (cmd);
+ }
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 87a91e16f17..aee8e6becf6 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -34,6 +34,7 @@
+ #include <grub/efi/disk.h>
+ #include <grub/efi/pe32.h>
+ #include <grub/efi/linux.h>
++#include <grub/efi/sb.h>
+ #include <grub/command.h>
+ #include <grub/i18n.h>
+ #include <grub/net.h>
+diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c
+index 8f691e0e2d1..b671f59b62a 100644
+--- a/grub-core/loader/i386/bsd.c
++++ b/grub-core/loader/i386/bsd.c
+@@ -38,6 +38,7 @@
+ #ifdef GRUB_MACHINE_PCBIOS
+ #include <grub/machine/int.h>
+ #endif
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -2111,6 +2112,9 @@ static grub_command_t cmd_netbsd_module_elf, cmd_openbsd_ramdisk;
+ 
+ GRUB_MOD_INIT (bsd)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   /* Net and OpenBSD kernels are often compressed.  */
+   grub_dl_load ("gzio");
+ 
+@@ -2150,6 +2154,9 @@ GRUB_MOD_INIT (bsd)
+ 
+ GRUB_MOD_FINI (bsd)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   grub_unregister_extcmd (cmd_freebsd);
+   grub_unregister_extcmd (cmd_openbsd);
+   grub_unregister_extcmd (cmd_netbsd);
+diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
+index 2ae176315b6..bd37c69b5d0 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -35,6 +35,7 @@
+ #include <grub/i18n.h>
+ #include <grub/lib/cmdline.h>
+ #include <grub/linux.h>
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -1137,6 +1138,9 @@ static grub_command_t cmd_linux, cmd_initrd;
+ 
+ GRUB_MOD_INIT(linux)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   cmd_linux = grub_register_command ("linux", grub_cmd_linux,
+ 				     0, N_("Load Linux."));
+   cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
+@@ -1146,6 +1150,9 @@ GRUB_MOD_INIT(linux)
+ 
+ GRUB_MOD_FINI(linux)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   grub_unregister_command (cmd_linux);
+   grub_unregister_command (cmd_initrd);
+ }
+diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
+index b481e466846..b19527e8e17 100644
+--- a/grub-core/loader/i386/pc/linux.c
++++ b/grub-core/loader/i386/pc/linux.c
+@@ -35,6 +35,7 @@
+ #include <grub/i386/floppy.h>
+ #include <grub/lib/cmdline.h>
+ #include <grub/linux.h>
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -469,6 +470,9 @@ static grub_command_t cmd_linux, cmd_initrd;
+ 
+ GRUB_MOD_INIT(linux16)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   cmd_linux =
+     grub_register_command ("linux16", grub_cmd_linux,
+ 			   0, N_("Load Linux."));
+@@ -480,6 +484,9 @@ GRUB_MOD_INIT(linux16)
+ 
+ GRUB_MOD_FINI(linux16)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   grub_unregister_command (cmd_linux);
+   grub_unregister_command (cmd_initrd);
+ }
+diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
+index 4b71f336353..e4e696e8f89 100644
+--- a/grub-core/loader/multiboot.c
++++ b/grub-core/loader/multiboot.c
+@@ -42,6 +42,7 @@
+ #include <grub/video.h>
+ #include <grub/memory.h>
+ #include <grub/i18n.h>
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -383,6 +384,9 @@ static grub_command_t cmd_multiboot, cmd_module;
+ 
+ GRUB_MOD_INIT(multiboot)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   cmd_multiboot =
+ #ifdef GRUB_USE_MULTIBOOT2
+     grub_register_command ("multiboot2", grub_cmd_multiboot,
+@@ -403,6 +407,9 @@ GRUB_MOD_INIT(multiboot)
+ 
+ GRUB_MOD_FINI(multiboot)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   grub_unregister_command (cmd_multiboot);
+   grub_unregister_command (cmd_module);
+ }
+diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
+index cdd9715cedd..faffccc9744 100644
+--- a/grub-core/loader/xnu.c
++++ b/grub-core/loader/xnu.c
+@@ -33,6 +33,7 @@
+ #include <grub/extcmd.h>
+ #include <grub/env.h>
+ #include <grub/i18n.h>
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -1466,6 +1467,9 @@ static grub_extcmd_t cmd_splash;
+ 
+ GRUB_MOD_INIT(xnu)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+   cmd_kernel = grub_register_command ("xnu_kernel", grub_cmd_xnu_kernel, 0,
+ 				      N_("Load XNU image."));
+   cmd_kernel64 = grub_register_command ("xnu_kernel64", grub_cmd_xnu_kernel64,
+@@ -1506,6 +1510,9 @@ GRUB_MOD_INIT(xnu)
+ 
+ GRUB_MOD_FINI(xnu)
+ {
++  if (grub_efi_secure_boot())
++    return;
++
+ #ifndef GRUB_MACHINE_EMU
+   grub_unregister_command (cmd_resume);
+ #endif
+diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
+index 22456327e13..9a2da0eb38d 100644
+--- a/include/grub/efi/efi.h
++++ b/include/grub/efi/efi.h
+@@ -76,7 +76,6 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var,
+ 				     const grub_efi_guid_t *guid,
+ 				     void *data,
+ 				     grub_size_t datasize);
+-grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void);
+ int
+ EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
+ 					     const grub_efi_device_path_t *dp2);
+diff --git a/include/grub/efi/sb.h b/include/grub/efi/sb.h
+new file mode 100644
+index 00000000000..9629fbb0f9e
+--- /dev/null
++++ b/include/grub/efi/sb.h
+@@ -0,0 +1,29 @@
++/* sb.h - declare functions for EFI Secure Boot support */
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2006,2007,2008,2009  Free Software Foundation, Inc.
++ *
++ *  GRUB 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 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef GRUB_EFI_SB_HEADER
++#define GRUB_EFI_SB_HEADER	1
++
++#include <grub/types.h>
++#include <grub/dl.h>
++
++/* Functions.  */
++int EXPORT_FUNC (grub_efi_secure_boot) (void);
++
++#endif /* ! GRUB_EFI_SB_HEADER */
+diff --git a/include/grub/ia64/linux.h b/include/grub/ia64/linux.h
+new file mode 100644
+index 00000000000..e69de29bb2d
+diff --git a/include/grub/mips/linux.h b/include/grub/mips/linux.h
+new file mode 100644
+index 00000000000..e69de29bb2d
+diff --git a/include/grub/powerpc/linux.h b/include/grub/powerpc/linux.h
+new file mode 100644
+index 00000000000..e69de29bb2d
+diff --git a/include/grub/sparc64/linux.h b/include/grub/sparc64/linux.h
+new file mode 100644
+index 00000000000..e69de29bb2d
+diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
+index cb7fd9f98e8..be29e327f77 100644
+--- a/grub-core/Makefile.am
++++ b/grub-core/Makefile.am
+@@ -67,6 +67,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/device.h
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/disk.h
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dl.h
++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/sb.h
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env.h
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env_private.h
+ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/err.h
diff --git a/SOURCES/0222-Rework-linux-command.patch b/SOURCES/0222-Rework-linux-command.patch
new file mode 100644
index 0000000..faab6c2
--- /dev/null
+++ b/SOURCES/0222-Rework-linux-command.patch
@@ -0,0 +1,104 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Matthew Garrett <mjg59@coreos.com>
+Date: Sun, 9 Aug 2015 16:12:39 -0700
+Subject: [PATCH] Rework linux command
+
+We want a single buffer that contains the entire kernel image in order to
+perform a TPM measurement. Allocate one and copy the entire kernel into it
+before pulling out the individual blocks later on.
+---
+ grub-core/loader/i386/linux.c | 34 +++++++++++++++++++++-------------
+ 1 file changed, 21 insertions(+), 13 deletions(-)
+
+diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
+index bd37c69b5d0..53f74ae0685 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -682,12 +682,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_file_t file = 0;
+   struct linux_kernel_header lh;
+   grub_uint8_t setup_sects;
+-  grub_size_t real_size, prot_size, prot_file_size;
++  grub_size_t real_size, prot_size, prot_file_size, kernel_offset;
+   grub_ssize_t len;
+   int i;
+   grub_size_t align, min_align;
+   int relocatable;
+   grub_uint64_t preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
++  grub_uint8_t *kernel = NULL;
+ 
+   grub_dl_ref (my_mod);
+ 
+@@ -701,7 +702,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   if (! file)
+     goto fail;
+ 
+-  if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
++  len = grub_file_size (file);
++  kernel = grub_malloc (len);
++  if (!kernel)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
++      goto fail;
++    }
++
++  if (grub_file_read (file, kernel, len) != len)
+     {
+       if (!grub_errno)
+ 	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+@@ -709,6 +718,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
++  grub_memcpy (&lh, kernel, sizeof (lh));
++  kernel_offset = sizeof (lh);
++
+   if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
+     {
+       grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
+@@ -808,13 +820,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   linux_params.ps_mouse = linux_params.padding10 =  0;
+ 
+   len = sizeof (linux_params) - sizeof (lh);
+-  if (grub_file_read (file, (char *) &linux_params + sizeof (lh), len) != len)
+-    {
+-      if (!grub_errno)
+-	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+-		    argv[0]);
+-      goto fail;
+-    }
++
++  grub_memcpy (&linux_params + sizeof (lh), kernel + kernel_offset, len);
++  kernel_offset += len;
+ 
+   linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
+ 
+@@ -873,7 +881,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+   /* The other parameters are filled when booting.  */
+ 
+-  grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
++  kernel_offset = real_size + GRUB_DISK_SECTOR_SIZE;
+ 
+   grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
+ 		(unsigned) real_size, (unsigned) prot_size);
+@@ -1018,9 +1026,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 			      - (sizeof (LINUX_IMAGE) - 1));
+ 
+   len = prot_file_size;
+-  if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno)
+-    grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+-		argv[0]);
++  grub_memcpy (prot_mode_mem, kernel + kernel_offset, len);
+ 
+   if (grub_errno == GRUB_ERR_NONE)
+     {
+@@ -1031,6 +1037,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+  fail:
+ 
++  grub_free (kernel);
++
+   if (file)
+     grub_file_close (file);
+ 
diff --git a/SOURCES/0223-Rework-linux16-command.patch b/SOURCES/0223-Rework-linux16-command.patch
new file mode 100644
index 0000000..37c7671
--- /dev/null
+++ b/SOURCES/0223-Rework-linux16-command.patch
@@ -0,0 +1,153 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Matthew Garrett <mjg59@coreos.com>
+Date: Sun, 9 Aug 2015 16:20:58 -0700
+Subject: [PATCH] Rework linux16 command
+
+We want a single buffer that contains the entire kernel image in order to
+perform a TPM measurement. Allocate one and copy the entire kernel int it
+before pulling out the individual blocks later on.
+---
+ grub-core/loader/i386/pc/linux.c | 54 +++++++++++++++++++++++-----------------
+ 1 file changed, 31 insertions(+), 23 deletions(-)
+
+diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
+index b19527e8e17..60bb31fbf0d 100644
+--- a/grub-core/loader/i386/pc/linux.c
++++ b/grub-core/loader/i386/pc/linux.c
+@@ -124,13 +124,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_file_t file = 0;
+   struct linux_kernel_header lh;
+   grub_uint8_t setup_sects;
+-  grub_size_t real_size;
++  grub_size_t real_size, kernel_offset = 0;
+   grub_ssize_t len;
+   int i;
+   char *grub_linux_prot_chunk;
+   int grub_linux_is_bzimage;
+   grub_addr_t grub_linux_prot_target;
+   grub_err_t err;
++  grub_uint8_t *kernel = NULL;
+ 
+   grub_dl_ref (my_mod);
+ 
+@@ -144,7 +145,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   if (! file)
+     goto fail;
+ 
+-  if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
++  len = grub_file_size (file);
++  kernel = grub_malloc (len);
++  if (!kernel)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
++      goto fail;
++    }
++
++  if (grub_file_read (file, kernel, len) != len)
+     {
+       if (!grub_errno)
+ 	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+@@ -152,7 +161,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-  if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
++  grub_memcpy (&lh, kernel, sizeof (lh));
++  kernel_offset = sizeof (lh);
++
++  if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
+     {
+       grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
+       goto fail;
+@@ -170,7 +182,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+   maximal_cmdline_size = 256;
+ 
+-  if (lh.header == grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE)
++  if (lh.header == grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+       && grub_le_to_cpu16 (lh.version) >= 0x0200)
+     {
+       grub_linux_is_bzimage = (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL);
+@@ -189,7 +201,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+       if (grub_le_to_cpu16 (lh.version) >= 0x0201)
+ 	{
+-	  lh.heap_end_ptr = grub_cpu_to_le16 (GRUB_LINUX_HEAP_END_OFFSET);
++	  lh.heap_end_ptr = grub_cpu_to_le32_compile_time (GRUB_LINUX_HEAP_END_OFFSET);
+ 	  lh.loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP;
+ 	}
+ 
+@@ -197,17 +209,17 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 	lh.cmd_line_ptr = grub_linux_real_target + GRUB_LINUX_CL_OFFSET;
+       else
+ 	{
+-	  lh.cl_magic = grub_cpu_to_le16 (GRUB_LINUX_CL_MAGIC);
+-	  lh.cl_offset = grub_cpu_to_le16 (GRUB_LINUX_CL_OFFSET);
+-	  lh.setup_move_size = grub_cpu_to_le16 (GRUB_LINUX_CL_OFFSET
++	  lh.cl_magic = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_MAGIC);
++	  lh.cl_offset = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_OFFSET);
++	  lh.setup_move_size = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_OFFSET
+ 						 + maximal_cmdline_size);
+ 	}
+     }
+   else
+     {
+       /* Your kernel is quite old...  */
+-      lh.cl_magic = grub_cpu_to_le16 (GRUB_LINUX_CL_MAGIC);
+-      lh.cl_offset = grub_cpu_to_le16 (GRUB_LINUX_CL_OFFSET);
++      lh.cl_magic = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_MAGIC);
++      lh.cl_offset = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_OFFSET);
+ 
+       setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
+ 
+@@ -312,15 +324,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_memmove (grub_linux_real_chunk, &lh, sizeof (lh));
+ 
+   len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh);
+-  if (grub_file_read (file, grub_linux_real_chunk + sizeof (lh), len) != len)
+-    {
+-      if (!grub_errno)
+-	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+-		    argv[0]);
+-      goto fail;
+-    }
++  grub_memcpy (grub_linux_real_chunk + sizeof (lh), kernel + kernel_offset,
++	       len);
++  kernel_offset += len;
+ 
+-  if (lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE)
++  if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+       || grub_le_to_cpu16 (lh.version) < 0x0200)
+     /* Clear the heap space.  */
+     grub_memset (grub_linux_real_chunk
+@@ -353,10 +361,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   }
+ 
+   len = grub_linux16_prot_size;
+-  if (grub_file_read (file, grub_linux_prot_chunk, grub_linux16_prot_size)
+-      != (grub_ssize_t) grub_linux16_prot_size && !grub_errno)
+-    grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+-		argv[0]);
++  grub_memcpy (grub_linux_prot_chunk, kernel + kernel_offset, len);
++  kernel_offset += len;
+ 
+   if (grub_errno == GRUB_ERR_NONE)
+     {
+@@ -366,6 +372,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+  fail:
+ 
++  grub_free (kernel);
++
+   if (file)
+     grub_file_close (file);
+ 
+@@ -405,7 +413,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ 
+   lh = (struct linux_kernel_header *) grub_linux_real_chunk;
+ 
+-  if (!(lh->header == grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE)
++  if (!(lh->header == grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+ 	&& grub_le_to_cpu16 (lh->version) >= 0x0200))
+     {
+       grub_error (GRUB_ERR_BAD_OS, "the kernel is too old for initrd");
diff --git a/SOURCES/0224-Re-work-some-intricacies-of-PE-loading.patch b/SOURCES/0224-Re-work-some-intricacies-of-PE-loading.patch
new file mode 100644
index 0000000..cce6e3c
--- /dev/null
+++ b/SOURCES/0224-Re-work-some-intricacies-of-PE-loading.patch
@@ -0,0 +1,350 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 9 Jun 2016 12:22:29 -0400
+Subject: [PATCH] Re-work some intricacies of PE loading.
+
+The PE spec is not a well written document, and awesomely every place
+where there's an ambiguous way to read something, Windows' bootmgfw.efi
+takes a different read than either of them.
+---
+ grub-core/loader/efi/chainloader.c | 156 +++++++++++++++++++++++++++++--------
+ include/grub/efi/pe32.h            |  32 +++++++-
+ 2 files changed, 152 insertions(+), 36 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index aee8e6becf6..4b77a7d5adb 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -301,7 +301,7 @@ image_is_64_bit (grub_pe_header_t *pe_hdr)
+   return 0;
+ }
+ 
+-static const grub_uint16_t machine_type =
++static const grub_uint16_t machine_type __attribute__((__unused__)) =
+ #if defined(__x86_64__)
+   GRUB_PE32_MACHINE_X86_64;
+ #elif defined(__aarch64__)
+@@ -367,10 +367,10 @@ relocate_coff (pe_coff_loader_image_context_t *context,
+ 
+   reloc_base = image_address (orig, size, section->raw_data_offset);
+   reloc_base_end = image_address (orig, size, section->raw_data_offset
+-				  + section->virtual_size - 1);
++				  + section->virtual_size);
+ 
+-  grub_dprintf ("chain", "reloc_base %p reloc_base_end %p\n", reloc_base,
+-		reloc_base_end);
++  grub_dprintf ("chain", "relocate_coff(): reloc_base %p reloc_base_end %p\n",
++		reloc_base, reloc_base_end);
+ 
+   if (!reloc_base && !reloc_base_end)
+     return GRUB_EFI_SUCCESS;
+@@ -507,12 +507,13 @@ handle_image (void *data, grub_efi_uint32_t datasize)
+   grub_efi_status_t efi_status;
+   char *buffer = NULL;
+   char *buffer_aligned = NULL;
+-  grub_efi_uint32_t i, size;
++  grub_efi_uint32_t i;
+   struct grub_pe32_section_table *section;
+   char *base, *end;
+   pe_coff_loader_image_context_t context;
+   grub_uint32_t section_alignment;
+   grub_uint32_t buffer_size;
++  int found_entry_point = 0;
+ 
+   b = grub_efi_system_table->boot_services;
+ 
+@@ -526,8 +527,28 @@ handle_image (void *data, grub_efi_uint32_t datasize)
+       goto error_exit;
+     }
+ 
++  /*
++   * The spec says, uselessly, of SectionAlignment:
++   * =====
++   * The alignment (in bytes) of sections when they are loaded into
++   * memory. It must be greater than or equal to FileAlignment. The
++   * default is the page size for the architecture.
++   * =====
++   * Which doesn't tell you whose responsibility it is to enforce the
++   * "default", or when.  It implies that the value in the field must
++   * be > FileAlignment (also poorly defined), but it appears visual
++   * studio will happily write 512 for FileAlignment (its default) and
++   * 0 for SectionAlignment, intending to imply PAGE_SIZE.
++   *
++   * We only support one page size, so if it's zero, nerf it to 4096.
++   */
+   section_alignment = context.section_alignment;
++  if (section_alignment == 0)
++    section_alignment = 4096;
++
+   buffer_size = context.image_size + section_alignment;
++  grub_dprintf ("chain", "image size is %08lx, datasize is %08x\n",
++	       context.image_size, datasize);
+ 
+   efi_status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA,
+ 			   buffer_size, &buffer);
+@@ -539,7 +560,6 @@ handle_image (void *data, grub_efi_uint32_t datasize)
+     }
+ 
+   buffer_aligned = (char *)ALIGN_UP ((grub_addr_t)buffer, section_alignment);
+-
+   if (!buffer_aligned)
+     {
+       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+@@ -548,27 +568,62 @@ handle_image (void *data, grub_efi_uint32_t datasize)
+ 
+   grub_memcpy (buffer_aligned, data, context.size_of_headers);
+ 
++  entry_point = image_address (buffer_aligned, context.image_size,
++			       context.entry_point);
++
++  grub_dprintf ("chain", "entry_point: %p\n", entry_point);
++  if (!entry_point)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid entry point");
++      goto error_exit;
++    }
++
+   char *reloc_base, *reloc_base_end;
+-  reloc_base = image_address (buffer_aligned, datasize,
++  grub_dprintf ("chain", "reloc_dir: %p reloc_size: 0x%08x\n",
++		(void *)(unsigned long long)context.reloc_dir->rva,
++		context.reloc_dir->size);
++  reloc_base = image_address (buffer_aligned, context.image_size,
+ 			      context.reloc_dir->rva);
+   /* RelocBaseEnd here is the address of the last byte of the table */
+-  reloc_base_end = image_address (buffer_aligned, datasize,
++  reloc_base_end = image_address (buffer_aligned, context.image_size,
+ 				  context.reloc_dir->rva
+ 				  + context.reloc_dir->size - 1);
++  grub_dprintf ("chain", "reloc_base: %p reloc_base_end: %p\n",
++		reloc_base, reloc_base_end);
++
+   struct grub_pe32_section_table *reloc_section = NULL;
+ 
+   section = context.first_section;
+   for (i = 0; i < context.number_of_sections; i++, section++)
+     {
+-      size = section->virtual_size;
+-      if (size > section->raw_data_size)
+-        size = section->raw_data_size;
++      char name[9];
+ 
+       base = image_address (buffer_aligned, context.image_size,
+ 			    section->virtual_address);
+       end = image_address (buffer_aligned, context.image_size,
+-			   section->virtual_address + size - 1);
++			   section->virtual_address + section->virtual_size -1);
+ 
++      grub_strncpy(name, section->name, 9);
++      name[8] = '\0';
++      grub_dprintf ("chain", "Section %d \"%s\" at %p..%p\n", i,
++		   name, base, end);
++
++      if (end < base)
++	{
++	  grub_dprintf ("chain", " base is %p but end is %p... bad.\n",
++		       base, end);
++	  grub_error (GRUB_ERR_BAD_ARGUMENT,
++		      "Image has invalid negative size");
++	  goto error_exit;
++	}
++
++      if (section->virtual_address <= context.entry_point &&
++	  (section->virtual_address + section->raw_data_size - 1)
++	  > context.entry_point)
++	{
++	  found_entry_point++;
++	  grub_dprintf ("chain", " section contains entry point\n");
++	}
+ 
+       /* We do want to process .reloc, but it's often marked
+        * discardable, so we don't want to memcpy it. */
+@@ -587,21 +642,46 @@ handle_image (void *data, grub_efi_uint32_t datasize)
+ 	  if (section->raw_data_size && section->virtual_size &&
+ 	      base && end && reloc_base == base && reloc_base_end == end)
+ 	    {
++	      grub_dprintf ("chain", " section is relocation section\n");
+ 	      reloc_section = section;
+ 	    }
++	  else
++	    {
++	      grub_dprintf ("chain", " section is not reloc section?\n");
++	      grub_dprintf ("chain", " rds: 0x%08x, vs: %08x\n",
++			    section->raw_data_size, section->virtual_size);
++	      grub_dprintf ("chain", " base: %p end: %p\n", base, end);
++	      grub_dprintf ("chain", " reloc_base: %p reloc_base_end: %p\n",
++			    reloc_base, reloc_base_end);
++	    }
+ 	}
+ 
+-      if (section->characteristics && GRUB_PE32_SCN_MEM_DISCARDABLE)
+-	continue;
++      grub_dprintf ("chain", " Section characteristics are %08x\n",
++		   section->characteristics);
++      grub_dprintf ("chain", " Section virtual size: %08x\n",
++		   section->virtual_size);
++      grub_dprintf ("chain", " Section raw_data size: %08x\n",
++		   section->raw_data_size);
++      if (section->characteristics & GRUB_PE32_SCN_MEM_DISCARDABLE)
++	{
++	  grub_dprintf ("chain", " Discarding section\n");
++	  continue;
++	}
+ 
+       if (!base || !end)
+         {
++	  grub_dprintf ("chain", " section is invalid\n");
+           grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid section size");
+           goto error_exit;
+         }
+ 
+-      if (section->virtual_address < context.size_of_headers ||
+-	  section->raw_data_offset < context.size_of_headers)
++      if (section->characteristics & GRUB_PE32_SCN_CNT_UNINITIALIZED_DATA)
++	{
++	  if (section->raw_data_size != 0)
++	    grub_dprintf ("chain", " UNINITIALIZED_DATA section has data?\n");
++	}
++      else if (section->virtual_address < context.size_of_headers ||
++	       section->raw_data_offset < context.size_of_headers)
+ 	{
+ 	  grub_error (GRUB_ERR_BAD_ARGUMENT,
+ 		      "Section %d is inside image headers", i);
+@@ -609,13 +689,24 @@ handle_image (void *data, grub_efi_uint32_t datasize)
+ 	}
+ 
+       if (section->raw_data_size > 0)
+-        grub_memcpy (base, (grub_efi_uint8_t*)data + section->raw_data_offset,
+-		     size);
++	{
++	  grub_dprintf ("chain", " copying 0x%08x bytes to %p\n",
++			section->raw_data_size, base);
++	  grub_memcpy (base,
++		       (grub_efi_uint8_t*)data + section->raw_data_offset,
++		       section->raw_data_size);
++	}
+ 
+-      if (size < section->virtual_size)
+-        grub_memset (base + size, 0, section->virtual_size - size);
++      if (section->raw_data_size < section->virtual_size)
++	{
++	  grub_dprintf ("chain", " padding with 0x%08x bytes at %p\n",
++			section->virtual_size - section->raw_data_size,
++			base + section->raw_data_size);
++	  grub_memset (base + section->raw_data_size, 0,
++		       section->virtual_size - section->raw_data_size);
++	}
+ 
+-      grub_dprintf ("chain", "copied section %s\n", section->name);
++      grub_dprintf ("chain", " finished section %s\n", name);
+     }
+ 
+   /* 5 == EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC */
+@@ -638,12 +729,15 @@ handle_image (void *data, grub_efi_uint32_t datasize)
+ 	}
+     }
+ 
+-  entry_point = image_address (buffer_aligned, context.image_size,
+-			       context.entry_point);
+-
+-  if (!entry_point)
++  if (!found_entry_point)
+     {
+-      grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid entry point");
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "entry point is not within sections");
++      goto error_exit;
++    }
++  if (found_entry_point > 1)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "%d sections contain entry point",
++		  found_entry_point);
+       goto error_exit;
+     }
+ 
+@@ -661,26 +755,24 @@ handle_image (void *data, grub_efi_uint32_t datasize)
+   li->load_options_size = cmdline_len;
+   li->file_path = grub_efi_get_media_file_path (file_path);
+   li->device_handle = dev_handle;
+-  if (li->file_path)
+-    {
+-      grub_printf ("file path: ");
+-      grub_efi_print_device_path (li->file_path);
+-    }
+-  else
++  if (!li->file_path)
+     {
+       grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found");
+       goto error_exit;
+     }
+ 
++  grub_dprintf ("chain", "booting via entry point\n");
+   efi_status = efi_call_2 (entry_point, grub_efi_image_handle,
+ 			   grub_efi_system_table);
+ 
++  grub_dprintf ("chain", "entry_point returned %ld\n", efi_status);
+   grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t));
+   efi_status = efi_call_1 (b->free_pool, buffer);
+ 
+   return 1;
+ 
+ error_exit:
++  grub_dprintf ("chain", "error_exit: grub_errno: %d\n", grub_errno);
+   if (buffer)
+       efi_call_1 (b->free_pool, buffer);
+ 
+diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
+index f79782e1bde..8396bde4917 100644
+--- a/include/grub/efi/pe32.h
++++ b/include/grub/efi/pe32.h
+@@ -227,12 +227,18 @@ struct grub_pe32_section_table
+   grub_uint32_t characteristics;
+ };
+ 
++#define GRUB_PE32_SCN_TYPE_NO_PAD		0x00000008
+ #define GRUB_PE32_SCN_CNT_CODE			0x00000020
+ #define GRUB_PE32_SCN_CNT_INITIALIZED_DATA	0x00000040
+-#define GRUB_PE32_SCN_MEM_DISCARDABLE		0x02000000
+-#define GRUB_PE32_SCN_MEM_EXECUTE		0x20000000
+-#define GRUB_PE32_SCN_MEM_READ			0x40000000
+-#define GRUB_PE32_SCN_MEM_WRITE			0x80000000
++#define GRUB_PE32_SCN_CNT_UNINITIALIZED_DATA	0x00000080
++#define GRUB_PE32_SCN_LNK_OTHER			0x00000100
++#define GRUB_PE32_SCN_LNK_INFO			0x00000200
++#define GRUB_PE32_SCN_LNK_REMOVE		0x00000800
++#define GRUB_PE32_SCN_LNK_COMDAT		0x00001000
++#define GRUB_PE32_SCN_GPREL			0x00008000
++#define GRUB_PE32_SCN_MEM_16BIT			0x00020000
++#define GRUB_PE32_SCN_MEM_LOCKED		0x00040000
++#define GRUB_PE32_SCN_MEM_PRELOAD		0x00080000
+ 
+ #define GRUB_PE32_SCN_ALIGN_1BYTES		0x00100000
+ #define GRUB_PE32_SCN_ALIGN_2BYTES		0x00200000
+@@ -241,10 +247,28 @@ struct grub_pe32_section_table
+ #define GRUB_PE32_SCN_ALIGN_16BYTES		0x00500000
+ #define GRUB_PE32_SCN_ALIGN_32BYTES		0x00600000
+ #define GRUB_PE32_SCN_ALIGN_64BYTES		0x00700000
++#define GRUB_PE32_SCN_ALIGN_128BYTES		0x00800000
++#define GRUB_PE32_SCN_ALIGN_256BYTES		0x00900000
++#define GRUB_PE32_SCN_ALIGN_512BYTES		0x00A00000
++#define GRUB_PE32_SCN_ALIGN_1024BYTES		0x00B00000
++#define GRUB_PE32_SCN_ALIGN_2048BYTES		0x00C00000
++#define GRUB_PE32_SCN_ALIGN_4096BYTES		0x00D00000
++#define GRUB_PE32_SCN_ALIGN_8192BYTES		0x00E00000
+ 
+ #define GRUB_PE32_SCN_ALIGN_SHIFT		20
+ #define GRUB_PE32_SCN_ALIGN_MASK		7
+ 
++#define GRUB_PE32_SCN_LNK_NRELOC_OVFL		0x01000000
++#define GRUB_PE32_SCN_MEM_DISCARDABLE		0x02000000
++#define GRUB_PE32_SCN_MEM_NOT_CACHED		0x04000000
++#define GRUB_PE32_SCN_MEM_NOT_PAGED		0x08000000
++#define GRUB_PE32_SCN_MEM_SHARED		0x10000000
++#define GRUB_PE32_SCN_MEM_EXECUTE		0x20000000
++#define GRUB_PE32_SCN_MEM_READ			0x40000000
++#define GRUB_PE32_SCN_MEM_WRITE			0x80000000
++
++
++
+ #define GRUB_PE32_SIGNATURE_SIZE 4
+ 
+ struct grub_pe32_header
diff --git a/SOURCES/0225-Rework-even-more-of-efi-chainload-so-non-sb-cases-wo.patch b/SOURCES/0225-Rework-even-more-of-efi-chainload-so-non-sb-cases-wo.patch
new file mode 100644
index 0000000..e099f5e
--- /dev/null
+++ b/SOURCES/0225-Rework-even-more-of-efi-chainload-so-non-sb-cases-wo.patch
@@ -0,0 +1,385 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Fri, 10 Jun 2016 14:06:15 -0400
+Subject: [PATCH] Rework even more of efi chainload so non-sb cases work right.
+
+This ensures that if shim protocol is not loaded, or is loaded but shim
+is disabled, we will fall back to a correct load method for the efi
+chain loader.
+
+Here's what I tested with this version:
+
+results                             expected    actual
+------------------------------------------------------------
+sb + enabled + shim + fedora        success     success
+sb + enabled + shim + win           success     success
+sb + enabled + grub + fedora        fail        fail
+sb + enabled + grub + win           fail        fail
+
+sb + mokdisabled + shim + fedora    success     success
+sb + mokdisabled + shim + win       success     success
+sb + mokdisabled + grub + fedora    fail        fail
+sb + mokdisabled + grub + win       fail        fail
+
+sb disabled + shim + fedora         success     success*
+sb disabled + shim + win            success     success*
+sb disabled + grub + fedora         success     success
+sb disabled + grub + win            success     success
+
+nosb + shim + fedora                success     success*
+nosb + shim + win                   success     success*
+nosb + grub + fedora                success     success
+nosb + grub + win                   success     success
+
+* for some reason shim protocol is being installed in these cases, and I
+  can't see why, but I think it may be this firmware build returning an
+  erroneous value.  But this effectively falls back to the mokdisabled
+  behavior, which works correctly, and the presence of the "grub" (i.e.
+  no shim) tests effectively tests the desired behavior here.
+
+Resolves: rhbz#1344512
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/kern/efi/sb.c            |  14 +++--
+ grub-core/loader/arm64/linux.c     |   4 +-
+ grub-core/loader/efi/chainloader.c | 117 ++++++++++++++++++++++---------------
+ grub-core/loader/efi/linux.c       |  13 +++--
+ grub-core/loader/i386/efi/linux.c  |  10 +++-
+ include/grub/efi/linux.h           |   2 +-
+ 6 files changed, 100 insertions(+), 60 deletions(-)
+
+diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
+index a41b6c5b851..d74778b0cac 100644
+--- a/grub-core/kern/efi/sb.c
++++ b/grub-core/kern/efi/sb.c
+@@ -36,14 +36,20 @@ grub_efi_secure_boot (void)
+   grub_efi_boolean_t ret = 0;
+ 
+   secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
+-
+   if (datasize != 1 || !secure_boot)
+-    goto out;
++    {
++      grub_dprintf ("secureboot", "No SecureBoot variable\n");
++      goto out;
++    }
++  grub_dprintf ("secureboot", "SecureBoot: %d\n", *secure_boot);
+ 
+   setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
+-
+   if (datasize != 1 || !setup_mode)
+-    goto out;
++    {
++      grub_dprintf ("secureboot", "No SetupMode variable\n");
++      goto out;
++    }
++  grub_dprintf ("secureboot", "SetupMode: %d\n", *setup_mode);
+ 
+   if (*secure_boot && !*setup_mode)
+     ret = 1;
+diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
+index bdd9c9b4968..0452a20e98b 100644
+--- a/grub-core/loader/arm64/linux.c
++++ b/grub-core/loader/arm64/linux.c
+@@ -380,6 +380,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_file_t file = 0;
+   struct grub_arm64_linux_kernel_header lh;
+   struct grub_arm64_linux_pe_header *pe;
++  int rc;
+ 
+   grub_dl_ref (my_mod);
+ 
+@@ -424,7 +425,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+   grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
+ 
+-  if (!grub_linuxefi_secure_validate (kernel_addr, kernel_size))
++  rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size);
++  if (rc < 0)
+     {
+       grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
+       goto fail;
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 4b77a7d5adb..3e89de9006c 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -182,7 +182,6 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
+   /* Fill the file path for the directory.  */
+   d = (grub_efi_device_path_t *) ((char *) file_path
+ 				  + ((char *) d - (char *) dp));
+-  grub_efi_print_device_path (d);
+   copy_file_path ((grub_efi_file_path_device_path_t *) d,
+ 		  dir_start, dir_end - dir_start);
+ 
+@@ -252,10 +251,9 @@ read_header (void *data, grub_efi_uint32_t size,
+   grub_efi_status_t status;
+ 
+   shim_lock = grub_efi_locate_protocol (&guid, NULL);
+-
+   if (!shim_lock)
+     {
+-      grub_error (GRUB_ERR_BAD_ARGUMENT, "no shim lock protocol");
++      grub_dprintf ("chain", "no shim lock protocol");
+       return 0;
+     }
+ 
+@@ -280,7 +278,7 @@ read_header (void *data, grub_efi_uint32_t size,
+       break;
+     }
+ 
+-  return 0;
++  return -1;
+ }
+ 
+ static void*
+@@ -514,18 +512,25 @@ handle_image (void *data, grub_efi_uint32_t datasize)
+   grub_uint32_t section_alignment;
+   grub_uint32_t buffer_size;
+   int found_entry_point = 0;
++  int rc;
+ 
+   b = grub_efi_system_table->boot_services;
+ 
+-  if (read_header (data, datasize, &context))
+-    {
+-      grub_dprintf ("chain", "Succeed to read header\n");
+-    }
+-  else
++  rc = read_header (data, datasize, &context);
++  if (rc < 0)
+     {
+       grub_dprintf ("chain", "Failed to read header\n");
+       goto error_exit;
+     }
++  else if (rc == 0)
++    {
++      grub_dprintf ("chain", "Secure Boot is not enabled\n");
++      return 0;
++    }
++  else
++    {
++      grub_dprintf ("chain", "Header read without error\n");
++    }
+ 
+   /*
+    * The spec says, uselessly, of SectionAlignment:
+@@ -796,10 +801,56 @@ grub_secureboot_chainloader_unload (void)
+   return GRUB_ERR_NONE;
+ }
+ 
++static grub_err_t
++grub_load_and_start_image(void *boot_image)
++{
++  grub_efi_boot_services_t *b;
++  grub_efi_status_t status;
++  grub_efi_loaded_image_t *loaded_image;
++
++  b = grub_efi_system_table->boot_services;
++
++  status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
++		       boot_image, fsize, &image_handle);
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      if (status == GRUB_EFI_OUT_OF_RESOURCES)
++	grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
++      else
++	grub_error (GRUB_ERR_BAD_OS, "cannot load image");
++      return -1;
++    }
++
++  /* LoadImage does not set a device handler when the image is
++     loaded from memory, so it is necessary to set it explicitly here.
++     This is a mess.  */
++  loaded_image = grub_efi_get_loaded_image (image_handle);
++  if (! loaded_image)
++    {
++      grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
++      return -1;
++    }
++  loaded_image->device_handle = dev_handle;
++
++  if (cmdline)
++    {
++      loaded_image->load_options = cmdline;
++      loaded_image->load_options_size = cmdline_len;
++    }
++
++  return 0;
++}
++
+ static grub_err_t
+ grub_secureboot_chainloader_boot (void)
+ {
+-  handle_image ((void *)address, fsize);
++  int rc;
++  rc = handle_image ((void *)address, fsize);
++  if (rc == 0)
++    {
++      grub_load_and_start_image((void *)address);
++    }
++
+   grub_loader_unset ();
+   return grub_errno;
+ }
+@@ -813,9 +864,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   grub_efi_boot_services_t *b;
+   grub_device_t dev = 0;
+   grub_efi_device_path_t *dp = 0;
+-  grub_efi_loaded_image_t *loaded_image;
+   char *filename;
+   void *boot_image = 0;
++  int rc;
+ 
+   if (argc == 0)
+     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+@@ -902,9 +953,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   if (! file_path)
+     goto fail;
+ 
+-  grub_printf ("file path: ");
+-  grub_efi_print_device_path (file_path);
+-
+   fsize = grub_file_size (file);
+   if (!fsize)
+     {
+@@ -979,51 +1027,28 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+     }
+ #endif
+ 
+-  if (grub_linuxefi_secure_validate((void *)address, fsize))
++  rc = grub_linuxefi_secure_validate((void *)address, fsize);
++  grub_dprintf ("chain", "linuxefi_secure_validate: %d\n", rc);
++  if (rc > 0)
+     {
+       grub_file_close (file);
+       grub_loader_set (grub_secureboot_chainloader_boot,
+ 		       grub_secureboot_chainloader_unload, 0);
+       return 0;
+     }
+-
+-  status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
+-		       boot_image, fsize, &image_handle);
+-  if (status != GRUB_EFI_SUCCESS)
++  else if (rc == 0)
+     {
+-      if (status == GRUB_EFI_OUT_OF_RESOURCES)
+-	grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
+-      else
+-	grub_error (GRUB_ERR_BAD_OS, "cannot load image");
+-
+-      goto fail;
+-    }
++      grub_load_and_start_image(boot_image);
++      grub_file_close (file);
++      grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
+ 
+-  /* LoadImage does not set a device handler when the image is
+-     loaded from memory, so it is necessary to set it explicitly here.
+-     This is a mess.  */
+-  loaded_image = grub_efi_get_loaded_image (image_handle);
+-  if (! loaded_image)
+-    {
+-      grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
+-      goto fail;
+-    }
+-  loaded_image->device_handle = dev_handle;
+-
+-  if (cmdline)
+-    {
+-      loaded_image->load_options = cmdline;
+-      loaded_image->load_options_size = cmdline_len;
++      return 0;
+     }
+ 
+   grub_file_close (file);
+   grub_device_close (dev);
+ 
+-  grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
+-  return 0;
+-
+- fail:
+-
++fail:
+   if (dev)
+     grub_device_close (dev);
+ 
+diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
+index aea378adf5c..8890bdf059a 100644
+--- a/grub-core/loader/efi/linux.c
++++ b/grub-core/loader/efi/linux.c
+@@ -33,21 +33,24 @@ struct grub_efi_shim_lock
+ };
+ typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
+ 
+-grub_efi_boolean_t
++int
+ grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
+ {
+   grub_efi_guid_t guid = SHIM_LOCK_GUID;
+   grub_efi_shim_lock_t *shim_lock;
++  grub_efi_status_t status;
+ 
+   shim_lock = grub_efi_locate_protocol(&guid, NULL);
+-
++  grub_dprintf ("secureboot", "shim_lock: %p\n", shim_lock);
+   if (!shim_lock)
+-    return 1;
++    return 0;
+ 
+-  if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS)
++  status = shim_lock->verify(data, size);
++  grub_dprintf ("secureboot", "shim_lock->verify(): %ld\n", status);
++  if (status == GRUB_EFI_SUCCESS)
+     return 1;
+ 
+-  return 0;
++  return -1;
+ }
+ 
+ typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 7ccf32d9d45..82f75b7f3ab 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -155,6 +155,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   struct linux_kernel_header lh;
+   grub_ssize_t len, start, filelen;
+   void *kernel = NULL;
++  int rc;
+ 
+   grub_dl_ref (my_mod);
+ 
+@@ -180,13 +181,16 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+   if (grub_file_read (file, kernel, filelen) != filelen)
+     {
+-      grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]);
++      grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"),
++		  argv[0]);
+       goto fail;
+     }
+ 
+-  if (! grub_linuxefi_secure_validate (kernel, filelen))
++  rc = grub_linuxefi_secure_validate (kernel, filelen);
++  if (rc < 0)
+     {
+-      grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
++      grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"),
++		  argv[0]);
+       grub_free (kernel);
+       goto fail;
+     }
+diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h
+index d9ede36773b..0033d9305a9 100644
+--- a/include/grub/efi/linux.h
++++ b/include/grub/efi/linux.h
+@@ -22,7 +22,7 @@
+ #include <grub/err.h>
+ #include <grub/symbol.h>
+ 
+-grub_efi_boolean_t
++int
+ EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size);
+ grub_err_t
+ EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
diff --git a/SOURCES/0226-linuxefi-fix-double-free-on-verification-failure.patch b/SOURCES/0226-linuxefi-fix-double-free-on-verification-failure.patch
new file mode 100644
index 0000000..7d1b3c8
--- /dev/null
+++ b/SOURCES/0226-linuxefi-fix-double-free-on-verification-failure.patch
@@ -0,0 +1,22 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 14 Jun 2016 09:50:25 -0400
+Subject: [PATCH] linuxefi: fix double free on verification failure.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/i386/efi/linux.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 82f75b7f3ab..010bf982d80 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -191,7 +191,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+     {
+       grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"),
+ 		  argv[0]);
+-      grub_free (kernel);
+       goto fail;
+     }
+ 
diff --git a/SOURCES/0227-efi-chainloader-fix-wrong-sanity-check-in-relocate_c.patch b/SOURCES/0227-efi-chainloader-fix-wrong-sanity-check-in-relocate_c.patch
new file mode 100644
index 0000000..9a00fab
--- /dev/null
+++ b/SOURCES/0227-efi-chainloader-fix-wrong-sanity-check-in-relocate_c.patch
@@ -0,0 +1,35 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Mon, 21 Nov 2016 15:34:00 +0100
+Subject: [PATCH] efi/chainloader: fix wrong sanity check in relocate_coff()
+
+In relocate_coff(), the relocation entries are parsed from the original
+image (not the section-wise copied image). The original image is
+pointed-to by the "orig" pointer. The current check
+
+  (void *)reloc_end < data
+
+compares the addresses of independent memory allocations. "data" is a typo
+here, it should be "orig".
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1347291
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+Tested-by: Bogdan Costescu <bcostescu@gmail.com>
+Tested-by: Juan Orti <j.orti.alcaine@gmail.com>
+---
+ grub-core/loader/efi/chainloader.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 3e89de9006c..ed8c364789a 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -401,7 +401,7 @@ relocate_coff (pe_coff_loader_image_context_t *context,
+       reloc_end = (struct grub_pe32_fixup_block *)
+ 	((char *)reloc_base + reloc_base->size);
+ 
+-      if ((void *)reloc_end < data || (void *)reloc_end > image_end)
++      if ((void *)reloc_end < orig || (void *)reloc_end > image_end)
+         {
+           grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc entry %d overflows binary",
+ 		      n);
diff --git a/SOURCES/0228-efi-chainloader-truncate-overlong-relocation-section.patch b/SOURCES/0228-efi-chainloader-truncate-overlong-relocation-section.patch
new file mode 100644
index 0000000..3bd7f11
--- /dev/null
+++ b/SOURCES/0228-efi-chainloader-truncate-overlong-relocation-section.patch
@@ -0,0 +1,110 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Wed, 23 Nov 2016 06:27:09 +0100
+Subject: [PATCH] efi/chainloader: truncate overlong relocation section
+
+The UEFI Windows 7 boot loader ("EFI/Microsoft/Boot/bootmgfw.efi", SHA1
+31b410e029bba87d2068c65a80b88882f9f8ea25) has inconsistent headers.
+
+Compare:
+
+> The Data Directory
+> ...
+> Entry 5 00000000000d9000 00000574 Base Relocation Directory [.reloc]
+
+Versus:
+
+> Sections:
+> Idx Name      Size      VMA               LMA               File off ...
+> ...
+>  10 .reloc    00000e22  00000000100d9000  00000000100d9000  000a1800 ...
+
+That is, the size reported by the RelocDir entry (0x574) is smaller than
+the virtual size of the .reloc section (0xe22).
+
+Quoting the grub2 debug log for the same:
+
+> chainloader.c:595: reloc_dir: 0xd9000 reloc_size: 0x00000574
+> chainloader.c:603: reloc_base: 0x7d208000 reloc_base_end: 0x7d208573
+> ...
+> chainloader.c:620: Section 10 ".reloc" at 0x7d208000..0x7d208e21
+> chainloader.c:661:  section is not reloc section?
+> chainloader.c:663:  rds: 0x00001000, vs: 00000e22
+> chainloader.c:664:  base: 0x7d208000 end: 0x7d208e21
+> chainloader.c:666:  reloc_base: 0x7d208000 reloc_base_end: 0x7d208573
+> chainloader.c:671:  Section characteristics are 42000040
+> chainloader.c:673:  Section virtual size: 00000e22
+> chainloader.c:675:  Section raw_data size: 00001000
+> chainloader.c:678:  Discarding section
+
+After hexdumping "bootmgfw.efi" and manually walking its relocation blocks
+(yes, really), I determined that the (smaller) RelocDir value is correct.
+The remaining area that extends up to the .reloc section size (== 0xe22 -
+0x574 == 0x8ae bytes) exists as zero padding in the file.
+
+This zero padding shouldn't be passed to relocate_coff() for parsing. In
+order to cope with it, split the handling of .reloc sections into the
+following branches:
+
+- original case (equal size): original behavior (--> relocation
+  attempted),
+
+- overlong .reloc section (longer than reported by RelocDir): truncate the
+  section to the RelocDir size for the purposes of relocate_coff(), and
+  attempt relocation,
+
+- .reloc section is too short, or other checks fail: original behavior
+  (--> relocation not attempted).
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1347291
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+---
+ grub-core/loader/efi/chainloader.c | 26 +++++++++++++++++++++-----
+ 1 file changed, 21 insertions(+), 5 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index ed8c364789a..db1ffeefc93 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -596,7 +596,7 @@ handle_image (void *data, grub_efi_uint32_t datasize)
+   grub_dprintf ("chain", "reloc_base: %p reloc_base_end: %p\n",
+ 		reloc_base, reloc_base_end);
+ 
+-  struct grub_pe32_section_table *reloc_section = NULL;
++  struct grub_pe32_section_table *reloc_section = NULL, fake_reloc_section;
+ 
+   section = context.first_section;
+   for (i = 0; i < context.number_of_sections; i++, section++)
+@@ -645,12 +645,28 @@ handle_image (void *data, grub_efi_uint32_t datasize)
+ 	   * made sense, and the VA and size match RelocDir's
+ 	   * versions, then we believe in this section table. */
+ 	  if (section->raw_data_size && section->virtual_size &&
+-	      base && end && reloc_base == base && reloc_base_end == end)
++	      base && end && reloc_base == base)
+ 	    {
+-	      grub_dprintf ("chain", " section is relocation section\n");
+-	      reloc_section = section;
++	      if (reloc_base_end == end)
++		{
++		  grub_dprintf ("chain", " section is relocation section\n");
++		  reloc_section = section;
++		}
++	      else if (reloc_base_end && reloc_base_end < end)
++	        {
++		  /* Bogus virtual size in the reloc section -- RelocDir
++		   * reported a smaller Base Relocation Directory. Decrease
++		   * the section's virtual size so that it equal RelocDir's
++		   * idea, but only for the purposes of relocate_coff(). */
++		  grub_dprintf ("chain",
++				" section is (overlong) relocation section\n");
++		  grub_memcpy (&fake_reloc_section, section, sizeof *section);
++		  fake_reloc_section.virtual_size -= (end - reloc_base_end);
++		  reloc_section = &fake_reloc_section;
++		}
+ 	    }
+-	  else
++
++	  if (!reloc_section)
+ 	    {
+ 	      grub_dprintf ("chain", " section is not reloc section?\n");
+ 	      grub_dprintf ("chain", " rds: 0x%08x, vs: %08x\n",
diff --git a/SOURCES/0229-Add-some-grub_dprintf-in-the-linuxefi-path.patch b/SOURCES/0229-Add-some-grub_dprintf-in-the-linuxefi-path.patch
new file mode 100644
index 0000000..4050058
--- /dev/null
+++ b/SOURCES/0229-Add-some-grub_dprintf-in-the-linuxefi-path.patch
@@ -0,0 +1,85 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 9 May 2016 14:15:17 -0400
+Subject: [PATCH] Add some grub_dprintf() in the linuxefi path.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/efi/linux.c      | 16 +++++++++++++---
+ grub-core/loader/i386/efi/linux.c | 10 +++++++++-
+ 2 files changed, 22 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
+index 8890bdf059a..dbf63e20ed8 100644
+--- a/grub-core/loader/efi/linux.c
++++ b/grub-core/loader/efi/linux.c
+@@ -43,12 +43,22 @@ grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
+   shim_lock = grub_efi_locate_protocol(&guid, NULL);
+   grub_dprintf ("secureboot", "shim_lock: %p\n", shim_lock);
+   if (!shim_lock)
+-    return 0;
++    {
++      grub_dprintf ("secureboot", "shim not available\n");
++      return 0;
++    }
+ 
+-  status = shim_lock->verify(data, size);
++  grub_dprintf ("secureboot", "Asking shim to verify kernel signature\n");
++  status = shim_lock->verify (data, size);
+   grub_dprintf ("secureboot", "shim_lock->verify(): %ld\n", status);
+   if (status == GRUB_EFI_SUCCESS)
+-    return 1;
++    {
++      grub_dprintf ("secureboot", "Kernel signature verification passed\n");
++      return 1;
++    }
++
++  grub_dprintf ("secureboot", "Kernel signature verification failed (0x%lx)\n",
++		(unsigned long) status);
+ 
+   return -1;
+ }
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 010bf982d80..a95e29700c5 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -114,6 +114,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
++  grub_dprintf ("linuxefi", "initrd_mem = %lx\n", (unsigned long) initrd_mem);
++
+   params->ramdisk_size = size;
+   params->ramdisk_image = (grub_uint32_t)(grub_uint64_t) initrd_mem;
+ 
+@@ -202,6 +204,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
++  grub_dprintf ("linuxefi", "params = %lx\n", (unsigned long) params);
++
+   grub_memset (params, 0, 16384);
+ 
+   grub_memcpy (&lh, kernel, sizeof (lh));
+@@ -239,6 +243,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
++  grub_dprintf ("linuxefi", "linux_cmdline = %lx\n",
++		(unsigned long)linux_cmdline);
++
+   grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
+   grub_create_loader_cmdline (argc, argv,
+                               linux_cmdline + sizeof (LINUX_IMAGE) - 1,
+@@ -272,9 +279,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_memcpy (params, &lh, 2 * 512);
+ 
+   params->type_of_loader = 0x21;
++  grub_dprintf("linuxefi", "kernel_mem: %p handover_offset: %08x\n",
++	       kernel_mem, handover_offset);
+ 
+  fail:
+-
+   if (file)
+     grub_file_close (file);
+ 
diff --git a/SOURCES/0230-linuxefi-minor-cleanups.patch b/SOURCES/0230-linuxefi-minor-cleanups.patch
new file mode 100644
index 0000000..b27fd18
--- /dev/null
+++ b/SOURCES/0230-linuxefi-minor-cleanups.patch
@@ -0,0 +1,86 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 14 Feb 2017 16:31:52 -0500
+Subject: [PATCH] linuxefi: minor cleanups
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/i386/efi/linux.c | 30 ++++++++++++++++++++----------
+ 1 file changed, 20 insertions(+), 10 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index a95e29700c5..806031838ae 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -61,13 +61,18 @@ grub_linuxefi_unload (void)
+   grub_dl_unref (my_mod);
+   loaded = 0;
+   if (initrd_mem)
+-    grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(params->ramdisk_size));
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem,
++			 BYTES_TO_PAGES(params->ramdisk_size));
+   if (linux_cmdline)
+-    grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(params->cmdline_size + 1));
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
++			 linux_cmdline,
++			 BYTES_TO_PAGES(params->cmdline_size + 1));
+   if (kernel_mem)
+-    grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem,
++			 BYTES_TO_PAGES(kernel_size));
+   if (params)
+-    grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384));
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params,
++			 BYTES_TO_PAGES(16384));
+   return GRUB_ERR_NONE;
+ }
+ 
+@@ -117,7 +122,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   grub_dprintf ("linuxefi", "initrd_mem = %lx\n", (unsigned long) initrd_mem);
+ 
+   params->ramdisk_size = size;
+-  params->ramdisk_image = (grub_uint32_t)(grub_uint64_t) initrd_mem;
++  params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem;
+ 
+   ptr = initrd_mem;
+ 
+@@ -144,7 +149,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   grub_free (files);
+ 
+   if (initrd_mem && grub_errno)
+-    grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(size));
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem,
++			 BYTES_TO_PAGES(size));
+ 
+   return grub_errno;
+ }
+@@ -251,7 +257,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+                               linux_cmdline + sizeof (LINUX_IMAGE) - 1,
+ 			      lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1));
+ 
+-  lh.cmd_line_ptr = (grub_uint32_t)(grub_uint64_t)linux_cmdline;
++  lh.cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
+ 
+   handover_offset = lh.handover_offset;
+ 
+@@ -296,13 +302,17 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+     }
+ 
+   if (linux_cmdline && !loaded)
+-    grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(lh.cmdline_size + 1));
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
++			 linux_cmdline,
++			 BYTES_TO_PAGES(lh.cmdline_size + 1));
+ 
+   if (kernel_mem && !loaded)
+-    grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem,
++			 BYTES_TO_PAGES(kernel_size));
+ 
+   if (params && !loaded)
+-    grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384));
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params,
++			 BYTES_TO_PAGES(16384));
+ 
+   return grub_errno;
+ }
diff --git a/SOURCES/0231-Handle-multi-arch-64-on-32-boot-in-linuxefi-loader.patch b/SOURCES/0231-Handle-multi-arch-64-on-32-boot-in-linuxefi-loader.patch
new file mode 100644
index 0000000..a6b68e2
--- /dev/null
+++ b/SOURCES/0231-Handle-multi-arch-64-on-32-boot-in-linuxefi-loader.patch
@@ -0,0 +1,257 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 14 Feb 2017 16:18:54 -0500
+Subject: [PATCH] Handle multi-arch (64-on-32) boot in linuxefi loader.
+
+Allow booting 64-bit kernels on 32-bit EFI on x86.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/efi/linux.c      |   9 +++-
+ grub-core/loader/i386/efi/linux.c | 105 +++++++++++++++++++++++++++-----------
+ include/grub/i386/linux.h         |   7 ++-
+ 3 files changed, 87 insertions(+), 34 deletions(-)
+
+diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
+index dbf63e20ed8..7fe7201a388 100644
+--- a/grub-core/loader/efi/linux.c
++++ b/grub-core/loader/efi/linux.c
+@@ -66,12 +66,17 @@ grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
+ typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
+ 
+ grub_err_t
+-grub_efi_linux_boot (void *kernel_addr, grub_off_t offset,
++grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
+ 		     void *kernel_params)
+ {
+   handover_func hf;
++  int offset = 0;
+ 
+-  hf = (handover_func)((char *)kernel_addr + offset);
++#ifdef __x86_64__
++  offset = 512;
++#endif
++
++  hf = (handover_func)((char *)kernel_addr + handover_offset + offset);
+   hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
+ 
+   return GRUB_ERR_BUG;
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 806031838ae..c123afad19c 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -44,14 +44,10 @@ static char *linux_cmdline;
+ static grub_err_t
+ grub_linuxefi_boot (void)
+ {
+-  int offset = 0;
+-
+-#ifdef __x86_64__
+-  offset = 512;
+-#endif
+   asm volatile ("cli");
+ 
+-  return grub_efi_linux_boot ((char *)kernel_mem, handover_offset + offset,
++  return grub_efi_linux_boot ((char *)kernel_mem,
++			      handover_offset,
+ 			      params);
+ }
+ 
+@@ -155,14 +151,20 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   return grub_errno;
+ }
+ 
++#define MIN(a, b) \
++  ({ typeof (a) _a = (a); \
++     typeof (b) _b = (b); \
++     _a < _b ? _a : _b; })
++
+ static grub_err_t
+ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 		int argc, char *argv[])
+ {
+   grub_file_t file = 0;
+-  struct linux_kernel_header lh;
++  struct linux_kernel_header *lh;
+   grub_ssize_t len, start, filelen;
+   void *kernel = NULL;
++  int setup_header_end_offset;
+   int rc;
+ 
+   grub_dl_ref (my_mod);
+@@ -202,47 +204,78 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-  params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
+-
++  params = grub_efi_allocate_pages_max (0x3fffffff,
++					BYTES_TO_PAGES(sizeof(*params)));
+   if (! params)
+     {
+       grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
+       goto fail;
+     }
+ 
+-  grub_dprintf ("linuxefi", "params = %lx\n", (unsigned long) params);
++  grub_dprintf ("linuxefi", "params = %p\n", (unsigned long) params);
+ 
+-  grub_memset (params, 0, 16384);
++  grub_memset (params, 0, sizeof(*params));
+ 
+-  grub_memcpy (&lh, kernel, sizeof (lh));
+-
+-  if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
++  setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201);
++  grub_dprintf ("linuxefi", "copying %lu bytes from %p to %p\n",
++		MIN(0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1,
++		(grub_uint8_t *)kernel + 0x1f1,
++		(grub_uint8_t *)params + 0x1f1);
++  grub_memcpy ((grub_uint8_t *)params + 0x1f1,
++	       (grub_uint8_t *)kernel + 0x1f1,
++		MIN(0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
++  lh = (struct linux_kernel_header *)params;
++  grub_dprintf ("linuxefi", "lh is at %p\n", lh);
++  grub_dprintf ("linuxefi", "checking lh->boot_flag\n");
++  if (lh->boot_flag != grub_cpu_to_le16 (0xaa55))
+     {
+       grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number"));
+       goto fail;
+     }
+ 
+-  if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
++  grub_dprintf ("linuxefi", "checking lh->setup_sects\n");
++  if (lh->setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
+     {
+       grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
+       goto fail;
+     }
+ 
+-  if (lh.version < grub_cpu_to_le16 (0x020b))
++  grub_dprintf ("linuxefi", "checking lh->version\n");
++  if (lh->version < grub_cpu_to_le16 (0x020b))
+     {
+       grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
+       goto fail;
+     }
+ 
+-  if (!lh.handover_offset)
++  grub_dprintf ("linuxefi", "checking lh->handover_offset\n");
++  if (!lh->handover_offset)
+     {
+       grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
+       goto fail;
+     }
+ 
++#ifdef defined(__x86_64__) || defined(__aarch64__)
++  grub_dprintf ("linuxefi", "checking lh->xloadflags\n");
++  if (!(lh->xloadflags & LINUX_XLF_KERNEL_64))
++    {
++      grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support 64-bit CPUs"));
++      goto fail;
++    }
++#endif
++
++#if defined(__i386__)
++  if ((lh->xloadflags & LINUX_XLF_KERNEL_64) &&
++      !(lh->xloadflags & LINUX_XLF_EFI_HANDOVER_32))
++    {
++      grub_error (GRUB_ERR_BAD_OS,
++		  N_("kernel doesn't support 32-bit handover"));
++      goto fail;
++    }
++#endif
++
++  grub_dprintf ("linuxefi", "setting up cmdline\n");
+   linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
+-					 BYTES_TO_PAGES(lh.cmdline_size + 1));
+-
++					 BYTES_TO_PAGES(lh->cmdline_size + 1));
+   if (!linux_cmdline)
+     {
+       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
+@@ -255,21 +288,24 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
+   grub_create_loader_cmdline (argc, argv,
+                               linux_cmdline + sizeof (LINUX_IMAGE) - 1,
+-			      lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1));
++			      lh->cmdline_size - (sizeof (LINUX_IMAGE) - 1));
+ 
+-  lh.cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
++  grub_dprintf ("linuxefi", "cmdline:%s\n", linux_cmdline);
++  grub_dprintf ("linuxefi", "setting lh->cmd_line_ptr\n");
++  lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
+ 
+-  handover_offset = lh.handover_offset;
++  grub_dprintf ("linuxefi", "computing handover offset\n");
++  handover_offset = lh->handover_offset;
+ 
+-  start = (lh.setup_sects + 1) * 512;
++  start = (lh->setup_sects + 1) * 512;
+   len = grub_file_size(file) - start;
+ 
+-  kernel_mem = grub_efi_allocate_pages(lh.pref_address,
+-				       BYTES_TO_PAGES(lh.init_size));
++  kernel_mem = grub_efi_allocate_pages(lh->pref_address,
++				       BYTES_TO_PAGES(lh->init_size));
+ 
+   if (!kernel_mem)
+     kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
+-					     BYTES_TO_PAGES(lh.init_size));
++					     BYTES_TO_PAGES(lh->init_size));
+ 
+   if (!kernel_mem)
+     {
+@@ -277,14 +313,21 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-  grub_memcpy (kernel_mem, (char *)kernel + start, len);
++  grub_dprintf ("linuxefi", "kernel_mem = %lx\n", (unsigned long) kernel_mem);
++
+   grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
+   loaded=1;
++  grub_dprintf ("linuxefi", "setting lh->code32_start to %p\n", kernel_mem);
++  lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
+ 
+-  lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
+-  grub_memcpy (params, &lh, 2 * 512);
++  grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start);
+ 
+-  params->type_of_loader = 0x21;
++  grub_dprintf ("linuxefi", "setting lh->type_of_loader\n");
++  lh->type_of_loader = 0x6;
++
++  grub_dprintf ("linuxefi", "setting lh->ext_loader_{type,ver}\n");
++  params->ext_loader_type = 0;
++  params->ext_loader_ver = 2;
+   grub_dprintf("linuxefi", "kernel_mem: %p handover_offset: %08x\n",
+ 	       kernel_mem, handover_offset);
+ 
+@@ -304,7 +347,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   if (linux_cmdline && !loaded)
+     grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
+ 			 linux_cmdline,
+-			 BYTES_TO_PAGES(lh.cmdline_size + 1));
++			 BYTES_TO_PAGES(lh->cmdline_size + 1));
+ 
+   if (kernel_mem && !loaded)
+     grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem,
+diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
+index fc36bdaf367..110ecf806fb 100644
+--- a/include/grub/i386/linux.h
++++ b/include/grub/i386/linux.h
+@@ -130,7 +130,12 @@ struct linux_kernel_header
+   grub_uint32_t kernel_alignment;
+   grub_uint8_t relocatable;
+   grub_uint8_t min_alignment;
+-  grub_uint8_t pad[2];
++#define LINUX_XLF_KERNEL_64                   (1<<0)
++#define LINUX_XLF_CAN_BE_LOADED_ABOVE_4G      (1<<1)
++#define LINUX_XLF_EFI_HANDOVER_32             (1<<2)
++#define LINUX_XLF_EFI_HANDOVER_64             (1<<3)
++#define LINUX_XLF_EFI_KEXEC                   (1<<4)
++  grub_uint16_t xloadflags;
+   grub_uint32_t cmdline_size;
+   grub_uint32_t hardware_subarch;
+   grub_uint64_t hardware_subarch_data;
diff --git a/SOURCES/0232-efidisk-Respect-block_io_protocol-buffer-alignment.patch b/SOURCES/0232-efidisk-Respect-block_io_protocol-buffer-alignment.patch
new file mode 100644
index 0000000..255ab30
--- /dev/null
+++ b/SOURCES/0232-efidisk-Respect-block_io_protocol-buffer-alignment.patch
@@ -0,0 +1,92 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Leif Lindholm <leif.lindholm@linaro.org>
+Date: Sat, 27 Feb 2016 13:44:59 +0100
+Subject: [PATCH] efidisk: Respect block_io_protocol buffer alignment
+
+Returned from the OpenProtocol operation, the grub_efi_block_io_media
+structure contains the io_align field, specifying the minimum alignment
+required for buffers used in any data transfers with the device.
+
+Make grub_efidisk_readwrite() allocate a temporary buffer, aligned to
+this boundary, if the buffer passed to it does not already meet the
+requirements.
+
+Also sanity check the io_align field in grub_efidisk_open() for
+power-of-two-ness and bail if invalid.
+
+Cherry-picked-from: 51f375d688529b7c1819ba40188ee52b9333887c
+Resolves: rhbz#1300009
+---
+ grub-core/disk/efi/efidisk.c | 48 +++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 41 insertions(+), 7 deletions(-)
+
+diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c
+index 845c66fa9ab..f04f20b84ff 100644
+--- a/grub-core/disk/efi/efidisk.c
++++ b/grub-core/disk/efi/efidisk.c
+@@ -487,8 +487,15 @@ grub_efidisk_open (const char *name, struct grub_disk *disk)
+   m = d->block_io->media;
+   /* FIXME: Probably it is better to store the block size in the disk,
+      and total sectors should be replaced with total blocks.  */
+-  grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
+-		m, (unsigned long long) m->last_block, m->block_size);
++  grub_dprintf ("efidisk",
++		"m = %p, last block = %llx, block size = %x, io align = %x\n",
++		m, (unsigned long long) m->last_block, m->block_size,
++		m->io_align);
++
++  /* Ensure required buffer alignment is a power of two (or is zero). */
++  if (m->io_align & (m->io_align - 1))
++    return grub_error (GRUB_ERR_IO, "invalid buffer alignment %d", m->io_align);
++
+   disk->total_sectors = m->last_block + 1;
+   /* Don't increase this value due to bug in some EFI.  */
+   disk->max_agglomerate = 0xa0000 >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS);
+@@ -518,15 +525,42 @@ grub_efidisk_readwrite (struct grub_disk *disk, grub_disk_addr_t sector,
+ {
+   struct grub_efidisk_data *d;
+   grub_efi_block_io_t *bio;
++  grub_efi_status_t status;
++  grub_size_t io_align, num_bytes;
++  char *aligned_buf;
+ 
+   d = disk->data;
+   bio = d->block_io;
+ 
+-  return efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio,
+-		     bio->media->media_id,
+-		     (grub_efi_uint64_t) sector,
+-		     (grub_efi_uintn_t) size << disk->log_sector_size,
+-		     buf);
++  /* Set alignment to 1 if 0 specified */
++  io_align = bio->media->io_align ? bio->media->io_align : 1;
++  num_bytes = size << disk->log_sector_size;
++
++  if ((grub_addr_t) buf & (io_align - 1))
++    {
++      aligned_buf = grub_memalign (io_align, num_bytes);
++      if (! aligned_buf)
++	return GRUB_EFI_OUT_OF_RESOURCES;
++      if (wr)
++	grub_memcpy (aligned_buf, buf, num_bytes);
++    }
++  else
++    {
++      aligned_buf = buf;
++    }
++
++  status =  efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio,
++			bio->media->media_id, (grub_efi_uint64_t) sector,
++			(grub_efi_uintn_t) num_bytes, aligned_buf);
++
++  if ((grub_addr_t) buf & (io_align - 1))
++    {
++      if (!wr)
++	grub_memcpy (buf, aligned_buf, num_bytes);
++      grub_free (aligned_buf);
++    }
++
++  return status;
+ }
+ 
+ static grub_err_t
diff --git a/SOURCES/0233-loader-linux-Make-trailer-initrd-entry-aligned-again.patch b/SOURCES/0233-loader-linux-Make-trailer-initrd-entry-aligned-again.patch
new file mode 100644
index 0000000..e87d491
--- /dev/null
+++ b/SOURCES/0233-loader-linux-Make-trailer-initrd-entry-aligned-again.patch
@@ -0,0 +1,42 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bernhard=20=C3=9Cbelacker?= <bernhardu@vr-web.de>
+Date: Mon, 20 Jul 2015 14:06:45 +0200
+Subject: [PATCH] loader/linux: Make trailer initrd entry aligned again.
+
+Regression from commit:
+  loader/linux: do not pad initrd with zeroes at the end
+  a8c473288d3f0a5e17a903a5121dea1a695dda3b
+
+Wimboot fails since the change above because it expects the "trailer"
+initrd element on an aligned address.
+This issue shows only when newc_name is used and the last initrd
+entry has a not aligned size.
+---
+ grub-core/loader/linux.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
+index d2cd591f604..be6fa0f4d45 100644
+--- a/grub-core/loader/linux.c
++++ b/grub-core/loader/linux.c
+@@ -213,6 +213,7 @@ grub_initrd_init (int argc, char *argv[],
+ 
+   if (newc)
+     {
++      initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4);
+       initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head)
+ 				    + sizeof ("TRAILER!!!") - 1, 4);
+       free_dir (root);
+@@ -290,7 +291,11 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
+       ptr += cursize;
+     }
+   if (newc)
+-    ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0);
++    {
++      grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
++      ptr += ALIGN_UP_OVERHEAD (cursize, 4);
++      ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0);
++    }
+   free_dir (root);
+   root = 0;
+   return GRUB_ERR_NONE;
diff --git a/SOURCES/0234-Make-exit-take-a-return-code.patch b/SOURCES/0234-Make-exit-take-a-return-code.patch
new file mode 100644
index 0000000..6eca76a
--- /dev/null
+++ b/SOURCES/0234-Make-exit-take-a-return-code.patch
@@ -0,0 +1,260 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 26 Feb 2014 21:49:12 -0500
+Subject: [PATCH] Make "exit" take a return code.
+
+This adds "exit" with a return code.  With this patch, any "exit"
+command /may/ include a return code, and on platforms that support
+returning with an exit status, we will do so.  By default we return the
+same exit status we did before this patch.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/commands/minicmd.c         | 20 ++++++++++++++++----
+ grub-core/kern/efi/efi.c             |  9 +++++++--
+ grub-core/kern/emu/main.c            |  6 ++++++
+ grub-core/kern/emu/misc.c            |  5 +++--
+ grub-core/kern/i386/coreboot/init.c  |  2 +-
+ grub-core/kern/i386/qemu/init.c      |  2 +-
+ grub-core/kern/ieee1275/init.c       |  2 +-
+ grub-core/kern/mips/arc/init.c       |  2 +-
+ grub-core/kern/mips/loongson/init.c  |  2 +-
+ grub-core/kern/mips/qemu_mips/init.c |  2 +-
+ grub-core/kern/misc.c                |  2 +-
+ grub-core/kern/uboot/init.c          |  6 +++---
+ grub-core/kern/xen/init.c            |  2 +-
+ include/grub/misc.h                  |  2 +-
+ 14 files changed, 44 insertions(+), 20 deletions(-)
+
+diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
+index a3a11824172..b25ca4b9f17 100644
+--- a/grub-core/commands/minicmd.c
++++ b/grub-core/commands/minicmd.c
+@@ -176,12 +176,24 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
+ }
+ 
+ /* exit */
+-static grub_err_t __attribute__ ((noreturn))
++static grub_err_t
+ grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
+-		    int argc __attribute__ ((unused)),
+-		    char *argv[] __attribute__ ((unused)))
++		    int argc, char *argv[])
+ {
+-  grub_exit ();
++  int retval = -1;
++  unsigned long n;
++
++  if (argc < 0 || argc > 1)
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
++
++  if (argc == 1)
++    {
++      n = grub_strtoul (argv[0], 0, 10);
++      if (n != ~0UL)
++	retval = n;
++    }
++
++  grub_exit (retval);
+   /* Not reached.  */
+ }
+ 
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index 7dfe2ef1455..453f97a7595 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -155,11 +155,16 @@ grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
+ }
+ 
+ void
+-grub_exit (void)
++grub_exit (int retval)
+ {
++  int rc = GRUB_EFI_LOAD_ERROR;
++
++  if (retval == 0)
++    rc = GRUB_EFI_SUCCESS;
++
+   grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
+   efi_call_4 (grub_efi_system_table->boot_services->exit,
+-              grub_efi_image_handle, GRUB_EFI_LOAD_ERROR, 0, 0);
++              grub_efi_image_handle, rc, 0, 0);
+   for (;;) ;
+ }
+ 
+diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c
+index 4b509139c4a..d7c880c0c1f 100644
+--- a/grub-core/kern/emu/main.c
++++ b/grub-core/kern/emu/main.c
+@@ -65,6 +65,12 @@ grub_reboot (void)
+   longjmp (main_env, 1);
+ }
+ 
++void
++grub_exit (int retval __attribute__((unused)))
++{
++  grub_reboot ();
++}
++
+ void
+ grub_machine_init (void)
+ {
+diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c
+index bb606da2803..258a5649e2d 100644
+--- a/grub-core/kern/emu/misc.c
++++ b/grub-core/kern/emu/misc.c
+@@ -135,9 +135,10 @@ xasprintf (const char *fmt, ...)
+ #endif
+ 
+ void
+-grub_exit (void)
++__attribute__ ((noreturn))
++grub_exit (int rc)
+ {
+-  exit (1);
++  exit (rc < 0 ? 1 : rc);
+ }
+ 
+ grub_uint64_t
+diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c
+index 3314f027fec..36f9134b7b7 100644
+--- a/grub-core/kern/i386/coreboot/init.c
++++ b/grub-core/kern/i386/coreboot/init.c
+@@ -41,7 +41,7 @@ extern grub_uint8_t _end[];
+ extern grub_uint8_t _edata[];
+ 
+ void  __attribute__ ((noreturn))
+-grub_exit (void)
++grub_exit (int rc __attribute__((unused)))
+ {
+   /* We can't use grub_fatal() in this function.  This would create an infinite
+      loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit().  */
+diff --git a/grub-core/kern/i386/qemu/init.c b/grub-core/kern/i386/qemu/init.c
+index 271b6fbfabd..9fafe98f015 100644
+--- a/grub-core/kern/i386/qemu/init.c
++++ b/grub-core/kern/i386/qemu/init.c
+@@ -42,7 +42,7 @@ extern grub_uint8_t _end[];
+ extern grub_uint8_t _edata[];
+ 
+ void  __attribute__ ((noreturn))
+-grub_exit (void)
++grub_exit (int rc __attribute__((unused)))
+ {
+   /* We can't use grub_fatal() in this function.  This would create an infinite
+      loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit().  */
+diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
+index 8ca4bf79f09..e2540bc41ce 100644
+--- a/grub-core/kern/ieee1275/init.c
++++ b/grub-core/kern/ieee1275/init.c
+@@ -60,7 +60,7 @@ grub_addr_t grub_ieee1275_original_stack;
+ #endif
+ 
+ void
+-grub_exit (void)
++grub_exit (int rc __attribute__((unused)))
+ {
+   grub_ieee1275_exit ();
+ }
+diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c
+index b4f50e49642..90049cb53ce 100644
+--- a/grub-core/kern/mips/arc/init.c
++++ b/grub-core/kern/mips/arc/init.c
+@@ -276,7 +276,7 @@ grub_halt (void)
+ }
+ 
+ void
+-grub_exit (void)
++grub_exit (int rc __attribute__((unused)))
+ {
+   GRUB_ARC_FIRMWARE_VECTOR->exit ();
+ 
+diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c
+index 7b96531b983..dff598ca7b0 100644
+--- a/grub-core/kern/mips/loongson/init.c
++++ b/grub-core/kern/mips/loongson/init.c
+@@ -304,7 +304,7 @@ grub_halt (void)
+ }
+ 
+ void
+-grub_exit (void)
++grub_exit (int rc __attribute__((unused)))
+ {
+   grub_halt ();
+ }
+diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c
+index be88b77d22d..8b6c55ffc01 100644
+--- a/grub-core/kern/mips/qemu_mips/init.c
++++ b/grub-core/kern/mips/qemu_mips/init.c
+@@ -75,7 +75,7 @@ grub_machine_fini (int flags __attribute__ ((unused)))
+ }
+ 
+ void
+-grub_exit (void)
++grub_exit (int rc __attribute__((unused)))
+ {
+   grub_halt ();
+ }
+diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
+index 392c697db03..240396c55f3 100644
+--- a/grub-core/kern/misc.c
++++ b/grub-core/kern/misc.c
+@@ -1278,7 +1278,7 @@ grub_abort (void)
+       grub_getkey ();
+     }
+ 
+-  grub_exit ();
++  grub_exit (1);
+ }
+ 
+ #if defined (__clang__) && !defined (GRUB_UTIL)
+diff --git a/grub-core/kern/uboot/init.c b/grub-core/kern/uboot/init.c
+index 5dcc106ed9b..430c62b66e0 100644
+--- a/grub-core/kern/uboot/init.c
++++ b/grub-core/kern/uboot/init.c
+@@ -43,9 +43,9 @@ extern grub_uint32_t grub_uboot_machine_type;
+ extern grub_addr_t grub_uboot_boot_data;
+ 
+ void
+-grub_exit (void)
++grub_exit (int rc)
+ {
+-  grub_uboot_return (0);
++  grub_uboot_return (rc < 0 ? 1 : rc);
+ }
+ 
+ grub_uint32_t
+@@ -94,7 +94,7 @@ grub_machine_init (void)
+   if (!ver)
+     {
+       /* Don't even have a console to log errors to... */
+-      grub_exit ();
++      grub_exit (-1);
+     }
+   else if (ver > API_SIG_VERSION)
+     {
+diff --git a/grub-core/kern/xen/init.c b/grub-core/kern/xen/init.c
+index 0559c033c3d..fce526d417b 100644
+--- a/grub-core/kern/xen/init.c
++++ b/grub-core/kern/xen/init.c
+@@ -549,7 +549,7 @@ grub_machine_init (void)
+ }
+ 
+ void
+-grub_exit (void)
++grub_exit (int rc __attribute__((unused)))
+ {
+   struct sched_shutdown arg;
+ 
+diff --git a/include/grub/misc.h b/include/grub/misc.h
+index 34250291908..c6851fb9dcf 100644
+--- a/include/grub/misc.h
++++ b/include/grub/misc.h
+@@ -398,7 +398,7 @@ int EXPORT_FUNC(grub_vsnprintf) (char *str, grub_size_t n, const char *fmt,
+ char *EXPORT_FUNC(grub_xasprintf) (const char *fmt, ...)
+      __attribute__ ((format (GNU_PRINTF, 1, 2))) WARN_UNUSED_RESULT;
+ char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args) WARN_UNUSED_RESULT;
+-void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn));
++void EXPORT_FUNC(grub_exit) (int rc) __attribute__ ((noreturn));
+ grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
+ 					  grub_uint64_t d,
+ 					  grub_uint64_t *r);
diff --git a/SOURCES/0235-efi-fix-memory-leak-in-variable-handling.patch b/SOURCES/0235-efi-fix-memory-leak-in-variable-handling.patch
new file mode 100644
index 0000000..7985372
--- /dev/null
+++ b/SOURCES/0235-efi-fix-memory-leak-in-variable-handling.patch
@@ -0,0 +1,35 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Ignat Korchagin <ignat@cloudflare.com>
+Date: Thu, 23 Jul 2015 21:13:09 +0300
+Subject: [PATCH] efi: fix memory leak in variable handling
+
+---
+ grub-core/kern/efi/efi.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index 453f97a7595..0cd64cdb59e 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -211,6 +211,7 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid,
+ 			| GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS
+ 			| GRUB_EFI_VARIABLE_RUNTIME_ACCESS),
+ 		       datasize, data);
++  grub_free (var16);
+   if (status == GRUB_EFI_SUCCESS)
+     return GRUB_ERR_NONE;
+ 
+@@ -242,8 +243,11 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
+ 
+   status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, NULL);
+ 
+-  if (!datasize)
+-    return NULL;
++  if (status != GRUB_EFI_SUCCESS || !datasize)
++    {
++      grub_free (var16);
++      return NULL;
++    }
+ 
+   data = grub_malloc (datasize);
+   if (!data)
diff --git a/SOURCES/0236-efi-fix-GetVariable-return-status-check-in-81ca24a.patch b/SOURCES/0236-efi-fix-GetVariable-return-status-check-in-81ca24a.patch
new file mode 100644
index 0000000..786f17a
--- /dev/null
+++ b/SOURCES/0236-efi-fix-GetVariable-return-status-check-in-81ca24a.patch
@@ -0,0 +1,24 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Ignat Korchagin <ignat@cloudflare.com>
+Date: Fri, 24 Jul 2015 20:46:02 +0300
+Subject: [PATCH] efi: fix GetVariable return status check in 81ca24a
+
+GetVariable should return EFI_BUFFER_TOO_SMALL if given buffer of size
+zero; commit incorrectly checked for EFI_SUCCESS.
+---
+ grub-core/kern/efi/efi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index 0cd64cdb59e..101307fc71e 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -243,7 +243,7 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
+ 
+   status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, NULL);
+ 
+-  if (status != GRUB_EFI_SUCCESS || !datasize)
++  if (status != GRUB_EFI_BUFFER_TOO_SMALL || !datasize)
+     {
+       grub_free (var16);
+       return NULL;
diff --git a/SOURCES/0237-linux.c-Ensure-that-initrd-is-page-aligned.patch b/SOURCES/0237-linux.c-Ensure-that-initrd-is-page-aligned.patch
new file mode 100644
index 0000000..ab1325c
--- /dev/null
+++ b/SOURCES/0237-linux.c-Ensure-that-initrd-is-page-aligned.patch
@@ -0,0 +1,59 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Thu, 7 May 2015 16:23:39 +0200
+Subject: [PATCH] linux.c: Ensure that initrd is page-aligned.
+
+---
+ grub-core/loader/i386/linux.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
+index 53f74ae0685..764cde20318 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -70,7 +70,6 @@ static grub_addr_t prot_mode_target;
+ static void *initrd_mem;
+ static grub_addr_t initrd_mem_target;
+ static grub_size_t prot_init_space;
+-static grub_uint32_t initrd_pages;
+ static struct grub_relocator *relocator = NULL;
+ static void *efi_mmap_buf;
+ static grub_size_t maximal_cmdline_size;
+@@ -1055,7 +1054,7 @@ static grub_err_t
+ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ 		 int argc, char *argv[])
+ {
+-  grub_size_t size = 0;
++  grub_size_t size = 0, aligned_size = 0;
+   grub_addr_t addr_min, addr_max;
+   grub_addr_t addr;
+   grub_err_t err;
+@@ -1077,8 +1076,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+     goto fail;
+ 
+   size = grub_get_initrd_size (&initrd_ctx);
+-
+-  initrd_pages = (page_align (size) >> 12);
++  aligned_size = ALIGN_UP (size, 4096);
+ 
+   /* Get the highest address available for the initrd.  */
+   if (grub_le_to_cpu16 (linux_params.version) >= 0x0203)
+@@ -1106,7 +1104,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   addr_min = (grub_addr_t) prot_mode_target + prot_init_space;
+ 
+   /* Put the initrd as high as possible, 4KiB aligned.  */
+-  addr = (addr_max - size) & ~0xFFF;
++  addr = (addr_max - aligned_size) & ~0xFFF;
+ 
+   if (addr < addr_min)
+     {
+@@ -1117,7 +1115,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   {
+     grub_relocator_chunk_t ch;
+     err = grub_relocator_alloc_chunk_align (relocator, &ch,
+-					    addr_min, addr, size, 0x1000,
++					    addr_min, addr, aligned_size,
++					    0x1000,
+ 					    GRUB_RELOCATOR_PREFERENCE_HIGH,
+ 					    1);
+     if (err)
diff --git a/SOURCES/0238-arm64-make-sure-fdt-has-address-cells-and-size-cells.patch b/SOURCES/0238-arm64-make-sure-fdt-has-address-cells-and-size-cells.patch
new file mode 100644
index 0000000..0511a41
--- /dev/null
+++ b/SOURCES/0238-arm64-make-sure-fdt-has-address-cells-and-size-cells.patch
@@ -0,0 +1,42 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Mark Salter <msalter@redhat.com>
+Date: Mon, 17 Apr 2017 08:44:29 -0400
+Subject: [PATCH] arm64: make sure fdt has #address-cells and #size-cells
+ properties
+
+Recent upstream changes to kexec-tools relies on #address-cells
+and #size-cells properties in the FDT. If grub2 needs to create
+a chosen node, it is likely because firmware did not provide one.
+In that case, set #address-cells and #size-cells properties to
+make sure they exist.
+---
+ grub-core/loader/arm64/linux.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
+index 0452a20e98b..1eb332a892c 100644
+--- a/grub-core/loader/arm64/linux.c
++++ b/grub-core/loader/arm64/linux.c
+@@ -147,7 +147,21 @@ finalize_params (void)
+ 
+   node = grub_fdt_find_subnode (fdt, 0, "chosen");
+   if (node < 0)
+-    node = grub_fdt_add_subnode (fdt, 0, "chosen");
++    {
++      /*
++       * If we have to create a chosen node, Make sure we
++       * have #address-cells and #size-cells properties.
++       */
++      retval = grub_fdt_set_prop32(fdt, 0, "#address-cells", 2);
++      if (retval)
++	goto failure;
++
++      retval = grub_fdt_set_prop32(fdt, 0, "#size-cells", 2);
++      if (retval)
++	goto failure;
++
++      node = grub_fdt_add_subnode (fdt, 0, "chosen");
++    }
+ 
+   if (node < 1)
+     goto failure;
diff --git a/SOURCES/0239-Don-t-guess-boot-efi-as-on-ppc-machines.patch b/SOURCES/0239-Don-t-guess-boot-efi-as-on-ppc-machines.patch
new file mode 100644
index 0000000..88e421e
--- /dev/null
+++ b/SOURCES/0239-Don-t-guess-boot-efi-as-on-ppc-machines.patch
@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 20 Apr 2017 13:29:06 -0400
+Subject: [PATCH] Don't guess /boot/efi/ as  on ppc machines
+
+This should never be trying this, and since we've consolidated the
+grubenv to always be on /boot/efi/EFI/redhat/, this code causes it to
+always make the wrong decision.
+
+Resolves: rhbz#1443809
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ util/grub-install.c | 12 +-----------
+ 1 file changed, 1 insertion(+), 11 deletions(-)
+
+diff --git a/util/grub-install.c b/util/grub-install.c
+index 7d61c32be2f..947a2d2ddf5 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -1151,18 +1151,8 @@ main (int argc, char *argv[])
+ 	  char *d;
+ 
+ 	  is_guess = 1;
+-	  d = grub_util_path_concat (2, bootdir, "macppc");
+-	  if (!grub_util_is_directory (d))
+-	    {
+-	      free (d);
+-	      d = grub_util_path_concat (2, bootdir, "efi");
+-	    }
+ 	  /* Find the Mac HFS(+) System Partition.  */
+-	  if (!grub_util_is_directory (d))
+-	    {
+-	      free (d);
+-	      d = grub_util_path_concat (2, bootdir, "EFI");
+-	    }
++	  d = grub_util_path_concat (2, bootdir, "macppc");
+ 	  if (!grub_util_is_directory (d))
+ 	    {
+ 	      free (d);
diff --git a/SOURCES/0240-Clean-up-some-errors-in-the-linuxefi-loader.patch b/SOURCES/0240-Clean-up-some-errors-in-the-linuxefi-loader.patch
new file mode 100644
index 0000000..d793767
--- /dev/null
+++ b/SOURCES/0240-Clean-up-some-errors-in-the-linuxefi-loader.patch
@@ -0,0 +1,74 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 24 May 2017 15:58:18 -0400
+Subject: [PATCH] Clean up some errors in the linuxefi loader
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/i386/efi/linux.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index c123afad19c..7166ec17f8f 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -161,8 +161,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 		int argc, char *argv[])
+ {
+   grub_file_t file = 0;
+-  struct linux_kernel_header *lh;
+-  grub_ssize_t len, start, filelen;
++  struct linux_kernel_header *lh = NULL;
++  grub_ssize_t start, filelen;
+   void *kernel = NULL;
+   int setup_header_end_offset;
+   int rc;
+@@ -212,18 +212,19 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-  grub_dprintf ("linuxefi", "params = %p\n", (unsigned long) params);
++  grub_dprintf ("linuxefi", "params = %p\n", params);
+ 
+   grub_memset (params, 0, sizeof(*params));
+ 
+   setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201);
+   grub_dprintf ("linuxefi", "copying %lu bytes from %p to %p\n",
+-		MIN(0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1,
++		MIN((grub_size_t)0x202+setup_header_end_offset,
++		    sizeof (*params)) - 0x1f1,
+ 		(grub_uint8_t *)kernel + 0x1f1,
+ 		(grub_uint8_t *)params + 0x1f1);
+   grub_memcpy ((grub_uint8_t *)params + 0x1f1,
+ 	       (grub_uint8_t *)kernel + 0x1f1,
+-		MIN(0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
++		MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
+   lh = (struct linux_kernel_header *)params;
+   grub_dprintf ("linuxefi", "lh is at %p\n", lh);
+   grub_dprintf ("linuxefi", "checking lh->boot_flag\n");
+@@ -254,7 +255,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-#ifdef defined(__x86_64__) || defined(__aarch64__)
++#if defined(__x86_64__) || defined(__aarch64__)
+   grub_dprintf ("linuxefi", "checking lh->xloadflags\n");
+   if (!(lh->xloadflags & LINUX_XLF_KERNEL_64))
+     {
+@@ -298,7 +299,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   handover_offset = lh->handover_offset;
+ 
+   start = (lh->setup_sects + 1) * 512;
+-  len = grub_file_size(file) - start;
+ 
+   kernel_mem = grub_efi_allocate_pages(lh->pref_address,
+ 				       BYTES_TO_PAGES(lh->init_size));
+@@ -344,7 +344,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       loaded = 0;
+     }
+ 
+-  if (linux_cmdline && !loaded)
++  if (linux_cmdline && lh && !loaded)
+     grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
+ 			 linux_cmdline,
+ 			 BYTES_TO_PAGES(lh->cmdline_size + 1));
diff --git a/SOURCES/0241-Revert-trim-arp-packets-with-abnormal-size.patch b/SOURCES/0241-Revert-trim-arp-packets-with-abnormal-size.patch
new file mode 100644
index 0000000..53e9303
--- /dev/null
+++ b/SOURCES/0241-Revert-trim-arp-packets-with-abnormal-size.patch
@@ -0,0 +1,27 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 18 May 2017 14:25:45 -0400
+Subject: [PATCH] Revert "trim arp packets with abnormal size"
+
+This reverts commit d11b2eb425d2125f67dd8d8e9b11d9be7d6f3f11.
+---
+ grub-core/net/arp.c | 6 ------
+ 1 file changed, 6 deletions(-)
+
+diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c
+index 77581f4b29a..d62d0cc1e01 100644
+--- a/grub-core/net/arp.c
++++ b/grub-core/net/arp.c
+@@ -162,12 +162,6 @@ grub_net_arp_receive (struct grub_net_buff *nb,
+     if (grub_net_addr_cmp (&inf->address, &target_addr) == 0
+ 	&& grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST)
+       {
+-        if ((nb->tail - nb->data) > 50)
+-          {
+-            grub_dprintf ("net", "arp packet with abnormal size (%ld bytes).\n",
+-                         nb->tail - nb->data);
+-            nb->tail = nb->data + 50;
+-          }
+ 	grub_net_link_level_address_t target;
+ 	/* We've already checked that pln is either 4 or 16.  */
+ 	char tmp[16];
diff --git a/SOURCES/0242-cleanup-grub_cpu_to_XXX_compile_time-for-constants.patch b/SOURCES/0242-cleanup-grub_cpu_to_XXX_compile_time-for-constants.patch
new file mode 100644
index 0000000..dbaa347
--- /dev/null
+++ b/SOURCES/0242-cleanup-grub_cpu_to_XXX_compile_time-for-constants.patch
@@ -0,0 +1,727 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Mon, 22 Sep 2014 20:47:10 +0400
+Subject: [PATCH] cleanup: grub_cpu_to_XXX_compile_time for constants
+
+This tries to catch all cases where grub_cpu_to_XXX was used for constant
+expressions (including sizeof).
+---
+ grub-core/bus/usb/ehci.c         | 44 ++++++++++++++++++++--------------------
+ grub-core/bus/usb/ohci.c         |  8 ++++----
+ grub-core/commands/gptsync.c     |  6 +++---
+ grub-core/disk/mdraid_linux.c    | 12 +++++------
+ grub-core/disk/scsi.c            |  2 +-
+ grub-core/disk/usbms.c           |  4 ++--
+ grub-core/fs/hfs.c               |  2 +-
+ grub-core/fs/reiserfs.c          | 12 +++++------
+ grub-core/lib/fdt.c              | 12 +++++------
+ grub-core/loader/i386/linux.c    |  2 +-
+ grub-core/loader/i386/pc/linux.c | 12 +++++------
+ grub-core/loader/i386/xen_file.c |  4 ++--
+ grub-core/net/arp.c              |  4 ++--
+ grub-core/net/bootp.c            |  4 ++--
+ grub-core/net/ip.c               |  2 +-
+ grub-core/net/net.c              |  2 +-
+ grub-core/net/tftp.c             |  8 ++++----
+ grub-core/partmap/acorn.c        |  4 ++--
+ grub-core/partmap/bsdlabel.c     |  2 +-
+ grub-core/partmap/gpt.c          |  2 +-
+ grub-core/partmap/msdos.c        |  4 ++--
+ grub-core/tests/video_checksum.c |  6 +++---
+ util/grub-mkfont.c               |  4 ++--
+ util/grub-mklayout.c             |  2 +-
+ util/mkimage.c                   | 15 +++++++-------
+ 25 files changed, 90 insertions(+), 89 deletions(-)
+
+diff --git a/grub-core/bus/usb/ehci.c b/grub-core/bus/usb/ehci.c
+index c0feefafe4a..8ece40086ec 100644
+--- a/grub-core/bus/usb/ehci.c
++++ b/grub-core/bus/usb/ehci.c
+@@ -670,23 +670,23 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
+   for (i = 0; i < (GRUB_EHCI_N_TD - 1); i++)
+     {
+       e->td_virt[i].link_td = e->td_phys + (i + 1) * sizeof (struct grub_ehci_td);
+-      e->td_virt[i].next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
+-      e->td_virt[i].alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
++      e->td_virt[i].next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
++      e->td_virt[i].alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
+     }
+   e->td_virt[GRUB_EHCI_N_TD - 1].next_td =
+-    grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
++    grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
+   e->td_virt[GRUB_EHCI_N_TD - 1].alt_next_td =
+-    grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
++    grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
+   e->tdfree_virt = e->td_virt;
+   /* Set Terminate in first QH, which is used in framelist */
+-  e->qh_virt[0].qh_hptr = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE | GRUB_EHCI_HPTR_TYPE_QH);
+-  e->qh_virt[0].td_overlay.next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
++  e->qh_virt[0].qh_hptr = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE | GRUB_EHCI_HPTR_TYPE_QH);
++  e->qh_virt[0].td_overlay.next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
+   e->qh_virt[0].td_overlay.alt_next_td =
+-    grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
++    grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
+   /* Also set Halted bit in token */
+-  e->qh_virt[0].td_overlay.token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED);
++  e->qh_virt[0].td_overlay.token = grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED);
+   /* Set the H bit in first QH used for AL */
+-  e->qh_virt[1].ep_char = grub_cpu_to_le32 (GRUB_EHCI_H);
++  e->qh_virt[1].ep_char = grub_cpu_to_le32_compile_time (GRUB_EHCI_H);
+   /* Set Terminate into TD in rest of QHs and set horizontal link
+    * pointer to itself - these QHs will be used for asynchronous
+    * schedule and they should have valid value in horiz. link */
+@@ -697,12 +697,12 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
+ 						e->qh_chunk) &
+ 			   GRUB_EHCI_POINTER_MASK) | GRUB_EHCI_HPTR_TYPE_QH);
+       e->qh_virt[i].td_overlay.next_td =
+-	grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
++	grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
+       e->qh_virt[i].td_overlay.alt_next_td =
+-	grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
++	grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
+       /* Also set Halted bit in token */
+       e->qh_virt[i].td_overlay.token =
+-	grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED);
++	grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED);
+     }
+ 
+   /* Note: QH 0 and QH 1 are reserved and must not be used anywhere.
+@@ -991,7 +991,7 @@ grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer)
+   target = ((transfer->endpoint << GRUB_EHCI_EP_NUM_OFF) |
+ 	    transfer->devaddr) & GRUB_EHCI_TARGET_MASK;
+   target = grub_cpu_to_le32 (target);
+-  mask = grub_cpu_to_le32 (GRUB_EHCI_TARGET_MASK);
++  mask = grub_cpu_to_le32_compile_time (GRUB_EHCI_TARGET_MASK);
+ 
+   /* low speed interrupt transfers are linked to the periodic */
+   /* schedule, everything else to the asynchronous schedule */
+@@ -1200,7 +1200,7 @@ grub_ehci_transaction (struct grub_ehci *e,
+   grub_memset ((void *) td, 0, sizeof (struct grub_ehci_td));
+ 
+   /* Don't point to any TD yet, just terminate.  */
+-  td->next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
++  td->next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
+   /* Set alternate pointer. When short packet occurs, alternate TD
+    * will not be really fetched because it is not active. But don't
+    * forget, EHCI will try to fetch alternate TD every scan of AL
+@@ -1325,9 +1325,9 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
+   /* Fill whole alternate TD by zeros (= inactive) and set
+    * Terminate bits and Halt bit */
+   grub_memset ((void *) cdata->td_alt_virt, 0, sizeof (struct grub_ehci_td));
+-  cdata->td_alt_virt->next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
+-  cdata->td_alt_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
+-  cdata->td_alt_virt->token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED);
++  cdata->td_alt_virt->next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
++  cdata->td_alt_virt->alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
++  cdata->td_alt_virt->token = grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED);
+ 
+   /* Allocate appropriate number of TDs and set */
+   for (i = 0; i < transfer->transcnt; i++)
+@@ -1364,7 +1364,7 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
+   cdata->td_last_virt = td;
+   cdata->td_last_phys = grub_dma_virt2phys (td, e->td_chunk);
+   /* Last TD should not have set alternate TD */
+-  cdata->td_last_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
++  cdata->td_last_virt->alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
+ 
+   grub_dprintf ("ehci", "setup_transfer: cdata=%p, qh=%p\n",
+ 		cdata,cdata->qh_virt);
+@@ -1377,14 +1377,14 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
+   /* Start transfer: */
+   /* Unlink possible alternate pointer in QH */
+   cdata->qh_virt->td_overlay.alt_next_td =
+-    grub_cpu_to_le32 (GRUB_EHCI_TERMINATE);
++    grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE);
+   /* Link new TDs with QH via next_td */
+   cdata->qh_virt->td_overlay.next_td =
+     grub_cpu_to_le32 (grub_dma_virt2phys
+ 		      (cdata->td_first_virt, e->td_chunk));
+   /* Reset Active and Halted bits in QH to activate Advance Queue,
+    * i.e. reset token */
+-  cdata->qh_virt->td_overlay.token = grub_cpu_to_le32 (0);
++  cdata->qh_virt->td_overlay.token = grub_cpu_to_le32_compile_time (0);
+ 
+   /* Finito */
+   transfer->controller_data = cdata;
+@@ -1408,9 +1408,9 @@ grub_ehci_pre_finish_transfer (grub_usb_transfer_t transfer)
+    * safely manipulate with QH TD part. */
+   cdata->qh_virt->td_overlay.token = (cdata->qh_virt->td_overlay.token
+ 				      |
+-				      grub_cpu_to_le32
++				      grub_cpu_to_le32_compile_time
+ 				      (GRUB_EHCI_STATUS_HALTED)) &
+-    grub_cpu_to_le32 (~GRUB_EHCI_STATUS_ACTIVE);
++    grub_cpu_to_le32_compile_time (~GRUB_EHCI_STATUS_ACTIVE);
+ 
+   /* Print debug data here if necessary */
+ 
+diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c
+index 946a4ed7d5b..d27bfe7fb9d 100644
+--- a/grub-core/bus/usb/ohci.c
++++ b/grub-core/bus/usb/ohci.c
+@@ -314,7 +314,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
+   grub_memset ((void *) o->ed_ctrl, 0, sizeof (struct grub_ohci_ed)
+ 	       * GRUB_OHCI_CTRL_EDS);
+   for (j=0; j < GRUB_OHCI_CTRL_EDS; j++)
+-    o->ed_ctrl[j].target = grub_cpu_to_le32 (1 << 14); /* skip */
++    o->ed_ctrl[j].target = grub_cpu_to_le32_compile_time (1 << 14); /* skip */
+     
+   grub_dprintf ("ohci", "EDs-C: chunk=%p, virt=%p, phys=0x%02x\n",
+                 o->ed_ctrl_chunk, o->ed_ctrl, o->ed_ctrl_addr);
+@@ -329,7 +329,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
+   /* Preset EDs */
+   grub_memset ((void*)o->ed_bulk, 0, sizeof(struct grub_ohci_ed) * GRUB_OHCI_BULK_EDS);
+   for (j=0; j < GRUB_OHCI_BULK_EDS; j++)
+-    o->ed_bulk[j].target = grub_cpu_to_le32 (1 << 14); /* skip */
++    o->ed_bulk[j].target = grub_cpu_to_le32_compile_time (1 << 14); /* skip */
+ 
+   grub_dprintf ("ohci", "EDs-B: chunk=%p, virt=%p, phys=0x%02x\n",
+                 o->ed_bulk_chunk, o->ed_bulk, o->ed_bulk_addr);
+@@ -1349,10 +1349,10 @@ grub_ohci_fini_hw (int noreturn __attribute__ ((unused)))
+       /* Set skip in all EDs */
+       if (o->ed_bulk)
+         for (i=0; i < GRUB_OHCI_BULK_EDS; i++)
+-          o->ed_bulk[i].target |= grub_cpu_to_le32 (1 << 14); /* skip */
++          o->ed_bulk[i].target |= grub_cpu_to_le32_compile_time (1 << 14); /* skip */
+       if (o->ed_ctrl)
+         for (i=0; i < GRUB_OHCI_CTRL_EDS; i++)
+-          o->ed_ctrl[i].target |= grub_cpu_to_le32 (1 << 14); /* skip */
++          o->ed_ctrl[i].target |= grub_cpu_to_le32_compile_time (1 << 14); /* skip */
+ 
+       /* We should wait for next SOF to be sure that all EDs are
+        * unaccessed by OHCI. But OHCI can be non-functional, so
+diff --git a/grub-core/commands/gptsync.c b/grub-core/commands/gptsync.c
+index 3db62887b92..16592e9bbe8 100644
+--- a/grub-core/commands/gptsync.c
++++ b/grub-core/commands/gptsync.c
+@@ -101,7 +101,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
+     }
+ 
+   /* Check if it is valid.  */
+-  if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
++  if (mbr.signature != grub_cpu_to_le16_compile_time (GRUB_PC_PARTITION_SIGNATURE))
+     {
+       grub_device_close (dev);
+       return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
+@@ -216,7 +216,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
+     first_sector--;
+   mbr.entries[0].flag = 0;
+   mbr.entries[0].type = GRUB_PC_PARTITION_TYPE_GPT_DISK;
+-  mbr.entries[0].start = grub_cpu_to_le32 (1);
++  mbr.entries[0].start = grub_cpu_to_le32_compile_time (1);
+   lba_to_chs (1,
+ 	      &(mbr.entries[0].start_sector),
+ 	      &(mbr.entries[0].start_cylinder),
+@@ -227,7 +227,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
+ 	      &(mbr.entries[0].end_head));
+   mbr.entries[0].length = grub_cpu_to_le32 (first_sector);
+ 
+-  mbr.signature = grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE);
++  mbr.signature = grub_cpu_to_le16_compile_time (GRUB_PC_PARTITION_SIGNATURE);
+ 
+   if (grub_disk_write (dev->disk, 0, 0, sizeof (mbr), &mbr))
+     {
+diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c
+index 4aa5882352e..11024ae31e0 100644
+--- a/grub-core/disk/mdraid_linux.c
++++ b/grub-core/disk/mdraid_linux.c
+@@ -33,16 +33,16 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ #define grub_md_to_cpu64 grub_be_to_cpu64
+ #define grub_md_to_cpu32 grub_be_to_cpu32
+ #define grub_md_to_cpu16 grub_be_to_cpu16
+-#define grub_cpu_to_md64_compile_time grub_cpu_to_be64
+-#define grub_cpu_to_md32_compile_time grub_cpu_to_be32
+-#define grub_cpu_to_md16_compile_time grub_cpu_to_be16
++#define grub_cpu_to_md64_compile_time grub_cpu_to_be64_compile_time
++#define grub_cpu_to_md32_compile_time grub_cpu_to_be32_compile_time
++#define grub_cpu_to_md16_compile_time grub_cpu_to_be16_compile_time
+ #else
+ #define grub_md_to_cpu64 grub_le_to_cpu64
+ #define grub_md_to_cpu32 grub_le_to_cpu32
+ #define grub_md_to_cpu16 grub_le_to_cpu16
+-#define grub_cpu_to_md64_compile_time grub_cpu_to_le64
+-#define grub_cpu_to_md32_compile_time grub_cpu_to_le32
+-#define grub_cpu_to_md16_compile_time grub_cpu_to_le16
++#define grub_cpu_to_md64_compile_time grub_cpu_to_le64_compile_time
++#define grub_cpu_to_md32_compile_time grub_cpu_to_le32_compile_time
++#define grub_cpu_to_md16_compile_time grub_cpu_to_le16_compile_time
+ #endif
+ 
+ #define RESERVED_BYTES			(64 * 1024)
+diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c
+index b6cb2f42109..92084d0f8ed 100644
+--- a/grub-core/disk/scsi.c
++++ b/grub-core/disk/scsi.c
+@@ -201,7 +201,7 @@ grub_scsi_read_capacity16 (grub_scsi_t scsi)
+   rc.opcode = grub_scsi_cmd_read_capacity16;
+   rc.lun = (scsi->lun << GRUB_SCSI_LUN_SHIFT) | 0x10;
+   rc.logical_block_addr = 0;
+-  rc.alloc_len = grub_cpu_to_be32 (sizeof (rcd));
++  rc.alloc_len = grub_cpu_to_be32_compile_time (sizeof (rcd));
+   rc.PMI = 0;
+   rc.control = 0;
+ 	
+diff --git a/grub-core/disk/usbms.c b/grub-core/disk/usbms.c
+index 2b769bdd8e1..380ca4c4cbf 100644
+--- a/grub-core/disk/usbms.c
++++ b/grub-core/disk/usbms.c
+@@ -307,7 +307,7 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
+ 
+   /* Setup the request.  */
+   grub_memset (&cbw, 0, sizeof (cbw));
+-  cbw.signature = grub_cpu_to_le32 (0x43425355);
++  cbw.signature = grub_cpu_to_le32_compile_time (0x43425355);
+   cbw.tag = tag;
+   cbw.transfer_length = grub_cpu_to_le32 (size);
+   cbw.flags = (!read_write) << GRUB_USBMS_DIRECTION_BIT;
+@@ -414,7 +414,7 @@ CheckCSW:
+   
+   /* If phase error or not valid signature, do bulk-only reset device. */
+   if ((status.status == 2) ||
+-      (status.signature != grub_cpu_to_le32(0x53425355)))
++      (status.signature != grub_cpu_to_le32_compile_time(0x53425355)))
+     { /* Bulk-only reset device. */
+       grub_dprintf ("usb", "Bulk-only reset device - bad status\n");
+       grub_usbms_reset (dev);
+diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c
+index 1e593059a74..d1dc015455d 100644
+--- a/grub-core/fs/hfs.c
++++ b/grub-core/fs/hfs.c
+@@ -369,7 +369,7 @@ grub_hfs_mount (grub_disk_t disk)
+ 
+   /* Lookup the root directory node in the catalog tree using the
+      volume name.  */
+-  key.parent_dir = grub_cpu_to_be32 (1);
++  key.parent_dir = grub_cpu_to_be32_compile_time (1);
+   key.strlen = data->sblock.volname[0];
+   grub_strcpy ((char *) key.str, (char *) (data->sblock.volname + 1));
+ 
+diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c
+index ac65054d363..de3d4fa3c64 100644
+--- a/grub-core/fs/reiserfs.c
++++ b/grub-core/fs/reiserfs.c
+@@ -365,7 +365,7 @@ grub_reiserfs_set_key_offset (struct grub_reiserfs_key *key,
+     key->u.v1.offset = grub_cpu_to_le32 (value);
+   else
+     key->u.v2.offset_type \
+-      = ((key->u.v2.offset_type & grub_cpu_to_le64 (15ULL << 60))
++      = ((key->u.v2.offset_type & grub_cpu_to_le64_compile_time (15ULL << 60))
+          | grub_cpu_to_le64 (value & (~0ULL >> 4)));
+ }
+ 
+@@ -412,7 +412,7 @@ grub_reiserfs_set_key_type (struct grub_reiserfs_key *key,
+     key->u.v1.type = grub_cpu_to_le32 (type);
+   else
+     key->u.v2.offset_type
+-      = ((key->u.v2.offset_type & grub_cpu_to_le64 (~0ULL >> 4))
++      = ((key->u.v2.offset_type & grub_cpu_to_le64_compile_time (~0ULL >> 4))
+          | grub_cpu_to_le64 ((grub_uint64_t) type << 60));
+ 
+   assert (grub_reiserfs_get_key_type (key) == grub_type);
+@@ -997,8 +997,8 @@ grub_reiserfs_open (struct grub_file *file, const char *name)
+   data = grub_reiserfs_mount (file->device->disk);
+   if (! data)
+     goto fail;
+-  key.directory_id = grub_cpu_to_le32 (1);
+-  key.object_id = grub_cpu_to_le32 (2);
++  key.directory_id = grub_cpu_to_le32_compile_time (1);
++  key.object_id = grub_cpu_to_le32_compile_time (2);
+   key.u.v2.offset_type = 0;
+   grub_reiserfs_set_key_type (&key, GRUB_REISERFS_DIRECTORY, 2);
+   grub_reiserfs_set_key_offset (&key, 1);
+@@ -1289,8 +1289,8 @@ grub_reiserfs_dir (grub_device_t device, const char *path,
+   data = grub_reiserfs_mount (device->disk);
+   if (! data)
+     goto fail;
+-  root_key.directory_id = grub_cpu_to_le32 (1);
+-  root_key.object_id = grub_cpu_to_le32 (2);
++  root_key.directory_id = grub_cpu_to_le32_compile_time (1);
++  root_key.object_id = grub_cpu_to_le32_compile_time (2);
+   root_key.u.v2.offset_type = 0;
+   grub_reiserfs_set_key_type (&root_key, GRUB_REISERFS_DIRECTORY, 2);
+   grub_reiserfs_set_key_offset (&root_key, 1);
+diff --git a/grub-core/lib/fdt.c b/grub-core/lib/fdt.c
+index 907a7bff61f..7e76dc06bbc 100644
+--- a/grub-core/lib/fdt.c
++++ b/grub-core/lib/fdt.c
+@@ -164,10 +164,10 @@ static int add_subnode (void *fdt, int parentoffset, const char *name)
+ insert:
+   grub_memmove (token + entry_size / sizeof(*token), token,
+                 (grub_addr_t) end - (grub_addr_t) token);
+-  *token = grub_cpu_to_be32(FDT_BEGIN_NODE);
++  *token = grub_cpu_to_be32_compile_time(FDT_BEGIN_NODE);
+   token[entry_size / sizeof(*token) - 2] = 0;	/* padding bytes */
+   grub_strcpy((char *) (token + 1), name);
+-  token[entry_size / sizeof(*token) - 1] = grub_cpu_to_be32(FDT_END_NODE);
++  token[entry_size / sizeof(*token) - 1] = grub_cpu_to_be32_compile_time(FDT_END_NODE);
+   grub_fdt_set_size_dt_struct (fdt, struct_size + entry_size);
+   return ((grub_addr_t) token - (grub_addr_t) fdt
+           - grub_fdt_get_off_dt_struct(fdt));
+@@ -377,7 +377,7 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
+ 
+       prop_name_present = 1;
+ 	  for (i = 0; i < prop_len / sizeof(grub_uint32_t); i++)
+-        *(prop + 3 + i) = grub_cpu_to_be32 (FDT_NOP);
++        *(prop + 3 + i) = grub_cpu_to_be32_compile_time (FDT_NOP);
+       if (len > ALIGN_UP(prop_len, sizeof(grub_uint32_t)))
+         {
+           /* Length of new property value is greater than the space allocated
+@@ -385,7 +385,7 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
+              nameoff field of the current entry and replace the current entry
+              with NOP tokens. */
+           nameoff = grub_be_to_cpu32 (*(prop + 2));
+-    	  *prop = *(prop + 1) = *(prop + 2) = grub_cpu_to_be32 (FDT_NOP);
++          *prop = *(prop + 1) = *(prop + 2) = grub_cpu_to_be32_compile_time (FDT_NOP);
+           prop = NULL;
+         }
+     }
+@@ -419,7 +419,7 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
+                   struct_end(fdt) - (grub_addr_t) prop);
+     grub_fdt_set_size_dt_struct (fdt, grub_fdt_get_size_dt_struct (fdt)
+                                  + prop_entry_size(len));
+-    *prop = grub_cpu_to_be32 (FDT_PROP);
++    *prop = grub_cpu_to_be32_compile_time (FDT_PROP);
+     *(prop + 2) = grub_cpu_to_be32 (nameoff);
+   }
+   *(prop + 1) = grub_cpu_to_be32 (len);
+@@ -447,7 +447,7 @@ grub_fdt_create_empty_tree (void *fdt, unsigned int size)
+   et->empty_node.node_end = grub_cpu_to_be32_compile_time (FDT_END_NODE);
+   et->empty_node.node_start = grub_cpu_to_be32_compile_time (FDT_BEGIN_NODE);
+   ((struct grub_fdt_empty_tree *) fdt)->header.off_mem_rsvmap =
+-    grub_cpu_to_be32 (ALIGN_UP (sizeof (grub_fdt_header_t), 8));
++    grub_cpu_to_be32_compile_time (ALIGN_UP (sizeof (grub_fdt_header_t), 8));
+ 
+   grub_fdt_set_off_dt_strings (fdt, sizeof (*et));
+   grub_fdt_set_off_dt_struct (fdt,
+diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
+index 764cde20318..e3906eb658f 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -734,7 +734,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+   /* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and
+      still not support 32-bit boot.  */
+-  if (lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE)
++  if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+       || grub_le_to_cpu16 (lh.version) < 0x0203)
+     {
+       grub_error (GRUB_ERR_BAD_OS, "version too old for 32-bit boot"
+diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
+index 60bb31fbf0d..c2e5fa9abcc 100644
+--- a/grub-core/loader/i386/pc/linux.c
++++ b/grub-core/loader/i386/pc/linux.c
+@@ -201,7 +201,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+       if (grub_le_to_cpu16 (lh.version) >= 0x0201)
+ 	{
+-	  lh.heap_end_ptr = grub_cpu_to_le32_compile_time (GRUB_LINUX_HEAP_END_OFFSET);
++	  lh.heap_end_ptr = grub_cpu_to_le16_compile_time (GRUB_LINUX_HEAP_END_OFFSET);
+ 	  lh.loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP;
+ 	}
+ 
+@@ -209,17 +209,17 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 	lh.cmd_line_ptr = grub_linux_real_target + GRUB_LINUX_CL_OFFSET;
+       else
+ 	{
+-	  lh.cl_magic = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_MAGIC);
+-	  lh.cl_offset = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_OFFSET);
+-	  lh.setup_move_size = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_OFFSET
++	  lh.cl_magic = grub_cpu_to_le16_compile_time (GRUB_LINUX_CL_MAGIC);
++	  lh.cl_offset = grub_cpu_to_le16_compile_time (GRUB_LINUX_CL_OFFSET);
++	  lh.setup_move_size = grub_cpu_to_le16_compile_time (GRUB_LINUX_CL_OFFSET
+ 						 + maximal_cmdline_size);
+ 	}
+     }
+   else
+     {
+       /* Your kernel is quite old...  */
+-      lh.cl_magic = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_MAGIC);
+-      lh.cl_offset = grub_cpu_to_le32_compile_time (GRUB_LINUX_CL_OFFSET);
++      lh.cl_magic = grub_cpu_to_le16_compile_time (GRUB_LINUX_CL_MAGIC);
++      lh.cl_offset = grub_cpu_to_le16_compile_time (GRUB_LINUX_CL_OFFSET);
+ 
+       setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
+ 
+diff --git a/grub-core/loader/i386/xen_file.c b/grub-core/loader/i386/xen_file.c
+index ff23235f064..58362189098 100644
+--- a/grub-core/loader/i386/xen_file.c
++++ b/grub-core/loader/i386/xen_file.c
+@@ -38,8 +38,8 @@ grub_xen_file (grub_file_t file)
+   if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
+     goto fail;
+ 
+-  if (lh.boot_flag != grub_cpu_to_le16 (0xaa55)
+-      || lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE)
++  if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55)
++      || lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+       || grub_le_to_cpu16 (lh.version) < 0x0208)
+     {
+       grub_error (GRUB_ERR_BAD_OS, "version too old for xen boot");
+diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c
+index d62d0cc1e01..8cc390b0e28 100644
+--- a/grub-core/net/arp.c
++++ b/grub-core/net/arp.c
+@@ -81,11 +81,11 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
+     return err;
+ 
+   arp_header = (struct arphdr *) nb.data;
+-  arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET);
++  arp_header->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET);
+   arp_header->hln = 6;
+   arp_header->pro = grub_cpu_to_be16 (etherpro);
+   arp_header->pln = addrlen;
+-  arp_header->op = grub_cpu_to_be16 (ARP_REQUEST);
++  arp_header->op = grub_cpu_to_be16_compile_time (ARP_REQUEST);
+   aux = (grub_uint8_t *) arp_header + sizeof (*arp_header);
+   /* Sender hardware address.  */
+   grub_memcpy (aux, &inf->hwaddress.mac, 6);
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index 46ce8135ac5..b4b8159cdad 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -767,8 +767,8 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
+ 	  grub_netbuff_push (nb, sizeof (*udph));
+ 
+ 	  udph = (struct udphdr *) nb->data;
+-	  udph->src = grub_cpu_to_be16 (68);
+-	  udph->dst = grub_cpu_to_be16 (67);
++	  udph->src = grub_cpu_to_be16_compile_time (68);
++	  udph->dst = grub_cpu_to_be16_compile_time (67);
+ 	  udph->chksum = 0;
+ 	  udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
+ 	  target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
+diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
+index c6971f9fcd2..5a609544403 100644
+--- a/grub-core/net/ip.c
++++ b/grub-core/net/ip.c
+@@ -611,7 +611,7 @@ grub_net_send_ip6_packet (struct grub_net_network_level_interface *inf,
+   grub_netbuff_push (nb, sizeof (*iph));
+   iph = (struct ip6hdr *) nb->data;
+ 
+-  iph->version_class_flow = grub_cpu_to_be32 ((6 << 28));
++  iph->version_class_flow = grub_cpu_to_be32_compile_time ((6 << 28));
+   iph->len = grub_cpu_to_be16 (nb->tail - nb->data - sizeof (*iph));
+   iph->protocol = proto;
+   iph->ttl = 0xff;
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index 36fc0d8b2e8..fc6f714bf7f 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -306,7 +306,7 @@ grub_net_ipv6_get_link_local (struct grub_net_card *card,
+     return NULL;
+ 
+   addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
+-  addr.ipv6[0] = grub_cpu_to_be64 (0xfe80ULL << 48);
++  addr.ipv6[0] = grub_cpu_to_be64_compile_time (0xfe80ULL << 48);
+   addr.ipv6[1] = grub_net_ipv6_get_id (hwaddr);
+ 
+   FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
+diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
+index 8632339de97..3931884c6dd 100644
+--- a/grub-core/net/tftp.c
++++ b/grub-core/net/tftp.c
+@@ -149,7 +149,7 @@ ack (tftp_data_t data, grub_uint64_t block)
+     return err;
+ 
+   tftph_ack = (struct tftphdr *) nb_ack.data;
+-  tftph_ack->opcode = grub_cpu_to_be16 (TFTP_ACK);
++  tftph_ack->opcode = grub_cpu_to_be16_compile_time (TFTP_ACK);
+   tftph_ack->u.ack.block = grub_cpu_to_be16 (block);
+ 
+   err = grub_net_send_udp_packet (data->sock, &nb_ack);
+@@ -352,7 +352,7 @@ tftp_open (struct grub_file *file, const char *filename)
+   rrq = (char *) tftph->u.rrq;
+   rrqlen = 0;
+ 
+-  tftph->opcode = grub_cpu_to_be16 (TFTP_RRQ);
++  tftph->opcode = grub_cpu_to_be16_compile_time (TFTP_RRQ);
+ 
+   /* Copy and normalize the filename to work-around issues on some tftp
+      servers when file names are being matched for remapping. */
+@@ -469,8 +469,8 @@ tftp_close (struct grub_file *file)
+       if (!err)
+ 	{
+ 	  tftph = (struct tftphdr *) nb_err.data;
+-	  tftph->opcode = grub_cpu_to_be16 (TFTP_ERROR);
+-	  tftph->u.err.errcode = grub_cpu_to_be16 (TFTP_EUNDEF);
++	  tftph->opcode = grub_cpu_to_be16_compile_time (TFTP_ERROR);
++	  tftph->u.err.errcode = grub_cpu_to_be16_compile_time (TFTP_EUNDEF);
+ 	  grub_memcpy (tftph->u.err.errmsg, "closed", sizeof ("closed"));
+ 
+ 	  err = grub_net_send_udp_packet (data->sock, &nb_err);
+diff --git a/grub-core/partmap/acorn.c b/grub-core/partmap/acorn.c
+index 7bb93d9bec9..c022c61ddfc 100644
+--- a/grub-core/partmap/acorn.c
++++ b/grub-core/partmap/acorn.c
+@@ -25,8 +25,8 @@
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+-#define LINUX_NATIVE_MAGIC grub_cpu_to_le32 (0xdeafa1de)
+-#define LINUX_SWAP_MAGIC   grub_cpu_to_le32 (0xdeafab1e)
++#define LINUX_NATIVE_MAGIC grub_cpu_to_le32_compile_time (0xdeafa1de)
++#define LINUX_SWAP_MAGIC   grub_cpu_to_le32_compile_time (0xdeafab1e)
+ #define LINUX_MAP_ENTRIES  (512 / 12)
+ 
+ #define NONADFS_PARTITION_TYPE_LINUX 9
+diff --git a/grub-core/partmap/bsdlabel.c b/grub-core/partmap/bsdlabel.c
+index cf0f967c1fa..1d785906b6a 100644
+--- a/grub-core/partmap/bsdlabel.c
++++ b/grub-core/partmap/bsdlabel.c
+@@ -53,7 +53,7 @@ iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd,
+     return grub_errno;
+ 
+   /* Check if it is valid.  */
+-  if (label.magic != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC))
++  if (label.magic != grub_cpu_to_le32_compile_time (GRUB_PC_PARTITION_BSD_LABEL_MAGIC))
+     return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
+ 
+   /* A kludge to determine a base of be.offset.  */
+diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c
+index 38df7b3c9b8..83bcba77914 100644
+--- a/grub-core/partmap/gpt.c
++++ b/grub-core/partmap/gpt.c
+@@ -65,7 +65,7 @@ grub_gpt_partition_map_iterate (grub_disk_t disk,
+     return grub_errno;
+ 
+   /* Check if it is valid.  */
+-  if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
++  if (mbr.signature != grub_cpu_to_le16_compile_time (GRUB_PC_PARTITION_SIGNATURE))
+     return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
+ 
+   /* Make sure the MBR is a protective MBR and not a normal MBR.  */
+diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c
+index 1d81a53573b..46c406bff1f 100644
+--- a/grub-core/partmap/msdos.c
++++ b/grub-core/partmap/msdos.c
+@@ -162,7 +162,7 @@ grub_partition_msdos_iterate (grub_disk_t disk,
+ 	lastaddr = p.offset;
+ 
+       /* Check if it is valid.  */
+-      if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
++      if (mbr.signature != grub_cpu_to_le16_compile_time (GRUB_PC_PARTITION_SIGNATURE))
+ 	return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
+ 
+       for (i = 0; i < 4; i++)
+@@ -280,7 +280,7 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
+ 	lastaddr = offset;
+ 
+       /* Check if it is valid.  */
+-      if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
++      if (mbr.signature != grub_cpu_to_le16_compile_time (GRUB_PC_PARTITION_SIGNATURE))
+ 	return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
+ 
+       for (i = 0; i < 4; i++)
+diff --git a/grub-core/tests/video_checksum.c b/grub-core/tests/video_checksum.c
+index 491bc55731c..74d5b65e5c7 100644
+--- a/grub-core/tests/video_checksum.c
++++ b/grub-core/tests/video_checksum.c
+@@ -288,16 +288,16 @@ grub_video_capture_write_bmp (const char *fname,
+   if (mode_info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB)
+     {
+       head.filesize = grub_cpu_to_le32 (sizeof (head) + mode_info->width * mode_info->height * 3);
+-      head.bmp_off = grub_cpu_to_le32 (sizeof (head));
++      head.bmp_off = grub_cpu_to_le32_compile_time (sizeof (head));
+       head.bpp = grub_cpu_to_le16_compile_time (24);
+     }
+   else
+     {
+       head.filesize = grub_cpu_to_le32 (sizeof (head) + 3 * 256 + mode_info->width * mode_info->height);
+-      head.bmp_off = grub_cpu_to_le32 (sizeof (head) + 3 * 256);
++      head.bmp_off = grub_cpu_to_le32_compile_time (sizeof (head) + 3 * 256);
+       head.bpp = grub_cpu_to_le16_compile_time (8);
+     }
+-  head.head_size = grub_cpu_to_le32 (sizeof (head) - 14);
++  head.head_size = grub_cpu_to_le32_compile_time (sizeof (head) - 14);
+   head.width = grub_cpu_to_le16 (mode_info->width);
+   head.height = grub_cpu_to_le16 (mode_info->height);
+   head.planes = grub_cpu_to_le16_compile_time (1);
+diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c
+index e6485b40f28..a0cab3a93f8 100644
+--- a/util/grub-mkfont.c
++++ b/util/grub-mkfont.c
+@@ -704,7 +704,7 @@ write_be16_section (const char *name, grub_uint16_t data, int* offset,
+ {
+   grub_uint32_t leng;
+ 
+-  leng = grub_cpu_to_be32 (2);
++  leng = grub_cpu_to_be32_compile_time (2);
+   data = grub_cpu_to_be16 (data);
+   grub_util_write_image (name, 4, file, filename);
+   grub_util_write_image ((char *) &leng, 4, file, filename);
+@@ -801,7 +801,7 @@ write_font_pf2 (struct grub_font_info *font_info, char *output_file)
+ 
+   offset = 0;
+ 
+-  leng = grub_cpu_to_be32 (4);
++  leng = grub_cpu_to_be32_compile_time (4);
+   grub_util_write_image (FONT_FORMAT_SECTION_NAMES_FILE,
+   			 sizeof(FONT_FORMAT_SECTION_NAMES_FILE) - 1, file,
+ 			 output_file);
+diff --git a/util/grub-mklayout.c b/util/grub-mklayout.c
+index 692f881900b..1a4f1b4c855 100644
+--- a/util/grub-mklayout.c
++++ b/util/grub-mklayout.c
+@@ -329,7 +329,7 @@ write_file (FILE *out, const char *fname, struct grub_keyboard_layout *layout)
+   grub_uint32_t version;
+   unsigned i;
+ 
+-  version = grub_cpu_to_le32 (GRUB_KEYBOARD_LAYOUTS_VERSION);
++  version = grub_cpu_to_le32_compile_time (GRUB_KEYBOARD_LAYOUTS_VERSION);
+   
+   for (i = 0; i < ARRAY_SIZE (layout->keyboard_map); i++)
+     layout->keyboard_map[i] = grub_cpu_to_le32(layout->keyboard_map[i]);
+diff --git a/util/mkimage.c b/util/mkimage.c
+index 26d9816e07e..e6b799fd73c 100644
+--- a/util/mkimage.c
++++ b/util/mkimage.c
+@@ -1528,9 +1528,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
+ 	text_section->virtual_address = grub_cpu_to_le32 (header_size);
+ 	text_section->raw_data_size = grub_cpu_to_le32 (exec_size);
+ 	text_section->raw_data_offset = grub_cpu_to_le32 (header_size);
+-	text_section->characteristics = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_CODE
+-							  | GRUB_PE32_SCN_MEM_EXECUTE
+-							  | GRUB_PE32_SCN_MEM_READ);
++	text_section->characteristics = grub_cpu_to_le32_compile_time (
++						  GRUB_PE32_SCN_CNT_CODE
++						| GRUB_PE32_SCN_MEM_EXECUTE
++						| GRUB_PE32_SCN_MEM_READ);
+ 
+ 	data_section = text_section + 1;
+ 	strcpy (data_section->name, ".data");
+@@ -1539,7 +1540,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
+ 	data_section->raw_data_size = grub_cpu_to_le32 (kernel_size - exec_size);
+ 	data_section->raw_data_offset = grub_cpu_to_le32 (header_size + exec_size);
+ 	data_section->characteristics
+-	  = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
++	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
+ 			      | GRUB_PE32_SCN_MEM_READ
+ 			      | GRUB_PE32_SCN_MEM_WRITE);
+ 
+@@ -1551,7 +1552,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
+ 	bss_section->raw_data_size = 0;
+ 	bss_section->raw_data_offset = 0;
+ 	bss_section->characteristics
+-	  = grub_cpu_to_le32 (GRUB_PE32_SCN_MEM_READ
++	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_MEM_READ
+ 			      | GRUB_PE32_SCN_MEM_WRITE
+ 			      | GRUB_PE32_SCN_ALIGN_64BYTES
+ 			      | GRUB_PE32_SCN_CNT_INITIALIZED_DATA
+@@ -1565,7 +1566,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
+ 	mods_section->raw_data_size = grub_cpu_to_le32 (reloc_addr - kernel_size - header_size);
+ 	mods_section->raw_data_offset = grub_cpu_to_le32 (header_size + kernel_size);
+ 	mods_section->characteristics
+-	  = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
++	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
+ 			      | GRUB_PE32_SCN_MEM_READ
+ 			      | GRUB_PE32_SCN_MEM_WRITE);
+ 
+@@ -1576,7 +1577,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
+ 	reloc_section->raw_data_size = grub_cpu_to_le32 (reloc_size);
+ 	reloc_section->raw_data_offset = grub_cpu_to_le32 (reloc_addr);
+ 	reloc_section->characteristics
+-	  = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
++	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
+ 			      | GRUB_PE32_SCN_MEM_DISCARDABLE
+ 			      | GRUB_PE32_SCN_MEM_READ);
+ 	free (core_img);
diff --git a/SOURCES/0243-arp-icmp-Fix-handling-in-case-of-oversized-or-invali.patch b/SOURCES/0243-arp-icmp-Fix-handling-in-case-of-oversized-or-invali.patch
new file mode 100644
index 0000000..7d3faa6
--- /dev/null
+++ b/SOURCES/0243-arp-icmp-Fix-handling-in-case-of-oversized-or-invali.patch
@@ -0,0 +1,309 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 20 Mar 2015 21:14:23 +0100
+Subject: [PATCH] arp, icmp: Fix handling in case of oversized or invalid
+ packets.
+
+This restrict ARP handling to MAC and IP addresses but in practice we need
+only this case anyway and other cases are very rar if exist at all. It makes
+code much simpler and less error-prone.
+---
+ grub-core/net/arp.c        | 139 ++++++++++++++++++++++-----------------------
+ grub-core/net/icmp.c       |  14 +----
+ grub-core/net/netbuff.c    |  20 +++++++
+ include/grub/net/netbuff.h |   1 +
+ 4 files changed, 90 insertions(+), 84 deletions(-)
+
+diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c
+index 8cc390b0e28..6cc580d6f85 100644
+--- a/grub-core/net/arp.c
++++ b/grub-core/net/arp.c
+@@ -37,12 +37,16 @@ enum
+     GRUB_NET_ARPHRD_ETHERNET = 1
+   };
+ 
+-struct arphdr {
++struct arppkt {
+   grub_uint16_t hrd;
+   grub_uint16_t pro;
+   grub_uint8_t hln;
+   grub_uint8_t pln;
+   grub_uint16_t op;
++  grub_uint8_t sender_mac[6];
++  grub_uint32_t sender_ip;
++  grub_uint8_t recv_mac[6];
++  grub_uint32_t recv_ip;
+ } GRUB_PACKED;
+ 
+ static int have_pending;
+@@ -53,21 +57,14 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
+ 			   const grub_net_network_level_address_t *proto_addr)
+ {
+   struct grub_net_buff nb;
+-  struct arphdr *arp_header;
+-  grub_net_link_level_address_t target_hw_addr;
+-  grub_uint8_t *aux, arp_data[128];
++  struct arppkt *arp_packet;
++  grub_net_link_level_address_t target_mac_addr;
+   grub_err_t err;
+   int i;
+-  grub_size_t addrlen;
+-  grub_uint16_t etherpro;
+   grub_uint8_t *nbd;
++  grub_uint8_t arp_data[128];
+ 
+-  if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
+-    {
+-      addrlen = 4;
+-      etherpro = GRUB_NET_ETHERTYPE_IP;
+-    }
+-  else
++  if (proto_addr->type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
+     return grub_error (GRUB_ERR_BUG, "unsupported address family");
+ 
+   /* Build a request packet.  */
+@@ -76,34 +73,28 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
+   grub_netbuff_clear (&nb);
+   grub_netbuff_reserve (&nb, 128);
+ 
+-  err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + addrlen));
++  err = grub_netbuff_push (&nb, sizeof (*arp_packet));
+   if (err)
+     return err;
+ 
+-  arp_header = (struct arphdr *) nb.data;
+-  arp_header->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET);
+-  arp_header->hln = 6;
+-  arp_header->pro = grub_cpu_to_be16 (etherpro);
+-  arp_header->pln = addrlen;
+-  arp_header->op = grub_cpu_to_be16_compile_time (ARP_REQUEST);
+-  aux = (grub_uint8_t *) arp_header + sizeof (*arp_header);
++  arp_packet = (struct arppkt *) nb.data;
++  arp_packet->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET);
++  arp_packet->hln = 6;
++  arp_packet->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP);
++  arp_packet->pln = 4;
++  arp_packet->op = grub_cpu_to_be16_compile_time (ARP_REQUEST);
+   /* Sender hardware address.  */
+   grub_memcpy (aux, &inf->hwaddress.mac, 6);
+ 
+-  aux += 6;
+-  /* Sender protocol address */
+-  grub_memcpy (aux, &inf->address.ipv4, 4);
+-  aux += addrlen;
+-  /* Target hardware address */
+-  for (i = 0; i < 6; i++)
+-    aux[i] = 0x00;
+-  aux += 6;
++  grub_memcpy (arp_packet->sender_mac, &inf->hwaddress.mac, 6);
++  arp_packet->sender_ip = inf->address.ipv4;
++  grub_memset (arp_packet->recv_mac, 0, 6);
++  arp_packet->recv_ip = proto_addr->ipv4;
+   /* Target protocol address */
+-  grub_memcpy (aux, &proto_addr->ipv4, 4);
+-  grub_memset (&target_hw_addr.mac, 0xff, 6);
++  grub_memset (&target_mac_addr.mac, 0xff, 6);
+ 
+   nbd = nb.data;
+-  send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP);
++  send_ethernet_packet (inf, &nb, target_mac_addr, GRUB_NET_ETHERTYPE_ARP);
+   for (i = 0; i < GRUB_NET_TRIES; i++)
+     {
+       if (grub_net_link_layer_resolve_check (inf, proto_addr))
+@@ -115,7 +106,7 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
+       if (grub_net_link_layer_resolve_check (inf, proto_addr))
+ 	return GRUB_ERR_NONE;
+       nb.data = nbd;
+-      send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP);
++      send_ethernet_packet (inf, &nb, target_mac_addr, GRUB_NET_ETHERTYPE_ARP);
+     }
+ 
+   return GRUB_ERR_NONE;
+@@ -125,63 +116,67 @@ grub_err_t
+ grub_net_arp_receive (struct grub_net_buff *nb,
+ 		      struct grub_net_card *card)
+ {
+-  struct arphdr *arp_header = (struct arphdr *) nb->data;
+-  grub_uint8_t *sender_hardware_address;
+-  grub_uint8_t *target_hardware_address;
++  struct arppkt *arp_packet = (struct arppkt *) nb->data;
+   grub_net_network_level_address_t sender_addr, target_addr;
+-  grub_net_link_level_address_t sender_hw_addr;
++  grub_net_link_level_address_t sender_mac_addr;
+   struct grub_net_network_level_interface *inf;
+-  grub_uint8_t *sender_protocol_address, *target_protocol_address;
+ 
+-  sender_hardware_address =
+-    (grub_uint8_t *) arp_header + sizeof (*arp_header);
+-  sender_protocol_address = sender_hardware_address + arp_header->hln;
+-  target_hardware_address = sender_protocol_address + arp_header->pln;
+-  target_protocol_address = target_hardware_address + arp_header->hln;
+-  if (grub_be_to_cpu16 (arp_header->pro) == GRUB_NET_ETHERTYPE_IP
+-      && arp_header->pln == 4)
+-    {
+-      sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
+-      target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
+-      grub_memcpy (&sender_addr.ipv4, sender_protocol_address, 4);
+-      grub_memcpy (&target_addr.ipv4, target_protocol_address, 4);
+-      if (grub_memcmp (sender_protocol_address, &pending_req, 4) == 0)
+-	have_pending = 1;
+-    }
+-  else
++  if (arp_packet->pro != grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP)
++      || arp_packet->pln != 4 || arp_packet->hln != 6
++      || nb->tail - nb->data < (int) sizeof (*arp_packet))
+     return GRUB_ERR_NONE;
+ 
+-  sender_hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+-  grub_memcpy (sender_hw_addr.mac, sender_hardware_address,
+-	       sizeof (sender_hw_addr.mac));
+-  grub_net_link_layer_add_address (card, &sender_addr, &sender_hw_addr, 1);
++  sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
++  target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
++  sender_addr.ipv4 = arp_packet->sender_ip;
++  target_addr.ipv4 = arp_packet->recv_ip;
++  if (arp_packet->sender_ip == pending_req)
++    have_pending = 1;
++
++  sender_mac_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
++  grub_memcpy (sender_mac_addr.mac, arp_packet->sender_mac,
++	       sizeof (sender_mac_addr.mac));
++  grub_net_link_layer_add_address (card, &sender_addr, &sender_mac_addr, 1);
+ 
+   FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
+   {
+     /* Am I the protocol address target? */
+     if (grub_net_addr_cmp (&inf->address, &target_addr) == 0
+-	&& grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST)
++	&& arp_packet->op == grub_cpu_to_be16_compile_time (ARP_REQUEST))
+       {
+ 	grub_net_link_level_address_t target;
+-	/* We've already checked that pln is either 4 or 16.  */
+-	char tmp[16];
+-	grub_size_t pln = arp_header->pln;
++	struct grub_net_buff nb_reply;
++	struct arppkt *arp_reply;
++	grub_uint8_t arp_data[128];
++	grub_err_t err;
+ 
+-	if (pln > 16)
+-	  pln = 16;
++	nb_reply.head = arp_data;
++	nb_reply.end = arp_data + sizeof (arp_data);
++	grub_netbuff_clear (&nb_reply);
++	grub_netbuff_reserve (&nb_reply, 128);
++
++	err = grub_netbuff_push (&nb_reply, sizeof (*arp_packet));
++	if (err)
++	  return err;
++
++	arp_reply = (struct arppkt *) nb_reply.data;
++
++	arp_reply->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET);
++	arp_reply->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP);
++	arp_reply->pln = 4;
++	arp_reply->hln = 6;
++	arp_reply->op = grub_cpu_to_be16_compile_time (ARP_REPLY);
++	arp_reply->sender_ip = arp_packet->recv_ip;
++	arp_reply->recv_ip = arp_packet->sender_ip;
++	arp_reply->hln = 6;
+ 
+ 	target.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+-	grub_memcpy (target.mac, sender_hardware_address, 6);
+-	grub_memcpy (target_hardware_address, target.mac, 6);
+-	grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6);
+-
+-	grub_memcpy (tmp, sender_protocol_address, pln);
+-	grub_memcpy (sender_protocol_address, target_protocol_address, pln);
+-	grub_memcpy (target_protocol_address, tmp, pln);
++	grub_memcpy (target.mac, arp_packet->sender_mac, 6);
++	grub_memcpy (arp_reply->sender_mac, inf->hwaddress.mac, 6);
++	grub_memcpy (arp_reply->recv_mac, arp_packet->sender_mac, 6);
+ 
+ 	/* Change operation to REPLY and send packet */
+-	arp_header->op = grub_be_to_cpu16 (ARP_REPLY);
+-	send_ethernet_packet (inf, nb, target, GRUB_NET_ETHERTYPE_ARP);
++	send_ethernet_packet (inf, &nb_reply, target, GRUB_NET_ETHERTYPE_ARP);
+       }
+   }
+   return GRUB_ERR_NONE;
+diff --git a/grub-core/net/icmp.c b/grub-core/net/icmp.c
+index 28d825ba04c..b1eef114e03 100644
+--- a/grub-core/net/icmp.c
++++ b/grub-core/net/icmp.c
+@@ -85,22 +85,13 @@ grub_net_recv_icmp_packet (struct grub_net_buff *nb,
+ 	struct icmp_header *icmphr;
+ 	if (icmph->code)
+ 	  break;
+-	nb_reply = grub_netbuff_alloc (nb->tail - nb->data + 512);
++	nb_reply = grub_netbuff_make_pkt (nb->tail - nb->data + sizeof (*icmphr));
+ 	if (!nb_reply)
+ 	  {
+ 	    grub_netbuff_free (nb);
+ 	    return grub_errno;
+ 	  }
+-	err = grub_netbuff_reserve (nb_reply, nb->tail - nb->data + 512);
+-	if (err)
+-	  goto ping_fail;
+-	err = grub_netbuff_push (nb_reply, nb->tail - nb->data);
+-	if (err)
+-	  goto ping_fail;
+-	grub_memcpy (nb_reply->data, nb->data, nb->tail - nb->data);
+-	err = grub_netbuff_push (nb_reply, sizeof (*icmphr));
+-	if (err)
+-	  goto ping_fail;
++	grub_memcpy (nb_reply->data + sizeof (*icmphr), nb->data, nb->tail - nb->data);
+ 	icmphr = (struct icmp_header *) nb_reply->data;
+ 	icmphr->type = ICMP_ECHO_REPLY;
+ 	icmphr->code = 0;
+@@ -110,7 +101,6 @@ grub_net_recv_icmp_packet (struct grub_net_buff *nb,
+ 	err = grub_net_send_ip_packet (inf, src, ll_src,
+ 				       nb_reply, GRUB_NET_IP_ICMP);
+ 
+-      ping_fail:
+ 	grub_netbuff_free (nb);
+ 	grub_netbuff_free (nb_reply);
+ 	return err;
+diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c
+index e97ecd23e9c..dbeeefe4783 100644
+--- a/grub-core/net/netbuff.c
++++ b/grub-core/net/netbuff.c
+@@ -97,6 +97,26 @@ grub_netbuff_alloc (grub_size_t len)
+   return nb;
+ }
+ 
++struct grub_net_buff *
++grub_netbuff_make_pkt (grub_size_t len)
++{
++  struct grub_net_buff *nb;
++  grub_err_t err;
++  nb = grub_netbuff_alloc (len + 512);
++  if (!nb)
++    return NULL;
++  err = grub_netbuff_reserve (nb, len + 512);
++  if (err)
++    goto fail;
++  err = grub_netbuff_push (nb, len);
++  if (err)
++    goto fail;
++  return nb;
++ fail:
++  grub_netbuff_free (nb);
++  return NULL;
++}
++
+ void
+ grub_netbuff_free (struct grub_net_buff *nb)
+ {
+diff --git a/include/grub/net/netbuff.h b/include/grub/net/netbuff.h
+index 9ac168c897c..1177c122051 100644
+--- a/include/grub/net/netbuff.h
++++ b/include/grub/net/netbuff.h
+@@ -25,6 +25,7 @@ grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff, grub_size_t len);
+ grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff, grub_size_t len);
+ grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff);
+ struct grub_net_buff * grub_netbuff_alloc (grub_size_t len);
++struct grub_net_buff * grub_netbuff_make_pkt (grub_size_t len);
+ void grub_netbuff_free (struct grub_net_buff *net_buff);
+ 
+ #endif
diff --git a/SOURCES/0244-net-trivial-grub_cpu_to_XX_compile_time-cleanup.patch b/SOURCES/0244-net-trivial-grub_cpu_to_XX_compile_time-cleanup.patch
new file mode 100644
index 0000000..e1249a9
--- /dev/null
+++ b/SOURCES/0244-net-trivial-grub_cpu_to_XX_compile_time-cleanup.patch
@@ -0,0 +1,38 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Fri, 27 Mar 2015 18:58:57 +0300
+Subject: [PATCH] net: trivial grub_cpu_to_XX_compile_time cleanup
+
+---
+ grub-core/net/arp.c   | 2 +-
+ grub-core/net/icmp6.c | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c
+index 6cc580d6f85..996473e1091 100644
+--- a/grub-core/net/arp.c
++++ b/grub-core/net/arp.c
+@@ -80,7 +80,7 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
+   arp_packet = (struct arppkt *) nb.data;
+   arp_packet->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET);
+   arp_packet->hln = 6;
+-  arp_packet->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP);
++  arp_packet->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP);
+   arp_packet->pln = 4;
+   arp_packet->op = grub_cpu_to_be16_compile_time (ARP_REQUEST);
+   /* Sender hardware address.  */
+diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c
+index 78223946031..7953e68ecfa 100644
+--- a/grub-core/net/icmp6.c
++++ b/grub-core/net/icmp6.c
+@@ -552,8 +552,8 @@ grub_net_icmp6_send_router_solicit (struct grub_net_network_level_interface *inf
+   struct icmp_header *icmphr;
+ 
+   multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
+-  multicast.ipv6[0] = grub_cpu_to_be64 (0xff02ULL << 48);
+-  multicast.ipv6[1] = grub_cpu_to_be64 (0x02ULL);
++  multicast.ipv6[0] = grub_cpu_to_be64_compile_time (0xff02ULL << 48);
++  multicast.ipv6[1] = grub_cpu_to_be64_compile_time (0x02ULL);
+ 
+   err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast);
+   if (err)
diff --git a/SOURCES/0245-bootp-ignore-gateway_ip-relay-field.patch b/SOURCES/0245-bootp-ignore-gateway_ip-relay-field.patch
new file mode 100644
index 0000000..53cfb25
--- /dev/null
+++ b/SOURCES/0245-bootp-ignore-gateway_ip-relay-field.patch
@@ -0,0 +1,72 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Sun, 17 May 2015 22:38:30 +0300
+Subject: [PATCH] bootp: ignore gateway_ip (relay) field.
+
+From RFC1542:
+
+   The 'giaddr' field is rather poorly named.  It exists to facilitate
+   the transfer of BOOTREQUEST messages from a client, through BOOTP
+   relay agents, to servers on different networks than the client.
+   Similarly, it facilitates the delivery of BOOTREPLY messages from the
+   servers, through BOOTP relay agents, back to the client.  In no case
+   does it represent a general IP router to be used by the client.  A
+   BOOTP client MUST set the 'giaddr' field to zero (0.0.0.0) in all
+   BOOTREQUEST messages it generates.
+
+   A BOOTP client MUST NOT interpret the 'giaddr' field of a BOOTREPLY
+   message to be the IP address of an IP router.  A BOOTP client SHOULD
+   completely ignore the contents of the 'giaddr' field in BOOTREPLY
+   messages.
+
+Leave code ifdef'd out for the time being in case we see regression.
+
+Suggested by: Rink Springer <rink@rink.nu>
+Closes: 43396
+---
+ grub-core/net/bootp.c | 7 +++++++
+ docs/grub.texi        | 6 ++++--
+ 2 files changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index b4b8159cdad..62d602d9645 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -237,6 +237,12 @@ grub_net_configure_by_dhcp_ack (const char *name,
+   hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+ 
+   inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags);
++#if 0
++  /* This is likely based on misunderstanding. gateway_ip refers to
++     address of BOOTP relay and should not be used after BOOTP transaction
++     is complete.
++     See RFC1542, 3.4 Interpretation of the 'giaddr' field
++   */
+   if (bp->gateway_ip)
+     {
+       grub_net_network_level_netaddress_t target;
+@@ -258,6 +264,7 @@ grub_net_configure_by_dhcp_ack (const char *name,
+       target.ipv4.masksize = 32;
+       grub_net_add_route (name, target, inter);
+     }
++#endif
+ 
+   if (size > OFFSET_OF (boot_file, bp))
+     grub_env_set_net_property (name, "boot_file", bp->boot_file,
+diff --git a/docs/grub.texi b/docs/grub.texi
+index ef09c832482..98138e04d5b 100644
+--- a/docs/grub.texi
++++ b/docs/grub.texi
+@@ -5211,8 +5211,10 @@ by @var{shortname} which can be used to remove it (@pxref{net_del_route}).
+ Perform configuration of @var{card} using DHCP protocol. If no card name
+ is specified, try to configure all existing cards. If configuration was
+ successful, interface with name @var{card}@samp{:dhcp} and configured
+-address is added to @var{card}. If server provided gateway information in
+-DHCP ACK packet, it is added as route entry with the name @var{card}@samp{:dhcp:gw}. Additionally the following DHCP options are recognized and processed:
++address is added to @var{card}.
++@comment If server provided gateway information in
++@comment DHCP ACK packet, it is added as route entry with the name @var{card}@samp{:dhcp:gw}.
++Additionally the following DHCP options are recognized and processed:
+ 
+ @table @samp
+ @item 1 (Subnet Mask)
diff --git a/SOURCES/0246-bootp-check-that-interface-is-not-NULL-in-configure_.patch b/SOURCES/0246-bootp-check-that-interface-is-not-NULL-in-configure_.patch
new file mode 100644
index 0000000..2132f27
--- /dev/null
+++ b/SOURCES/0246-bootp-check-that-interface-is-not-NULL-in-configure_.patch
@@ -0,0 +1,26 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Sun, 20 Mar 2016 10:32:33 +0300
+Subject: [PATCH] bootp: check that interface is not NULL in
+ configure_by_dhcp_ack
+
+grub_net_add_addr may fail with OOM and we use returned interface
+later without any checks.
+---
+ grub-core/net/bootp.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index 62d602d9645..7df7f55110e 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -237,6 +237,9 @@ grub_net_configure_by_dhcp_ack (const char *name,
+   hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+ 
+   inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags);
++  if (!inter)
++    return 0;
++
+ #if 0
+   /* This is likely based on misunderstanding. gateway_ip refers to
+      address of BOOTP relay and should not be used after BOOTP transaction
diff --git a/SOURCES/0247-Use-xid-to-match-DHCP-replies.patch b/SOURCES/0247-Use-xid-to-match-DHCP-replies.patch
new file mode 100644
index 0000000..95b3ffb
--- /dev/null
+++ b/SOURCES/0247-Use-xid-to-match-DHCP-replies.patch
@@ -0,0 +1,65 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrzej Kacprowski <andrzej.kacprowski@intel.com>
+Date: Fri, 21 Apr 2017 09:20:38 +0200
+Subject: [PATCH] Use xid to match DHCP replies
+
+Transaction identifier (xid) from DHCP request
+packet is stored in network level interface and used
+to match request with the responses it generates.
+
+Resolves: rhbz#1370642
+
+Signed-off-by: Andrzej Kacprowski <andrzej.kacprowski@intel.com>
+---
+ grub-core/net/bootp.c | 3 ++-
+ grub-core/net/ip.c    | 1 +
+ include/grub/net.h    | 3 ++-
+ 3 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index 7df7f55110e..dfdf7e08d90 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -769,7 +769,8 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
+ 	      grub_errno = GRUB_ERR_NONE;
+ 	      t = 0;
+ 	    }
+-	  pack->ident = grub_cpu_to_be32 (t);
++	  pack->xid = grub_cpu_to_be32 (t);
++	  ifaces[j].dhcp_xid = pack->xid;
+ 	  pack->seconds = grub_cpu_to_be16 (t);
+ 
+ 	  grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); 
+diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
+index 5a609544403..9e7930caa03 100644
+--- a/grub-core/net/ip.c
++++ b/grub-core/net/ip.c
+@@ -271,6 +271,7 @@ handle_dgram (struct grub_net_buff *nb,
+ 	FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
+ 	  if (inf->card == card
+ 	      && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV
++	      && inf->dhcp_xid == bootp->xid
+ 	      && inf->hwaddress.type == GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET
+ 	      && grub_memcmp (inf->hwaddress.mac, &bootp->mac_addr,
+ 			      sizeof (inf->hwaddress.mac)) == 0)
+diff --git a/include/grub/net.h b/include/grub/net.h
+index bd930f4dd8c..b1bc23048f1 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -279,6 +279,7 @@ struct grub_net_network_level_interface
+   grub_net_interface_flags_t flags;
+   struct grub_net_bootp_packet *dhcp_ack;
+   grub_size_t dhcp_acklen;
++  grub_uint32_t dhcp_xid;
+   void *data;
+ };
+ 
+@@ -405,7 +406,7 @@ struct grub_net_bootp_packet
+   grub_uint8_t hw_type;		/* hardware type.  */
+   grub_uint8_t hw_len;		/* hardware addr len.  */
+   grub_uint8_t gate_hops;	/* zero it.  */
+-  grub_uint32_t ident;		/* random number chosen by client.  */
++  grub_uint32_t xid;		/* transaction id chosen by client.  */
+   grub_uint16_t seconds;	/* seconds since did initial bootstrap.  */
+   grub_uint16_t flags;
+   grub_uint32_t	client_ip;
diff --git a/SOURCES/0248-Add-support-for-non-Ethernet-network-cards.patch b/SOURCES/0248-Add-support-for-non-Ethernet-network-cards.patch
new file mode 100644
index 0000000..48bf748
--- /dev/null
+++ b/SOURCES/0248-Add-support-for-non-Ethernet-network-cards.patch
@@ -0,0 +1,758 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrzej Kacprowski <andrzej.kacprowski@intel.com>
+Date: Fri, 21 Apr 2017 10:06:20 +0200
+Subject: [PATCH] Add support for non-Ethernet network cards
+
+This patch replaces fixed 6-byte link layer address with
+up to 32-byte variable sized address.
+This allows supporting Infiniband and Omni-Path fabric
+which use 20-byte address, but other network card types
+can also take advantage of this change.
+The network card driver is responsible for replacing L2
+header provided by grub2 if needed.
+This approach is compatible with UEFI network stack which
+also allows up to 32-byte variable size link address.
+
+The BOOTP/DHCP packet format is limited to 16 byte client
+hardware address, if link address is more that 16-bytes
+then chaddr field in BOOTP it will be set to 0 as per rfc4390.
+
+Resolves: rhbz#1370642
+
+Signed-off-by: Andrzej Kacprowski <andrzej.kacprowski@intel.com>
+
+Conflicts:
+	grub-core/net/ip.c
+---
+ grub-core/net/arp.c                    | 157 +++++++++++++++++++++------------
+ grub-core/net/bootp.c                  |  14 ++-
+ grub-core/net/drivers/efi/efinet.c     |   8 +-
+ grub-core/net/drivers/emu/emunet.c     |   1 +
+ grub-core/net/drivers/i386/pc/pxe.c    |  13 +--
+ grub-core/net/drivers/ieee1275/ofnet.c |   2 +
+ grub-core/net/drivers/uboot/ubootnet.c |   1 +
+ grub-core/net/ethernet.c               |  83 +++++++++--------
+ grub-core/net/icmp6.c                  |  15 ++--
+ grub-core/net/ip.c                     |   4 +-
+ grub-core/net/net.c                    |  48 +++++-----
+ include/grub/net.h                     |  19 ++--
+ 12 files changed, 213 insertions(+), 152 deletions(-)
+
+diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c
+index 996473e1091..badd2d3e684 100644
+--- a/grub-core/net/arp.c
++++ b/grub-core/net/arp.c
+@@ -31,22 +31,12 @@ enum
+     ARP_REPLY = 2
+   };
+ 
+-enum
+-  {
+-    /* IANA ARP constant to define hardware type as ethernet. */
+-    GRUB_NET_ARPHRD_ETHERNET = 1
+-  };
+-
+-struct arppkt {
++struct arphdr {
+   grub_uint16_t hrd;
+   grub_uint16_t pro;
+   grub_uint8_t hln;
+   grub_uint8_t pln;
+   grub_uint16_t op;
+-  grub_uint8_t sender_mac[6];
+-  grub_uint32_t sender_ip;
+-  grub_uint8_t recv_mac[6];
+-  grub_uint32_t recv_ip;
+ } GRUB_PACKED;
+ 
+ static int have_pending;
+@@ -57,12 +47,16 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
+ 			   const grub_net_network_level_address_t *proto_addr)
+ {
+   struct grub_net_buff nb;
+-  struct arppkt *arp_packet;
++  struct arphdr *arp_header;
+   grub_net_link_level_address_t target_mac_addr;
+   grub_err_t err;
+   int i;
+   grub_uint8_t *nbd;
+   grub_uint8_t arp_data[128];
++  grub_uint8_t hln;
++  grub_uint8_t pln;
++  grub_uint8_t arp_packet_len;
++  grub_uint8_t *tmp_ptr;
+ 
+   if (proto_addr->type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
+     return grub_error (GRUB_ERR_BUG, "unsupported address family");
+@@ -73,25 +67,39 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
+   grub_netbuff_clear (&nb);
+   grub_netbuff_reserve (&nb, 128);
+ 
+-  err = grub_netbuff_push (&nb, sizeof (*arp_packet));
++  hln = inf->card->default_address.len;
++  pln = sizeof (proto_addr->ipv4);
++  arp_packet_len = sizeof (*arp_header) + 2 * (hln + pln);
++
++  err = grub_netbuff_push (&nb, arp_packet_len);
+   if (err)
+     return err;
+ 
+-  arp_packet = (struct arppkt *) nb.data;
+-  arp_packet->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET);
+-  arp_packet->hln = 6;
+-  arp_packet->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP);
+-  arp_packet->pln = 4;
+-  arp_packet->op = grub_cpu_to_be16_compile_time (ARP_REQUEST);
+-  /* Sender hardware address.  */
+-  grub_memcpy (aux, &inf->hwaddress.mac, 6);
+-
+-  grub_memcpy (arp_packet->sender_mac, &inf->hwaddress.mac, 6);
+-  arp_packet->sender_ip = inf->address.ipv4;
+-  grub_memset (arp_packet->recv_mac, 0, 6);
+-  arp_packet->recv_ip = proto_addr->ipv4;
+-  /* Target protocol address */
+-  grub_memset (&target_mac_addr.mac, 0xff, 6);
++  arp_header = (struct arphdr *) nb.data;
++  arp_header->hrd = grub_cpu_to_be16 (inf->card->default_address.type);
++  arp_header->hln = hln;
++  arp_header->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP);
++  arp_header->pln = pln;
++  arp_header->op = grub_cpu_to_be16_compile_time (ARP_REQUEST);
++  tmp_ptr = nb.data + sizeof (*arp_header);
++
++  /* The source hardware address. */
++  grub_memcpy (tmp_ptr, inf->hwaddress.mac, hln);
++  tmp_ptr += hln;
++
++  /* The source protocol address. */
++  grub_memcpy (tmp_ptr, &inf->address.ipv4, pln);
++  tmp_ptr += pln;
++
++  /* The target hardware address. */
++  grub_memset (tmp_ptr, 0, hln);
++  tmp_ptr += hln;
++
++  /* The target protocol address */
++  grub_memcpy (tmp_ptr, &proto_addr->ipv4, pln);
++  tmp_ptr += pln;
++
++  grub_memset (&target_mac_addr.mac, 0xff, hln);
+ 
+   nbd = nb.data;
+   send_ethernet_packet (inf, &nb, target_mac_addr, GRUB_NET_ETHERTYPE_ARP);
+@@ -116,37 +124,62 @@ grub_err_t
+ grub_net_arp_receive (struct grub_net_buff *nb,
+ 		      struct grub_net_card *card)
+ {
+-  struct arppkt *arp_packet = (struct arppkt *) nb->data;
++  struct arphdr *arp_header = (struct arphdr *) nb->data;
+   grub_net_network_level_address_t sender_addr, target_addr;
+   grub_net_link_level_address_t sender_mac_addr;
+   struct grub_net_network_level_interface *inf;
++  grub_uint16_t hw_type;
++  grub_uint8_t hln;
++  grub_uint8_t pln;
++  grub_uint8_t arp_packet_len;
++  grub_uint8_t *tmp_ptr;
+ 
+-  if (arp_packet->pro != grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP)
+-      || arp_packet->pln != 4 || arp_packet->hln != 6
+-      || nb->tail - nb->data < (int) sizeof (*arp_packet))
++  hw_type = card->default_address.type;
++  hln = card->default_address.len;
++  pln = sizeof(sender_addr.ipv4);
++  arp_packet_len = sizeof (*arp_header) + 2 * (pln + hln);
++
++  if (arp_header->pro != grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP)
++      || arp_header->hrd != grub_cpu_to_be16 (hw_type)
++      || arp_header->hln != hln || arp_header->pln != pln
++      || nb->tail - nb->data < (int) arp_packet_len) {
+     return GRUB_ERR_NONE;
++  }
+ 
++  tmp_ptr =  nb->data + sizeof (*arp_header);
++
++  /* The source hardware address. */
++  sender_mac_addr.type = hw_type;
++  sender_mac_addr.len = hln;
++  grub_memcpy (sender_mac_addr.mac, tmp_ptr, hln);
++  tmp_ptr += hln;
++
++  /* The source protocol address. */
+   sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
++  grub_memcpy(&sender_addr.ipv4, tmp_ptr, pln);
++  tmp_ptr += pln;
++
++  grub_net_link_layer_add_address (card, &sender_addr, &sender_mac_addr, 1);
++
++  /* The target hardware address. */
++  tmp_ptr += hln;
++
++  /* The target protocol address. */
+   target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
+-  sender_addr.ipv4 = arp_packet->sender_ip;
+-  target_addr.ipv4 = arp_packet->recv_ip;
+-  if (arp_packet->sender_ip == pending_req)
++  grub_memcpy(&target_addr.ipv4, tmp_ptr, pln);
++
++  if (sender_addr.ipv4 == pending_req)
+     have_pending = 1;
+ 
+-  sender_mac_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+-  grub_memcpy (sender_mac_addr.mac, arp_packet->sender_mac,
+-	       sizeof (sender_mac_addr.mac));
+-  grub_net_link_layer_add_address (card, &sender_addr, &sender_mac_addr, 1);
+-
+   FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
+   {
+     /* Am I the protocol address target? */
+     if (grub_net_addr_cmp (&inf->address, &target_addr) == 0
+-	&& arp_packet->op == grub_cpu_to_be16_compile_time (ARP_REQUEST))
++	&& arp_header->op == grub_cpu_to_be16_compile_time (ARP_REQUEST))
+       {
+ 	grub_net_link_level_address_t target;
+ 	struct grub_net_buff nb_reply;
+-	struct arppkt *arp_reply;
++	struct arphdr *arp_reply;
+ 	grub_uint8_t arp_data[128];
+ 	grub_err_t err;
+ 
+@@ -155,25 +188,39 @@ grub_net_arp_receive (struct grub_net_buff *nb,
+ 	grub_netbuff_clear (&nb_reply);
+ 	grub_netbuff_reserve (&nb_reply, 128);
+ 
+-	err = grub_netbuff_push (&nb_reply, sizeof (*arp_packet));
++	err = grub_netbuff_push (&nb_reply, arp_packet_len);
+ 	if (err)
+ 	  return err;
+ 
+-	arp_reply = (struct arppkt *) nb_reply.data;
++	arp_reply = (struct arphdr *) nb_reply.data;
+ 
+-	arp_reply->hrd = grub_cpu_to_be16_compile_time (GRUB_NET_ARPHRD_ETHERNET);
++	arp_reply->hrd = grub_cpu_to_be16 (hw_type);
+ 	arp_reply->pro = grub_cpu_to_be16_compile_time (GRUB_NET_ETHERTYPE_IP);
+-	arp_reply->pln = 4;
+-	arp_reply->hln = 6;
++	arp_reply->pln = pln;
++	arp_reply->hln = hln;
+ 	arp_reply->op = grub_cpu_to_be16_compile_time (ARP_REPLY);
+-	arp_reply->sender_ip = arp_packet->recv_ip;
+-	arp_reply->recv_ip = arp_packet->sender_ip;
+-	arp_reply->hln = 6;
+-
+-	target.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+-	grub_memcpy (target.mac, arp_packet->sender_mac, 6);
+-	grub_memcpy (arp_reply->sender_mac, inf->hwaddress.mac, 6);
+-	grub_memcpy (arp_reply->recv_mac, arp_packet->sender_mac, 6);
++
++	tmp_ptr = nb_reply.data + sizeof (*arp_reply);
++
++	/* The source hardware address. */
++	grub_memcpy (tmp_ptr, inf->hwaddress.mac, hln);
++	tmp_ptr += hln;
++
++	/* The source protocol address. */
++	grub_memcpy (tmp_ptr, &target_addr.ipv4, pln);
++	tmp_ptr += pln;
++
++	/* The target hardware address. */
++	grub_memcpy (tmp_ptr, sender_mac_addr.mac, hln);
++	tmp_ptr += hln;
++
++	/* The target protocol address */
++	grub_memcpy (tmp_ptr, &sender_addr.ipv4, pln);
++	tmp_ptr += pln;
++
++	target.type = hw_type;
++	target.len = hln;
++	grub_memcpy (target.mac, sender_mac_addr.mac, hln);
+ 
+ 	/* Change operation to REPLY and send packet */
+ 	send_ethernet_packet (inf, &nb_reply, target, GRUB_NET_ETHERTYPE_ARP);
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index dfdf7e08d90..0a2d11b8820 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -219,7 +219,6 @@ grub_net_configure_by_dhcp_ack (const char *name,
+ 				int is_def, char **device, char **path)
+ {
+   grub_net_network_level_address_t addr;
+-  grub_net_link_level_address_t hwaddr;
+   struct grub_net_network_level_interface *inter;
+   int mask = -1;
+ 
+@@ -231,12 +230,8 @@ grub_net_configure_by_dhcp_ack (const char *name,
+   if (path)
+     *path = 0;
+ 
+-  grub_memcpy (hwaddr.mac, bp->mac_addr,
+-	       bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len
+-	       : sizeof (hwaddr.mac));
+-  hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+-
+-  inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags);
++  grub_dprintf("dhcp", "configuring dhcp for %s\n", name);
++  inter = grub_net_add_addr (name, card, &addr, &card->default_address, flags);
+   if (!inter)
+     return 0;
+ 
+@@ -762,7 +757,8 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
+ 	  grub_memset (pack, 0, sizeof (*pack) + 64);
+ 	  pack->opcode = 1;
+ 	  pack->hw_type = 1;
+-	  pack->hw_len = 6;
++	  pack->hw_len = ifaces[j].hwaddress.len > 16 ? 0
++						      : ifaces[j].hwaddress.len;
+ 	  err = grub_get_datetime (&date);
+ 	  if (err || !grub_datetime2unixtime (&date, &t))
+ 	    {
+@@ -773,7 +769,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
+ 	  ifaces[j].dhcp_xid = pack->xid;
+ 	  pack->seconds = grub_cpu_to_be16 (t);
+ 
+-	  grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); 
++	  grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, pack->hw_len);
+ 
+ 	  grub_netbuff_push (nb, sizeof (*udph));
+ 
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 69b0fc7a8fe..b9ed13fcad1 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -290,6 +290,9 @@ grub_efinet_findcards (void)
+ 	/* This should not happen... Why?  */
+ 	continue;
+ 
++      if (net->mode->hwaddr_size > GRUB_NET_MAX_LINK_ADDRESS_SIZE)
++	continue;
++
+       if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
+ 	  && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS)
+ 	continue;
+@@ -326,10 +329,11 @@ grub_efinet_findcards (void)
+       card->name = grub_xasprintf ("efinet%d", i++);
+       card->driver = &efidriver;
+       card->flags = 0;
+-      card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
++      card->default_address.type = net->mode->if_type;
++      card->default_address.len = net->mode->hwaddr_size;
+       grub_memcpy (card->default_address.mac,
+ 		   net->mode->current_address,
+-		   sizeof (card->default_address.mac));
++		   net->mode->hwaddr_size);
+       card->efi_net = net;
+       card->efi_handle = *handle;
+ 
+diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c
+index 7c977cd52ca..962b0c86d2b 100644
+--- a/grub-core/net/drivers/emu/emunet.c
++++ b/grub-core/net/drivers/emu/emunet.c
+@@ -46,6 +46,7 @@ static struct grub_net_card emucard =
+     .mtu = 1500,
+     .default_address = {
+ 			 .type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET,
++			 . len = 6,
+ 			 {.mac = {0, 1, 2, 3, 4, 5}}
+ 		       },
+     .flags = 0
+diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c
+index e8c0b22e294..5660149503d 100644
+--- a/grub-core/net/drivers/i386/pc/pxe.c
++++ b/grub-core/net/drivers/i386/pc/pxe.c
+@@ -387,20 +387,21 @@ GRUB_MOD_INIT(pxe)
+   grub_memset (ui, 0, sizeof (*ui));
+   grub_pxe_call (GRUB_PXENV_UNDI_GET_INFORMATION, ui, pxe_rm_entry);
+ 
++  grub_pxe_card.default_address.len = 6;
+   grub_memcpy (grub_pxe_card.default_address.mac, ui->current_addr,
+-	       sizeof (grub_pxe_card.default_address.mac));
+-  for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++)
++	       grub_pxe_card.default_address.len);
++  for (i = 0; i < grub_pxe_card.default_address.len; i++)
+     if (grub_pxe_card.default_address.mac[i] != 0)
+       break;
+-  if (i != sizeof (grub_pxe_card.default_address.mac))
++  if (i != grub_pxe_card.default_address.len)
+     {
+-      for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++)
++      for (i = 0; i < grub_pxe_card.default_address.len; i++)
+ 	if (grub_pxe_card.default_address.mac[i] != 0xff)
+ 	  break;
+     }
+-  if (i == sizeof (grub_pxe_card.default_address.mac))
++  if (i == grub_pxe_card.default_address.len)
+     grub_memcpy (grub_pxe_card.default_address.mac, ui->permanent_addr,
+-		 sizeof (grub_pxe_card.default_address.mac));
++		 grub_pxe_card.default_address.len);
+   grub_pxe_card.mtu = ui->mtu;
+ 
+   grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c
+index cd24ddc99c5..5a199bcaa75 100644
+--- a/grub-core/net/drivers/ieee1275/ofnet.c
++++ b/grub-core/net/drivers/ieee1275/ofnet.c
+@@ -154,6 +154,7 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
+   struct grub_net_network_level_interface *inter;
+ 
+   hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
++  hw_addr.len = 6;
+ 
+   args = bootpath + grub_strlen (devpath) + 1;
+   do
+@@ -369,6 +370,7 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
+     grub_memcpy (&lla.mac, pprop, 6);
+ 
+   lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
++  lla.len = 6;
+   card->default_address = lla;
+ 
+   card->txbufsize = ALIGN_UP (card->mtu, 64) + 256;
+diff --git a/grub-core/net/drivers/uboot/ubootnet.c b/grub-core/net/drivers/uboot/ubootnet.c
+index 056052e40d5..22ebcbf211e 100644
+--- a/grub-core/net/drivers/uboot/ubootnet.c
++++ b/grub-core/net/drivers/uboot/ubootnet.c
+@@ -131,6 +131,7 @@ GRUB_MOD_INIT (ubootnet)
+ 
+       grub_memcpy (&(card->default_address.mac), &devinfo->di_net.hwaddr, 6);
+       card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
++      card->default_address.len = 6;
+ 
+       card->txbufsize = ALIGN_UP (card->mtu, 64) + 256;
+       card->txbuf = grub_zalloc (card->txbufsize);
+diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c
+index faaca67c50e..1b479d3cadc 100644
+--- a/grub-core/net/ethernet.c
++++ b/grub-core/net/ethernet.c
+@@ -29,13 +29,6 @@
+ 
+ #define LLCADDRMASK 0x7f
+ 
+-struct etherhdr
+-{
+-  grub_uint8_t dst[6];
+-  grub_uint8_t src[6];
+-  grub_uint16_t type;
+-} GRUB_PACKED;
+-
+ struct llchdr
+ {
+   grub_uint8_t dsap;
+@@ -55,13 +48,15 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
+ 		      grub_net_link_level_address_t target_addr,
+ 		      grub_net_ethertype_t ethertype)
+ {
+-  struct etherhdr *eth;
++  grub_uint8_t *eth;
+   grub_err_t err;
+   grub_uint32_t vlantag = 0;
+-  grub_uint8_t etherhdr_size;
++  grub_uint8_t hw_addr_len = inf->card->default_address.len;
++  grub_uint8_t etherhdr_size = 2 * hw_addr_len + 2;
+ 
+-  etherhdr_size = sizeof (*eth);
+-  COMPILE_TIME_ASSERT (sizeof (*eth) + 4 < GRUB_NET_MAX_LINK_HEADER_SIZE);
++  /* Source and destination link addresses + ethertype + vlan tag */
++  COMPILE_TIME_ASSERT ((GRUB_NET_MAX_LINK_ADDRESS_SIZE * 2 + 2 + 4) <
++		       GRUB_NET_MAX_LINK_HEADER_SIZE);
+ 
+   const char *vlantag_text = grub_env_get ("vlan-tag");
+   if (vlantag_text != 0) {
+@@ -72,11 +67,22 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
+   err = grub_netbuff_push (nb, etherhdr_size);
+   if (err)
+     return err;
+-  eth = (struct etherhdr *) nb->data;
+-  grub_memcpy (eth->dst, target_addr.mac, 6);
+-  grub_memcpy (eth->src, inf->hwaddress.mac, 6);
++  eth = nb->data;
++  grub_memcpy (eth, target_addr.mac, hw_addr_len);
++  eth += hw_addr_len;
++  grub_memcpy (eth, inf->hwaddress.mac, hw_addr_len);
++  eth += hw_addr_len;
++
++  /* Check if a vlan-tag is present. */
++  if (vlantag != 0)
++    {
++      *((grub_uint32_t *)eth) = grub_cpu_to_be32 (vlantag);
++      eth += sizeof (vlantag);
++    }
++
++  /* Write ethertype */
++  *((grub_uint16_t*) eth) = grub_cpu_to_be16 (ethertype);
+ 
+-  eth->type = grub_cpu_to_be16 (ethertype);
+   if (!inf->card->opened)
+     {
+       err = GRUB_ERR_NONE;
+@@ -87,18 +93,6 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
+       inf->card->opened = 1;
+     }
+ 
+-  /* Check if a vlan-tag is needed. */
+-  if (vlantag != 0)
+-    {
+-      /* Move eth type to the right */
+-      grub_memcpy((char *) nb->data + etherhdr_size - 2,
+-                  (char *) nb->data + etherhdr_size - 6, 2);
+-
+-      /* Add the tag in the middle */
+-      grub_memcpy((char *) nb->data + etherhdr_size - 6,
+-                  &vlantag, 4);
+-    }
+-
+   return inf->card->driver->send (inf->card, nb);
+ }
+ 
+@@ -106,29 +100,37 @@ grub_err_t
+ grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
+ 			       struct grub_net_card *card)
+ {
+-  struct etherhdr *eth;
++  grub_uint8_t *eth;
+   struct llchdr *llch;
+   struct snaphdr *snaph;
+   grub_net_ethertype_t type;
+   grub_net_link_level_address_t hwaddress;
+   grub_net_link_level_address_t src_hwaddress;
+   grub_err_t err;
+-  grub_uint8_t etherhdr_size = sizeof (*eth);
++  grub_uint8_t hw_addr_len = card->default_address.len;
++  grub_uint8_t etherhdr_size = 2 * hw_addr_len + 2;
+ 
+-  grub_uint16_t vlantag_identifier = 0;
+-  grub_memcpy (&vlantag_identifier, nb->data + etherhdr_size - 2, 2);
++  eth = nb->data;
+ 
+-  /* Check if a vlan-tag is present. */
+-  if (vlantag_identifier == VLANTAG_IDENTIFIER)
++  hwaddress.type = card->default_address.type;
++  hwaddress.len = hw_addr_len;
++  grub_memcpy (hwaddress.mac, eth, hw_addr_len);
++  eth += hw_addr_len;
++
++  src_hwaddress.type = card->default_address.type;
++  src_hwaddress.len = hw_addr_len;
++  grub_memcpy (src_hwaddress.mac, eth, hw_addr_len);
++  eth += hw_addr_len;
++
++  type = grub_be_to_cpu16 (*(grub_uint16_t*)(eth));
++  if (type == VLANTAG_IDENTIFIER)
+     {
++      /* Skip vlan tag */
+       etherhdr_size += 4;
+-      /* Move eth type to the original position */
+-      grub_memcpy((char *) nb->data + etherhdr_size - 6,
+-                  (char *) nb->data + etherhdr_size - 2, 2);
++      eth += 4;
++      type = grub_be_to_cpu16 (*(grub_uint16_t*)(eth));
+     }
+ 
+-  eth = (struct etherhdr *) nb->data;
+-  type = grub_be_to_cpu16 (eth->type);
+   err = grub_netbuff_pull (nb, etherhdr_size);
+   if (err)
+     return err;
+@@ -148,11 +150,6 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
+ 	}
+     }
+ 
+-  hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+-  grub_memcpy (hwaddress.mac, eth->dst, sizeof (hwaddress.mac));
+-  src_hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+-  grub_memcpy (src_hwaddress.mac, eth->src, sizeof (src_hwaddress.mac));
+-
+   switch (type)
+     {
+       /* ARP packet. */
+diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c
+index 7953e68ecfa..7e7a6bcbd68 100644
+--- a/grub-core/net/icmp6.c
++++ b/grub-core/net/icmp6.c
+@@ -230,8 +230,9 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
+ 		&& ohdr->len == 1)
+ 	      {
+ 		grub_net_link_level_address_t ll_address;
+-		ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+-		grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac));
++		ll_address.type = card->default_address.type;
++		ll_address.len = card->default_address.len;
++		grub_memcpy (ll_address.mac, ohdr + 1, ll_address.len);
+ 		grub_net_link_layer_add_address (card, source, &ll_address, 0);
+ 	      }
+ 	  }
+@@ -334,8 +335,9 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
+ 		&& ohdr->len == 1)
+ 	      {
+ 		grub_net_link_level_address_t ll_address;
+-		ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+-		grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac));
++		ll_address.type = card->default_address.type;
++		ll_address.len = card->default_address.len;
++		grub_memcpy (ll_address.mac, ohdr + 1, ll_address.len);
+ 		grub_net_link_layer_add_address (card, source, &ll_address, 0);
+ 	      }
+ 	  }
+@@ -366,8 +368,9 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
+ 		&& ohdr->len == 1)
+ 	      {
+ 		grub_net_link_level_address_t ll_address;
+-		ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+-		grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac));
++		ll_address.type = card->default_address.type;
++		ll_address.len = card->default_address.len;
++		grub_memcpy (ll_address.mac, ohdr + 1, ll_address.len);
+ 		grub_net_link_layer_add_address (card, source, &ll_address, 0);
+ 	      }
+ 	    if (ohdr->type == OPTION_PREFIX && ohdr->len == 4)
+diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
+index 9e7930caa03..311213feec1 100644
+--- a/grub-core/net/ip.c
++++ b/grub-core/net/ip.c
+@@ -273,8 +273,8 @@ handle_dgram (struct grub_net_buff *nb,
+ 	      && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV
+ 	      && inf->dhcp_xid == bootp->xid
+ 	      && inf->hwaddress.type == GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET
+-	      && grub_memcmp (inf->hwaddress.mac, &bootp->mac_addr,
+-			      sizeof (inf->hwaddress.mac)) == 0)
++	      && (grub_memcmp (inf->hwaddress.mac, &bootp->mac_addr,
++			       bootp->hw_len) == 0 || bootp->hw_len == 0))
+ 	    {
+ 	      grub_net_process_dhcp (nb, inf->card);
+ 	      grub_netbuff_free (nb);
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index fc6f714bf7f..b3a80ba2954 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -143,8 +143,9 @@ grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf,
+ 								   << 48)
+ 	  && proto_addr->ipv6[1] == (grub_be_to_cpu64_compile_time (1))))
+     {
+-      hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+-      grub_memset (hw_addr->mac, -1, 6);
++      hw_addr->type = inf->card->default_address.type;
++      hw_addr->len = inf->card->default_address.len;
++      grub_memset (hw_addr->mac, -1, hw_addr->len);
+       return GRUB_ERR_NONE;
+     }
+ 
+@@ -152,6 +153,7 @@ grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf,
+       && ((grub_be_to_cpu64 (proto_addr->ipv6[0]) >> 56) == 0xff))
+     {
+       hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
++      hw_addr->len = inf->card->default_address.len;
+       hw_addr->mac[0] = 0x33;
+       hw_addr->mac[1] = 0x33;
+       hw_addr->mac[2] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 24) & 0xff);
+@@ -771,23 +773,21 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf)
+ void
+ grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str)
+ {
+-  str[0] = 0;
+-  switch (addr->type)
++  char *ptr;
++  unsigned i;
++
++  if (addr->len > GRUB_NET_MAX_LINK_ADDRESS_SIZE)
+     {
+-    case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET:
+-      {
+-	char *ptr;
+-	unsigned i;
+-	for (ptr = str, i = 0; i < ARRAY_SIZE (addr->mac); i++)
+-	  {
+-	    grub_snprintf (ptr, GRUB_NET_MAX_STR_HWADDR_LEN - (ptr - str),
+-			   "%02x:", addr->mac[i] & 0xff);
+-	    ptr += (sizeof ("XX:") - 1);
+-	  }
+-      return;
+-      }
++       str[0] = 0;
++       grub_printf (_("Unsupported hw address type %d len %d\n"),
++		    addr->type, addr->len);
++       return;
++    }
++  for (ptr = str, i = 0; i < addr->len; i++)
++    {
++      ptr += grub_snprintf (ptr, GRUB_NET_MAX_STR_HWADDR_LEN - (ptr - str),
++		     "%02x:", addr->mac[i] & 0xff);
+     }
+-  grub_printf (_("Unsupported hw address type %d\n"), addr->type);
+ }
+ 
+ int
+@@ -798,13 +798,17 @@ grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a,
+     return -1;
+   if (a->type > b->type)
+     return +1;
+-  switch (a->type)
++  if (a->len < b->len)
++    return -1;
++  if (a->len > b->len)
++    return +1;
++  if (a->len > GRUB_NET_MAX_LINK_ADDRESS_SIZE)
+     {
+-    case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET:
+-      return grub_memcmp (a->mac, b->mac, sizeof (a->mac));
++      grub_printf (_("Unsupported hw address type %d len %d\n"),
++		   a->type, a->len);
++      return + 1;
+     }
+-  grub_printf (_("Unsupported hw address type %d\n"), a->type);
+-  return 1;
++  return grub_memcmp (a->mac, b->mac, a->len);
+ }
+ 
+ int
+diff --git a/include/grub/net.h b/include/grub/net.h
+index b1bc23048f1..0d9213d6759 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -29,7 +29,8 @@
+ 
+ enum
+   {
+-    GRUB_NET_MAX_LINK_HEADER_SIZE = 64,
++    GRUB_NET_MAX_LINK_HEADER_SIZE = 96,
++    GRUB_NET_MAX_LINK_ADDRESS_SIZE = 32,
+     GRUB_NET_UDP_HEADER_SIZE = 8,
+     GRUB_NET_TCP_HEADER_SIZE = 20,
+     GRUB_NET_OUR_IPV4_HEADER_SIZE = 20,
+@@ -42,15 +43,17 @@ enum
+ 
+ typedef enum grub_link_level_protocol_id 
+ {
+-  GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET
++  /* IANA ARP constant to define hardware type. */
++  GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET = 1,
+ } grub_link_level_protocol_id_t;
+ 
+ typedef struct grub_net_link_level_address
+ {
+   grub_link_level_protocol_id_t type;
++  grub_uint8_t len;
+   union
+   {
+-    grub_uint8_t mac[6];
++    grub_uint8_t mac[GRUB_NET_MAX_LINK_ADDRESS_SIZE];
+   };
+ } grub_net_link_level_address_t;
+ 
+@@ -531,11 +534,13 @@ grub_net_addr_cmp (const grub_net_network_level_address_t *a,
+ #define GRUB_NET_MAX_STR_ADDR_LEN sizeof ("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX")
+ 
+ /*
+-  Currently suppoerted adresses:
+-  ethernet:   XX:XX:XX:XX:XX:XX
++  Up to 32 byte hardware address supported, see GRUB_NET_MAX_LINK_ADDRESS_SIZE
+  */
+-
+-#define GRUB_NET_MAX_STR_HWADDR_LEN (sizeof ("XX:XX:XX:XX:XX:XX"))
++#define GRUB_NET_MAX_STR_HWADDR_LEN (sizeof (\
++	"XX:XX:XX:XX:XX:XX:XX:XX:"\
++	"XX:XX:XX:XX:XX:XX:XX:XX:"\
++	"XX:XX:XX:XX:XX:XX:XX:XX:"\
++	"XX:XX:XX:XX:XX:XX:XX:XX"))
+ 
+ void
+ grub_net_addr_to_str (const grub_net_network_level_address_t *target,
diff --git a/SOURCES/0249-misc-fix-invalid-character-recongition-in-strto-l.patch b/SOURCES/0249-misc-fix-invalid-character-recongition-in-strto-l.patch
new file mode 100644
index 0000000..51feac7
--- /dev/null
+++ b/SOURCES/0249-misc-fix-invalid-character-recongition-in-strto-l.patch
@@ -0,0 +1,32 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Aaron Miller <aaronmiller@fb.com>
+Date: Fri, 29 Jul 2016 17:41:27 +0800
+Subject: [PATCH] misc: fix invalid character recongition in strto*l
+
+Would previously allow digits larger than the base and didn't check that
+subtracting the difference from 0-9 to lowercase letters for characters
+larger than 9 didn't result in a value lower than 9, which allowed the
+parses: ` = 9, _ = 8, ^ = 7, ] = 6, \ = 5, and [ = 4
+---
+ grub-core/kern/misc.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
+index 240396c55f3..d0ca2ee603b 100644
+--- a/grub-core/kern/misc.c
++++ b/grub-core/kern/misc.c
+@@ -436,9 +436,13 @@ grub_strtoull (const char *str, char **end, int base)
+       if (digit > 9)
+ 	{
+ 	  digit += '0' - 'a' + 10;
+-	  if (digit >= (unsigned long) base)
++	  /* digit <= 9 check is needed to keep chars larger than
++	     '9' but less than 'a' from being read as numbers */
++	  if (digit >= (unsigned long) base || digit <= 9)
+ 	    break;
+ 	}
++      if (digit >= (unsigned long) base)
++	break;
+ 
+       found = 1;
+ 
diff --git a/SOURCES/0250-net-read-bracketed-ipv6-addrs-and-port-numbers.patch b/SOURCES/0250-net-read-bracketed-ipv6-addrs-and-port-numbers.patch
new file mode 100644
index 0000000..5b10e5d
--- /dev/null
+++ b/SOURCES/0250-net-read-bracketed-ipv6-addrs-and-port-numbers.patch
@@ -0,0 +1,230 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Aaron Miller <aaronmiller@fb.com>
+Date: Fri, 29 Jul 2016 17:41:38 +0800
+Subject: [PATCH] net: read bracketed ipv6 addrs and port numbers
+
+Allow specifying port numbers for http and tftp paths, and allow ipv6 addresses
+to be recognized with brackets around them, which is required to specify a port
+number
+---
+ grub-core/net/http.c | 23 ++++++++++++----
+ grub-core/net/net.c  | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ grub-core/net/tftp.c |  8 ++++--
+ include/grub/net.h   |  1 +
+ 4 files changed, 102 insertions(+), 7 deletions(-)
+
+diff --git a/grub-core/net/http.c b/grub-core/net/http.c
+index ef9538c539c..6d99051d345 100644
+--- a/grub-core/net/http.c
++++ b/grub-core/net/http.c
+@@ -312,12 +312,14 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
+   int i;
+   struct grub_net_buff *nb;
+   grub_err_t err;
++  char* server = file->device->net->server;
++  int port = file->device->net->port;
+ 
+   nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE
+ 			   + sizeof ("GET ") - 1
+ 			   + grub_strlen (data->filename)
+ 			   + sizeof (" HTTP/1.1\r\nHost: ") - 1
+-			   + grub_strlen (file->device->net->server)
++			   + grub_strlen (server) + sizeof (":XXXXXXXXXX")
+ 			   + sizeof ("\r\nUser-Agent: " PACKAGE_STRING
+ 				     "\r\n") - 1
+ 			   + sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX"
+@@ -356,7 +358,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
+ 	       sizeof (" HTTP/1.1\r\nHost: ") - 1);
+ 
+   ptr = nb->tail;
+-  err = grub_netbuff_put (nb, grub_strlen (file->device->net->server));
++  err = grub_netbuff_put (nb, grub_strlen (server));
+   if (err)
+     {
+       grub_netbuff_free (nb);
+@@ -365,6 +367,15 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
+   grub_memcpy (ptr, file->device->net->server,
+ 	       grub_strlen (file->device->net->server));
+ 
++  if (port)
++    {
++      ptr = nb->tail;
++      grub_snprintf ((char *) ptr,
++	  sizeof (":XXXXXXXXXX"),
++	  ":%d",
++	  port);
++    }
++
+   ptr = nb->tail;
+   err = grub_netbuff_put (nb, 
+ 			  sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n")
+@@ -391,9 +402,11 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
+   grub_netbuff_put (nb, 2);
+   grub_memcpy (ptr, "\r\n", 2);
+ 
+-  data->sock = grub_net_tcp_open (file->device->net->server,
+-				  HTTP_PORT, http_receive,
+-				  http_err, NULL,
++  grub_dprintf ("http", "opening path %s on host %s TCP port %d\n",
++		data->filename, server, port ? port : HTTP_PORT);
++  data->sock = grub_net_tcp_open (server,
++				  port ? port : HTTP_PORT, http_receive,
++				  http_err, http_err,
+ 				  file);
+   if (!data->sock)
+     {
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index b3a80ba2954..b062f6fd0cd 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -462,6 +462,12 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
+   grub_uint16_t newip[8];
+   const char *ptr = val;
+   int word, quaddot = -1;
++  int bracketed = 0;
++
++  if (ptr[0] == '[') {
++    bracketed = 1;
++    ptr++;
++  }
+ 
+   if (ptr[0] == ':' && ptr[1] != ':')
+     return 0;
+@@ -500,6 +506,9 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
+       grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0]));
+     }
+   grub_memcpy (ip, newip, 16);
++  if (bracketed && *ptr == ']') {
++    ptr++;
++  }
+   if (rest)
+     *rest = ptr;
+   return 1;
+@@ -1348,8 +1357,10 @@ grub_net_open_real (const char *name)
+ {
+   grub_net_app_level_t proto;
+   const char *protname, *server;
++  char *host;
+   grub_size_t protnamelen;
+   int try;
++  int port = 0;
+ 
+   if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
+     {
+@@ -1387,6 +1398,72 @@ grub_net_open_real (const char *name)
+       return NULL;
+     }  
+ 
++  char* port_start;
++  /* ipv6 or port specified? */
++  if ((port_start = grub_strchr (server, ':')))
++  {
++      char* ipv6_begin;
++      if((ipv6_begin = grub_strchr (server, '[')))
++	{
++	  char* ipv6_end = grub_strchr (server, ']');
++	  if(!ipv6_end)
++	    {
++	      grub_error (GRUB_ERR_NET_BAD_ADDRESS,
++		      N_("mismatched [ in address"));
++	      return NULL;
++	    }
++	  /* port number after bracketed ipv6 addr */
++	  if(ipv6_end[1] == ':')
++	    {
++	      port = grub_strtoul (ipv6_end + 2, NULL, 10);
++	      if(port > 65535)
++		{
++		  grub_error (GRUB_ERR_NET_BAD_ADDRESS,
++			  N_("bad port number"));
++		  return NULL;
++		}
++	    }
++	  host = grub_strndup (ipv6_begin, (ipv6_end - ipv6_begin) + 1);
++	}
++      else
++	{
++	  if (grub_strchr (port_start + 1, ':'))
++	    {
++	      int iplen = grub_strlen (server);
++	      /* bracket bare ipv6 addrs */
++	      host = grub_malloc (iplen + 3);
++	      if(!host)
++		{
++		  return NULL;
++		}
++	      host[0] = '[';
++	      grub_memcpy (host + 1, server, iplen);
++	      host[iplen + 1] = ']';
++	      host[iplen + 2] = '\0';
++	    }
++	  else
++	    {
++	      /* hostname:port or ipv4:port */
++	      port = grub_strtol (port_start + 1, NULL, 10);
++	      if(port > 65535)
++		{
++		  grub_error (GRUB_ERR_NET_BAD_ADDRESS,
++			  N_("bad port number"));
++		  return NULL;
++		}
++	      host = grub_strndup (server, port_start - server);
++	    }
++	}
++    }
++  else
++    {
++      host = grub_strdup (server);
++    }
++  if (!host)
++    {
++      return NULL;
++    }
++
+   for (try = 0; try < 2; try++)
+     {
+       FOR_NET_APP_LEVEL (proto)
+diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
+index 3931884c6dd..d13a6c8ed2d 100644
+--- a/grub-core/net/tftp.c
++++ b/grub-core/net/tftp.c
+@@ -333,6 +333,7 @@ tftp_open (struct grub_file *file, const char *filename)
+   grub_err_t err;
+   grub_uint8_t *nbd;
+   grub_net_network_level_address_t addr;
++  int port = file->device->net->port;
+ 
+   data = grub_zalloc (sizeof (*data));
+   if (!data)
+@@ -396,14 +397,17 @@ tftp_open (struct grub_file *file, const char *filename)
+   err = grub_net_resolve_address (file->device->net->server, &addr);
+   if (err)
+     {
+-      grub_dprintf("tftp", "Address resolution failed: %d\n", err);
++      grub_dprintf ("tftp", "Address resolution failed: %d\n", err);
++      grub_dprintf ("tftp", "file_size is %llu, block_size is %llu\n",
++		    (unsigned long long)data->file_size,
++		    (unsigned long long)data->block_size);
+       destroy_pq (data);
+       return err;
+     }
+ 
+   grub_dprintf("tftp", "opening connection\n");
+   data->sock = grub_net_udp_open (addr,
+-				  TFTP_SERVER_PORT, tftp_receive,
++				  port ? port : TFTP_SERVER_PORT, tftp_receive,
+ 				  file);
+   if (!data->sock)
+     {
+diff --git a/include/grub/net.h b/include/grub/net.h
+index 0d9213d6759..20e699bb025 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -261,6 +261,7 @@ typedef struct grub_net
+ {
+   char *server;
+   char *name;
++  int port;
+   grub_net_app_level_t protocol;
+   grub_net_packets_t packs;
+   grub_off_t offset;
diff --git a/SOURCES/0251-net-read-bracketed-ipv6-addrs-and-port-numbers-pjone.patch b/SOURCES/0251-net-read-bracketed-ipv6-addrs-and-port-numbers-pjone.patch
new file mode 100644
index 0000000..b8a71b6
--- /dev/null
+++ b/SOURCES/0251-net-read-bracketed-ipv6-addrs-and-port-numbers-pjone.patch
@@ -0,0 +1,183 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Aaron Miller <aaronmiller@fb.com>
+Date: Fri, 29 Jul 2016 17:41:38 +0800
+Subject: [PATCH] net: read bracketed ipv6 addrs and port numbers (pjones
+ fixup)
+
+Various bug fixes related to previous patch.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/net/http.c |  6 ++++--
+ grub-core/net/net.c  | 31 +++++++++++++------------------
+ grub-core/net/tftp.c | 19 ++++++++++++++++---
+ 3 files changed, 33 insertions(+), 23 deletions(-)
+
+diff --git a/grub-core/net/http.c b/grub-core/net/http.c
+index 6d99051d345..2b46e4672fc 100644
+--- a/grub-core/net/http.c
++++ b/grub-core/net/http.c
+@@ -289,7 +289,9 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
+ 	  nb2 = grub_netbuff_alloc (data->chunk_rem);
+ 	  if (!nb2)
+ 	    return grub_errno;
+-	  grub_netbuff_put (nb2, data->chunk_rem);
++	  err = grub_netbuff_put (nb2, data->chunk_rem);
++	  if (err)
++	    return grub_errno;
+ 	  grub_memcpy (nb2->data, nb->data, data->chunk_rem);
+ 	  if (file->device->net->packs.count >= 20)
+ 	    {
+@@ -406,7 +408,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
+ 		data->filename, server, port ? port : HTTP_PORT);
+   data->sock = grub_net_tcp_open (server,
+ 				  port ? port : HTTP_PORT, http_receive,
+-				  http_err, http_err,
++				  http_err, NULL,
+ 				  file);
+   if (!data->sock)
+     {
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index b062f6fd0cd..6b4b10ba444 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -464,10 +464,11 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
+   int word, quaddot = -1;
+   int bracketed = 0;
+ 
+-  if (ptr[0] == '[') {
+-    bracketed = 1;
+-    ptr++;
+-  }
++  if (ptr[0] == '[')
++    {
++      bracketed = 1;
++      ptr++;
++    }
+ 
+   if (ptr[0] == ':' && ptr[1] != ':')
+     return 0;
+@@ -506,9 +507,8 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
+       grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0]));
+     }
+   grub_memcpy (ip, newip, 16);
+-  if (bracketed && *ptr == ']') {
++  if (bracketed && *ptr == ']')
+     ptr++;
+-  }
+   if (rest)
+     *rest = ptr;
+   return 1;
+@@ -1401,7 +1401,7 @@ grub_net_open_real (const char *name)
+   char* port_start;
+   /* ipv6 or port specified? */
+   if ((port_start = grub_strchr (server, ':')))
+-  {
++    {
+       char* ipv6_begin;
+       if((ipv6_begin = grub_strchr (server, '[')))
+ 	{
+@@ -1473,19 +1473,13 @@ grub_net_open_real (const char *name)
+ 	  {
+ 	    grub_net_t ret = grub_zalloc (sizeof (*ret));
+ 	    if (!ret)
+-	      return NULL;
+-	    ret->protocol = proto;
+-	    if (server)
+ 	      {
+-		ret->server = grub_strdup (server);
+-		if (!ret->server)
+-		  {
+-		    grub_free (ret);
+-		    return NULL;
+-		  }
++		grub_free (host);
++		return NULL;
+ 	      }
+-	    else
+-	      ret->server = NULL;
++	    ret->protocol = proto;
++	    ret->port = port;
++	    ret->server = host;
+ 	    ret->fs = &grub_net_fs;
+ 	    ret->offset = 0;
+ 	    ret->eof = 0;
+@@ -1516,6 +1510,7 @@ grub_net_open_real (const char *name)
+   grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"),
+ 	      name);
+ 
++  grub_free (host);
+   return NULL;
+ }
+ 
+diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
+index d13a6c8ed2d..17583cba380 100644
+--- a/grub-core/net/tftp.c
++++ b/grub-core/net/tftp.c
+@@ -346,7 +346,10 @@ tftp_open (struct grub_file *file, const char *filename)
+   grub_netbuff_reserve (&nb, 1500);
+   err = grub_netbuff_push (&nb, sizeof (*tftph));
+   if (err)
+-    return err;
++    {
++      grub_free (data);
++      return err;
++    }
+ 
+   tftph = (struct tftphdr *) nb.data;
+ 
+@@ -384,14 +387,20 @@ tftp_open (struct grub_file *file, const char *filename)
+ 
+   err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen));
+   if (err)
+-    return err;
++    {
++      grub_free (data);
++      return err;
++    }
+ 
+   file->not_easily_seekable = 1;
+   file->data = data;
+ 
+   data->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp);
+   if (!data->pq)
+-    return grub_errno;
++    {
++      grub_free (data);
++      return grub_errno;
++    }
+ 
+   grub_dprintf("tftp", "resolving address for %s\n", file->device->net->server);
+   err = grub_net_resolve_address (file->device->net->server, &addr);
+@@ -402,6 +411,7 @@ tftp_open (struct grub_file *file, const char *filename)
+ 		    (unsigned long long)data->file_size,
+ 		    (unsigned long long)data->block_size);
+       destroy_pq (data);
++      grub_free (data);
+       return err;
+     }
+ 
+@@ -413,6 +423,7 @@ tftp_open (struct grub_file *file, const char *filename)
+     {
+       grub_dprintf("tftp", "connection failed\n");
+       destroy_pq (data);
++      grub_free (data);
+       return grub_errno;
+     }
+ 
+@@ -426,6 +437,7 @@ tftp_open (struct grub_file *file, const char *filename)
+ 	{
+ 	  grub_net_udp_close (data->sock);
+ 	  destroy_pq (data);
++	  grub_free (data);
+ 	  return err;
+ 	}
+       grub_net_poll_cards (GRUB_NET_INTERVAL + (i * GRUB_NET_INTERVAL_ADDITION),
+@@ -442,6 +454,7 @@ tftp_open (struct grub_file *file, const char *filename)
+     {
+       grub_net_udp_close (data->sock);
+       destroy_pq (data);
++      grub_free (data);
+       return grub_errno;
+     }
+ 
diff --git a/SOURCES/0252-tftp-Fix-a-minor-const-error.patch b/SOURCES/0252-tftp-Fix-a-minor-const-error.patch
new file mode 100644
index 0000000..eb6abd9
--- /dev/null
+++ b/SOURCES/0252-tftp-Fix-a-minor-const-error.patch
@@ -0,0 +1,23 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 21 Jun 2018 19:09:11 -0400
+Subject: [PATCH] tftp: Fix a minor const error
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/net/tftp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
+index 17583cba380..e267af354f4 100644
+--- a/grub-core/net/tftp.c
++++ b/grub-core/net/tftp.c
+@@ -307,7 +307,7 @@ static void
+ grub_normalize_filename (char *normalized, const char *filename)
+ {
+   char *dest = normalized;
+-  char *src = filename;
++  const char *src = filename;
+ 
+   while (*src != '\0')
+     {
diff --git a/SOURCES/0253-bootp-New-net_bootp6-command.patch b/SOURCES/0253-bootp-New-net_bootp6-command.patch
new file mode 100644
index 0000000..5cfc9cf
--- /dev/null
+++ b/SOURCES/0253-bootp-New-net_bootp6-command.patch
@@ -0,0 +1,1304 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Sun, 10 Jul 2016 23:46:06 +0800
+Subject: [PATCH] bootp: New net_bootp6 command
+
+Implement new net_bootp6 command for IPv6 network auto configuration via the
+DHCPv6 protocol (RFC3315).
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Ken Lin <ken.lin@hpe.com>
+---
+ grub-core/net/bootp.c | 1048 +++++++++++++++++++++++++++++++++++++++++--------
+ grub-core/net/ip.c    |   39 ++
+ include/grub/net.h    |   91 +++--
+ 3 files changed, 985 insertions(+), 193 deletions(-)
+
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index 0a2d11b8820..26b3d83d0bc 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -25,6 +25,98 @@
+ #include <grub/net/udp.h>
+ #include <grub/net/url.h>
+ #include <grub/datetime.h>
++#include <grub/time.h>
++#include <grub/list.h>
++
++static int
++dissect_url (const char *url, char **proto, char **host, char **path)
++{
++  const char *p, *ps;
++  grub_size_t l;
++
++  *proto = *host = *path = NULL;
++  ps = p = url;
++
++  while ((p = grub_strchr (p, ':')))
++    {
++      if (grub_strlen (p) < sizeof ("://") - 1)
++	break;
++      if (grub_memcmp (p, "://", sizeof ("://") - 1) == 0)
++	{
++	  l = p - ps;
++	  *proto = grub_malloc (l + 1);
++	  if (!*proto)
++	    {
++	      grub_print_error ();
++	      return 0;
++	    }
++
++	  grub_memcpy (*proto, ps, l);
++	  (*proto)[l] = '\0';
++	  p +=  sizeof ("://") - 1;
++	  break;
++	}
++      ++p;
++    }
++
++  if (!*proto)
++    {
++      grub_dprintf ("bootp", "url: %s is not valid, protocol not found\n", url);
++      return 0;
++    }
++
++  ps = p;
++  p = grub_strchr (p, '/');
++
++  if (!p)
++    {
++      grub_dprintf ("bootp", "url: %s is not valid, host/path not found\n", url);
++      grub_free (*proto);
++      *proto = NULL;
++      return 0;
++    }
++
++  l = p - ps;
++
++  if (l > 2 && ps[0] == '[' && ps[l - 1] == ']')
++    {
++      *host = grub_malloc (l - 1);
++      if (!*host)
++	{
++	  grub_print_error ();
++	  grub_free (*proto);
++	  *proto = NULL;
++	  return 0;
++	}
++      grub_memcpy (*host, ps + 1, l - 2);
++      (*host)[l - 2] = 0;
++    }
++  else
++    {
++      *host = grub_malloc (l + 1);
++      if (!*host)
++	{
++	  grub_print_error ();
++	  grub_free (*proto);
++	  *proto = NULL;
++	  return 0;
++	}
++      grub_memcpy (*host, ps, l);
++      (*host)[l] = 0;
++    }
++
++  *path = grub_strdup (p);
++  if (!*path)
++    {
++      grub_print_error ();
++      grub_free (*host);
++      grub_free (*proto);
++      *host = NULL;
++      *proto = NULL;
++      return 0;
++    }
++  return 1;
++}
+ 
+ static char *
+ grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
+@@ -341,178 +433,578 @@ grub_net_configure_by_dhcp_ack (const char *name,
+   return inter;
+ }
+ 
+-struct grub_net_network_level_interface *
+-grub_net_configure_by_dhcpv6_ack (const char *name,
+-				  struct grub_net_card *card,
+-				  grub_net_interface_flags_t flags
+-				    __attribute__((__unused__)),
+-				  const grub_net_link_level_address_t *hwaddr,
+-				  const struct grub_net_dhcpv6_packet *packet,
+-				  int is_def, char **device, char **path)
+-{
+-  struct grub_net_network_level_interface *inter = NULL;
+-  struct grub_net_network_level_address addr;
+-  int mask = -1;
+-
+-  if (!device || !path)
++/* The default netbuff size for sending DHCPv6 packets which should be
++   large enough to hold the information */
++#define GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE 512
++
++struct grub_dhcp6_options
++{
++  grub_uint8_t *client_duid;
++  grub_uint16_t client_duid_len;
++  grub_uint8_t *server_duid;
++  grub_uint16_t server_duid_len;
++  grub_uint32_t iaid;
++  grub_uint32_t t1;
++  grub_uint32_t t2;
++  grub_net_network_level_address_t *ia_addr;
++  grub_uint32_t preferred_lifetime;
++  grub_uint32_t valid_lifetime;
++  grub_net_network_level_address_t *dns_server_addrs;
++  grub_uint16_t num_dns_server;
++  char *boot_file_proto;
++  char *boot_file_server_ip;
++  char *boot_file_path;
++};
++
++typedef struct grub_dhcp6_options *grub_dhcp6_options_t;
++
++struct grub_dhcp6_session
++{
++  struct grub_dhcp6_session *next;
++  struct grub_dhcp6_session **prev;
++  grub_uint32_t iaid;
++  grub_uint32_t transaction_id:24;
++  grub_uint64_t start_time;
++  struct grub_net_dhcp6_option_duid_ll duid;
++  struct grub_net_network_level_interface *iface;
++
++  /* The associated dhcpv6 options */
++  grub_dhcp6_options_t adv;
++  grub_dhcp6_options_t reply;
++};
++
++typedef struct grub_dhcp6_session *grub_dhcp6_session_t;
++
++typedef void (*dhcp6_option_hook_fn) (const struct grub_net_dhcp6_option *opt, void *data);
++
++static void
++foreach_dhcp6_option (const struct grub_net_dhcp6_option *opt, grub_size_t size,
++		      dhcp6_option_hook_fn hook, void *hook_data);
++
++static void
++parse_dhcp6_iaaddr (const struct grub_net_dhcp6_option *opt, void *data)
++{
++  grub_dhcp6_options_t dhcp6 = (grub_dhcp6_options_t )data;
++
++  grub_uint16_t code = grub_be_to_cpu16 (opt->code);
++  grub_uint16_t len = grub_be_to_cpu16 (opt->len);
++
++  if (code == GRUB_NET_DHCP6_OPTION_IAADDR)
++    {
++      const struct grub_net_dhcp6_option_iaaddr *iaaddr;
++      iaaddr = (const struct grub_net_dhcp6_option_iaaddr *)opt->data;
++
++      if (len < sizeof (*iaaddr))
++	{
++	  grub_dprintf ("bootp", "DHCPv6: code %u with insufficient length %u\n", code, len);
++	  return;
++	}
++      if (!dhcp6->ia_addr)
++	{
++	  dhcp6->ia_addr = grub_malloc (sizeof(*dhcp6->ia_addr));
++	  dhcp6->ia_addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
++	  dhcp6->ia_addr->ipv6[0] = grub_get_unaligned64 (iaaddr->addr);
++	  dhcp6->ia_addr->ipv6[1] = grub_get_unaligned64 (iaaddr->addr + 8);
++	  dhcp6->preferred_lifetime = grub_be_to_cpu32 (iaaddr->preferred_lifetime);
++	  dhcp6->valid_lifetime = grub_be_to_cpu32 (iaaddr->valid_lifetime);
++	}
++    }
++}
++
++static void
++parse_dhcp6_option (const struct grub_net_dhcp6_option *opt, void *data)
++{
++  grub_dhcp6_options_t dhcp6 = (grub_dhcp6_options_t)data;
++  grub_uint16_t code = grub_be_to_cpu16 (opt->code);
++  grub_uint16_t len = grub_be_to_cpu16 (opt->len);
++
++  switch (code)
++    {
++      case GRUB_NET_DHCP6_OPTION_CLIENTID:
++
++	if (dhcp6->client_duid || !len)
++	  {
++	    grub_dprintf ("bootp", "Skipped DHCPv6 CLIENTID with length %u\n", len);
++	    break;
++	  }
++	dhcp6->client_duid = grub_malloc (len);
++	grub_memcpy (dhcp6->client_duid, opt->data, len);
++	dhcp6->client_duid_len = len;
++	break;
++
++      case GRUB_NET_DHCP6_OPTION_SERVERID:
++
++	if (dhcp6->server_duid || !len)
++	  {
++	    grub_dprintf ("bootp", "Skipped DHCPv6 SERVERID with length %u\n", len);
++	    break;
++	  }
++	dhcp6->server_duid = grub_malloc (len);
++	grub_memcpy (dhcp6->server_duid, opt->data, len);
++	dhcp6->server_duid_len = len;
++	break;
++
++      case GRUB_NET_DHCP6_OPTION_IA_NA:
++	{
++	  const struct grub_net_dhcp6_option_iana *ia_na;
++	  grub_uint16_t data_len;
++
++	  if (dhcp6->iaid || len < sizeof (*ia_na))
++	    {
++	      grub_dprintf ("bootp", "Skipped DHCPv6 IA_NA with length %u\n", len);
++	      break;
++	    }
++	  ia_na = (const struct grub_net_dhcp6_option_iana *)opt->data;
++	  dhcp6->iaid = grub_be_to_cpu32 (ia_na->iaid);
++	  dhcp6->t1 = grub_be_to_cpu32 (ia_na->t1);
++	  dhcp6->t2 = grub_be_to_cpu32 (ia_na->t2);
++
++	  data_len = len - sizeof (*ia_na);
++	  if (data_len)
++	    foreach_dhcp6_option ((const struct grub_net_dhcp6_option *)ia_na->data, data_len, parse_dhcp6_iaaddr, dhcp6);
++	}
++	break;
++
++      case GRUB_NET_DHCP6_OPTION_DNS_SERVERS:
++	{
++	  const grub_uint8_t *po;
++	  grub_uint16_t ln;
++	  grub_net_network_level_address_t *la;
++
++	  if (!len || len & 0xf)
++	    {
++	      grub_dprintf ("bootp", "Skip invalid length DHCPv6 DNS_SERVERS \n");
++	      break;
++	    }
++	  dhcp6->num_dns_server = ln = len >> 4;
++	  dhcp6->dns_server_addrs = la = grub_zalloc (ln * sizeof (*la));
++
++	  for (po = opt->data; ln > 0; po += 0x10, la++, ln--)
++	    {
++	      la->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
++	      la->ipv6[0] = grub_get_unaligned64 (po);
++	      la->ipv6[1] = grub_get_unaligned64 (po + 8);
++	      la->option = DNS_OPTION_PREFER_IPV6;
++	    }
++	}
++	break;
++
++      case GRUB_NET_DHCP6_OPTION_BOOTFILE_URL:
++	dissect_url ((const char *)opt->data,
++		      &dhcp6->boot_file_proto,
++		      &dhcp6->boot_file_server_ip,
++		      &dhcp6->boot_file_path);
++	break;
++
++      default:
++	break;
++    }
++}
++
++static void
++foreach_dhcp6_option (const struct grub_net_dhcp6_option *opt, grub_size_t size, dhcp6_option_hook_fn hook, void *hook_data)
++{
++  while (size)
++    {
++      grub_uint16_t code, len;
++
++      if (size < sizeof (*opt))
++	{
++	  grub_dprintf ("bootp", "DHCPv6: Options stopped with remaining size %" PRIxGRUB_SIZE "\n", size);
++	  break;
++	}
++      size -= sizeof (*opt);
++      len = grub_be_to_cpu16 (opt->len);
++      code = grub_be_to_cpu16 (opt->code);
++      if (size < len)
++	{
++	  grub_dprintf ("bootp", "DHCPv6: Options stopped at out of bound length %u for option %u\n", len, code);
++	  break;
++	}
++      if (!len)
++	{
++	  grub_dprintf ("bootp", "DHCPv6: Options stopped at zero length option %u\n", code);
++	  break;
++	}
++      else
++	{
++	  if (hook)
++	    hook (opt, hook_data);
++	  size -= len;
++	  opt = (const struct grub_net_dhcp6_option *)((grub_uint8_t *)opt + len + sizeof (*opt));
++	}
++    }
++}
++
++static grub_dhcp6_options_t
++grub_dhcp6_options_get (const struct grub_net_dhcp6_packet *v6h,
++			grub_size_t size)
++{
++  grub_dhcp6_options_t options;
++
++  if (size < sizeof (*v6h))
++    {
++      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("DHCPv6 packet size too small"));
++      return NULL;
++    }
++
++  options = grub_zalloc (sizeof(*options));
++  if (!options)
+     return NULL;
+ 
+-  *device = 0;
+-  *path = 0;
+-
+-  grub_dprintf ("net", "mac address is %02x:%02x:%02x:%02x:%02x:%02x\n",
+-		hwaddr->mac[0], hwaddr->mac[1], hwaddr->mac[2],
+-		hwaddr->mac[3], hwaddr->mac[4], hwaddr->mac[5]);
+-
+-  if (is_def)
+-    grub_net_default_server = 0;
+-
+-  if (is_def && !grub_net_default_server && packet)
++  foreach_dhcp6_option ((const struct grub_net_dhcp6_option *)v6h->dhcp_options,
++		       size - sizeof (*v6h), parse_dhcp6_option, options);
++
++  return options;
++}
++
++static void
++grub_dhcp6_options_free (grub_dhcp6_options_t options)
++{
++  if (options->client_duid)
++    grub_free (options->client_duid);
++  if (options->server_duid)
++    grub_free (options->server_duid);
++  if (options->ia_addr)
++    grub_free (options->ia_addr);
++  if (options->dns_server_addrs)
++    grub_free (options->dns_server_addrs);
++  if (options->boot_file_proto)
++    grub_free (options->boot_file_proto);
++  if (options->boot_file_server_ip)
++    grub_free (options->boot_file_server_ip);
++  if (options->boot_file_path)
++    grub_free (options->boot_file_path);
++
++  grub_free (options);
++}
++
++static grub_dhcp6_session_t grub_dhcp6_sessions;
++#define FOR_DHCP6_SESSIONS_SAFE(var, next) FOR_LIST_ELEMENTS_SAFE (var, next, grub_dhcp6_sessions)
++#define FOR_DHCP6_SESSIONS(var) FOR_LIST_ELEMENTS (var, grub_dhcp6_sessions)
++
++static void
++grub_net_configure_by_dhcp6_info (const char *name,
++	  struct grub_net_card *card,
++	  grub_dhcp6_options_t dhcp6,
++	  int is_def,
++	  int flags,
++	  struct grub_net_network_level_interface **ret_inf)
++{
++  grub_net_network_level_netaddress_t netaddr;
++  struct grub_net_network_level_interface *inf;
++
++  if (dhcp6->ia_addr)
+     {
+-      const grub_uint8_t *options = packet->dhcp_options;
+-      unsigned int option_max = 1024 - OFFSET_OF (dhcp_options, packet);
+-      unsigned int i;
+-
+-      for (i = 0; i < option_max - sizeof (grub_net_dhcpv6_option_t); )
+-	{
+-	  grub_uint16_t num, len;
+-	  grub_net_dhcpv6_option_t *opt =
+-	    (grub_net_dhcpv6_option_t *)(options + i);
+-
+-	  num = grub_be_to_cpu16(opt->option_num);
+-	  len = grub_be_to_cpu16(opt->option_len);
+-
+-	  grub_dprintf ("net", "got dhcpv6 option %d len %d\n", num, len);
+-
+-	  if (len == 0)
+-	    break;
+-
+-	  if (len + i > 1024)
+-	    break;
+-
+-	  if (num == GRUB_NET_DHCP6_BOOTFILE_URL)
+-	    {
+-	      char *scheme, *userinfo, *host, *file;
+-	      char *tmp;
+-	      int hostlen;
+-	      int port;
+-	      int rc = extract_url_info ((const char *)opt->option_data,
+-					 (grub_size_t)len,
+-					 &scheme, &userinfo, &host, &port,
+-					 &file);
+-	      if (rc < 0)
+-		continue;
+-
+-	      /* right now this only handles tftp. */
+-	      if (grub_strcmp("tftp", scheme))
+-		{
+-		  grub_free (scheme);
+-		  grub_free (userinfo);
+-		  grub_free (host);
+-		  grub_free (file);
+-		  continue;
+-		}
+-	      grub_free (userinfo);
+-
+-	      hostlen = grub_strlen (host);
+-	      if (hostlen > 2 && host[0] == '[' && host[hostlen-1] == ']')
+-		{
+-		  tmp = host+1;
+-		  host[hostlen-1] = '\0';
+-		}
+-	      else
+-		tmp = host;
++      inf = grub_net_add_addr (name, card, dhcp6->ia_addr, &card->default_address, flags);
+ 
+-	      *device = grub_xasprintf ("%s,%s", scheme, tmp);
+-	      grub_free (scheme);
+-	      grub_free (host);
++      netaddr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
++      netaddr.ipv6.base[0] = dhcp6->ia_addr->ipv6[0];
++      netaddr.ipv6.base[1] = 0;
++      netaddr.ipv6.masksize = 64;
++      grub_net_add_route (name, netaddr, inf);
+ 
+-	      if (file && *file)
+-		{
+-		  tmp = grub_strrchr (file, '/');
+-		  if (tmp)
+-		    *(tmp+1) = '\0';
+-		  else
+-		    file[0] = '\0';
+-		}
+-	      else if (!file)
+-		file = grub_strdup ("");
+-
+-	      if (file[0] == '/')
+-		{
+-		  *path = grub_strdup (file+1);
+-		  grub_free (file);
+-		}
+-	      else
+-		*path = file;
+-	    }
+-	  else if (num == GRUB_NET_DHCP6_IA_NA)
+-	    {
+-	      const grub_net_dhcpv6_option_t *ia_na_opt;
+-	      const grub_net_dhcpv6_opt_ia_na_t *ia_na =
+-		(const grub_net_dhcpv6_opt_ia_na_t *)opt;
+-	      unsigned int left = len - OFFSET_OF (options, ia_na);
+-	      unsigned int j;
+-
+-	      if ((grub_uint8_t *)ia_na + left >
+-		  (grub_uint8_t *)options + option_max)
+-		left -= ((grub_uint8_t *)ia_na + left)
+-		        - ((grub_uint8_t *)options + option_max);
+-
+-	      if (len < OFFSET_OF (option_data, opt)
+-			+ sizeof (grub_net_dhcpv6_option_t))
+-		{
+-		  grub_dprintf ("net",
+-				"found dhcpv6 ia_na option with no address\n");
+-		  continue;
+-		}
+-
+-	      for (j = 0; left > sizeof (grub_net_dhcpv6_option_t); )
+-		{
+-		  ia_na_opt = (const grub_net_dhcpv6_option_t *)
+-			       (ia_na->options + j);
+-		  grub_uint16_t ia_na_opt_num, ia_na_opt_len;
+-
+-		  ia_na_opt_num = grub_be_to_cpu16 (ia_na_opt->option_num);
+-		  ia_na_opt_len = grub_be_to_cpu16 (ia_na_opt->option_len);
+-		  if (ia_na_opt_len == 0)
+-		    break;
+-		  if (j + ia_na_opt_len > left)
+-		    break;
+-		  if (ia_na_opt_num == GRUB_NET_DHCP6_IA_ADDRESS)
+-		    {
+-		      const grub_net_dhcpv6_opt_ia_address_t *ia_addr;
+-
+-		      ia_addr = (const grub_net_dhcpv6_opt_ia_address_t *)
+-				 ia_na_opt;
+-		      addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
+-		      grub_memcpy(addr.ipv6, ia_addr->ipv6_address,
+-				  sizeof (ia_addr->ipv6_address));
+-		      inter = grub_net_add_addr (name, card, &addr, hwaddr, 0);
+-		    }
+-
+-		  j += ia_na_opt_len;
+-		  left -= ia_na_opt_len;
+-		}
+-	    }
++      if (ret_inf)
++	*ret_inf = inf;
++    }
+ 
+-	  i += len + 4;
+-	}
++  if (dhcp6->dns_server_addrs)
++    {
++      grub_uint16_t i;
+ 
+-      grub_print_error ();
++      for (i = 0; i < dhcp6->num_dns_server; ++i)
++	grub_net_add_dns_server (dhcp6->dns_server_addrs + i);
+     }
+ 
+-  if (is_def)
++  if (dhcp6->boot_file_path)
++    grub_env_set_net_property (name, "boot_file", dhcp6->boot_file_path,
++			  grub_strlen (dhcp6->boot_file_path));
++
++  if (is_def && dhcp6->boot_file_server_ip)
+     {
++      grub_net_default_server = grub_strdup (dhcp6->boot_file_server_ip);
+       grub_env_set ("net_default_interface", name);
+       grub_env_export ("net_default_interface");
+     }
++}
++
++static void
++grub_dhcp6_session_add (struct grub_net_network_level_interface *iface,
++			grub_uint32_t iaid)
++{
++  grub_dhcp6_session_t se;
++  struct grub_datetime date;
++  grub_err_t err;
++  grub_int32_t t = 0;
++
++  se = grub_malloc (sizeof (*se));
++
++  err = grub_get_datetime (&date);
++  if (err || !grub_datetime2unixtime (&date, &t))
++    {
++      grub_errno = GRUB_ERR_NONE;
++      t = 0;
++    }
++
++  se->iface = iface;
++  se->iaid = iaid;
++  se->transaction_id = t;
++  se->start_time = grub_get_time_ms ();
++  se->duid.type = grub_cpu_to_be16_compile_time (3) ;
++  se->duid.hw_type = grub_cpu_to_be16_compile_time (1);
++  grub_memcpy (&se->duid.hwaddr, &iface->hwaddress.mac, sizeof (se->duid.hwaddr));
++  se->adv = NULL;
++  se->reply = NULL;
++  grub_list_push (GRUB_AS_LIST_P (&grub_dhcp6_sessions), GRUB_AS_LIST (se));
++}
++
++static void
++grub_dhcp6_session_remove (grub_dhcp6_session_t se)
++{
++  grub_list_remove (GRUB_AS_LIST (se));
++  if (se->adv)
++    grub_dhcp6_options_free (se->adv);
++  if (se->reply)
++    grub_dhcp6_options_free (se->reply);
++  grub_free (se);
++}
++
++static void
++grub_dhcp6_session_remove_all (void)
++{
++  grub_dhcp6_session_t se, next;
++
++  FOR_DHCP6_SESSIONS_SAFE (se, next)
++    {
++      grub_dhcp6_session_remove (se);
++    }
++  grub_dhcp6_sessions = NULL;
++}
++
++static grub_err_t
++grub_dhcp6_session_configure_network (grub_dhcp6_session_t se)
++{
++  char *name;
+ 
+-    if (inter)
+-      grub_net_add_ipv6_local (inter, mask);
+-    return inter;
++  name = grub_xasprintf ("%s:dhcp6", se->iface->card->name);
++  if (!name)
++    return grub_errno;
++
++  grub_net_configure_by_dhcp6_info (name, se->iface->card, se->reply, 1, 0, 0);
++  grub_free (name);
++
++  return GRUB_ERR_NONE;
+ }
+ 
++static grub_err_t
++grub_dhcp6_session_send_request (grub_dhcp6_session_t se)
++{
++  struct grub_net_buff *nb;
++  struct grub_net_dhcp6_option *opt;
++  struct grub_net_dhcp6_packet *v6h;
++  struct grub_net_dhcp6_option_iana *ia_na;
++  struct grub_net_dhcp6_option_iaaddr *iaaddr;
++  struct udphdr *udph;
++  grub_net_network_level_address_t multicast;
++  grub_net_link_level_address_t ll_multicast;
++  grub_uint64_t elapsed;
++  struct grub_net_network_level_interface *inf = se->iface;
++  grub_dhcp6_options_t dhcp6 = se->adv;
++  grub_err_t err = GRUB_ERR_NONE;
++
++  multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
++  multicast.ipv6[0] = grub_cpu_to_be64_compile_time (0xff02ULL << 48);
++  multicast.ipv6[1] = grub_cpu_to_be64_compile_time (0x10002ULL);
++
++  err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast);
++  if (err)
++    return err;
++
++  nb = grub_netbuff_alloc (GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE);
++
++  if (!nb)
++    return grub_errno;
++
++  err = grub_netbuff_reserve (nb, GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE);
++  if (err)
++    {
++      grub_netbuff_free (nb);
++      return err;
++    }
++
++  err = grub_netbuff_push (nb, dhcp6->client_duid_len + sizeof (*opt));
++  if (err)
++    {
++      grub_netbuff_free (nb);
++      return err;
++    }
++  opt = (struct grub_net_dhcp6_option *)nb->data;
++  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_CLIENTID);
++  opt->len = grub_cpu_to_be16 (dhcp6->client_duid_len);
++  grub_memcpy (opt->data, dhcp6->client_duid , dhcp6->client_duid_len);
++
++  err = grub_netbuff_push (nb, dhcp6->server_duid_len + sizeof (*opt));
++  if (err)
++    {
++      grub_netbuff_free (nb);
++      return err;
++    }
++  opt = (struct grub_net_dhcp6_option *)nb->data;
++  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_SERVERID);
++  opt->len = grub_cpu_to_be16 (dhcp6->server_duid_len);
++  grub_memcpy (opt->data, dhcp6->server_duid , dhcp6->server_duid_len);
++
++  err = grub_netbuff_push (nb, sizeof (*ia_na) + sizeof (*opt));
++  if (err)
++    {
++      grub_netbuff_free (nb);
++      return err;
++    }
++
++  if (dhcp6->ia_addr)
++    {
++      err = grub_netbuff_push (nb, sizeof(*iaaddr) + sizeof (*opt));
++      if (err)
++	{
++	  grub_netbuff_free (nb);
++	  return err;
++	}
++    }
++  opt = (struct grub_net_dhcp6_option *)nb->data;
++  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA);
++  opt->len = grub_cpu_to_be16 (sizeof (*ia_na));
++  if (dhcp6->ia_addr)
++    opt->len += grub_cpu_to_be16 (sizeof(*iaaddr) + sizeof (*opt));
++
++  ia_na = (struct grub_net_dhcp6_option_iana *)opt->data;
++  ia_na->iaid = grub_cpu_to_be32 (dhcp6->iaid);
++
++  ia_na->t1 = grub_cpu_to_be32 (dhcp6->t1);
++  ia_na->t2 = grub_cpu_to_be32 (dhcp6->t2);
++
++  if (dhcp6->ia_addr)
++    {
++      opt = (struct grub_net_dhcp6_option *)ia_na->data;
++      opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR);
++      opt->len = grub_cpu_to_be16 (sizeof (*iaaddr));
++      iaaddr = (struct grub_net_dhcp6_option_iaaddr *)opt->data;
++      grub_set_unaligned64 (iaaddr->addr, dhcp6->ia_addr->ipv6[0]);
++      grub_set_unaligned64 (iaaddr->addr + 8, dhcp6->ia_addr->ipv6[1]);
++
++      iaaddr->preferred_lifetime = grub_cpu_to_be32 (dhcp6->preferred_lifetime);
++      iaaddr->valid_lifetime = grub_cpu_to_be32 (dhcp6->valid_lifetime);
++    }
++
++  err = grub_netbuff_push (nb, sizeof (*opt) + 2 * sizeof (grub_uint16_t));
++  if (err)
++    {
++      grub_netbuff_free (nb);
++      return err;
++    }
++
++  opt = (struct grub_net_dhcp6_option*) nb->data;
++  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ORO);
++  opt->len = grub_cpu_to_be16_compile_time (2 * sizeof (grub_uint16_t));
++  grub_set_unaligned16 (opt->data, grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL));
++  grub_set_unaligned16 (opt->data + 2, grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS));
++
++  err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (grub_uint16_t));
++  if (err)
++    {
++      grub_netbuff_free (nb);
++      return err;
++    }
++  opt = (struct grub_net_dhcp6_option*) nb->data;
++  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ELAPSED_TIME);
++  opt->len = grub_cpu_to_be16_compile_time (sizeof (grub_uint16_t));
++
++  /* the time is expressed in hundredths of a second */
++  elapsed = grub_divmod64 (grub_get_time_ms () - se->start_time, 10, 0);
++
++  if (elapsed > 0xffff)
++    elapsed = 0xffff;
++
++  grub_set_unaligned16 (opt->data,  grub_cpu_to_be16 ((grub_uint16_t)elapsed));
++
++  err = grub_netbuff_push (nb, sizeof (*v6h));
++  if (err)
++    {
++      grub_netbuff_free (nb);
++      return err;
++    }
++
++  v6h = (struct grub_net_dhcp6_packet *) nb->data;
++  v6h->message_type = GRUB_NET_DHCP6_REQUEST;
++  v6h->transaction_id = se->transaction_id;
++
++  err = grub_netbuff_push (nb, sizeof (*udph));
++  if (err)
++    {
++      grub_netbuff_free (nb);
++      return err;
++    }
++
++  udph = (struct udphdr *) nb->data;
++  udph->src = grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT);
++  udph->dst = grub_cpu_to_be16_compile_time (DHCP6_SERVER_PORT);
++  udph->chksum = 0;
++  udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
++
++  udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP,
++						 &inf->address,
++						 &multicast);
++  err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb,
++				 GRUB_NET_IP_UDP);
++
++  grub_netbuff_free (nb);
++
++  return err;
++}
++
++struct grub_net_network_level_interface *
++grub_net_configure_by_dhcpv6_reply (const char *name,
++	struct grub_net_card *card,
++	grub_net_interface_flags_t flags,
++	const struct grub_net_dhcp6_packet *v6h,
++	grub_size_t size,
++	int is_def,
++	char **device, char **path)
++{
++  struct grub_net_network_level_interface *inf;
++  grub_dhcp6_options_t dhcp6;
++
++  dhcp6 = grub_dhcp6_options_get (v6h, size);
++  if (!dhcp6)
++    {
++      grub_print_error ();
++      return NULL;
++    }
++
++  grub_net_configure_by_dhcp6_info (name, card, dhcp6, is_def, flags, &inf);
++
++  if (device && dhcp6->boot_file_proto && dhcp6->boot_file_server_ip)
++    {
++      *device = grub_xasprintf ("%s,%s", dhcp6->boot_file_proto, dhcp6->boot_file_server_ip);
++      grub_print_error ();
++    }
++  if (path && dhcp6->boot_file_path)
++    {
++      *path = grub_strdup (dhcp6->boot_file_path);
++      grub_print_error ();
++      if (*path)
++	{
++	  char *slash;
++	  slash = grub_strrchr (*path, '/');
++	  if (slash)
++	    *slash = 0;
++	  else
++	    **path = 0;
++	}
++    }
++
++  grub_dhcp6_options_free (dhcp6);
++  return inf;
++}
+ 
+ void
+ grub_net_process_dhcp (struct grub_net_buff *nb,
+@@ -546,6 +1038,77 @@ grub_net_process_dhcp (struct grub_net_buff *nb,
+     }
+ }
+ 
++grub_err_t
++grub_net_process_dhcp6 (struct grub_net_buff *nb,
++			struct grub_net_card *card __attribute__ ((unused)))
++{
++  const struct grub_net_dhcp6_packet *v6h;
++  grub_dhcp6_session_t se;
++  grub_size_t size;
++  grub_dhcp6_options_t options;
++
++  v6h = (const struct grub_net_dhcp6_packet *) nb->data;
++  size = nb->tail - nb->data;
++
++  options = grub_dhcp6_options_get (v6h, size);
++  if (!options)
++    return grub_errno;
++
++  if (!options->client_duid || !options->server_duid || !options->ia_addr)
++    {
++      grub_dhcp6_options_free (options);
++      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Bad DHCPv6 Packet");
++    }
++
++  FOR_DHCP6_SESSIONS (se)
++    {
++      if (se->transaction_id == v6h->transaction_id &&
++	  grub_memcmp (options->client_duid, &se->duid, sizeof (se->duid)) == 0 &&
++	  se->iaid == options->iaid)
++	break;
++    }
++
++  if (!se)
++    {
++      grub_dprintf ("bootp", "DHCPv6 session not found\n");
++      grub_dhcp6_options_free (options);
++      return GRUB_ERR_NONE;
++    }
++
++  if (v6h->message_type == GRUB_NET_DHCP6_ADVERTISE)
++    {
++      if (se->adv)
++	{
++	  grub_dprintf ("bootp", "Skipped DHCPv6 Advertised .. \n");
++	  grub_dhcp6_options_free (options);
++	  return GRUB_ERR_NONE;
++	}
++
++      se->adv = options;
++      return grub_dhcp6_session_send_request (se);
++    }
++  else if (v6h->message_type == GRUB_NET_DHCP6_REPLY)
++    {
++      if (!se->adv)
++	{
++	  grub_dprintf ("bootp", "Skipped DHCPv6 Reply .. \n");
++	  grub_dhcp6_options_free (options);
++	  return GRUB_ERR_NONE;
++	}
++
++      se->reply = options;
++      grub_dhcp6_session_configure_network (se);
++      grub_dhcp6_session_remove (se);
++      return GRUB_ERR_NONE;
++    }
++  else
++    {
++      grub_dhcp6_options_free (options);
++    }
++
++  return GRUB_ERR_NONE;
++}
++
+ static grub_err_t
+ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
+ 		  int argc, char **args)
+@@ -816,7 +1379,174 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
+   return err;
+ }
+ 
+-static grub_command_t cmd_getdhcp, cmd_bootp;
++static grub_err_t
++grub_cmd_bootp6 (struct grub_command *cmd __attribute__ ((unused)),
++		  int argc, char **args)
++{
++  struct grub_net_card *card;
++  grub_uint32_t iaid = 0;
++  int interval;
++  grub_err_t err;
++  grub_dhcp6_session_t se;
++
++  err = GRUB_ERR_NONE;
++
++  FOR_NET_CARDS (card)
++  {
++    struct grub_net_network_level_interface *iface;
++
++    if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
++      continue;
++
++    iface = grub_net_ipv6_get_link_local (card, &card->default_address);
++    if (!iface)
++      {
++	grub_dhcp6_session_remove_all ();
++	return grub_errno;
++      }
++
++    grub_dhcp6_session_add (iface, iaid++);
++  }
++
++  for (interval = 200; interval < 10000; interval *= 2)
++    {
++      int done = 1;
++
++      FOR_DHCP6_SESSIONS (se)
++	{
++	  struct grub_net_buff *nb;
++	  struct grub_net_dhcp6_option *opt;
++	  struct grub_net_dhcp6_packet *v6h;
++	  struct grub_net_dhcp6_option_duid_ll *duid;
++	  struct grub_net_dhcp6_option_iana *ia_na;
++	  grub_net_network_level_address_t multicast;
++	  grub_net_link_level_address_t ll_multicast;
++	  struct udphdr *udph;
++
++	  multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
++	  multicast.ipv6[0] = grub_cpu_to_be64_compile_time (0xff02ULL << 48);
++	  multicast.ipv6[1] = grub_cpu_to_be64_compile_time (0x10002ULL);
++
++	  err = grub_net_link_layer_resolve (se->iface,
++		    &multicast, &ll_multicast);
++	  if (err)
++	    {
++	      grub_dhcp6_session_remove_all ();
++	      return err;
++	    }
++
++	  nb = grub_netbuff_alloc (GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE);
++
++	  if (!nb)
++	    {
++	      grub_dhcp6_session_remove_all ();
++	      return grub_errno;
++	    }
++
++	  err = grub_netbuff_reserve (nb, GRUB_DHCP6_DEFAULT_NETBUFF_ALLOC_SIZE);
++	  if (err)
++	    {
++	      grub_dhcp6_session_remove_all ();
++	      grub_netbuff_free (nb);
++	      return err;
++	    }
++
++	  err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (grub_uint16_t));
++	  if (err)
++	    {
++	      grub_dhcp6_session_remove_all ();
++	      grub_netbuff_free (nb);
++	      return err;
++	    }
++
++	  opt = (struct grub_net_dhcp6_option *)nb->data;
++	  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_ELAPSED_TIME);
++	  opt->len = grub_cpu_to_be16_compile_time (sizeof (grub_uint16_t));
++	  grub_set_unaligned16 (opt->data, 0);
++
++	  err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (*duid));
++	  if (err)
++	    {
++	      grub_dhcp6_session_remove_all ();
++	      grub_netbuff_free (nb);
++	      return err;
++	    }
++
++	  opt = (struct grub_net_dhcp6_option *)nb->data;
++	  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_CLIENTID);
++	  opt->len = grub_cpu_to_be16 (sizeof (*duid));
++
++	  duid = (struct grub_net_dhcp6_option_duid_ll *) opt->data;
++	  grub_memcpy (duid, &se->duid, sizeof (*duid));
++
++	  err = grub_netbuff_push (nb, sizeof (*opt) + sizeof (*ia_na));
++	  if (err)
++	    {
++	      grub_dhcp6_session_remove_all ();
++	      grub_netbuff_free (nb);
++	      return err;
++	    }
++
++	  opt = (struct grub_net_dhcp6_option *)nb->data;
++	  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA);
++	  opt->len = grub_cpu_to_be16 (sizeof (*ia_na));
++	  ia_na = (struct grub_net_dhcp6_option_iana *)opt->data;
++	  ia_na->iaid = grub_cpu_to_be32 (se->iaid);
++	  ia_na->t1 = 0;
++	  ia_na->t2 = 0;
++
++	  err = grub_netbuff_push (nb, sizeof (*v6h));
++	  if (err)
++	    {
++	      grub_dhcp6_session_remove_all ();
++	      grub_netbuff_free (nb);
++	      return err;
++	    }
++
++	  v6h = (struct grub_net_dhcp6_packet *)nb->data;
++	  v6h->message_type = GRUB_NET_DHCP6_SOLICIT;
++	  v6h->transaction_id = se->transaction_id;
++
++	  grub_netbuff_push (nb, sizeof (*udph));
++
++	  udph = (struct udphdr *) nb->data;
++	  udph->src = grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT);
++	  udph->dst = grub_cpu_to_be16_compile_time (DHCP6_SERVER_PORT);
++	  udph->chksum = 0;
++	  udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
++
++	  udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP,
++			    &se->iface->address, &multicast);
++
++	  err = grub_net_send_ip_packet (se->iface, &multicast,
++		    &ll_multicast, nb, GRUB_NET_IP_UDP);
++	  done = 0;
++	  grub_netbuff_free (nb);
++
++	  if (err)
++	    {
++	      grub_dhcp6_session_remove_all ();
++	      return err;
++	    }
++	}
++      if (!done)
++	grub_net_poll_cards (interval, 0);
++    }
++
++  FOR_DHCP6_SESSIONS (se)
++    {
++      grub_error_push ();
++      err = grub_error (GRUB_ERR_FILE_NOT_FOUND,
++			N_("couldn't autoconfigure %s"),
++			se->iface->card->name);
++    }
++
++  grub_dhcp6_session_remove_all ();
++
++  return err;
++}
++
++static grub_command_t cmd_getdhcp, cmd_bootp, cmd_bootp6;
+ 
+ void
+ grub_bootp_init (void)
+@@ -827,6 +1557,9 @@ grub_bootp_init (void)
+   cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt,
+ 				       N_("VAR INTERFACE NUMBER DESCRIPTION"),
+ 				       N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value."));
++  cmd_bootp6 = grub_register_command ("net_bootp6", grub_cmd_bootp6,
++				     N_("[CARD]"),
++				     N_("perform a DHCPv6 autoconfiguration"));
+ }
+ 
+ void
+@@ -834,4 +1567,5 @@ grub_bootp_fini (void)
+ {
+   grub_unregister_command (cmd_getdhcp);
+   grub_unregister_command (cmd_bootp);
++  grub_unregister_command (cmd_bootp6);
+ }
+diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
+index 311213feec1..daa5b03516b 100644
+--- a/grub-core/net/ip.c
++++ b/grub-core/net/ip.c
+@@ -235,6 +235,45 @@ handle_dgram (struct grub_net_buff *nb,
+   {
+     struct udphdr *udph;
+     udph = (struct udphdr *) nb->data;
++
++    if (proto == GRUB_NET_IP_UDP && udph->dst == grub_cpu_to_be16_compile_time (DHCP6_CLIENT_PORT))
++      {
++	if (udph->chksum)
++	  {
++	    grub_uint16_t chk, expected;
++	    chk = udph->chksum;
++	    udph->chksum = 0;
++	    expected = grub_net_ip_transport_checksum (nb,
++						       GRUB_NET_IP_UDP,
++						       source,
++						       dest);
++	    if (expected != chk)
++	      {
++		grub_dprintf ("net", "Invalid UDP checksum. "
++			      "Expected %x, got %x\n",
++			      grub_be_to_cpu16 (expected),
++			      grub_be_to_cpu16 (chk));
++		grub_netbuff_free (nb);
++		return GRUB_ERR_NONE;
++	      }
++	    udph->chksum = chk;
++	  }
++
++	err = grub_netbuff_pull (nb, sizeof (*udph));
++	if (err)
++	  {
++	    grub_netbuff_free (nb);
++	    return err;
++	  }
++
++	err = grub_net_process_dhcp6 (nb, card);
++	if (err)
++	  grub_print_error ();
++
++	grub_netbuff_free (nb);
++	return GRUB_ERR_NONE;
++      }
++
+     if (proto == GRUB_NET_IP_UDP && grub_be_to_cpu16 (udph->dst) == 68)
+       {
+ 	const struct grub_net_bootp_packet *bootp;
+diff --git a/include/grub/net.h b/include/grub/net.h
+index 20e699bb025..8ecfbb49221 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -423,50 +423,65 @@ struct grub_net_bootp_packet
+   grub_uint8_t vendor[0];
+ } GRUB_PACKED;
+ 
+-enum
+-  {
+-    GRUB_NET_DHCP6_IA_NA = 3,
+-    GRUB_NET_DHCP6_IA_ADDRESS = 5,
+-    GRUB_NET_DHCP6_BOOTFILE_URL = 59,
+-  };
+-
+-struct grub_net_dhcpv6_option
++struct grub_net_dhcp6_packet
+ {
+-  grub_uint16_t option_num;
+-  grub_uint16_t option_len;
+-  grub_uint8_t option_data[];
++  grub_uint32_t message_type:8;
++  grub_uint32_t transaction_id:24;
++  grub_uint8_t dhcp_options[0];
+ } GRUB_PACKED;
+-typedef struct grub_net_dhcpv6_option grub_net_dhcpv6_option_t;
+ 
+-struct grub_net_dhcpv6_opt_ia_na
+-{
+-  grub_uint16_t option_num;
+-  grub_uint16_t option_len;
++struct grub_net_dhcp6_option {
++  grub_uint16_t code;
++  grub_uint16_t len;
++  grub_uint8_t data[0];
++} GRUB_PACKED;
++
++struct grub_net_dhcp6_option_iana {
+   grub_uint32_t iaid;
+   grub_uint32_t t1;
+   grub_uint32_t t2;
+-  grub_uint8_t options[];
++  grub_uint8_t data[0];
+ } GRUB_PACKED;
+-typedef struct grub_net_dhcpv6_opt_ia_na grub_net_dhcpv6_opt_ia_na_t;
+ 
+-struct grub_net_dhcpv6_opt_ia_address
+-{
+-  grub_uint16_t option_num;
+-  grub_uint16_t option_len;
+-  grub_uint64_t ipv6_address[2];
++struct grub_net_dhcp6_option_iaaddr {
++  grub_uint8_t addr[16];
+   grub_uint32_t preferred_lifetime;
+   grub_uint32_t valid_lifetime;
+-  grub_uint8_t options[];
++  grub_uint8_t data[0];
+ } GRUB_PACKED;
+-typedef struct grub_net_dhcpv6_opt_ia_address grub_net_dhcpv6_opt_ia_address_t;
+ 
+-struct grub_net_dhcpv6_packet
++struct grub_net_dhcp6_option_duid_ll
+ {
+-  grub_uint32_t message_type:8;
+-  grub_uint32_t transaction_id:24;
+-  grub_uint8_t dhcp_options[1024];
++  grub_uint16_t type;
++  grub_uint16_t hw_type;
++  grub_uint8_t hwaddr[6];
+ } GRUB_PACKED;
+-typedef struct grub_net_dhcpv6_packet grub_net_dhcpv6_packet_t;
++
++enum
++  {
++    GRUB_NET_DHCP6_SOLICIT = 1,
++    GRUB_NET_DHCP6_ADVERTISE = 2,
++    GRUB_NET_DHCP6_REQUEST = 3,
++    GRUB_NET_DHCP6_REPLY = 7
++  };
++
++enum
++  {
++    DHCP6_CLIENT_PORT = 546,
++    DHCP6_SERVER_PORT = 547
++  };
++
++enum
++  {
++    GRUB_NET_DHCP6_OPTION_CLIENTID = 1,
++    GRUB_NET_DHCP6_OPTION_SERVERID = 2,
++    GRUB_NET_DHCP6_OPTION_IA_NA = 3,
++    GRUB_NET_DHCP6_OPTION_IAADDR = 5,
++    GRUB_NET_DHCP6_OPTION_ORO = 6,
++    GRUB_NET_DHCP6_OPTION_ELAPSED_TIME = 8,
++    GRUB_NET_DHCP6_OPTION_DNS_SERVERS = 23,
++    GRUB_NET_DHCP6_OPTION_BOOTFILE_URL = 59
++  };
+ 
+ #define	GRUB_NET_BOOTP_RFC1048_MAGIC_0	0x63
+ #define	GRUB_NET_BOOTP_RFC1048_MAGIC_1	0x82
+@@ -497,12 +512,12 @@ grub_net_configure_by_dhcp_ack (const char *name,
+ 				int is_def, char **device, char **path);
+ 
+ struct grub_net_network_level_interface *
+-grub_net_configure_by_dhcpv6_ack (const char *name,
+-				 struct grub_net_card *card,
+-				 grub_net_interface_flags_t flags,
+-				 const grub_net_link_level_address_t *hwaddr,
+-				 const struct grub_net_dhcpv6_packet *packet,
+-				 int is_def, char **device, char **path);
++grub_net_configure_by_dhcpv6_reply (const char *name,
++				    struct grub_net_card *card,
++				    grub_net_interface_flags_t flags,
++				    const struct grub_net_dhcp6_packet *v6,
++				    grub_size_t size,
++				    int is_def, char **device, char **path);
+ 
+ int
+ grub_ipv6_get_masksize(grub_uint16_t *mask);
+@@ -519,6 +534,10 @@ void
+ grub_net_process_dhcp (struct grub_net_buff *nb,
+ 		       struct grub_net_card *card);
+ 
++grub_err_t
++grub_net_process_dhcp6 (struct grub_net_buff *nb,
++			struct grub_net_card *card);
++
+ int
+ grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a,
+ 		     const grub_net_link_level_address_t *b);
diff --git a/SOURCES/0254-Put-back-our-code-to-add-a-local-route.patch b/SOURCES/0254-Put-back-our-code-to-add-a-local-route.patch
new file mode 100644
index 0000000..3c638ba
--- /dev/null
+++ b/SOURCES/0254-Put-back-our-code-to-add-a-local-route.patch
@@ -0,0 +1,35 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 21 Jun 2018 18:32:26 -0400
+Subject: [PATCH] Put back our code to add a local route.
+
+This was removed by the previous patch.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/net/bootp.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index 26b3d83d0bc..dd4660601e2 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -972,6 +972,7 @@ grub_net_configure_by_dhcpv6_reply (const char *name,
+ {
+   struct grub_net_network_level_interface *inf;
+   grub_dhcp6_options_t dhcp6;
++  int mask = -1;
+ 
+   dhcp6 = grub_dhcp6_options_get (v6h, size);
+   if (!dhcp6)
+@@ -1003,6 +1004,10 @@ grub_net_configure_by_dhcpv6_reply (const char *name,
+     }
+ 
+   grub_dhcp6_options_free (dhcp6);
++
++  if (inf)
++    grub_net_add_ipv6_local (inf, mask);
++
+   return inf;
+ }
+ 
diff --git a/SOURCES/0255-efinet-UEFI-IPv6-PXE-support.patch b/SOURCES/0255-efinet-UEFI-IPv6-PXE-support.patch
new file mode 100644
index 0000000..6f0c915
--- /dev/null
+++ b/SOURCES/0255-efinet-UEFI-IPv6-PXE-support.patch
@@ -0,0 +1,154 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Wed, 15 Apr 2015 14:48:30 +0800
+Subject: [PATCH] efinet: UEFI IPv6 PXE support
+
+When grub2 image is booted from UEFI IPv6 PXE, the DHCPv6 Reply packet is
+cached in firmware buffer which can be obtained by PXE Base Code protocol. The
+network interface can be setup through the parameters in that obtained packet.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Ken Lin <ken.lin@hpe.com>
+---
+ grub-core/net/drivers/efi/efinet.c | 22 ++++++------
+ include/grub/efi/api.h             | 71 +++++++++++++++++++++++---------------
+ 2 files changed, 54 insertions(+), 39 deletions(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index b9ed13fcad1..8bb0db014ac 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -404,9 +404,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+     pxe_mode = pxe->mode;
+     if (pxe_mode->using_ipv6)
+       {
+-	grub_net_link_level_address_t hwaddr;
+-	struct grub_net_network_level_interface *intf;
+-
+ 	grub_dprintf ("efinet", "using ipv6 and dhcpv6\n");
+ 	grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n",
+ 		      pxe_mode->dhcp_ack_received ? "yes" : "no",
+@@ -414,16 +411,17 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 	if (!pxe_mode->dhcp_ack_received)
+ 	  continue;
+ 
+-	hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
+-	grub_memcpy (hwaddr.mac,
+-		     card->efi_net->mode->current_address,
+-		     sizeof (hwaddr.mac));
+-
+-	intf = grub_net_configure_by_dhcpv6_ack (card->name, card, 0, &hwaddr,
+-	      (const struct grub_net_dhcpv6_packet *)&pxe_mode->dhcp_ack.dhcpv6,
+-	      1, device, path);
+-	if (intf && device && path)
++	grub_net_configure_by_dhcpv6_reply (card->name, card, 0,
++					    (struct grub_net_dhcp6_packet *)
++					    &pxe_mode->dhcp_ack,
++					    sizeof (pxe_mode->dhcp_ack),
++					    1, device, path);
++	if (grub_errno)
++	  grub_print_error ();
++	if (device && path)
+ 	  grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
++	if (grub_errno)
++	  grub_print_error ();
+       }
+     else
+       {
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 9422ba9a9db..2d0f37a8164 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -1446,31 +1446,6 @@ typedef union
+   grub_efi_pxe_dhcpv6_packet_t dhcpv6;
+ } grub_efi_pxe_packet_t;
+ 
+-#define GRUB_EFI_PXE_MAX_IPCNT 8
+-#define GRUB_EFI_PXE_MAX_ARP_ENTRIES 8
+-#define GRUB_EFI_PXE_MAX_ROUTE_ENTRIES 8
+-
+-typedef struct grub_efi_pxe_ip_filter
+-{
+-  grub_efi_uint8_t filters;
+-  grub_efi_uint8_t ip_count;
+-  grub_efi_uint8_t reserved;
+-  grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_MAX_IPCNT];
+-} grub_efi_pxe_ip_filter_t;
+-
+-typedef struct grub_efi_pxe_arp_entry
+-{
+-  grub_efi_ip_address_t ip_addr;
+-  grub_efi_mac_address_t mac_addr;
+-} grub_efi_pxe_arp_entry_t;
+-
+-typedef struct grub_efi_pxe_route_entry
+-{
+-  grub_efi_ip_address_t ip_addr;
+-  grub_efi_ip_address_t subnet_mask;
+-  grub_efi_ip_address_t gateway_addr;
+-} grub_efi_pxe_route_entry_t;
+-
+ typedef struct grub_efi_pxe_icmp_error
+ {
+   grub_efi_uint8_t type;
+@@ -1496,6 +1471,48 @@ typedef struct grub_efi_pxe_tftp_error
+   grub_efi_char8_t error_string[127];
+ } grub_efi_pxe_tftp_error_t;
+ 
++typedef struct {
++  grub_uint8_t addr[4];
++} grub_efi_pxe_ipv4_address_t;
++
++typedef struct {
++  grub_uint8_t addr[16];
++} grub_efi_pxe_ipv6_address_t;
++
++typedef struct {
++  grub_uint8_t addr[32];
++} grub_efi_pxe_mac_address_t;
++
++typedef union {
++  grub_uint32_t addr[4];
++  grub_efi_pxe_ipv4_address_t v4;
++  grub_efi_pxe_ipv6_address_t v6;
++} grub_efi_pxe_ip_address_t;
++
++#define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8
++typedef struct grub_efi_pxe_ip_filter
++{
++  grub_efi_uint8_t filters;
++  grub_efi_uint8_t ip_count;
++  grub_efi_uint16_t reserved;
++  grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT];
++} grub_efi_pxe_ip_filter_t;
++
++typedef struct {
++  grub_efi_pxe_ip_address_t ip_addr;
++  grub_efi_pxe_mac_address_t mac_addr;
++} grub_efi_pxe_arp_entry_t;
++
++typedef struct {
++  grub_efi_pxe_ip_address_t ip_addr;
++  grub_efi_pxe_ip_address_t subnet_mask;
++  grub_efi_pxe_ip_address_t gw_addr;
++} grub_efi_pxe_route_entry_t;
++
++
++#define GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES 8
++#define GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES 8
++
+ typedef struct grub_efi_pxe_mode
+ {
+   grub_efi_boolean_t started;
+@@ -1527,9 +1544,9 @@ typedef struct grub_efi_pxe_mode
+   grub_efi_pxe_packet_t pxe_bis_reply;
+   grub_efi_pxe_ip_filter_t ip_filter;
+   grub_efi_uint32_t arp_cache_entries;
+-  grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_MAX_ARP_ENTRIES];
++  grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES];
+   grub_efi_uint32_t route_table_entries;
+-  grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_MAX_ROUTE_ENTRIES];
++  grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES];
+   grub_efi_pxe_icmp_error_t icmp_error;
+   grub_efi_pxe_tftp_error_t tftp_error;
+ } grub_efi_pxe_mode_t;
diff --git a/SOURCES/0256-grub.texi-Add-net_bootp6-doument.patch b/SOURCES/0256-grub.texi-Add-net_bootp6-doument.patch
new file mode 100644
index 0000000..da2c8e7
--- /dev/null
+++ b/SOURCES/0256-grub.texi-Add-net_bootp6-doument.patch
@@ -0,0 +1,48 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Tue, 5 May 2015 14:19:24 +0800
+Subject: [PATCH] grub.texi: Add net_bootp6 doument
+
+Update grub documentation for net_bootp6 command.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Ken Lin <ken.lin@hpe.com>
+---
+ docs/grub.texi | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/docs/grub.texi b/docs/grub.texi
+index 98138e04d5b..bd3457af9a9 100644
+--- a/docs/grub.texi
++++ b/docs/grub.texi
+@@ -5159,6 +5159,7 @@ List available video modes. If resolution is given, show only matching modes.
+ * net_add_dns::                 Add a DNS server
+ * net_add_route::               Add routing entry
+ * net_bootp::                   Perform a bootp autoconfiguration
++* net_bootp6::                  Perform a DHCPv6 autoconfiguration
+ * net_del_addr::                Remove IP address from interface
+ * net_del_dns::                 Remove a DNS server
+ * net_del_route::               Remove a route entry
+@@ -5240,6 +5241,22 @@ Sets environment variable @samp{net_}@var{<card>}@samp{_dhcp_extensionspath}
+ 
+ @end deffn
+ 
++@node net_bootp6
++@subsection net_bootp6
++
++@deffn Command net_bootp6 [@var{card}]
++Perform configuration of @var{card} using DHCPv6 protocol. If no card name is
++specified, try to configure all existing cards. If configuration was
++successful, interface with name @var{card}@samp{:dhcp6} and configured address
++is added to @var{card}.
++
++@table @samp
++@item 1 (Domain Name Server)
++Adds all servers from option value to the list of servers used during name
++resolution.
++@end table
++
++@end deffn
+ 
+ @node net_del_addr
+ @subsection net_del_addr
diff --git a/SOURCES/0257-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch b/SOURCES/0257-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch
new file mode 100644
index 0000000..0e8ea37
--- /dev/null
+++ b/SOURCES/0257-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch
@@ -0,0 +1,135 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Thu, 14 Jul 2016 18:45:14 +0800
+Subject: [PATCH] bootp: Add processing DHCPACK packet from HTTP Boot
+
+The vendor class identifier with the string "HTTPClient" is used to denote the
+packet as responding to HTTP boot request. In DHCP4 config, the filename for
+HTTP boot is the URL of the boot file while for PXE boot it is the path to the
+boot file. As a consequence, the next-server becomes obseleted because the HTTP
+URL already contains the server address for the boot file. For DHCP6 config,
+there's no difference definition in existing config as dhcp6.bootfile-url can
+be used to specify URL for both HTTP and PXE boot file.
+
+This patch adds processing for "HTTPClient" vendor class identifier in DHCPACK
+packet by treating it as HTTP format, not as the PXE format.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Ken Lin <ken.lin@hpe.com>
+---
+ grub-core/net/bootp.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++--
+ include/grub/net.h    |  1 +
+ 2 files changed, 67 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index dd4660601e2..d47ad80a2ad 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -20,6 +20,7 @@
+ #include <grub/env.h>
+ #include <grub/i18n.h>
+ #include <grub/command.h>
++#include <grub/net.h>
+ #include <grub/net/ip.h>
+ #include <grub/net/netbuff.h>
+ #include <grub/net/udp.h>
+@@ -254,6 +255,11 @@ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
+                                      taglength);
+           break;
+ 
++        case GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER:
++          grub_env_set_net_property (name, "vendor_class_identifier", (const char *) ptr,
++                                     taglength);
++	  break;
++
+ 	case GRUB_NET_BOOTP_EXTENSIONS_PATH:
+           grub_env_set_net_property (name, "extensionspath", (const char *) ptr,
+                                      taglength);
+@@ -356,6 +362,66 @@ grub_net_configure_by_dhcp_ack (const char *name,
+     }
+ #endif
+ 
++  if (size > OFFSET_OF (vendor, bp))
++    {
++      char *cidvar;
++      const char *cid;
++
++      parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp), &mask);
++      cidvar = grub_xasprintf ("net_%s_%s", name, "vendor_class_identifier");
++      cid = grub_env_get (cidvar);
++      grub_free (cidvar);
++
++      if (cid && grub_strcmp (cid, "HTTPClient") == 0)
++	{
++	  char *proto, *ip, *pa;
++
++	  if (!dissect_url (bp->boot_file, &proto, &ip, &pa))
++	    return inter;
++
++	  grub_env_set_net_property (name, "boot_file", pa, grub_strlen (pa));
++	  if (is_def)
++	    {
++	      grub_net_default_server = grub_strdup (ip);
++	      grub_env_set ("net_default_interface", name);
++	      grub_env_export ("net_default_interface");
++	    }
++	  if (device && !*device)
++	    {
++	      *device = grub_xasprintf ("%s,%s", proto, ip);
++	      grub_print_error ();
++	    }
++	  if (path)
++	    {
++	      *path = grub_strdup (pa);
++	      grub_print_error ();
++	      if (*path)
++		{
++		  char *slash;
++		  slash = grub_strrchr (*path, '/');
++		  if (slash)
++		    *slash = 0;
++		  else
++		    **path = 0;
++		}
++	    }
++	  grub_net_add_ipv4_local (inter, mask);
++	  inter->dhcp_ack = grub_malloc (size);
++	  if (inter->dhcp_ack)
++	    {
++	      grub_memcpy (inter->dhcp_ack, bp, size);
++	      inter->dhcp_acklen = size;
++	    }
++	  else
++	    grub_errno = GRUB_ERR_NONE;
++
++	  grub_free (proto);
++	  grub_free (ip);
++	  grub_free (pa);
++	  return inter;
++	}
++    }
++
+   if (size > OFFSET_OF (boot_file, bp))
+     grub_env_set_net_property (name, "boot_file", bp->boot_file,
+                                sizeof (bp->boot_file));
+@@ -417,8 +483,6 @@ grub_net_configure_by_dhcp_ack (const char *name,
+ 	    **path = 0;
+ 	}
+     }
+-  if (size > OFFSET_OF (vendor, bp))
+-    parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp), &mask);
+   grub_net_add_ipv4_local (inter, mask);
+   
+   inter->dhcp_ack = grub_malloc (size);
+diff --git a/include/grub/net.h b/include/grub/net.h
+index 8ecfbb49221..1ec827b9bf3 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -498,6 +498,7 @@ enum
+     GRUB_NET_BOOTP_DOMAIN = 0x0f,
+     GRUB_NET_BOOTP_ROOT_PATH = 0x11,
+     GRUB_NET_BOOTP_EXTENSIONS_PATH = 0x12,
++    GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER = 0x3c,
+     GRUB_NET_BOOTP_CLIENT_ID = 0x3d,
+     GRUB_NET_BOOTP_CLIENT_UUID = 0x61,
+     GRUB_NET_BOOTP_END = 0xff
diff --git a/SOURCES/0258-efinet-Setting-network-from-UEFI-device-path.patch b/SOURCES/0258-efinet-Setting-network-from-UEFI-device-path.patch
new file mode 100644
index 0000000..97af921
--- /dev/null
+++ b/SOURCES/0258-efinet-Setting-network-from-UEFI-device-path.patch
@@ -0,0 +1,396 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Sun, 10 Jul 2016 23:46:31 +0800
+Subject: [PATCH] efinet: Setting network from UEFI device path
+
+The PXE Base Code protocol used to obtain cached PXE DHCPACK packet is no
+longer provided for HTTP Boot. Instead, we have to get the HTTP boot
+information from the device path nodes defined in following UEFI Specification
+sections.
+
+ 9.3.5.12 IPv4 Device Path
+ 9.3.5.13 IPv6 Device Path
+ 9.3.5.23 Uniform Resource Identifiers (URI) Device Path
+
+This patch basically does:
+
+include/grub/efi/api.h:
+Add new structure of Uniform Resource Identifiers (URI) Device Path
+
+grub-core/net/drivers/efi/efinet.c:
+Check if PXE Base Code is available, if not it will try to obtain the netboot
+information from the device path where the image booted from. The DHCPACK
+packet is recoverd from the information in device patch and feed into the same
+DHCP packet processing functions to ensure the network interface is setting up
+the same way it used to be.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Ken Lin <ken.lin@hpe.com>
+---
+ grub-core/net/drivers/efi/efinet.c | 273 +++++++++++++++++++++++++++++++++++--
+ include/grub/efi/api.h             |  11 ++
+ 2 files changed, 275 insertions(+), 9 deletions(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 8bb0db014ac..6f75ff1f9d1 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -27,6 +27,7 @@
+ #include <grub/i18n.h>
+ #include <grub/lib/hexdump.h>
+ #include <grub/types.h>
++#include <grub/net/netbuff.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -342,6 +343,227 @@ grub_efinet_findcards (void)
+   grub_free (handles);
+ }
+ 
++static struct grub_net_buff *
++grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6)
++{
++  grub_efi_uint16_t uri_len;
++  grub_efi_device_path_t *ldp, *ddp;
++  grub_efi_uri_device_path_t *uri_dp;
++  struct grub_net_buff *nb;
++  grub_err_t err;
++
++  ddp = grub_efi_duplicate_device_path (dp);
++  if (!ddp)
++    return NULL;
++
++  ldp = grub_efi_find_last_device_path (ddp);
++
++  if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
++      || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)
++    {
++      grub_free (ddp);
++      return NULL;
++    }
++
++  uri_len = GRUB_EFI_DEVICE_PATH_LENGTH (ldp) > 4 ? GRUB_EFI_DEVICE_PATH_LENGTH (ldp) - 4  : 0;
++
++  if (!uri_len)
++    {
++      grub_free (ddp);
++      return NULL;
++    }
++
++  uri_dp = (grub_efi_uri_device_path_t *) ldp;
++
++  ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++  ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++  ldp->length = sizeof (*ldp);
++
++  ldp = grub_efi_find_last_device_path (ddp);
++
++  if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
++      || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
++          && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
++    {
++      grub_free (ddp);
++      return NULL;
++    }
++
++  nb = grub_netbuff_alloc (512);
++  if (!nb)
++    {
++      grub_free (ddp);
++      return NULL;
++    }
++
++  if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE)
++    {
++      grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp;
++      struct grub_net_bootp_packet *bp;
++      grub_uint8_t *ptr;
++
++      bp = (struct grub_net_bootp_packet *) nb->tail;
++      err = grub_netbuff_put (nb, sizeof (*bp) + 4);
++      if (err)
++	{
++	  grub_free (ddp);
++	  grub_netbuff_free (nb);
++	  return NULL;
++	}
++
++      if (sizeof(bp->boot_file) < uri_len)
++	{
++	  grub_free (ddp);
++	  grub_netbuff_free (nb);
++	  return NULL;
++	}
++      grub_memcpy (bp->boot_file, uri_dp->uri, uri_len);
++      grub_memcpy (&bp->your_ip, ipv4->local_ip_address, sizeof (bp->your_ip));
++      grub_memcpy (&bp->server_ip, ipv4->remote_ip_address, sizeof (bp->server_ip));
++
++      bp->vendor[0] = GRUB_NET_BOOTP_RFC1048_MAGIC_0;
++      bp->vendor[1] = GRUB_NET_BOOTP_RFC1048_MAGIC_1;
++      bp->vendor[2] = GRUB_NET_BOOTP_RFC1048_MAGIC_2;
++      bp->vendor[3] = GRUB_NET_BOOTP_RFC1048_MAGIC_3;
++
++      ptr = nb->tail;
++      err = grub_netbuff_put (nb, sizeof (ipv4->subnet_mask) + 2);
++      if (err)
++	{
++	  grub_free (ddp);
++	  grub_netbuff_free (nb);
++	  return NULL;
++	}
++      *ptr++ = GRUB_NET_BOOTP_NETMASK;
++      *ptr++ = sizeof (ipv4->subnet_mask);
++      grub_memcpy (ptr, ipv4->subnet_mask, sizeof (ipv4->subnet_mask));
++
++      ptr = nb->tail;
++      err = grub_netbuff_put (nb, sizeof (ipv4->gateway_ip_address) + 2);
++      if (err)
++	{
++	  grub_free (ddp);
++	  grub_netbuff_free (nb);
++	  return NULL;
++	}
++      *ptr++ = GRUB_NET_BOOTP_ROUTER;
++      *ptr++ = sizeof (ipv4->gateway_ip_address);
++      grub_memcpy (ptr, ipv4->gateway_ip_address, sizeof (ipv4->gateway_ip_address));
++
++      ptr = nb->tail;
++      err = grub_netbuff_put (nb, sizeof ("HTTPClient") + 1);
++      if (err)
++	{
++	  grub_free (ddp);
++	  grub_netbuff_free (nb);
++	  return NULL;
++	}
++      *ptr++ = GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER;
++      *ptr++ = sizeof ("HTTPClient") - 1;
++      grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1);
++
++      ptr = nb->tail;
++      err = grub_netbuff_put (nb, 1);
++      if (err)
++	{
++	  grub_free (ddp);
++	  grub_netbuff_free (nb);
++	  return NULL;
++	}
++      *ptr = GRUB_NET_BOOTP_END;
++      *use_ipv6 = 0;
++
++      ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++      ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++      ldp->length = sizeof (*ldp);
++      ldp = grub_efi_find_last_device_path (ddp);
++
++      if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) ==  GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)
++	{
++	  grub_efi_mac_address_device_path_t *mac = (grub_efi_mac_address_device_path_t *) ldp;
++	  bp->hw_type = mac->if_type;
++	  bp->hw_len = sizeof (bp->mac_addr);
++	  grub_memcpy (bp->mac_addr, mac->mac_address, bp->hw_len);
++	}
++    }
++  else
++    {
++      grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) ldp;
++
++      struct grub_net_dhcp6_packet *d6p;
++      struct grub_net_dhcp6_option *opt;
++      struct grub_net_dhcp6_option_iana *iana;
++      struct grub_net_dhcp6_option_iaaddr *iaaddr;
++
++      d6p = (struct grub_net_dhcp6_packet *)nb->tail;
++      err = grub_netbuff_put (nb, sizeof(*d6p));
++      if (err)
++	{
++	  grub_free (ddp);
++	  grub_netbuff_free (nb);
++	  return NULL;
++	}
++      d6p->message_type = GRUB_NET_DHCP6_REPLY;
++
++      opt = (struct grub_net_dhcp6_option *)nb->tail;
++      err = grub_netbuff_put (nb, sizeof(*opt));
++      if (err)
++	{
++	  grub_free (ddp);
++	  grub_netbuff_free (nb);
++	  return NULL;
++	}
++      opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA);
++      opt->len = grub_cpu_to_be16_compile_time (sizeof(*iana) + sizeof(*opt) + sizeof(*iaaddr));
++
++      err = grub_netbuff_put (nb, sizeof(*iana));
++      if (err)
++	{
++	  grub_free (ddp);
++	  grub_netbuff_free (nb);
++	  return NULL;
++	}
++
++      opt = (struct grub_net_dhcp6_option *)nb->tail;
++      err = grub_netbuff_put (nb, sizeof(*opt));
++      if (err)
++	{
++	  grub_free (ddp);
++	  grub_netbuff_free (nb);
++	  return NULL;
++	}
++      opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR);
++      opt->len = grub_cpu_to_be16_compile_time (sizeof (*iaaddr));
++
++      iaaddr = (struct grub_net_dhcp6_option_iaaddr *)nb->tail;
++      err = grub_netbuff_put (nb, sizeof(*iaaddr));
++      if (err)
++	{
++	  grub_free (ddp);
++	  grub_netbuff_free (nb);
++	  return NULL;
++	}
++      grub_memcpy (iaaddr->addr, ipv6->local_ip_address, sizeof(ipv6->local_ip_address));
++
++      opt = (struct grub_net_dhcp6_option *)nb->tail;
++      err = grub_netbuff_put (nb, sizeof(*opt) + uri_len);
++      if (err)
++	{
++	  grub_free (ddp);
++	  grub_netbuff_free (nb);
++	  return NULL;
++	}
++      opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL);
++      opt->len = grub_cpu_to_be16 (uri_len);
++      grub_memcpy (opt->data, uri_dp->uri, uri_len);
++
++      *use_ipv6 = 1;
++    }
++
++  grub_free (ddp);
++  return nb;
++}
++
+ static void
+ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 			  char **path)
+@@ -358,6 +580,10 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+     grub_efi_device_path_t *cdp;
+     struct grub_efi_pxe *pxe;
+     struct grub_efi_pxe_mode *pxe_mode;
++    grub_uint8_t *packet_buf;
++    grub_size_t packet_bufsz ;
++    int ipv6;
++    struct grub_net_buff *nb = NULL;
+ 
+     if (card->driver != &efidriver)
+       continue;
+@@ -381,11 +607,21 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+          */
+ 	if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
+ 	    || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
+-		&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
++		&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE
++		&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE))
+ 	  continue;
+ 	dup_dp = grub_efi_duplicate_device_path (dp);
+ 	if (!dup_dp)
+ 	  continue;
++
++	if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)
++	  {
++	    dup_ldp = grub_efi_find_last_device_path (dup_dp);
++	    dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++	    dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++	    dup_ldp->length = sizeof (*dup_ldp);
++	  }
++
+ 	dup_ldp = grub_efi_find_last_device_path (dup_dp);
+ 	dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+ 	dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+@@ -398,11 +634,26 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 
+     pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
+ 				  GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+-    if (! pxe)
+-      continue;
++    if (!pxe)
++      {
++	nb = grub_efinet_create_dhcp_ack_from_device_path (dp, &ipv6);
++	if (!nb)
++	  {
++	    grub_print_error ();
++	    continue;
++	  }
++	packet_buf = nb->head;
++	packet_bufsz = nb->tail - nb->head;
++      }
++    else
++      {
++	pxe_mode = pxe->mode;
++	packet_buf = (grub_uint8_t *) &pxe_mode->dhcp_ack;
++	packet_bufsz = sizeof (pxe_mode->dhcp_ack);
++	ipv6 = pxe_mode->using_ipv6;
++      }
+ 
+-    pxe_mode = pxe->mode;
+-    if (pxe_mode->using_ipv6)
++    if (ipv6)
+       {
+ 	grub_dprintf ("efinet", "using ipv6 and dhcpv6\n");
+ 	grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n",
+@@ -413,8 +664,8 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 
+ 	grub_net_configure_by_dhcpv6_reply (card->name, card, 0,
+ 					    (struct grub_net_dhcp6_packet *)
+-					    &pxe_mode->dhcp_ack,
+-					    sizeof (pxe_mode->dhcp_ack),
++					    packet_buf,
++					    packet_bufsz,
+ 					    1, device, path);
+ 	if (grub_errno)
+ 	  grub_print_error ();
+@@ -428,11 +679,15 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 	grub_dprintf ("efinet", "using ipv4 and dhcp\n");
+ 	grub_net_configure_by_dhcp_ack (card->name, card, 0,
+ 					(struct grub_net_bootp_packet *)
+-					&pxe_mode->dhcp_ack,
+-					sizeof (pxe_mode->dhcp_ack),
++					packet_buf,
++					packet_bufsz,
+ 					1, device, path);
+ 	grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
+       }
++
++    if (nb)
++      grub_netbuff_free (nb);
++
+     return;
+   }
+ }
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 2d0f37a8164..76ad56aa2b0 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -786,6 +786,8 @@ struct grub_efi_ipv4_device_path
+   grub_efi_uint16_t remote_port;
+   grub_efi_uint16_t protocol;
+   grub_efi_uint8_t static_ip_address;
++  grub_efi_ipv4_address_t gateway_ip_address;
++  grub_efi_ipv4_address_t subnet_mask;
+ } GRUB_PACKED;
+ typedef struct grub_efi_ipv4_device_path grub_efi_ipv4_device_path_t;
+ 
+@@ -840,6 +842,15 @@ struct grub_efi_sata_device_path
+ } GRUB_PACKED;
+ typedef struct grub_efi_sata_device_path grub_efi_sata_device_path_t;
+ 
++#define GRUB_EFI_URI_DEVICE_PATH_SUBTYPE		24
++
++struct grub_efi_uri_device_path
++{
++  grub_efi_device_path_t header;
++  grub_efi_uint8_t uri[0];
++} GRUB_PACKED;
++typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t;
++
+ #define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE	10
+ 
+ /* Media Device Path.  */
diff --git a/SOURCES/0259-efinet-Setting-DNS-server-from-UEFI-protocol.patch b/SOURCES/0259-efinet-Setting-DNS-server-from-UEFI-protocol.patch
new file mode 100644
index 0000000..3623e0c
--- /dev/null
+++ b/SOURCES/0259-efinet-Setting-DNS-server-from-UEFI-protocol.patch
@@ -0,0 +1,337 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Thu, 14 Jul 2016 17:48:45 +0800
+Subject: [PATCH] efinet: Setting DNS server from UEFI protocol
+
+In the URI device path node, any name rahter than address can be used for
+looking up the resources so that DNS service become needed to get answer of the
+name's address. Unfortunately the DNS is not defined in any of the device path
+nodes so that we use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL
+to obtain it.
+
+These two protcols are defined the sections of UEFI specification.
+
+ 27.5 EFI IPv4 Configuration II Protocol
+ 27.7 EFI IPv6 Configuration Protocol
+
+include/grub/efi/api.h:
+Add new structure and protocol UUID of EFI_IP4_CONFIG2_PROTOCOL and
+EFI_IP6_CONFIG_PROTOCOL.
+
+grub-core/net/drivers/efi/efinet.c:
+Use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL to obtain the list
+of DNS server address for IPv4 and IPv6 respectively. The address of DNS
+servers is structured into DHCPACK packet and feed into the same DHCP packet
+processing functions to ensure the network interface is setting up the same way
+it used to be.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Ken Lin <ken.lin@hpe.com>
+---
+ grub-core/net/drivers/efi/efinet.c | 163 +++++++++++++++++++++++++++++++++++++
+ include/grub/efi/api.h             |  76 +++++++++++++++++
+ 2 files changed, 239 insertions(+)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 6f75ff1f9d1..25616a9c6c8 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -34,6 +34,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ /* GUID.  */
+ static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID;
+ static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID;
++static grub_efi_guid_t ip4_config_guid = GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID;
++static grub_efi_guid_t ip6_config_guid = GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID;
+ 
+ static grub_err_t
+ send_card_buffer (struct grub_net_card *dev,
+@@ -343,6 +345,125 @@ grub_efinet_findcards (void)
+   grub_free (handles);
+ }
+ 
++static grub_efi_handle_t
++grub_efi_locate_device_path (grub_efi_guid_t *protocol, grub_efi_device_path_t *device_path,
++			    grub_efi_device_path_t **r_device_path)
++{
++  grub_efi_handle_t handle;
++  grub_efi_status_t status;
++
++  status = efi_call_3 (grub_efi_system_table->boot_services->locate_device_path,
++		      protocol, &device_path, &handle);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++
++  if (r_device_path)
++    *r_device_path = device_path;
++
++  return handle;
++}
++
++static grub_efi_ipv4_address_t *
++grub_dns_server_ip4_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns)
++{
++  grub_efi_handle_t hnd;
++  grub_efi_status_t status;
++  grub_efi_ip4_config2_protocol_t *conf;
++  grub_efi_ipv4_address_t *addrs;
++  grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv4_address_t);
++
++  hnd = grub_efi_locate_device_path (&ip4_config_guid, dp, NULL);
++
++  if (!hnd)
++    return 0;
++
++  conf = grub_efi_open_protocol (hnd, &ip4_config_guid,
++				GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++  if (!conf)
++    return 0;
++
++  addrs  = grub_malloc (data_size);
++  if (!addrs)
++    return 0;
++
++  status = efi_call_4 (conf->get_data, conf,
++		      GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
++		      &data_size, addrs);
++
++  if (status == GRUB_EFI_BUFFER_TOO_SMALL)
++    {
++      grub_free (addrs);
++      addrs  = grub_malloc (data_size);
++      if (!addrs)
++	return 0;
++
++      status = efi_call_4 (conf->get_data,  conf,
++			  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
++			  &data_size, addrs);
++    }
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (addrs);
++      return 0;
++    }
++
++  *num_dns = data_size / sizeof (grub_efi_ipv4_address_t);
++  return addrs;
++}
++
++static grub_efi_ipv6_address_t *
++grub_dns_server_ip6_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns)
++{
++  grub_efi_handle_t hnd;
++  grub_efi_status_t status;
++  grub_efi_ip6_config_protocol_t *conf;
++  grub_efi_ipv6_address_t *addrs;
++  grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv6_address_t);
++
++  hnd = grub_efi_locate_device_path (&ip6_config_guid, dp, NULL);
++
++  if (!hnd)
++    return 0;
++
++  conf = grub_efi_open_protocol (hnd, &ip6_config_guid,
++				GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++  if (!conf)
++    return 0;
++
++  addrs  = grub_malloc (data_size);
++  if (!addrs)
++    return 0;
++
++  status = efi_call_4 (conf->get_data, conf,
++		      GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
++		      &data_size, addrs);
++
++  if (status == GRUB_EFI_BUFFER_TOO_SMALL)
++    {
++      grub_free (addrs);
++      addrs  = grub_malloc (data_size);
++      if (!addrs)
++	return 0;
++
++      status = efi_call_4 (conf->get_data,  conf,
++			  GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
++			  &data_size, addrs);
++    }
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (addrs);
++      return 0;
++    }
++
++  *num_dns = data_size / sizeof (grub_efi_ipv6_address_t);
++  return addrs;
++}
++
+ static struct grub_net_buff *
+ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6)
+ {
+@@ -401,6 +522,8 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+       grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp;
+       struct grub_net_bootp_packet *bp;
+       grub_uint8_t *ptr;
++      grub_efi_ipv4_address_t *dns;
++      grub_efi_uintn_t num_dns;
+ 
+       bp = (struct grub_net_bootp_packet *) nb->tail;
+       err = grub_netbuff_put (nb, sizeof (*bp) + 4);
+@@ -462,6 +585,25 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+       *ptr++ = sizeof ("HTTPClient") - 1;
+       grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1);
+ 
++      dns = grub_dns_server_ip4_address (dp, &num_dns);
++      if (dns)
++	{
++	  grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns;
++
++	  ptr = nb->tail;
++	  err = grub_netbuff_put (nb, size_dns + 2);
++	  if (err)
++	    {
++	      grub_free (ddp);
++	      grub_netbuff_free (nb);
++	      return NULL;
++	    }
++	  *ptr++ = GRUB_NET_BOOTP_DNS;
++	  *ptr++ = size_dns;
++	  grub_memcpy (ptr, dns, size_dns);
++	  grub_free (dns);
++	}
++
+       ptr = nb->tail;
+       err = grub_netbuff_put (nb, 1);
+       if (err)
+@@ -494,6 +636,8 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+       struct grub_net_dhcp6_option *opt;
+       struct grub_net_dhcp6_option_iana *iana;
+       struct grub_net_dhcp6_option_iaaddr *iaaddr;
++      grub_efi_ipv6_address_t *dns;
++      grub_efi_uintn_t num_dns;
+ 
+       d6p = (struct grub_net_dhcp6_packet *)nb->tail;
+       err = grub_netbuff_put (nb, sizeof(*d6p));
+@@ -557,6 +701,25 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+       opt->len = grub_cpu_to_be16 (uri_len);
+       grub_memcpy (opt->data, uri_dp->uri, uri_len);
+ 
++      dns = grub_dns_server_ip6_address (dp, &num_dns);
++      if (dns)
++	{
++	  grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns;
++
++	  opt = (struct grub_net_dhcp6_option *)nb->tail;
++	  err = grub_netbuff_put (nb, sizeof(*opt) + size_dns);
++	  if (err)
++	  {
++	    grub_free (ddp);
++	    grub_netbuff_free (nb);
++	    return NULL;
++	  }
++	  opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS);
++	  opt->len = grub_cpu_to_be16 (size_dns);
++	  grub_memcpy (opt->data, dns, size_dns);
++	  grub_free (dns);
++	}
++
+       *use_ipv6 = 1;
+     }
+ 
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 76ad56aa2b0..852daddfb0f 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -289,6 +289,16 @@
+       { 0x8B, 0x8C, 0xE2, 0x1B, 0x01, 0xAE, 0xF2, 0xB7 } \
+   }
+ 
++#define GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID \
++  { 0x5b446ed1, 0xe30b, 0x4faa, \
++      { 0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \
++  }
++
++#define GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID \
++  { 0x937fe521, 0x95ae, 0x4d1a, \
++      { 0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \
++  }
++
+ struct grub_efi_sal_system_table
+ {
+   grub_uint32_t signature;
+@@ -1785,6 +1795,72 @@ struct grub_efi_block_io
+ };
+ typedef struct grub_efi_block_io grub_efi_block_io_t;
+ 
++enum grub_efi_ip4_config2_data_type {
++  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO,
++  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY,
++  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
++  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_GATEWAY,
++  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
++  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MAXIMUM
++};
++typedef enum grub_efi_ip4_config2_data_type grub_efi_ip4_config2_data_type_t;
++
++struct grub_efi_ip4_config2_protocol
++{
++  grub_efi_status_t (*set_data) (struct grub_efi_ip4_config2_protocol *this,
++				 grub_efi_ip4_config2_data_type_t data_type,
++				 grub_efi_uintn_t data_size,
++				 void *data);
++
++  grub_efi_status_t (*get_data) (struct grub_efi_ip4_config2_protocol *this,
++				 grub_efi_ip4_config2_data_type_t data_type,
++				 grub_efi_uintn_t *data_size,
++				 void *data);
++
++  grub_efi_status_t (*register_data_notify) (struct grub_efi_ip4_config2_protocol *this,
++					     grub_efi_ip4_config2_data_type_t data_type,
++					     grub_efi_event_t event);
++
++  grub_efi_status_t (*unregister_datanotify) (struct grub_efi_ip4_config2_protocol *this,
++					     grub_efi_ip4_config2_data_type_t data_type,
++					     grub_efi_event_t event);
++};
++typedef struct grub_efi_ip4_config2_protocol grub_efi_ip4_config2_protocol_t;
++
++enum grub_efi_ip6_config_data_type {
++  GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO,
++  GRUB_EFI_IP6_CONFIG_DATA_TYPE_ALT_INTERFACEID,
++  GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY,
++  GRUB_EFI_IP6_CONFIG_DATA_TYPE_DUP_ADDR_DETECT_TRANSMITS,
++  GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS,
++  GRUB_EFI_IP6_CONFIG_DATA_TYPE_GATEWAY,
++  GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
++  GRUB_EFI_IP6_CONFIG_DATA_TYPE_MAXIMUM
++};
++typedef enum grub_efi_ip6_config_data_type grub_efi_ip6_config_data_type_t;
++
++struct grub_efi_ip6_config_protocol
++{
++  grub_efi_status_t (*set_data) (struct grub_efi_ip6_config_protocol *this,
++				 grub_efi_ip6_config_data_type_t data_type,
++				 grub_efi_uintn_t data_size,
++				 void *data);
++
++  grub_efi_status_t (*get_data) (struct grub_efi_ip6_config_protocol *this,
++				 grub_efi_ip6_config_data_type_t data_type,
++				 grub_efi_uintn_t *data_size,
++				 void *data);
++
++  grub_efi_status_t (*register_data_notify) (struct grub_efi_ip6_config_protocol *this,
++					     grub_efi_ip6_config_data_type_t data_type,
++					     grub_efi_event_t event);
++
++  grub_efi_status_t (*unregister_datanotify) (struct grub_efi_ip6_config_protocol *this,
++					     grub_efi_ip6_config_data_type_t data_type,
++					     grub_efi_event_t event);
++};
++typedef struct grub_efi_ip6_config_protocol grub_efi_ip6_config_protocol_t;
++
+ #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
+   || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__)
+ 
diff --git a/SOURCES/0260-set-rootpath.patch b/SOURCES/0260-set-rootpath.patch
new file mode 100644
index 0000000..155cc30
--- /dev/null
+++ b/SOURCES/0260-set-rootpath.patch
@@ -0,0 +1,46 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 24 May 2017 15:02:40 -0400
+Subject: [PATCH] set rootpath
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/net/bootp.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index d47ad80a2ad..249ca0c2dc6 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -398,11 +398,31 @@ grub_net_configure_by_dhcp_ack (const char *name,
+ 	      if (*path)
+ 		{
+ 		  char *slash;
++		  int root_path_len;
+ 		  slash = grub_strrchr (*path, '/');
+ 		  if (slash)
+ 		    *slash = 0;
+ 		  else
+ 		    **path = 0;
++		  root_path_len = grub_strlen (*path);
++		  if (root_path_len >= 9 &&
++		      !grub_strcasecmp (&(*path)[root_path_len - 9], "/efi/boot"))
++		    {
++		      char *root_path;
++		      grub_print_error ();
++		      if (root_path_len - 9 == 0)
++			{
++			  root_path_len = 1;
++			  root_path = grub_xasprintf ("/");
++			}
++		      else
++			{
++			  root_path_len -= 9;
++			  root_path = grub_strndup (*path, root_path_len);
++			}
++		      grub_env_set_net_property (name, "rootpath",
++						 root_path, root_path_len);
++		    }
+ 		}
+ 	    }
+ 	  grub_net_add_ipv4_local (inter, mask);
diff --git a/SOURCES/0261-Fix-one-more-coverity-complaint.patch b/SOURCES/0261-Fix-one-more-coverity-complaint.patch
new file mode 100644
index 0000000..ba00fbd
--- /dev/null
+++ b/SOURCES/0261-Fix-one-more-coverity-complaint.patch
@@ -0,0 +1,27 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 25 May 2017 11:27:40 -0400
+Subject: [PATCH] Fix one more coverity complaint
+
+No idea why covscan thinks this is an "added" bug, since the file hasn't
+changed in 3 years, but... yeah.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/normal/completion.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/normal/completion.c b/grub-core/normal/completion.c
+index 2c9b9e9312a..93aa0d8eda8 100644
+--- a/grub-core/normal/completion.c
++++ b/grub-core/normal/completion.c
+@@ -284,7 +284,8 @@ complete_file (void)
+ 
+       /* Cut away the filename part.  */
+       dirfile = grub_strrchr (dir, '/');
+-      dirfile[1] = '\0';
++      if (dirfile)
++	dirfile[1] = '\0';
+ 
+       /* Iterate the directory.  */
+       (fs->dir) (dev, dir, iterate_dir, NULL);
diff --git a/SOURCES/0262-Fix-up-linux-params-usage.patch b/SOURCES/0262-Fix-up-linux-params-usage.patch
new file mode 100644
index 0000000..0024568
--- /dev/null
+++ b/SOURCES/0262-Fix-up-linux-params-usage.patch
@@ -0,0 +1,42 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 30 May 2017 14:16:07 -0400
+Subject: [PATCH] Fix up linux params usage...
+
+Related: rhbz#1310763
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/i386/linux.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
+index e3906eb658f..656c75fd7e8 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -680,6 +680,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ {
+   grub_file_t file = 0;
+   struct linux_kernel_header lh;
++  grub_uint8_t *linux_params_ptr;
+   grub_uint8_t setup_sects;
+   grub_size_t real_size, prot_size, prot_file_size, kernel_offset;
+   grub_ssize_t len;
+@@ -811,6 +812,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 		      preferred_address))
+     goto fail;
+ 
++
+   grub_memset (&linux_params, 0, sizeof (linux_params));
+   grub_memcpy (&linux_params.setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
+ 
+@@ -820,7 +822,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+   len = sizeof (linux_params) - sizeof (lh);
+ 
+-  grub_memcpy (&linux_params + sizeof (lh), kernel + kernel_offset, len);
++  linux_params_ptr = (void *)&linux_params;
++  grub_memcpy (linux_params_ptr + sizeof (lh), kernel + kernel_offset, len);
+   kernel_offset += len;
+ 
+   linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
diff --git a/SOURCES/0263-Fix-grub_net_hwaddr_to_str.patch b/SOURCES/0263-Fix-grub_net_hwaddr_to_str.patch
new file mode 100644
index 0000000..c6f2d4f
--- /dev/null
+++ b/SOURCES/0263-Fix-grub_net_hwaddr_to_str.patch
@@ -0,0 +1,41 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Mark Salter <msalter@redhat.com>
+Date: Tue, 22 Aug 2017 12:21:12 -0400
+Subject: [PATCH] Fix grub_net_hwaddr_to_str
+
+commit 5c3b78c92f8 introduced support for larger network hw addresses.
+However, grub_net_hwaddr_to_str() relies on GRUB_NET_MAX_STR_ADDRESS_SIZE
+to prevent a spurious ':' at the end of the string. So now, if actual
+hwaddr size is less than max, an extra ':' appears at the end of the
+string. So calculate max string size based on actual hwaddr length to
+fix the problem.
+
+Signed-off-by: Mark Salter <msalter@redhat.com>
+---
+ grub-core/net/net.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index 6b4b10ba444..a6566bdb00a 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -784,6 +784,7 @@ grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str)
+ {
+   char *ptr;
+   unsigned i;
++  int maxstr;
+ 
+   if (addr->len > GRUB_NET_MAX_LINK_ADDRESS_SIZE)
+     {
+@@ -792,9 +793,10 @@ grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str)
+ 		    addr->type, addr->len);
+        return;
+     }
++  maxstr = addr->len * grub_strlen ("XX:");
+   for (ptr = str, i = 0; i < addr->len; i++)
+     {
+-      ptr += grub_snprintf (ptr, GRUB_NET_MAX_STR_HWADDR_LEN - (ptr - str),
++      ptr += grub_snprintf (ptr, maxstr - (ptr - str),
+ 		     "%02x:", addr->mac[i] & 0xff);
+     }
+ }
diff --git a/SOURCES/0264-Fixup-for-newer-compiler.patch b/SOURCES/0264-Fixup-for-newer-compiler.patch
new file mode 100644
index 0000000..e3a56de
--- /dev/null
+++ b/SOURCES/0264-Fixup-for-newer-compiler.patch
@@ -0,0 +1,50 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 10 May 2018 13:40:19 -0400
+Subject: [PATCH] Fixup for newer compiler
+
+---
+ grub-core/fs/btrfs.c         | 2 +-
+ include/grub/gpt_partition.h | 2 +-
+ conf/Makefile.common         | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
+index f7b6c152037..4a6efffeb46 100644
+--- a/grub-core/fs/btrfs.c
++++ b/grub-core/fs/btrfs.c
+@@ -183,7 +183,7 @@ struct grub_btrfs_inode
+   grub_uint64_t size;
+   grub_uint8_t dummy2[0x70];
+   struct grub_btrfs_time mtime;
+-} GRUB_PACKED;
++} GRUB_PACKED  __attribute__ ((aligned(8)));
+ 
+ struct grub_btrfs_extent_data
+ {
+diff --git a/include/grub/gpt_partition.h b/include/grub/gpt_partition.h
+index 1b32f6725a4..8cddf997efc 100644
+--- a/include/grub/gpt_partition.h
++++ b/include/grub/gpt_partition.h
+@@ -76,7 +76,7 @@ struct grub_gpt_partentry
+   grub_uint64_t end;
+   grub_uint64_t attrib;
+   char name[72];
+-} GRUB_PACKED;
++} GRUB_PACKED  __attribute__ ((aligned(8)));
+ 
+ grub_err_t
+ grub_gpt_partition_map_iterate (grub_disk_t disk,
+diff --git a/conf/Makefile.common b/conf/Makefile.common
+index 6f836d82771..9e0e8364f38 100644
+--- a/conf/Makefile.common
++++ b/conf/Makefile.common
+@@ -45,7 +45,7 @@ CFLAGS_KERNEL = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding
+ LDFLAGS_KERNEL = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) $(TARGET_LDFLAGS_STATIC_LIBGCC)
+ CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1
+ CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM)
+-STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version
++STRIPFLAGS_KERNEL = -R .eh_frame -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx -R .note.gnu.property -R .gnu.build.attributes
+ 
+ CFLAGS_MODULE = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding
+ LDFLAGS_MODULE = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d
diff --git a/SOURCES/0265-Support-UEFI-networking-protocols.patch b/SOURCES/0265-Support-UEFI-networking-protocols.patch
new file mode 100644
index 0000000..bda2ee2
--- /dev/null
+++ b/SOURCES/0265-Support-UEFI-networking-protocols.patch
@@ -0,0 +1,5055 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Wed, 22 Feb 2017 14:27:50 +0800
+Subject: [PATCH] Support UEFI networking protocols
+
+References: fate#320130, bsc#1015589, bsc#1076132
+Patch-Mainline: no
+
+V1:
+  * Add preliminary support of UEFI networking protocols
+  * Support UEFI HTTPS Boot
+
+V2:
+  * Workaround http data access in firmware
+  * Fix DNS device path parsing for efinet device
+  * Relaxed UEFI Protocol requirement
+  * Support Intel OPA (Omni-Path Architecture) PXE Boot
+
+V3:
+  * Fix bufio in calculating address of next_buf
+  * Check HTTP respond code
+  * Use HEAD request method to test before GET
+  * Finish HTTP transaction in one go
+  * Fix bsc#1076132
+---
+ grub-core/Makefile.core.def        |   18 +
+ grub-core/io/bufio.c               |    2 +-
+ grub-core/kern/efi/efi.c           |   96 ++-
+ grub-core/net/drivers/efi/efinet.c |   27 +
+ grub-core/net/efi/dhcp.c           |  397 ++++++++++
+ grub-core/net/efi/efi_netfs.c      |   57 ++
+ grub-core/net/efi/http.c           |  419 +++++++++++
+ grub-core/net/efi/ip4_config.c     |  398 ++++++++++
+ grub-core/net/efi/ip6_config.c     |  422 +++++++++++
+ grub-core/net/efi/net.c            | 1428 ++++++++++++++++++++++++++++++++++++
+ grub-core/net/efi/pxe.c            |  424 +++++++++++
+ grub-core/net/net.c                |   74 ++
+ util/grub-mknetdir.c               |   23 +-
+ include/grub/efi/api.h             |  180 ++++-
+ include/grub/efi/dhcp.h            |  343 +++++++++
+ include/grub/efi/http.h            |  215 ++++++
+ include/grub/net/efi.h             |  144 ++++
+ 17 files changed, 4626 insertions(+), 41 deletions(-)
+ create mode 100644 grub-core/net/efi/dhcp.c
+ create mode 100644 grub-core/net/efi/efi_netfs.c
+ create mode 100644 grub-core/net/efi/http.c
+ create mode 100644 grub-core/net/efi/ip4_config.c
+ create mode 100644 grub-core/net/efi/ip6_config.c
+ create mode 100644 grub-core/net/efi/net.c
+ create mode 100644 grub-core/net/efi/pxe.c
+ create mode 100644 include/grub/efi/dhcp.h
+ create mode 100644 include/grub/efi/http.h
+ create mode 100644 include/grub/net/efi.h
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index b340ceeec7f..00110ae5efd 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -2093,6 +2093,18 @@ module = {
+   common = hook/datehook.c;
+ };
+ 
++module = {
++  name = efi_netfs;
++  common = net/efi/efi_netfs.c;
++  common = net/efi/net.c;
++  common = net/efi/http.c;
++  common = net/efi/pxe.c;
++  common = net/efi/ip4_config.c;
++  common = net/efi/ip6_config.c;
++  common = net/efi/dhcp.c;
++  enable = efi;
++};
++
+ module = {
+   name = net;
+   common = net/net.c;
+@@ -2107,6 +2119,12 @@ module = {
+   common = net/arp.c;
+   common = net/netbuff.c;
+   common = net/url.c;
++  efi = net/efi/net.c;
++  efi = net/efi/http.c;
++  efi = net/efi/pxe.c;
++  efi = net/efi/ip4_config.c;
++  efi = net/efi/ip6_config.c;
++  efi = net/efi/dhcp.c;
+ };
+ 
+ module = {
+diff --git a/grub-core/io/bufio.c b/grub-core/io/bufio.c
+index 22438277d74..d0b0f71b6ed 100644
+--- a/grub-core/io/bufio.c
++++ b/grub-core/io/bufio.c
+@@ -132,7 +132,7 @@ grub_bufio_read (grub_file_t file, char *buf, grub_size_t len)
+     return res;
+ 
+   /* Need to read some more.  */
+-  next_buf = (file->offset + res + len - 1) & ~((grub_off_t) bufio->block_size - 1);
++  next_buf = (grub_divmod64 (file->offset + res + len - 1, bufio->block_size, NULL)) * bufio->block_size;
+   /* Now read between file->offset + res and bufio->buffer_at.  */
+   if (file->offset + res < next_buf)
+     {
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index 101307fc71e..570535f78d0 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -674,7 +674,7 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
+ 	      {
+ 		grub_efi_ipv4_device_path_t *ipv4
+ 		  = (grub_efi_ipv4_device_path_t *) dp;
+-		grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x)",
++		grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x",
+ 			     (unsigned) ipv4->local_ip_address[0],
+ 			     (unsigned) ipv4->local_ip_address[1],
+ 			     (unsigned) ipv4->local_ip_address[2],
+@@ -687,33 +687,60 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
+ 			     (unsigned) ipv4->remote_port,
+ 			     (unsigned) ipv4->protocol,
+ 			     (unsigned) ipv4->static_ip_address);
++		if (len == sizeof (*ipv4))
++		  {
++		    grub_printf (",%u.%u.%u.%u,%u.%u.%u.%u",
++			(unsigned) ipv4->gateway_ip_address[0],
++			(unsigned) ipv4->gateway_ip_address[1],
++			(unsigned) ipv4->gateway_ip_address[2],
++			(unsigned) ipv4->gateway_ip_address[3],
++			(unsigned) ipv4->subnet_mask[0],
++			(unsigned) ipv4->subnet_mask[1],
++			(unsigned) ipv4->subnet_mask[2],
++			(unsigned) ipv4->subnet_mask[3]);
++		  }
++		grub_printf (")");
+ 	      }
+ 	      break;
+ 	    case GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE:
+ 	      {
+ 		grub_efi_ipv6_device_path_t *ipv6
+ 		  = (grub_efi_ipv6_device_path_t *) dp;
+-		grub_printf ("/IPv6(%x:%x:%x:%x:%x:%x:%x:%x,%x:%x:%x:%x:%x:%x:%x:%x,%u,%u,%x,%x)",
+-			     (unsigned) ipv6->local_ip_address[0],
+-			     (unsigned) ipv6->local_ip_address[1],
+-			     (unsigned) ipv6->local_ip_address[2],
+-			     (unsigned) ipv6->local_ip_address[3],
+-			     (unsigned) ipv6->local_ip_address[4],
+-			     (unsigned) ipv6->local_ip_address[5],
+-			     (unsigned) ipv6->local_ip_address[6],
+-			     (unsigned) ipv6->local_ip_address[7],
+-			     (unsigned) ipv6->remote_ip_address[0],
+-			     (unsigned) ipv6->remote_ip_address[1],
+-			     (unsigned) ipv6->remote_ip_address[2],
+-			     (unsigned) ipv6->remote_ip_address[3],
+-			     (unsigned) ipv6->remote_ip_address[4],
+-			     (unsigned) ipv6->remote_ip_address[5],
+-			     (unsigned) ipv6->remote_ip_address[6],
+-			     (unsigned) ipv6->remote_ip_address[7],
++		grub_printf ("/IPv6(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,%u,%u,%x,%x",
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[0]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[1]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[2]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[3]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[4]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[5]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[6]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[7]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[0]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[1]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[2]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[3]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[4]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[5]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[6]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[7]),
+ 			     (unsigned) ipv6->local_port,
+ 			     (unsigned) ipv6->remote_port,
+ 			     (unsigned) ipv6->protocol,
+ 			     (unsigned) ipv6->static_ip_address);
++		if (len == sizeof (*ipv6))
++		  {
++		    grub_printf (",%u,%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
++			(unsigned) ipv6->prefix_length,
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[0]),
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[1]),
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[2]),
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[3]),
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[4]),
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[5]),
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[6]),
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[7]));
++		  }
++		grub_printf (")");
+ 	      }
+ 	      break;
+ 	    case GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE:
+@@ -753,6 +780,39 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
+ 	      dump_vendor_path ("Messaging",
+ 				(grub_efi_vendor_device_path_t *) dp);
+ 	      break;
++	    case GRUB_EFI_URI_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_uri_device_path_t *uri
++		  = (grub_efi_uri_device_path_t *) dp;
++		grub_printf ("/URI(%s)", uri->uri);
++	      }
++	      break;
++	    case GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_dns_device_path_t *dns
++		  = (grub_efi_dns_device_path_t *) dp;
++		if (dns->is_ipv6)
++		  {
++		    grub_printf ("/DNS(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x)",
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[0]) >> 16),
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[0])),
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[1]) >> 16),
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[1])),
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[2]) >> 16),
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[2])),
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[3]) >> 16),
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[3])));
++		  }
++		else
++		  {
++		    grub_printf ("/DNS(%d.%d.%d.%d)",
++			  dns->dns_server_ip[0].v4.addr[0],
++			  dns->dns_server_ip[0].v4.addr[1],
++			  dns->dns_server_ip[0].v4.addr[2],
++			  dns->dns_server_ip[0].v4.addr[3]);
++		  }
++	      }
++	      break;
+ 	    default:
+ 	      grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype);
+ 	      break;
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 25616a9c6c8..3bea6221745 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -28,6 +28,7 @@
+ #include <grub/lib/hexdump.h>
+ #include <grub/types.h>
+ #include <grub/net/netbuff.h>
++#include <grub/env.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -502,6 +503,17 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+ 
+   ldp = grub_efi_find_last_device_path (ddp);
+ 
++  /* Skip the DNS Device */
++  if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
++      && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE)
++    {
++      ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++      ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++      ldp->length = sizeof (*ldp);
++
++      ldp = grub_efi_find_last_device_path (ddp);
++    }
++
+   if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
+       || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
+           && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
+@@ -771,6 +783,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 	if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
+ 	    || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
+ 		&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE
++		&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE
+ 		&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE))
+ 	  continue;
+ 	dup_dp = grub_efi_duplicate_device_path (dp);
+@@ -785,6 +798,15 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 	    dup_ldp->length = sizeof (*dup_ldp);
+ 	  }
+ 
++	dup_ldp = grub_efi_find_last_device_path (dup_dp);
++	if (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE)
++	  {
++	    dup_ldp = grub_efi_find_last_device_path (dup_dp);
++	    dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++	    dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++	    dup_ldp->length = sizeof (*dup_ldp);
++	  }
++
+ 	dup_ldp = grub_efi_find_last_device_path (dup_dp);
+ 	dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+ 	dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+@@ -857,6 +879,9 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 
+ GRUB_MOD_INIT(efinet)
+ {
++  if (grub_efi_net_config)
++    return;
++
+   grub_efinet_findcards ();
+   grub_efi_net_config = grub_efi_net_config_real;
+ }
+@@ -868,5 +893,7 @@ GRUB_MOD_FINI(efinet)
+   FOR_NET_CARDS_SAFE (card, next) 
+     if (card->driver == &efidriver)
+       grub_net_card_unregister (card);
++
++  grub_efi_net_config = NULL;
+ }
+ 
+diff --git a/grub-core/net/efi/dhcp.c b/grub-core/net/efi/dhcp.c
+new file mode 100644
+index 00000000000..dbef63d8c08
+--- /dev/null
++++ b/grub-core/net/efi/dhcp.c
+@@ -0,0 +1,397 @@
++#include <grub/mm.h>
++#include <grub/command.h>
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/misc.h>
++#include <grub/net/efi.h>
++#include <grub/charset.h>
++
++#ifdef GRUB_EFI_NET_DEBUG
++static void
++dhcp4_mode_print (grub_efi_dhcp4_mode_data_t *mode)
++{
++    switch (mode->state)
++      {
++	case GRUB_EFI_DHCP4_STOPPED:
++	  grub_printf ("STATE: STOPPED\n");
++	  break;
++	case GRUB_EFI_DHCP4_INIT:
++	  grub_printf ("STATE: INIT\n");
++	  break;
++	case GRUB_EFI_DHCP4_SELECTING:
++	  grub_printf ("STATE: SELECTING\n");
++	  break;
++	case GRUB_EFI_DHCP4_REQUESTING:
++	  grub_printf ("STATE: REQUESTING\n");
++	  break;
++	case GRUB_EFI_DHCP4_BOUND:
++	  grub_printf ("STATE: BOUND\n");
++	  break;
++	case GRUB_EFI_DHCP4_RENEWING:
++	  grub_printf ("STATE: RENEWING\n");
++	  break;
++	case GRUB_EFI_DHCP4_REBINDING:
++	  grub_printf ("STATE: REBINDING\n");
++	  break;
++	case GRUB_EFI_DHCP4_INIT_REBOOT:
++	  grub_printf ("STATE: INIT_REBOOT\n");
++	  break;
++	case GRUB_EFI_DHCP4_REBOOTING:
++	  grub_printf ("STATE: REBOOTING\n");
++	  break;
++	default:
++	  grub_printf ("STATE: UNKNOWN\n");
++	  break;
++      }
++
++    grub_printf ("CLIENT_ADDRESS: %u.%u.%u.%u\n",
++      mode->client_address[0],
++      mode->client_address[1],
++      mode->client_address[2],
++      mode->client_address[3]);
++    grub_printf ("SERVER_ADDRESS: %u.%u.%u.%u\n",
++      mode->server_address[0],
++      mode->server_address[1],
++      mode->server_address[2],
++      mode->server_address[3]);
++    grub_printf ("SUBNET_MASK: %u.%u.%u.%u\n",
++      mode->subnet_mask[0],
++      mode->subnet_mask[1],
++      mode->subnet_mask[2],
++      mode->subnet_mask[3]);
++    grub_printf ("ROUTER_ADDRESS: %u.%u.%u.%u\n",
++      mode->router_address[0],
++      mode->router_address[1],
++      mode->router_address[2],
++      mode->router_address[3]);
++}
++#endif
++
++static grub_efi_ipv4_address_t *
++grub_efi_dhcp4_parse_dns (grub_efi_dhcp4_protocol_t *dhcp4, grub_efi_dhcp4_packet_t *reply_packet)
++{
++  grub_efi_dhcp4_packet_option_t **option_list;
++  grub_efi_status_t status;
++  grub_efi_uint32_t option_count = 0;
++  grub_efi_uint32_t i;
++
++  status = efi_call_4 (dhcp4->parse, dhcp4, reply_packet, &option_count, NULL);
++
++  if (status != GRUB_EFI_BUFFER_TOO_SMALL)
++    return NULL;
++
++  option_list = grub_malloc (option_count * sizeof(*option_list));
++  if (!option_list)
++    return NULL;
++
++  status = efi_call_4 (dhcp4->parse, dhcp4, reply_packet, &option_count, option_list);
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (option_list);
++      return NULL;
++    }
++
++  for (i = 0; i < option_count; ++i)
++    {
++      if (option_list[i]->op_code == 6)
++	{
++	  grub_efi_ipv4_address_t *dns_address;
++
++	  if (((option_list[i]->length & 0x3) != 0) || (option_list[i]->length == 0))
++	    continue;
++
++	  /* We only contact primary dns */
++	  dns_address = grub_malloc (sizeof (*dns_address));
++	  if (!dns_address)
++	    {
++	      grub_free (option_list);
++	      return NULL;
++	    }
++	  grub_memcpy (dns_address, option_list[i]->data, sizeof (dns_address));
++	  grub_free (option_list);
++	  return dns_address;
++	}
++    }
++
++  grub_free (option_list);
++  return NULL;
++}
++
++#if 0
++/* Somehow this doesn't work ... */
++static grub_err_t
++grub_cmd_efi_bootp (struct grub_command *cmd __attribute__ ((unused)),
++		    int argc __attribute__ ((unused)),
++		    char **args __attribute__ ((unused)))
++{
++  struct grub_efi_net_device *dev;
++  for (dev = net_devices; dev; dev = dev->next)
++    {
++      grub_efi_pxe_t *pxe = dev->ip4_pxe;
++      grub_efi_pxe_mode_t *mode = pxe->mode;
++      grub_efi_status_t status;
++
++      if (!mode->started)
++	{
++	  status = efi_call_2 (pxe->start, pxe, 0);
++
++	  if (status != GRUB_EFI_SUCCESS)
++	      grub_printf ("Couldn't start PXE\n");
++	}
++
++      status = efi_call_2 (pxe->dhcp, pxe, 0);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("dhcp4 configure failed, %d\n", (int)status);
++	  continue;
++	}
++
++      dev->prefer_ip6 = 0;
++    }
++
++  return GRUB_ERR_NONE;
++}
++#endif
++
++static grub_err_t
++grub_cmd_efi_bootp (struct grub_command *cmd __attribute__ ((unused)),
++		    int argc,
++		    char **args)
++{
++  struct grub_efi_net_device *netdev;
++
++  for (netdev = net_devices; netdev; netdev = netdev->next)
++    {
++      grub_efi_status_t status;
++      grub_efi_dhcp4_mode_data_t mode;
++      grub_efi_dhcp4_config_data_t config;
++      grub_efi_dhcp4_packet_option_t *options;
++      grub_efi_ipv4_address_t *dns_address;
++      grub_efi_net_ip_manual_address_t net_ip;
++      grub_efi_net_ip_address_t ip_addr;
++      grub_efi_net_interface_t *inf = NULL;
++
++      if (argc > 0 && grub_strcmp (netdev->card_name, args[0]) != 0)
++	continue;
++
++      grub_memset (&config, 0, sizeof(config));
++
++      config.option_count = 1;
++      options = grub_malloc (sizeof(*options) + 2);
++      /* Parameter request list */
++      options->op_code = 55;
++      options->length = 3;
++      /* subnet mask */
++      options->data[0] = 1;
++      /* router */
++      options->data[1] = 3;
++      /* DNS */
++      options->data[2] = 6;
++      config.option_list = &options;
++
++      /* FIXME: What if the dhcp has bounded */
++      status = efi_call_2 (netdev->dhcp4->configure, netdev->dhcp4, &config);
++      grub_free (options);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("dhcp4 configure failed, %d\n", (int)status);
++	  continue;
++	}
++
++      status = efi_call_2 (netdev->dhcp4->start, netdev->dhcp4, NULL);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("dhcp4 start failed, %d\n", (int)status);
++	  continue;
++	}
++
++      status = efi_call_2 (netdev->dhcp4->get_mode_data, netdev->dhcp4, &mode);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("dhcp4 get mode failed, %d\n", (int)status);
++	  continue;
++	}
++
++#ifdef GRUB_EFI_NET_DEBUG
++      dhcp4_mode_print (&mode);
++#endif
++
++      for (inf = netdev->net_interfaces; inf; inf = inf->next)
++	if (inf->prefer_ip6 == 0)
++	  break;
++
++      grub_memcpy (net_ip.ip4.address, mode.client_address, sizeof (net_ip.ip4.address));
++      grub_memcpy (net_ip.ip4.subnet_mask, mode.subnet_mask, sizeof (net_ip.ip4.subnet_mask));
++
++      if (!inf)
++	{
++	  char *name = grub_xasprintf ("%s:dhcp", netdev->card_name);
++
++	  net_ip.is_ip6 = 0;
++	  inf = grub_efi_net_create_interface (netdev,
++		    name,
++		    &net_ip,
++		    1);
++	  grub_free (name);
++	}
++      else
++	{
++	  efi_net_interface_set_address (inf, &net_ip, 1);
++	}
++
++      grub_memcpy (ip_addr.ip4, mode.router_address, sizeof (ip_addr.ip4));
++      efi_net_interface_set_gateway (inf, &ip_addr);
++
++      dns_address = grub_efi_dhcp4_parse_dns (netdev->dhcp4, mode.reply_packet);
++      if (dns_address)
++	efi_net_interface_set_dns (inf, (grub_efi_net_ip_address_t *)&dns_address);
++
++    }
++
++  return GRUB_ERR_NONE;
++}
++
++
++static grub_err_t
++grub_cmd_efi_bootp6 (struct grub_command *cmd __attribute__ ((unused)),
++		    int argc,
++		    char **args)
++{
++  struct grub_efi_net_device *dev;
++  grub_efi_uint32_t ia_id;
++
++  for (dev = net_devices, ia_id = 0; dev; dev = dev->next, ia_id++)
++    {
++      grub_efi_dhcp6_config_data_t config;
++      grub_efi_dhcp6_packet_option_t *option_list[1];
++      grub_efi_dhcp6_packet_option_t *opt;
++      grub_efi_status_t status;
++      grub_efi_dhcp6_mode_data_t mode;
++      grub_efi_dhcp6_retransmission_t retrans;
++      grub_efi_net_ip_manual_address_t net_ip;
++      grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
++      grub_efi_net_interface_t *inf = NULL;
++
++      if (argc > 0 && grub_strcmp (dev->card_name, args[0]) != 0)
++	continue;
++
++      opt = grub_malloc (sizeof(*opt) + 2 * sizeof (grub_efi_uint16_t));
++
++#define GRUB_EFI_DHCP6_OPT_ORO 6
++
++      opt->op_code = grub_cpu_to_be16_compile_time (GRUB_EFI_DHCP6_OPT_ORO);
++      opt->op_len = grub_cpu_to_be16_compile_time (2 * sizeof (grub_efi_uint16_t));
++
++#define GRUB_EFI_DHCP6_OPT_BOOT_FILE_URL 59
++#define GRUB_EFI_DHCP6_OPT_DNS_SERVERS 23
++
++      grub_set_unaligned16 (opt->data, grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_BOOT_FILE_URL));
++      grub_set_unaligned16 (opt->data + 1 * sizeof (grub_efi_uint16_t),
++	      grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_DNS_SERVERS));
++
++      option_list[0] = opt;
++      retrans.irt = 4;
++      retrans.mrc = 4;
++      retrans.mrt = 32;
++      retrans.mrd = 60;
++
++      config.dhcp6_callback = NULL;
++      config.callback_context = NULL;
++      config.option_count = 1;
++      config.option_list = option_list;
++      config.ia_descriptor.ia_id = ia_id;
++      config.ia_descriptor.type = GRUB_EFI_DHCP6_IA_TYPE_NA;
++      config.ia_info_event = NULL;
++      config.reconfigure_accept = 0;
++      config.rapid_commit = 0;
++      config.solicit_retransmission = &retrans;
++
++      status = efi_call_2 (dev->dhcp6->configure, dev->dhcp6, &config);
++      grub_free (opt);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("dhcp6 configure failed, %d\n", (int)status);
++	  continue;
++	}
++      status = efi_call_1 (dev->dhcp6->start, dev->dhcp6);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("dhcp6 start failed, %d\n", (int)status);
++	  continue;
++	}
++
++      status = efi_call_3 (dev->dhcp6->get_mode_data, dev->dhcp6, &mode, NULL);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("dhcp4 get mode failed, %d\n", (int)status);
++	  continue;
++	}
++
++      for (inf = dev->net_interfaces; inf; inf = inf->next)
++	if (inf->prefer_ip6 == 1)
++	  break;
++
++      grub_memcpy (net_ip.ip6.address, mode.ia->ia_address[0].ip_address, sizeof (net_ip.ip6.address));
++      net_ip.ip6.prefix_length = 64;
++      net_ip.ip6.is_anycast = 0;
++      net_ip.is_ip6 = 1;
++
++      if (!inf)
++	{
++	  char *name = grub_xasprintf ("%s:dhcp", dev->card_name);
++
++	  inf = grub_efi_net_create_interface (dev,
++		    name,
++		    &net_ip,
++		    1);
++	  grub_free (name);
++	}
++      else
++	{
++	  efi_net_interface_set_address (inf, &net_ip, 1);
++	}
++
++      {
++	grub_efi_uint32_t count = 0;
++	grub_efi_dhcp6_packet_option_t **options = NULL;
++	grub_efi_uint32_t i;
++
++	status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, NULL);
++
++	if (status == GRUB_EFI_BUFFER_TOO_SMALL && count)
++	  {
++	    options = grub_malloc (count * sizeof(*options));
++	    status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, options);
++	  }
++
++	if (status != GRUB_EFI_SUCCESS)
++	  {
++	    if (options)
++	      grub_free (options);
++	    continue;
++	  }
++
++	for (i = 0; i < count; ++i)
++	  {
++	    if (options[i]->op_code == grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_DNS_SERVERS))
++	      {
++		grub_efi_net_ip_address_t dns;
++		grub_memcpy (dns.ip6, options[i]->data, sizeof(net_ip.ip6));
++		efi_net_interface_set_dns (inf, &dns);
++		break;
++	      }
++	  }
++
++	if (options)
++	  grub_free (options);
++      }
++
++      efi_call_1 (b->free_pool, mode.client_id);
++      efi_call_1 (b->free_pool, mode.ia);
++    }
++
++  return GRUB_ERR_NONE;
++}
++
++grub_command_func_t grub_efi_net_bootp = grub_cmd_efi_bootp;
++grub_command_func_t grub_efi_net_bootp6 = grub_cmd_efi_bootp6;
+diff --git a/grub-core/net/efi/efi_netfs.c b/grub-core/net/efi/efi_netfs.c
+new file mode 100644
+index 00000000000..ef371d885ea
+--- /dev/null
++++ b/grub-core/net/efi/efi_netfs.c
+@@ -0,0 +1,57 @@
++#include <grub/dl.h>
++#include <grub/env.h>
++#define EFI_NET_CMD_PREFIX "net_efi"
++#include <grub/net/efi.h>
++
++GRUB_MOD_LICENSE ("GPLv3+");
++
++static grub_command_t cmd_efi_lsroutes;
++static grub_command_t cmd_efi_lscards;
++static grub_command_t cmd_efi_lsaddrs;
++static grub_command_t cmd_efi_addaddr;
++static grub_command_t cmd_efi_bootp;
++static grub_command_t cmd_efi_bootp6;
++
++static int initialized;
++
++GRUB_MOD_INIT(efi_netfs)
++{
++  if (grub_net_open)
++    return;
++
++  if (grub_efi_net_fs_init ())
++    {
++      cmd_efi_lsroutes = grub_register_command ("net_efi_ls_routes", grub_efi_net_list_routes,
++					    "", N_("list network routes"));
++      cmd_efi_lscards = grub_register_command ("net_efi_ls_cards", grub_efi_net_list_cards,
++					   "", N_("list network cards"));
++      cmd_efi_lsaddrs = grub_register_command ("net_efi_ls_addr", grub_efi_net_list_addrs,
++					  "", N_("list network addresses"));
++      cmd_efi_addaddr = grub_register_command ("net_efi_add_addr", grub_efi_net_add_addr,
++					  N_("SHORTNAME CARD ADDRESS [HWADDRESS]"),
++					  N_("Add a network address."));
++      cmd_efi_bootp = grub_register_command ("net_efi_bootp", grub_efi_net_bootp,
++					 N_("[CARD]"),
++					 N_("perform a bootp autoconfiguration"));
++      cmd_efi_bootp6 = grub_register_command ("net_efi_bootp6", grub_efi_net_bootp6,
++					 N_("[CARD]"),
++					 N_("perform a bootp autoconfiguration"));
++      initialized = 1;
++    }
++}
++
++GRUB_MOD_FINI(efi_netfs)
++{
++  if (initialized)
++    {
++      grub_unregister_command (cmd_efi_lsroutes);
++      grub_unregister_command (cmd_efi_lscards);
++      grub_unregister_command (cmd_efi_lsaddrs);
++      grub_unregister_command (cmd_efi_addaddr);
++      grub_unregister_command (cmd_efi_bootp);
++      grub_unregister_command (cmd_efi_bootp6);
++      grub_efi_net_fs_fini ();
++      initialized = 0;
++      return;
++    }
++}
+diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c
+new file mode 100644
+index 00000000000..3f61fd2fa5b
+--- /dev/null
++++ b/grub-core/net/efi/http.c
+@@ -0,0 +1,419 @@
++
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/misc.h>
++#include <grub/net/efi.h>
++#include <grub/charset.h>
++
++static void
++http_configure (struct grub_efi_net_device *dev, int prefer_ip6)
++{
++  grub_efi_http_config_data_t http_config;
++  grub_efi_httpv4_access_point_t httpv4_node;
++  grub_efi_httpv6_access_point_t httpv6_node;
++  grub_efi_status_t status;
++
++  grub_efi_http_t *http = dev->http;
++
++  grub_memset (&http_config, 0, sizeof(http_config));
++  http_config.http_version = GRUB_EFI_HTTPVERSION11;
++  http_config.timeout_millisec = 5000;
++
++  if (prefer_ip6)
++    {
++      grub_efi_uintn_t sz;
++      grub_efi_ip6_config_manual_address_t manual_address;
++
++      http_config.local_address_is_ipv6 = 1;
++      sz = sizeof (manual_address);
++      status = efi_call_4 (dev->ip6_config->get_data, dev->ip6_config,
++			GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS,
++			&sz, &manual_address);
++
++      if (status == GRUB_EFI_NOT_FOUND)
++	{
++	  grub_printf ("The MANUAL ADDRESS is not found\n");
++	}
++
++      /* FIXME: The manual interface would return BUFFER TOO SMALL !!! */
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("??? %d\n",(int) status);
++	  return;
++	}
++
++      grub_memcpy (httpv6_node.local_address, manual_address.address, sizeof (httpv6_node.local_address));
++      httpv6_node.local_port = 0;
++      http_config.access_point.ipv6_node = &httpv6_node;
++    }
++  else
++    {
++      http_config.local_address_is_ipv6 = 0;
++      grub_memset (&httpv4_node, 0, sizeof(httpv4_node));
++      httpv4_node.use_default_address = 1;
++
++      /* Use random port here */
++      /* See TcpBind() in edk2/NetworkPkg/TcpDxe/TcpDispatcher.c */
++      httpv4_node.local_port = 0;
++      http_config.access_point.ipv4_node = &httpv4_node;
++    }
++
++  status = efi_call_2 (http->configure, http, &http_config);
++
++  if (status == GRUB_EFI_ALREADY_STARTED)
++    {
++      /* XXX: This hangs HTTPS boot */
++#if 0
++      if (efi_call_2 (http->configure, http, NULL) != GRUB_EFI_SUCCESS)
++	{
++	  grub_error (GRUB_ERR_IO, N_("couldn't reset http instance"));
++	  grub_print_error ();
++	  return;
++	}
++      status = efi_call_2 (http->configure, http, &http_config);
++#endif
++      return;
++    }
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_error (GRUB_ERR_IO, N_("couldn't configure http protocol, reason: %d"), (int)status);
++      grub_print_error ();
++      return ;
++    }
++}
++
++static grub_efi_boolean_t request_callback_done;
++static grub_efi_boolean_t response_callback_done;
++
++static void
++grub_efi_http_request_callback (grub_efi_event_t event __attribute__ ((unused)),
++				void *context __attribute__ ((unused)))
++{
++  request_callback_done = 1;
++}
++
++static void
++grub_efi_http_response_callback (grub_efi_event_t event __attribute__ ((unused)),
++				void *context __attribute__ ((unused)))
++{
++  response_callback_done = 1;
++}
++
++static grub_err_t
++efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, int headeronly, grub_off_t *file_size)
++{
++  grub_efi_http_request_data_t request_data;
++  grub_efi_http_message_t request_message;
++  grub_efi_http_token_t request_token;
++  grub_efi_http_response_data_t response_data;
++  grub_efi_http_message_t response_message;
++  grub_efi_http_token_t response_token;
++  grub_efi_http_header_t request_headers[3];
++
++  grub_efi_status_t status;
++  grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
++  char *url = NULL;
++
++  request_headers[0].field_name = (grub_efi_char8_t *)"Host";
++  request_headers[0].field_value = (grub_efi_char8_t *)server;
++  request_headers[1].field_name = (grub_efi_char8_t *)"Accept";
++  request_headers[1].field_value = (grub_efi_char8_t *)"*/*";
++  request_headers[2].field_name = (grub_efi_char8_t *)"User-Agent";
++  request_headers[2].field_value = (grub_efi_char8_t *)"UefiHttpBoot/1.0";
++
++  {
++    grub_efi_ipv6_address_t address;
++    const char *rest;
++    grub_efi_char16_t *ucs2_url;
++    grub_size_t url_len, ucs2_url_len;
++    const char *protocol = (use_https == 1) ? "https" : "http";
++
++    if (grub_efi_string_to_ip6_address (server, &address, &rest) && *rest == 0)
++      url = grub_xasprintf ("%s://[%s]%s", protocol, server, name);
++    else
++      url = grub_xasprintf ("%s://%s%s", protocol, server, name);
++
++    if (!url)
++      {
++	return grub_errno;
++      }
++
++    url_len = grub_strlen (url);
++    ucs2_url_len = url_len * GRUB_MAX_UTF16_PER_UTF8;
++    ucs2_url = grub_malloc ((ucs2_url_len + 1) * sizeof (ucs2_url[0]));
++
++    if (!ucs2_url)
++      {
++	grub_free (url);
++	return grub_errno;
++      }
++
++    ucs2_url_len = grub_utf8_to_utf16 (ucs2_url, ucs2_url_len, (grub_uint8_t *)url, url_len, NULL); /* convert string format from ascii to usc2 */
++    ucs2_url[ucs2_url_len] = 0;
++    grub_free (url);
++    request_data.url = ucs2_url;
++  }
++
++  request_data.method = (headeronly > 0) ? GRUB_EFI_HTTPMETHODHEAD : GRUB_EFI_HTTPMETHODGET;
++
++  request_message.data.request = &request_data;
++  request_message.header_count = 3;
++  request_message.headers = request_headers;
++  request_message.body_length = 0;
++  request_message.body = NULL;
++
++  /* request token */
++  request_token.event = NULL;
++  request_token.status = GRUB_EFI_NOT_READY;
++  request_token.message = &request_message;
++
++  request_callback_done = 0;
++  status = efi_call_5 (b->create_event,
++                       GRUB_EFI_EVT_NOTIFY_SIGNAL,
++                       GRUB_EFI_TPL_CALLBACK,
++                       grub_efi_http_request_callback,
++                       NULL,
++                       &request_token.event);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (request_data.url);
++      return grub_error (GRUB_ERR_IO, "Fail to create an event! status=0x%x\n", status);
++    }
++
++  status = efi_call_2 (http->request, http, &request_token);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      efi_call_1 (b->close_event, request_token.event);
++      grub_free (request_data.url);
++      return grub_error (GRUB_ERR_IO, "Fail to send a request! status=0x%x\n", status);
++    }
++  /* TODO: Add Timeout */
++  while (!request_callback_done)
++    efi_call_1(http->poll, http);
++
++  response_data.status_code = GRUB_EFI_HTTP_STATUS_UNSUPPORTED_STATUS;
++  response_message.data.response = &response_data;
++  /* herader_count will be updated by the HTTP driver on response */
++  response_message.header_count = 0;
++  /* headers will be populated by the driver on response */
++  response_message.headers = NULL;
++  /* use zero BodyLength to only receive the response headers */
++  response_message.body_length = 0;
++  response_message.body = NULL;
++  response_token.event = NULL;
++
++  status = efi_call_5 (b->create_event,
++              GRUB_EFI_EVT_NOTIFY_SIGNAL,
++              GRUB_EFI_TPL_CALLBACK,
++              grub_efi_http_response_callback,
++              NULL,
++              &response_token.event);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      efi_call_1 (b->close_event, request_token.event);
++      grub_free (request_data.url);
++      return grub_error (GRUB_ERR_IO, "Fail to create an event! status=0x%x\n", status);
++    }
++
++  response_token.status = GRUB_EFI_SUCCESS;
++  response_token.message = &response_message;
++
++  /* wait for HTTP response */
++  response_callback_done = 0;
++  status = efi_call_2 (http->response, http, &response_token);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      efi_call_1 (b->close_event, response_token.event);
++      efi_call_1 (b->close_event, request_token.event);
++      grub_free (request_data.url);
++      return grub_error (GRUB_ERR_IO, "Fail to receive a response! status=%d\n", (int)status);
++    }
++
++  /* TODO: Add Timeout */
++  while (!response_callback_done)
++    efi_call_1 (http->poll, http);
++
++  if (response_message.data.response->status_code != GRUB_EFI_HTTP_STATUS_200_OK)
++    {
++      grub_efi_http_status_code_t status_code = response_message.data.response->status_code;
++
++      if (response_message.headers)
++	efi_call_1 (b->free_pool, response_message.headers);
++      efi_call_1 (b->close_event, response_token.event);
++      efi_call_1 (b->close_event, request_token.event);
++      grub_free (request_data.url);
++      if (status_code == GRUB_EFI_HTTP_STATUS_404_NOT_FOUND)
++	{
++	  return grub_error (GRUB_ERR_FILE_NOT_FOUND, _("file `%s' not found"), name);
++	}
++      else
++	{
++	  return grub_error (GRUB_ERR_NET_UNKNOWN_ERROR,
++		  _("unsupported uefi http status code 0x%x"), status_code);
++	}
++    }
++
++  if (file_size)
++    {
++      int i;
++      /* parse the length of the file from the ContentLength header */
++      for (*file_size = 0, i = 0; i < (int)response_message.header_count; ++i)
++	{
++	  if (!grub_strcmp((const char*)response_message.headers[i].field_name, "Content-Length"))
++	    {
++	      *file_size = grub_strtoul((const char*)response_message.headers[i].field_value, 0, 10);
++	      break;
++	    }
++	}
++    }
++
++  if (response_message.headers)
++    efi_call_1 (b->free_pool, response_message.headers);
++  efi_call_1 (b->close_event, response_token.event);
++  efi_call_1 (b->close_event, request_token.event);
++  grub_free (request_data.url);
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_ssize_t
++efihttp_read (struct grub_efi_net_device *dev,
++		  char *buf,
++		  grub_size_t len)
++{
++  grub_efi_http_message_t response_message;
++  grub_efi_http_token_t response_token;
++
++  grub_efi_status_t status;
++  grub_size_t sum = 0;
++  grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
++  grub_efi_http_t *http = dev->http;
++
++  if (!len)
++    {
++      grub_error (GRUB_ERR_BUG, "Invalid arguments to EFI HTTP Read");
++      return -1;
++    }
++
++  efi_call_5 (b->create_event,
++              GRUB_EFI_EVT_NOTIFY_SIGNAL,
++              GRUB_EFI_TPL_CALLBACK,
++              grub_efi_http_response_callback,
++              NULL,
++              &response_token.event);
++
++  while (len)
++    {
++      response_message.data.response = NULL;
++      response_message.header_count = 0;
++      response_message.headers = NULL;
++      response_message.body_length = len;
++      response_message.body = buf;
++
++      response_token.message = &response_message;
++      response_token.status = GRUB_EFI_NOT_READY;
++
++      response_callback_done = 0;
++
++      status = efi_call_2 (http->response, http, &response_token);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  efi_call_1 (b->close_event, response_token.event);
++	  grub_error (GRUB_ERR_IO, "Error! status=%d\n", (int)status);
++	  return -1;
++	}
++
++      while (!response_callback_done)
++	efi_call_1(http->poll, http);
++
++      sum += response_message.body_length;
++      buf += response_message.body_length;
++      len -= response_message.body_length;
++    }
++
++  efi_call_1 (b->close_event, response_token.event);
++
++  return sum;
++}
++
++static grub_err_t
++grub_efihttp_open (struct grub_efi_net_device *dev,
++		  int prefer_ip6 __attribute__ ((unused)),
++		  grub_file_t file,
++		  const char *filename __attribute__ ((unused)),
++		  int type)
++{
++  grub_err_t err;
++  grub_off_t size;
++  char *buf;
++
++  err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 1, 0);
++  if (err != GRUB_ERR_NONE)
++    return err;
++
++  err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 0, &size);
++  if (err != GRUB_ERR_NONE)
++    return err;
++
++  buf = grub_malloc (size);
++  efihttp_read (dev, buf, size);
++
++  file->size = size;
++  file->data = buf;
++  file->not_easily_seekable = 0;
++  file->device->net->offset = 0;
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_efihttp_close (struct grub_efi_net_device *dev __attribute__ ((unused)),
++		    int prefer_ip6 __attribute__ ((unused)),
++		    grub_file_t file)
++{
++  if (file->data)
++    grub_free (file->data);
++
++  file->data = 0;
++  file->offset = 0;
++  file->size = 0;
++  file->device->net->offset = 0;
++  return GRUB_ERR_NONE;
++}
++
++static grub_ssize_t
++grub_efihttp_read (struct grub_efi_net_device *dev __attribute__((unused)),
++		  int prefer_ip6 __attribute__((unused)),
++		  grub_file_t file,
++		  char *buf,
++		  grub_size_t len)
++{
++  grub_size_t r = len;
++
++  if (!file->data || !buf || !len)
++    return 0;
++
++  if ((file->device->net->offset + len) > file->size)
++    r = file->size - file->device->net->offset;
++
++  if (r)
++    {
++      grub_memcpy (buf, (char *)file->data + file->device->net->offset, r);
++      file->device->net->offset += r;
++    }
++
++  return r;
++}
++
++struct grub_efi_net_io io_http =
++  {
++    .configure = http_configure,
++    .open = grub_efihttp_open,
++    .read = grub_efihttp_read,
++    .close = grub_efihttp_close
++  };
+diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c
+new file mode 100644
+index 00000000000..b711a5d9457
+--- /dev/null
++++ b/grub-core/net/efi/ip4_config.c
+@@ -0,0 +1,398 @@
++
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/misc.h>
++#include <grub/net/efi.h>
++#include <grub/charset.h>
++
++char *
++grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address)
++{
++  char *hw_addr, *p;
++  int sz, s;
++  int i;
++
++  sz = (int)hw_address_size * (sizeof ("XX:") - 1) + 1;
++
++  hw_addr = grub_malloc (sz);
++  if (!hw_addr)
++    return NULL;
++
++  p = hw_addr;
++  s = sz;
++  for (i = 0; i < (int)hw_address_size; i++)
++    {
++      grub_snprintf (p, sz, "%02x:", hw_address[i]);
++      p +=  sizeof ("XX:") - 1;
++      s -=  sizeof ("XX:") - 1;
++    }
++
++  hw_addr[sz - 2] = '\0';
++  return hw_addr;
++}
++
++char *
++grub_efi_ip4_address_to_string (grub_efi_ipv4_address_t *address)
++{
++  char *addr;
++
++  addr = grub_malloc (sizeof ("XXX.XXX.XXX.XXX"));
++  if (!addr)
++      return NULL;
++
++  /* FIXME: Use grub_xasprintf ? */
++  grub_snprintf (addr,
++	  sizeof ("XXX.XXX.XXX.XXX"),
++	  "%u.%u.%u.%u",
++	  (*address)[0],
++	  (*address)[1],
++	  (*address)[2],
++	  (*address)[3]);
++
++  return addr;
++}
++
++int
++grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest)
++{
++  grub_uint32_t newip = 0;
++  int i;
++  const char *ptr = val;
++
++  for (i = 0; i < 4; i++)
++    {
++      unsigned long t;
++      t = grub_strtoul (ptr, (char **) &ptr, 0);
++      if (grub_errno)
++	{
++	  grub_errno = GRUB_ERR_NONE;
++	  return 0;
++	}
++      if (*ptr != '.' && i == 0)
++	{
++	  /* XXX: t is in host byte order */
++	  newip = t;
++	  break;
++	}
++      if (t & ~0xff)
++	return 0;
++      newip <<= 8;
++      newip |= t;
++      if (i != 3 && *ptr != '.')
++	return 0;
++      ptr++;
++    }
++
++  newip =  grub_cpu_to_be32 (newip);
++
++  grub_memcpy (address, &newip, sizeof(*address));
++
++  if (rest)
++    *rest = (ptr - 1);
++  return 1;
++}
++
++static grub_efi_ip4_config2_interface_info_t *
++efi_ip4_config_interface_info (grub_efi_ip4_config2_protocol_t *ip4_config)
++{
++  grub_efi_uintn_t sz;
++  grub_efi_status_t status;
++  grub_efi_ip4_config2_interface_info_t *interface_info;
++
++  sz = sizeof (*interface_info) + sizeof (*interface_info->route_table);
++  interface_info = grub_malloc (sz);
++  if (!interface_info)
++    return NULL;
++
++  status = efi_call_4 (ip4_config->get_data, ip4_config,
++		GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO,
++		&sz, interface_info);
++
++  if (status == GRUB_EFI_BUFFER_TOO_SMALL)
++    {
++      grub_free (interface_info);
++      interface_info = grub_malloc (sz);
++      status = efi_call_4 (ip4_config->get_data, ip4_config,
++		    GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO,
++		    &sz, interface_info);
++    }
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (interface_info);
++      return NULL;
++    }
++
++  return interface_info;
++}
++
++static grub_efi_ip4_config2_manual_address_t *
++efi_ip4_config_manual_address (grub_efi_ip4_config2_protocol_t *ip4_config)
++{
++  grub_efi_uintn_t sz;
++  grub_efi_status_t status;
++  grub_efi_ip4_config2_manual_address_t *manual_address;
++
++  sz = sizeof (*manual_address);
++  manual_address = grub_malloc (sz);
++  if (!manual_address)
++    return NULL;
++
++  status = efi_call_4 (ip4_config->get_data, ip4_config,
++		    GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
++		    &sz, manual_address);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (manual_address);
++      return NULL;
++    }
++
++  return manual_address;
++}
++
++char *
++grub_efi_ip4_interface_name (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip4_config2_interface_info_t *interface_info;
++  char *name;
++
++  interface_info = efi_ip4_config_interface_info (dev->ip4_config);
++
++  if (!interface_info)
++    return NULL;
++
++  name = grub_malloc (GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE
++		      * GRUB_MAX_UTF8_PER_UTF16 + 1);
++  *grub_utf16_to_utf8 ((grub_uint8_t *)name, interface_info->name,
++		      GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE) = 0;
++  grub_free (interface_info);
++  return name;
++}
++
++static char *
++grub_efi_ip4_interface_hw_address (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip4_config2_interface_info_t *interface_info;
++  char *hw_addr;
++
++  interface_info = efi_ip4_config_interface_info (dev->ip4_config);
++
++  if (!interface_info)
++    return NULL;
++
++  hw_addr = grub_efi_hw_address_to_string (interface_info->hw_address_size, interface_info->hw_address);
++  grub_free (interface_info);
++
++  return hw_addr;
++}
++
++static char *
++grub_efi_ip4_interface_address (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip4_config2_manual_address_t *manual_address;
++  char *addr;
++
++  manual_address = efi_ip4_config_manual_address (dev->ip4_config);
++
++  if (!manual_address)
++    return NULL;
++
++  addr = grub_efi_ip4_address_to_string (&manual_address->address);
++  grub_free (manual_address);
++  return addr;
++}
++
++
++static int
++address_mask_size (grub_efi_ipv4_address_t *address)
++{
++  grub_uint8_t i;
++  grub_uint32_t u32_addr = grub_be_to_cpu32 (grub_get_unaligned32 (address));
++
++  if (u32_addr == 0)
++    return 0;
++
++  for (i = 0; i < 32 ; ++i)
++    {
++      if (u32_addr == ((0xffffffff >> i) << i))
++	return (32 - i);
++    }
++
++  return -1;
++}
++
++static char **
++grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip4_config2_interface_info_t *interface_info;
++  char **ret;
++  int i, id;
++
++  interface_info = efi_ip4_config_interface_info (dev->ip4_config);
++  if (!interface_info)
++    return NULL;
++
++  ret = grub_malloc (sizeof (*ret) * (interface_info->route_table_size + 1));
++
++  if (!ret)
++    {
++      grub_free (interface_info);
++      return NULL;
++    }
++
++  id = 0;
++  for (i = 0; i < (int)interface_info->route_table_size; i++)
++    {
++      char *subnet, *gateway, *mask;
++      grub_uint32_t u32_subnet, u32_gateway;
++      int mask_size;
++      grub_efi_ip4_route_table_t *route_table = interface_info->route_table + i;
++      grub_efi_net_interface_t *inf;
++      char *interface_name = NULL;
++
++      for (inf = dev->net_interfaces; inf; inf = inf->next)
++	if (!inf->prefer_ip6)
++	  interface_name = inf->name;
++
++      u32_gateway = grub_get_unaligned32 (&route_table->gateway_address);
++      gateway = grub_efi_ip4_address_to_string (&route_table->gateway_address);
++      u32_subnet = grub_get_unaligned32 (&route_table->subnet_address);
++      subnet = grub_efi_ip4_address_to_string (&route_table->subnet_address);
++      mask_size = address_mask_size (&route_table->subnet_mask);
++      mask = grub_efi_ip4_address_to_string (&route_table->subnet_mask);
++      if (u32_subnet && !u32_gateway && interface_name)
++	ret[id++] = grub_xasprintf ("%s:local %s/%d %s", dev->card_name, subnet, mask_size, interface_name);
++      else if (u32_subnet && u32_gateway)
++	ret[id++] = grub_xasprintf ("%s:gw %s/%d gw %s", dev->card_name, subnet, mask_size, gateway);
++      else if (!u32_subnet && u32_gateway)
++	ret[id++] = grub_xasprintf ("%s:default %s/%d gw %s", dev->card_name, subnet, mask_size, gateway);
++      grub_free (subnet);
++      grub_free (gateway);
++      grub_free (mask);
++    }
++
++  ret[id] = NULL;
++  grub_free (interface_info);
++  return ret;
++}
++
++static grub_efi_net_interface_t *
++grub_efi_ip4_interface_match (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *ip_address)
++{
++  grub_efi_ip4_config2_interface_info_t *interface_info;
++  grub_efi_net_interface_t *inf;
++  int i;
++  grub_efi_ipv4_address_t *address = &ip_address->ip4;
++
++  interface_info = efi_ip4_config_interface_info (dev->ip4_config);
++  if (!interface_info)
++    return NULL;
++
++  for (i = 0; i < (int)interface_info->route_table_size; i++)
++    {
++      grub_efi_ip4_route_table_t *route_table = interface_info->route_table + i;
++      grub_uint32_t u32_address, u32_mask, u32_subnet;
++
++      u32_address = grub_get_unaligned32 (address);
++      u32_subnet = grub_get_unaligned32 (route_table->subnet_address);
++      u32_mask = grub_get_unaligned32 (route_table->subnet_mask);
++
++      /* SKIP Default GATEWAY */
++      if (!u32_subnet && !u32_mask)
++	continue;
++
++      if ((u32_address & u32_mask) == u32_subnet)
++	{
++	  for (inf = dev->net_interfaces; inf; inf = inf->next)
++	    if (!inf->prefer_ip6)
++	      {
++		grub_free (interface_info);
++		return inf;
++	      }
++	}
++    }
++
++  grub_free (interface_info);
++  return NULL;
++}
++
++static int
++grub_efi_ip4_interface_set_manual_address (struct grub_efi_net_device *dev,
++	    grub_efi_net_ip_manual_address_t *net_ip,
++	    int with_subnet)
++{
++  grub_efi_status_t status;
++  grub_efi_ip4_config2_manual_address_t *address = &net_ip->ip4;
++
++  if (!with_subnet)
++    {
++      grub_efi_ip4_config2_manual_address_t *manual_address =
++      efi_ip4_config_manual_address (dev->ip4_config);
++
++      if (manual_address)
++	{
++	  grub_memcpy (address->subnet_mask, manual_address->subnet_mask, sizeof(address->subnet_mask));
++	  grub_free (manual_address);
++	}
++      else
++	{
++	  /* XXX: */
++	  address->subnet_mask[0] = 0xff;
++	  address->subnet_mask[1] = 0xff;
++	  address->subnet_mask[2] = 0xff;
++	  address->subnet_mask[3] = 0;
++	}
++    }
++
++  status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config,
++		    GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
++		    sizeof(*address), address);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++
++  return 1;
++}
++
++static int
++grub_efi_ip4_interface_set_gateway (struct grub_efi_net_device *dev,
++	      grub_efi_net_ip_address_t *address)
++{
++  grub_efi_status_t status;
++
++  status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config,
++		GRUB_EFI_IP4_CONFIG2_DATA_TYPE_GATEWAY,
++		sizeof (address->ip4), &address->ip4);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++  return 1;
++}
++
++/* FIXME: Multiple DNS */
++static int
++grub_efi_ip4_interface_set_dns (struct grub_efi_net_device *dev,
++	      grub_efi_net_ip_address_t *address)
++{
++  grub_efi_status_t status;
++
++  status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config,
++		GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
++		sizeof (address->ip4), &address->ip4);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++  return 1;
++}
++
++grub_efi_net_ip_config_t *efi_net_ip4_config = &(grub_efi_net_ip_config_t)
++  {
++    .get_hw_address = grub_efi_ip4_interface_hw_address,
++    .get_address = grub_efi_ip4_interface_address,
++    .get_route_table = grub_efi_ip4_interface_route_table,
++    .best_interface = grub_efi_ip4_interface_match,
++    .set_address = grub_efi_ip4_interface_set_manual_address,
++    .set_gateway = grub_efi_ip4_interface_set_gateway,
++    .set_dns = grub_efi_ip4_interface_set_dns
++  };
+diff --git a/grub-core/net/efi/ip6_config.c b/grub-core/net/efi/ip6_config.c
+new file mode 100644
+index 00000000000..017c4d05bc7
+--- /dev/null
++++ b/grub-core/net/efi/ip6_config.c
+@@ -0,0 +1,422 @@
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/misc.h>
++#include <grub/net/efi.h>
++#include <grub/charset.h>
++
++char *
++grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address)
++{
++  char *str = grub_malloc (sizeof ("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX"));
++  char *p;
++  int i;
++  int squash;
++
++  if (!str)
++    return NULL;
++
++  p = str;
++  squash = 0;
++  for (i = 0; i < 8; ++i)
++    {
++      grub_uint16_t addr;
++
++      if (i == 7)
++	squash = 2;
++
++      addr = grub_get_unaligned16 (address->addr + i * 2);
++
++      if (grub_be_to_cpu16 (addr))
++	{
++	  char buf[sizeof ("XXXX")];
++	  if (i > 0)
++	    *p++ = ':';
++	  grub_snprintf (buf, sizeof (buf), "%x", grub_be_to_cpu16 (addr));
++	  grub_strcpy (p, buf);
++	  p += grub_strlen (buf);
++
++	  if (squash == 1)
++	    squash = 2;
++	}
++      else
++	{
++	  if (squash == 0)
++	    {
++	      *p++ = ':';
++	      squash = 1;
++	    }
++	  else if (squash == 2)
++	    {
++	      *p++ = ':';
++	      *p++ = '0';
++	    }
++	}
++    }
++  *p = '\0';
++  return str;
++}
++
++int
++grub_efi_string_to_ip6_address (const char *val, grub_efi_ipv6_address_t *address, const char **rest)
++{
++  grub_uint16_t newip[8];
++  const char *ptr = val;
++  int word, quaddot = -1;
++  int bracketed = 0;
++
++  if (ptr[0] == '[') {
++    bracketed = 1;
++    ptr++;
++  }
++
++  if (ptr[0] == ':' && ptr[1] != ':')
++    return 0;
++  if (ptr[0] == ':')
++    ptr++;
++
++  for (word = 0; word < 8; word++)
++    {
++      unsigned long t;
++      if (*ptr == ':')
++	{
++	  quaddot = word;
++	  word--;
++	  ptr++;
++	  continue;
++	}
++      t = grub_strtoul (ptr, (char **) &ptr, 16);
++      if (grub_errno)
++	{
++	  grub_errno = GRUB_ERR_NONE;
++	  break;
++	}
++      if (t & ~0xffff)
++	return 0;
++      newip[word] = grub_cpu_to_be16 (t);
++      if (*ptr != ':')
++	break;
++      ptr++;
++    }
++  if (quaddot == -1 && word < 7)
++    return 0;
++  if (quaddot != -1)
++    {
++      grub_memmove (&newip[quaddot + 7 - word], &newip[quaddot],
++		    (word - quaddot + 1) * sizeof (newip[0]));
++      grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0]));
++    }
++  grub_memcpy (address, newip, 16);
++  if (bracketed && *ptr == ']') {
++    ptr++;
++  }
++  if (rest)
++    *rest = ptr;
++  return 1;
++}
++
++static grub_efi_ip6_config_interface_info_t *
++efi_ip6_config_interface_info (grub_efi_ip6_config_protocol_t *ip6_config)
++{
++  grub_efi_uintn_t sz;
++  grub_efi_status_t status;
++  grub_efi_ip6_config_interface_info_t *interface_info;
++
++  sz = sizeof (*interface_info) + sizeof (*interface_info->route_table);
++  interface_info = grub_malloc (sz);
++
++  status = efi_call_4 (ip6_config->get_data, ip6_config,
++		GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO,
++		&sz, interface_info);
++
++  if (status == GRUB_EFI_BUFFER_TOO_SMALL)
++    {
++      grub_free (interface_info);
++      interface_info = grub_malloc (sz);
++      status = efi_call_4 (ip6_config->get_data, ip6_config,
++		    GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO,
++		    &sz, interface_info);
++    }
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (interface_info);
++      return NULL;
++    }
++
++  return interface_info;
++}
++
++static grub_efi_ip6_config_manual_address_t *
++efi_ip6_config_manual_address (grub_efi_ip6_config_protocol_t *ip6_config)
++{
++  grub_efi_uintn_t sz;
++  grub_efi_status_t status;
++  grub_efi_ip6_config_manual_address_t *manual_address;
++
++  sz = sizeof (*manual_address);
++  manual_address = grub_malloc (sz);
++  if (!manual_address)
++    return NULL;
++
++  status = efi_call_4 (ip6_config->get_data, ip6_config,
++		    GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS,
++		    &sz, manual_address);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (manual_address);
++      return NULL;
++    }
++
++  return manual_address;
++}
++
++char *
++grub_efi_ip6_interface_name (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip6_config_interface_info_t *interface_info;
++  char *name;
++
++  interface_info = efi_ip6_config_interface_info (dev->ip6_config);
++
++  if (!interface_info)
++    return NULL;
++
++  name = grub_malloc (GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE
++		      * GRUB_MAX_UTF8_PER_UTF16 + 1);
++  *grub_utf16_to_utf8 ((grub_uint8_t *)name, interface_info->name,
++		      GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE) = 0;
++  grub_free (interface_info);
++  return name;
++}
++
++static char *
++grub_efi_ip6_interface_hw_address (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip6_config_interface_info_t *interface_info;
++  char *hw_addr;
++
++  interface_info = efi_ip6_config_interface_info (dev->ip6_config);
++
++  if (!interface_info)
++    return NULL;
++
++  hw_addr = grub_efi_hw_address_to_string (interface_info->hw_address_size, interface_info->hw_address);
++  grub_free (interface_info);
++
++  return hw_addr;
++}
++
++static char *
++grub_efi_ip6_interface_address (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip6_config_manual_address_t *manual_address;
++  char *addr;
++
++  manual_address = efi_ip6_config_manual_address (dev->ip6_config);
++
++  if (!manual_address)
++    return NULL;
++
++  addr = grub_efi_ip6_address_to_string ((grub_efi_pxe_ipv6_address_t *)&manual_address->address);
++  grub_free (manual_address);
++  return addr;
++}
++
++static char **
++grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip6_config_interface_info_t *interface_info;
++  char **ret;
++  int i, id;
++
++  interface_info = efi_ip6_config_interface_info (dev->ip6_config);
++  if (!interface_info)
++    return NULL;
++
++  ret = grub_malloc (sizeof (*ret) * (interface_info->route_count + 1));
++
++  if (!ret)
++    {
++      grub_free (interface_info);
++      return NULL;
++    }
++
++  id = 0;
++  for (i = 0; i < (int)interface_info->route_count ; i++)
++    {
++      char *gateway, *destination;
++      grub_uint64_t u64_gateway[2];
++      grub_uint64_t u64_destination[2];
++      grub_efi_ip6_route_table_t *route_table = interface_info->route_table + i;
++      grub_efi_net_interface_t *inf;
++      char *interface_name = NULL;
++
++      gateway = grub_efi_ip6_address_to_string (&route_table->gateway);
++      destination = grub_efi_ip6_address_to_string (&route_table->destination);
++
++      u64_gateway[0] = grub_get_unaligned64 (route_table->gateway.addr);
++      u64_gateway[1] = grub_get_unaligned64 (route_table->gateway.addr + 8);
++      u64_destination[0] = grub_get_unaligned64 (route_table->destination.addr);
++      u64_destination[1] = grub_get_unaligned64 (route_table->destination.addr + 8);
++
++      for (inf = dev->net_interfaces; inf; inf = inf->next)
++	if (inf->prefer_ip6)
++	  interface_name = inf->name;
++
++      if ((!u64_gateway[0] && !u64_gateway[1])
++	  && (u64_destination[0] || u64_destination[1]))
++	{
++	  if (interface_name)
++	    {
++	      if ((grub_be_to_cpu64 (u64_destination[0]) == 0xfe80000000000000ULL)
++	      && (!u64_destination[1])
++	      && (route_table->prefix_length == 64))
++		ret[id++] = grub_xasprintf ("%s:link %s/%d %s", dev->card_name, destination, route_table->prefix_length, interface_name);
++	      else
++		ret[id++] = grub_xasprintf ("%s:local %s/%d %s", dev->card_name, destination, route_table->prefix_length, interface_name);
++	    }
++	}
++      else if ((u64_gateway[0] || u64_gateway[1])
++	  && (u64_destination[0] || u64_destination[1]))
++	ret[id++] = grub_xasprintf ("%s:gw %s/%d gw %s", dev->card_name, destination, route_table->prefix_length, gateway);
++      else if ((u64_gateway[0] || u64_gateway[1])
++	  && (!u64_destination[0] && !u64_destination[1]))
++	ret[id++] = grub_xasprintf ("%s:default %s/%d gw %s", dev->card_name, destination, route_table->prefix_length, gateway);
++
++      grub_free (gateway);
++      grub_free (destination);
++    }
++
++  ret[id] = NULL;
++  grub_free (interface_info);
++  return ret;
++}
++
++static grub_efi_net_interface_t *
++grub_efi_ip6_interface_match (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *ip_address)
++{
++  grub_efi_ip6_config_interface_info_t *interface_info;
++  grub_efi_net_interface_t *inf;
++  int i;
++  grub_efi_ipv6_address_t *address = &ip_address->ip6;
++
++  interface_info = efi_ip6_config_interface_info (dev->ip6_config);
++  if (!interface_info)
++    return NULL;
++
++  for (i = 0; i < (int)interface_info->route_count ; i++)
++    {
++      grub_uint64_t u64_addr[2];
++      grub_uint64_t u64_subnet[2];
++      grub_uint64_t u64_mask[2];
++
++      grub_efi_ip6_route_table_t *route_table = interface_info->route_table + i;
++
++      /* SKIP Default GATEWAY */
++      if (route_table->prefix_length == 0)
++	continue;
++
++      u64_addr[0] = grub_get_unaligned64 (address);
++      u64_addr[1] = grub_get_unaligned64 (address + 4);
++      u64_subnet[0] = grub_get_unaligned64 (route_table->destination.addr);
++      u64_subnet[1] = grub_get_unaligned64 (route_table->destination.addr + 8);
++      u64_mask[0] = (route_table->prefix_length <= 64) ?
++	    0xffffffffffffffffULL << (64 - route_table->prefix_length) :
++	    0xffffffffffffffffULL;
++      u64_mask[1] = (route_table->prefix_length <= 64) ?
++	    0 :
++	    0xffffffffffffffffULL << (128 - route_table->prefix_length);
++
++      if (((u64_addr[0] & u64_mask[0]) == u64_subnet[0])
++	  && ((u64_addr[1] & u64_mask[1]) == u64_subnet[1]))
++	{
++	  for (inf = dev->net_interfaces; inf; inf = inf->next)
++	    if (inf->prefer_ip6)
++	      {
++		grub_free (interface_info);
++		return inf;
++	      }
++	}
++    }
++
++  grub_free (interface_info);
++  return NULL;
++}
++
++static int
++grub_efi_ip6_interface_set_manual_address (struct grub_efi_net_device *dev,
++	    grub_efi_net_ip_manual_address_t *net_ip,
++	    int with_subnet)
++{
++  grub_efi_status_t status;
++  grub_efi_ip6_config_manual_address_t *address = &net_ip->ip6;
++
++  if (!with_subnet)
++    {
++      grub_efi_ip6_config_manual_address_t *manual_address =
++      efi_ip6_config_manual_address (dev->ip6_config);
++
++      if (manual_address)
++	{
++	  address->prefix_length = manual_address->prefix_length;
++	  grub_free (manual_address);
++	}
++      else
++	{
++	  /* XXX: */
++	  address->prefix_length = 64;
++	}
++    }
++
++  status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config,
++		    GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS,
++		    sizeof(*address), address);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++
++  return 1;
++}
++
++static int
++grub_efi_ip6_interface_set_gateway (struct grub_efi_net_device *dev,
++	      grub_efi_net_ip_address_t *address)
++{
++  grub_efi_status_t status;
++
++  status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config,
++		GRUB_EFI_IP6_CONFIG_DATA_TYPE_GATEWAY,
++		sizeof (address->ip6), &address->ip6);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++  return 1;
++}
++
++static int
++grub_efi_ip6_interface_set_dns (struct grub_efi_net_device *dev,
++	      grub_efi_net_ip_address_t *address)
++{
++
++  grub_efi_status_t status;
++
++  status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config,
++		GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
++		sizeof (address->ip6), &address->ip6);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++  return 1;
++}
++
++grub_efi_net_ip_config_t *efi_net_ip6_config = &(grub_efi_net_ip_config_t)
++  {
++    .get_hw_address = grub_efi_ip6_interface_hw_address,
++    .get_address = grub_efi_ip6_interface_address,
++    .get_route_table = grub_efi_ip6_interface_route_table,
++    .best_interface = grub_efi_ip6_interface_match,
++    .set_address = grub_efi_ip6_interface_set_manual_address,
++    .set_gateway = grub_efi_ip6_interface_set_gateway,
++    .set_dns = grub_efi_ip6_interface_set_dns
++  };
+diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c
+new file mode 100644
+index 00000000000..9e0078ac1c6
+--- /dev/null
++++ b/grub-core/net/efi/net.c
+@@ -0,0 +1,1428 @@
++#include <grub/net.h>
++#include <grub/env.h>
++#include <grub/mm.h>
++#include <grub/misc.h>
++#include <grub/dl.h>
++#include <grub/command.h>
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/i18n.h>
++#include <grub/bufio.h>
++#include <grub/efi/http.h>
++#include <grub/efi/dhcp.h>
++#include <grub/net/efi.h>
++#include <grub/charset.h>
++
++GRUB_MOD_LICENSE ("GPLv3+");
++
++#define GRUB_EFI_IP6_PREFIX_LENGTH 64
++
++static grub_efi_guid_t ip4_config_guid = GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID;
++static grub_efi_guid_t ip6_config_guid = GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID;
++static grub_efi_guid_t http_service_binding_guid = GRUB_EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID;
++static grub_efi_guid_t http_guid = GRUB_EFI_HTTP_PROTOCOL_GUID;
++static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID;
++static grub_efi_guid_t dhcp4_service_binding_guid = GRUB_EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID;
++static grub_efi_guid_t dhcp4_guid = GRUB_EFI_DHCP4_PROTOCOL_GUID;
++static grub_efi_guid_t dhcp6_service_binding_guid = GRUB_EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID;
++static grub_efi_guid_t dhcp6_guid = GRUB_EFI_DHCP6_PROTOCOL_GUID;
++
++struct grub_efi_net_device *net_devices;
++
++static char *default_server;
++static grub_efi_net_interface_t *net_interface;
++static grub_efi_net_interface_t *net_default_interface;
++
++#define efi_net_interface_configure(inf) inf->io->configure (inf->dev, inf->prefer_ip6)
++#define efi_net_interface_open(inf, file, name) inf->io->open (inf->dev, inf->prefer_ip6, file, name, inf->io_type)
++#define efi_net_interface_read(inf, file, buf, sz) inf->io->read (inf->dev, inf->prefer_ip6, file, buf, sz)
++#define efi_net_interface_close(inf, file) inf->io->close (inf->dev, inf->prefer_ip6, file)
++#define efi_net_interface(m,...) efi_net_interface_ ## m (net_interface, ## __VA_ARGS__)
++
++static grub_efi_handle_t
++grub_efi_locate_device_path (grub_efi_guid_t *protocol, grub_efi_device_path_t *device_path,
++                            grub_efi_device_path_t **r_device_path)
++{
++  grub_efi_handle_t handle;
++  grub_efi_status_t status;
++
++  status = efi_call_3 (grub_efi_system_table->boot_services->locate_device_path,
++                      protocol, &device_path, &handle);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++
++  if (r_device_path)
++    *r_device_path = device_path;
++
++  return handle;
++}
++
++static int
++url_parse_fields (const char *url, char **proto, char **host, char **path)
++{
++  const char *p, *ps;
++  grub_size_t l;
++
++  *proto = *host = *path = NULL;
++  ps = p = url;
++
++  while ((p = grub_strchr (p, ':')))
++    {
++      if (grub_strlen (p) < sizeof ("://") - 1)
++	break;
++      if (grub_memcmp (p, "://", sizeof ("://") - 1) == 0)
++	{
++	  l = p - ps;
++	  *proto = grub_malloc (l + 1);
++	  if (!*proto)
++	    {
++	      grub_print_error ();
++	      return 0;
++	    }
++
++	  grub_memcpy (*proto, ps, l);
++	  (*proto)[l] = '\0';
++	  p +=  sizeof ("://") - 1;
++	  break;
++	}
++      ++p;
++    }
++
++  if (!*proto)
++    {
++      grub_dprintf ("bootp", "url: %s is not valid, protocol not found\n", url);
++      return 0;
++    }
++
++  ps = p;
++  p = grub_strchr (p, '/');
++
++  if (!p)
++    {
++      grub_dprintf ("bootp", "url: %s is not valid, host/path not found\n", url);
++      grub_free (*proto);
++      *proto = NULL;
++      return 0;
++    }
++
++  l = p - ps;
++
++  if (l > 2 && ps[0] == '[' && ps[l - 1] == ']')
++    {
++      *host = grub_malloc (l - 1);
++      if (!*host)
++	{
++	  grub_print_error ();
++	  grub_free (*proto);
++	  *proto = NULL;
++	  return 0;
++	}
++      grub_memcpy (*host, ps + 1, l - 2);
++      (*host)[l - 2] = 0;
++    }
++  else
++    {
++      *host = grub_malloc (l + 1);
++      if (!*host)
++	{
++	  grub_print_error ();
++	  grub_free (*proto);
++	  *proto = NULL;
++	  return 0;
++	}
++      grub_memcpy (*host, ps, l);
++      (*host)[l] = 0;
++    }
++
++  *path = grub_strdup (p);
++  if (!*path)
++    {
++      grub_print_error ();
++      grub_free (*host);
++      grub_free (*proto);
++      *host = NULL;
++      *proto = NULL;
++      return 0;
++    }
++  return 1;
++}
++
++static void
++url_get_boot_location (const char *url, char **device, char **path, int is_default)
++{
++  char *protocol, *server, *file;
++  char *slash;
++
++  if (!url_parse_fields (url, &protocol, &server, &file))
++    return;
++
++  if ((slash = grub_strrchr (file, '/')))
++    *slash = 0;
++  else
++    *file = 0;
++
++  *device = grub_xasprintf ("%s,%s", protocol, server);
++  *path = grub_strdup(file);
++
++  if (is_default)
++    default_server = server;
++  else
++    grub_free (server);
++
++  grub_free (protocol);
++  grub_free (file);
++}
++
++static void
++pxe_get_boot_location (const struct grub_net_bootp_packet *bp,
++		  char **device,
++		  char **path,
++		  int is_default)
++{
++  char *server = grub_xasprintf ("%d.%d.%d.%d",
++	     ((grub_uint8_t *) &bp->server_ip)[0],
++	     ((grub_uint8_t *) &bp->server_ip)[1],
++	     ((grub_uint8_t *) &bp->server_ip)[2],
++	     ((grub_uint8_t *) &bp->server_ip)[3]);
++
++  *device = grub_xasprintf ("tftp,%s", server);
++
++  *path = grub_strndup (bp->boot_file, sizeof (bp->boot_file));
++
++  if (*path)
++    {
++      char *slash;
++      slash = grub_strrchr (*path, '/');
++      if (slash)
++	*slash = 0;
++      else
++	**path = 0;
++    }
++
++  if (is_default)
++    default_server = server;
++  else
++    grub_free (server);
++}
++
++static void
++pxe_get_boot_location_v6 (const struct grub_net_dhcp6_packet *dp,
++		  grub_size_t dhcp_size,
++		  char **device,
++		  char **path)
++{
++
++  struct grub_net_dhcp6_option *dhcp_opt;
++  grub_size_t dhcp_remain_size;
++  *device = *path = 0;
++
++  if (dhcp_size < sizeof (*dp))
++    {
++      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("DHCPv6 packet size too small"));
++      return;
++    }
++
++  dhcp_remain_size = dhcp_size - sizeof (*dp);
++  dhcp_opt = (struct grub_net_dhcp6_option *)dp->dhcp_options;
++
++  while (dhcp_remain_size)
++    {
++      grub_uint16_t code = grub_be_to_cpu16 (dhcp_opt->code);
++      grub_uint16_t len = grub_be_to_cpu16 (dhcp_opt->len);
++      grub_uint16_t option_size = sizeof (*dhcp_opt) + len;
++
++      if (dhcp_remain_size < option_size || code == 0)
++	break;
++
++      if (code == GRUB_NET_DHCP6_OPTION_BOOTFILE_URL)
++	{
++	  char *url = grub_malloc (len + 1);
++
++	  grub_memcpy (url, dhcp_opt->data, len);
++	  url[len] = 0;
++
++	  url_get_boot_location ((const char *)url, device, path, 1);
++	  grub_free (url);
++	  break;
++	}
++
++      dhcp_remain_size -= option_size;
++      dhcp_opt = (struct grub_net_dhcp6_option *)((grub_uint8_t *)dhcp_opt + option_size);
++    }
++}
++
++static grub_efi_net_interface_t *
++grub_efi_net_config_from_device_path (grub_efi_device_path_t *dp,
++		  struct grub_efi_net_device *netdev,
++		  char **device,
++		  char **path)
++{
++  grub_efi_net_interface_t *inf = NULL;
++
++  while (1)
++    {
++      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
++      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
++      grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
++
++      if (type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE)
++	{
++	  if (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)
++	    {
++	      grub_efi_uri_device_path_t *uri_dp;
++	      uri_dp = (grub_efi_uri_device_path_t *) dp;
++	      /* Beware that uri_dp->uri may not be null terminated */
++	      url_get_boot_location ((const char *)uri_dp->uri, device, path, 1);
++	    }
++	  else if (subtype == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE)
++	    {
++	      grub_efi_net_ip_manual_address_t net_ip;
++	      grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) dp;
++
++	      if (inf)
++		continue;
++	      grub_memcpy (net_ip.ip4.address, ipv4->local_ip_address, sizeof (net_ip.ip4.address));
++	      grub_memcpy (net_ip.ip4.subnet_mask, ipv4->subnet_mask, sizeof (net_ip.ip4.subnet_mask));
++	      net_ip.is_ip6 = 0;
++	      inf = grub_efi_net_create_interface (netdev,
++			    netdev->card_name,
++			    &net_ip,
++			    1);
++	    }
++	  else if (subtype == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)
++	    {
++	      grub_efi_net_ip_manual_address_t net_ip;
++	      grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) dp;
++
++	      if (inf)
++		continue;
++	      grub_memcpy (net_ip.ip6.address, ipv6->local_ip_address, sizeof (net_ip.ip6.address));
++	      net_ip.ip6.prefix_length = GRUB_EFI_IP6_PREFIX_LENGTH;
++	      net_ip.ip6.is_anycast = 0;
++	      net_ip.is_ip6 = 1;
++	      inf = grub_efi_net_create_interface (netdev,
++			    netdev->card_name,
++			    &net_ip,
++			    1);
++	    }
++	}
++
++      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
++        break;
++      dp = (grub_efi_device_path_t *) ((char *) dp + len);
++    }
++
++  return inf;
++}
++
++static grub_efi_net_interface_t *
++grub_efi_net_config_from_handle (grub_efi_handle_t *hnd,
++		  struct grub_efi_net_device *netdev,
++		  char **device,
++		  char **path)
++{
++  grub_efi_pxe_t *pxe = NULL;
++
++  if (hnd == netdev->ip4_pxe_handle)
++    pxe = netdev->ip4_pxe;
++  else if (hnd == netdev->ip6_pxe_handle)
++    pxe = netdev->ip6_pxe;
++
++  if (!pxe)
++    return (grub_efi_net_config_from_device_path (
++		grub_efi_get_device_path (hnd),
++		netdev,
++		device,
++		path));
++
++  if (pxe->mode->using_ipv6)
++    {
++      grub_efi_net_ip_manual_address_t net_ip;
++
++      pxe_get_boot_location_v6 (
++	    (const struct grub_net_dhcp6_packet *) &pxe->mode->dhcp_ack,
++	    sizeof (pxe->mode->dhcp_ack),
++	    device,
++	    path);
++
++      grub_memcpy (net_ip.ip6.address, pxe->mode->station_ip.v6, sizeof(net_ip.ip6.address));
++      net_ip.ip6.prefix_length = GRUB_EFI_IP6_PREFIX_LENGTH;
++      net_ip.ip6.is_anycast = 0;
++      net_ip.is_ip6 = 1;
++      return (grub_efi_net_create_interface (netdev,
++		    netdev->card_name,
++		    &net_ip,
++		    1));
++    }
++  else
++    {
++      grub_efi_net_ip_manual_address_t net_ip;
++
++      pxe_get_boot_location (
++		(const struct grub_net_bootp_packet *) &pxe->mode->dhcp_ack,
++		device,
++		path,
++		1);
++
++      grub_memcpy (net_ip.ip4.address, pxe->mode->station_ip.v4, sizeof (net_ip.ip4.address));
++      grub_memcpy (net_ip.ip4.subnet_mask, pxe->mode->subnet_mask.v4, sizeof (net_ip.ip4.subnet_mask));
++      net_ip.is_ip6 = 0;
++      return (grub_efi_net_create_interface (netdev,
++		    netdev->card_name,
++		    &net_ip,
++		    1));
++    }
++}
++
++static const char *
++grub_efi_net_var_get_address (struct grub_env_var *var,
++                   const char *val __attribute__ ((unused)))
++{
++  struct grub_efi_net_device *dev;
++
++  for (dev = net_devices; dev; dev = dev->next)
++    {
++      grub_efi_net_interface_t *inf;
++
++      for (inf = dev->net_interfaces; inf; inf = inf->next)
++	{
++	  char *var_name;
++
++	  var_name = grub_xasprintf ("net_%s_ip", inf->name);
++	  if (grub_strcmp (var_name, var->name) == 0)
++	    return efi_net_interface_get_address (inf);
++	  grub_free (var_name);
++	  var_name = grub_xasprintf ("net_%s_mac", inf->name);
++	  if (grub_strcmp (var_name, var->name) == 0)
++	    return efi_net_interface_get_hw_address (inf);
++	  grub_free (var_name);
++	}
++    }
++
++  return NULL;
++}
++
++static char *
++grub_efi_net_var_set_interface (struct grub_env_var *var __attribute__ ((unused)),
++		   const char *val)
++{
++  struct grub_efi_net_device *dev;
++  grub_efi_net_interface_t *inf;
++
++  for (dev = net_devices; dev; dev = dev->next)
++    for (inf = dev->net_interfaces; inf; inf = inf->next)
++      if (grub_strcmp (inf->name, val) == 0)
++	{
++	  net_default_interface = inf;
++	  return grub_strdup (val);
++	}
++
++  return NULL;
++}
++
++static char *
++grub_efi_net_var_set_server (struct grub_env_var *var __attribute__ ((unused)),
++		   const char *val)
++{
++  grub_free (default_server);
++  default_server = grub_strdup (val);
++  return grub_strdup (val);
++}
++
++static const char *
++grub_efi_net_var_get_server (struct grub_env_var *var __attribute__ ((unused)),
++		   const char *val __attribute__ ((unused)))
++{
++  return default_server ? : "";
++}
++
++static const char *
++grub_efi_net_var_get_ip (struct grub_env_var *var __attribute__ ((unused)),
++	       const char *val __attribute__ ((unused)))
++{
++  const char *intf = grub_env_get ("net_default_interface");
++  const char *ret = NULL;
++  if (intf)
++    {
++      char *buf = grub_xasprintf ("net_%s_ip", intf);
++      if (buf)
++	ret = grub_env_get (buf);
++      grub_free (buf);
++    }
++  return ret;
++}
++
++static const char *
++grub_efi_net_var_get_mac (struct grub_env_var *var __attribute__ ((unused)),
++	       const char *val __attribute__ ((unused)))
++{
++  const char *intf = grub_env_get ("net_default_interface");
++  const char *ret = NULL;
++  if (intf)
++    {
++      char *buf = grub_xasprintf ("net_%s_mac", intf);
++      if (buf)
++	ret = grub_env_get (buf);
++      grub_free (buf);
++    }
++  return ret;
++}
++
++static void
++grub_efi_net_export_interface_vars (void)
++{
++  struct grub_efi_net_device *dev;
++
++  for (dev = net_devices; dev; dev = dev->next)
++    {
++      grub_efi_net_interface_t *inf;
++
++      for (inf = dev->net_interfaces; inf; inf = inf->next)
++	{
++	  char *var;
++
++	  var = grub_xasprintf ("net_%s_ip", inf->name);
++	  grub_register_variable_hook (var, grub_efi_net_var_get_address, 0);
++	  grub_env_export (var);
++	  grub_free (var);
++	  var = grub_xasprintf ("net_%s_mac", inf->name);
++	  grub_register_variable_hook (var, grub_efi_net_var_get_address, 0);
++	  grub_env_export (var);
++	  grub_free (var);
++	}
++    }
++}
++
++static void
++grub_efi_net_unset_interface_vars (void)
++{
++  struct grub_efi_net_device *dev;
++
++  for (dev = net_devices; dev; dev = dev->next)
++    {
++      grub_efi_net_interface_t *inf;
++
++      for (inf = dev->net_interfaces; inf; inf = inf->next)
++	{
++	  char *var;
++
++	  var = grub_xasprintf ("net_%s_ip", inf->name);
++	  grub_register_variable_hook (var, 0, 0);
++	  grub_env_unset (var);
++	  grub_free (var);
++	  var = grub_xasprintf ("net_%s_mac", inf->name);
++	  grub_register_variable_hook (var, 0, 0);
++	  grub_env_unset (var);
++	  grub_free (var);
++	}
++    }
++}
++
++grub_efi_net_interface_t *
++grub_efi_net_create_interface (struct grub_efi_net_device *dev,
++		const char *interface_name,
++		grub_efi_net_ip_manual_address_t *net_ip,
++		int has_subnet)
++{
++  grub_efi_net_interface_t *inf;
++
++  for (inf = dev->net_interfaces; inf; inf = inf->next)
++    {
++      if (inf->prefer_ip6 == net_ip->is_ip6)
++	break;
++    }
++
++  if (!inf)
++    {
++      inf = grub_malloc (sizeof(*inf));
++      inf->name = grub_strdup (interface_name);
++      inf->prefer_ip6 = net_ip->is_ip6;
++      inf->dev = dev;
++      inf->next = dev->net_interfaces;
++      inf->ip_config = (net_ip->is_ip6) ? efi_net_ip6_config : efi_net_ip4_config ;
++      dev->net_interfaces = inf;
++    }
++  else
++    {
++      grub_free (inf->name);
++      inf->name = grub_strdup (interface_name);
++    }
++
++  if (!efi_net_interface_set_address (inf, net_ip, has_subnet))
++    {
++      grub_error (GRUB_ERR_BUG, N_("Set Address Failed"));
++      return NULL;
++    }
++
++  return inf;
++}
++
++static void
++grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
++			  char **path)
++{
++  grub_efi_handle_t config_hnd;
++
++  struct grub_efi_net_device *netdev;
++  grub_efi_net_interface_t *inf;
++
++  config_hnd = grub_efi_locate_device_path (&ip4_config_guid, grub_efi_get_device_path (hnd), NULL);
++
++  if (!config_hnd)
++    return;
++
++  for (netdev = net_devices; netdev; netdev = netdev->next)
++    if (netdev->handle == config_hnd)
++      break;
++
++  if (!netdev)
++    return;
++
++  if (!(inf = grub_efi_net_config_from_handle (hnd, netdev, device, path)))
++    return;
++
++  grub_env_set ("net_default_interface", inf->name);
++  grub_efi_net_export_interface_vars ();
++}
++
++static grub_err_t
++grub_efi_netfs_dir (grub_device_t device, const char *path __attribute__ ((unused)),
++		 grub_fs_dir_hook_t hook __attribute__ ((unused)),
++		 void *hook_data __attribute__ ((unused)))
++{
++  if (!device->net)
++    return grub_error (GRUB_ERR_BUG, "invalid net device");
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_efi_netfs_open (struct grub_file *file_out __attribute__ ((unused)),
++		  const char *name __attribute__ ((unused)))
++{
++  struct grub_file *file, *bufio;
++
++  file = grub_malloc (sizeof (*file));
++  if (!file)
++    return grub_errno;
++
++  grub_memcpy (file, file_out, sizeof (struct grub_file));
++  file->device->net->name = grub_strdup (name);
++
++  if (!file->device->net->name)
++    {
++      grub_free (file);
++      return grub_errno;
++    }
++
++  efi_net_interface(open, file, name);
++  grub_print_error ();
++
++  bufio = grub_bufio_open (file, 32768);
++  if (!bufio)
++    {
++      grub_free (file->device->net->name);
++      grub_free (file);
++      return grub_errno;
++    }
++  grub_memcpy (file_out, bufio, sizeof (struct grub_file));
++  grub_free (bufio);
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_ssize_t
++grub_efihttp_chunk_read (grub_file_t file, char *buf,
++			grub_size_t len, grub_size_t chunk_size)
++{
++  char *chunk = grub_malloc (chunk_size);
++  grub_size_t sum = 0;
++
++  while (len)
++    {
++      grub_ssize_t rd;
++      grub_size_t sz = (len > chunk_size) ? chunk_size : len;
++
++      rd = efi_net_interface (read, file, chunk, sz);
++
++      if (rd <= 0)
++	return rd;
++
++      if (buf)
++	{
++	  grub_memcpy (buf, chunk, rd);
++	  buf += rd;
++	}
++      sum += rd;
++      len -= rd;
++    }
++
++  grub_free (chunk);
++  return sum;
++}
++
++static grub_ssize_t
++grub_efi_netfs_read (grub_file_t file __attribute__ ((unused)),
++		  char *buf __attribute__ ((unused)), grub_size_t len __attribute__ ((unused)))
++{
++  if (file->offset > file->device->net->offset)
++    {
++      grub_efihttp_chunk_read (file, NULL, file->offset - file->device->net->offset, 10240);
++    }
++  else if (file->offset < file->device->net->offset)
++    {
++      efi_net_interface (close, file);
++      efi_net_interface (open, file, file->device->net->name);
++      if (file->offset)
++	grub_efihttp_chunk_read (file, NULL, file->offset, 10240);
++    }
++
++  return efi_net_interface (read, file, buf, len);
++}
++
++static grub_err_t
++grub_efi_netfs_close (grub_file_t file)
++{
++  efi_net_interface (close, file);
++  return GRUB_ERR_NONE;
++}
++
++static grub_efi_handle_t
++grub_efi_service_binding (grub_efi_handle_t dev, grub_efi_guid_t *service_binding_guid)
++{
++  grub_efi_service_binding_t *service;
++  grub_efi_status_t status;
++  grub_efi_handle_t child_dev = NULL;
++
++  service = grub_efi_open_protocol (dev, service_binding_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++  if (!service)
++    {
++      grub_error (GRUB_ERR_IO, N_("couldn't open efi service binding protocol"));
++      return NULL;
++    }
++
++  status = efi_call_2 (service->create_child, service, &child_dev);
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_error (GRUB_ERR_IO, N_("Failed to create child device of http service %x"), status);
++      return NULL;
++    }
++
++  return child_dev;
++}
++
++static grub_err_t
++grub_efi_net_parse_address (const char *address,
++    grub_efi_ip4_config2_manual_address_t *ip4,
++    grub_efi_ip6_config_manual_address_t *ip6,
++    int *is_ip6,
++    int *has_cidr)
++{
++  const char *rest;
++
++  if (grub_efi_string_to_ip4_address (address, &ip4->address, &rest))
++    {
++      *is_ip6 = 0;
++      if (*rest == '/')
++	{
++	  grub_uint32_t subnet_mask_size;
++
++	  subnet_mask_size = grub_strtoul (rest + 1, (char **) &rest, 0);
++
++	  if (!grub_errno && subnet_mask_size <= 32 && *rest == 0)
++	    {
++	      grub_uint32_t subnet_mask;
++
++	      subnet_mask = grub_cpu_to_be32 ((0xffffffffU << (32 - subnet_mask_size)));
++	      grub_memcpy (ip4->subnet_mask, &subnet_mask, sizeof (ip4->subnet_mask));
++	      if (has_cidr)
++		*has_cidr = 1;
++	      return GRUB_ERR_NONE;
++	    }
++	}
++      else if (*rest == 0)
++	{
++	  grub_uint32_t subnet_mask = 0xffffffffU;
++	  grub_memcpy (ip4->subnet_mask, &subnet_mask, sizeof (ip4->subnet_mask));
++	  if (has_cidr)
++	    *has_cidr = 0;
++	  return GRUB_ERR_NONE;
++	}
++    }
++  else if (grub_efi_string_to_ip6_address (address, &ip6->address, &rest))
++    {
++      *is_ip6 = 1;
++      if (*rest == '/')
++	{
++	  grub_efi_uint8_t prefix_length;
++
++	  prefix_length = grub_strtoul (rest + 1, (char **) &rest, 0);
++	  if (!grub_errno && prefix_length <= 128 && *rest == 0)
++	    {
++	      ip6->prefix_length = prefix_length;
++	      ip6->is_anycast = 0;
++	      if (has_cidr)
++		*has_cidr = 1;
++	      return GRUB_ERR_NONE;
++	    }
++	}
++      else if (*rest == 0)
++	{
++	  ip6->prefix_length = 128;
++	  ip6->is_anycast = 0;
++	  if (has_cidr)
++	    *has_cidr = 0;
++	  return GRUB_ERR_NONE;
++	}
++    }
++
++  return grub_error (GRUB_ERR_NET_BAD_ADDRESS,
++		   N_("unrecognised network address `%s'"),
++		   address);
++}
++
++static grub_efi_net_interface_t *
++match_route (const char *server)
++{
++  grub_err_t err;
++  grub_efi_ip4_config2_manual_address_t ip4;
++  grub_efi_ip6_config_manual_address_t ip6;
++  grub_efi_net_interface_t *inf;
++  int is_ip6 = 0;
++
++  err = grub_efi_net_parse_address (server, &ip4, &ip6, &is_ip6, 0);
++
++  if (err)
++    {
++      grub_print_error ();
++      return NULL;
++    }
++
++  if (is_ip6)
++    {
++      struct grub_efi_net_device *dev;
++      grub_efi_net_ip_address_t addr;
++
++      grub_memcpy (addr.ip6, ip6.address, sizeof(ip6.address));
++
++      for (dev = net_devices; dev; dev = dev->next)
++	  if ((inf = efi_net_ip6_config->best_interface (dev, &addr)))
++	    return inf;
++    }
++  else
++    {
++      struct grub_efi_net_device *dev;
++      grub_efi_net_ip_address_t addr;
++
++      grub_memcpy (addr.ip4, ip4.address, sizeof(ip4.address));
++
++      for (dev = net_devices; dev; dev = dev->next)
++	  if ((inf = efi_net_ip4_config->best_interface (dev, &addr)))
++	    return inf;
++    }
++
++  return 0;
++}
++
++static void
++grub_efi_net_add_pxebc_to_cards (void)
++{
++  grub_efi_uintn_t num_handles;
++  grub_efi_handle_t *handles;
++  grub_efi_handle_t *handle;
++
++  handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &pxe_io_guid,
++				    0, &num_handles);
++  if (!handles)
++    return;
++
++  for (handle = handles; num_handles--; handle++)
++    {
++      grub_efi_device_path_t *dp, *ddp, *ldp;
++      grub_efi_pxe_t *pxe;
++      struct grub_efi_net_device *d;
++      int is_ip6 = 0;
++
++      dp = grub_efi_get_device_path (*handle);
++      if (!dp)
++	continue;
++
++      ddp = grub_efi_duplicate_device_path (dp);
++      ldp = grub_efi_find_last_device_path (ddp);
++
++      if (ldp->type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
++	  && ldp->subtype == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE)
++	{
++	  ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++	  ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++	  ldp->length = sizeof (*ldp);
++	}
++      else if (ldp->type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
++	  && ldp->subtype == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)
++	{
++	  is_ip6 = 1;
++	  ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++	  ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++	  ldp->length = sizeof (*ldp);
++	}
++
++      for (d = net_devices; d; d = d->next)
++	if (grub_efi_compare_device_paths (ddp, grub_efi_get_device_path (d->handle)) == 0)
++	  break;
++
++      if (!d)
++	{
++	  grub_free (ddp);
++	  continue;
++	}
++
++      pxe = grub_efi_open_protocol (*handle, &pxe_io_guid,
++				GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++      if (!pxe)
++	{
++	  grub_free (ddp);
++	  continue;
++	}
++
++      if (is_ip6)
++	{
++	  d->ip6_pxe_handle = *handle;
++	  d->ip6_pxe = pxe;
++	}
++      else
++	{
++	  d->ip4_pxe_handle = *handle;
++	  d->ip4_pxe = pxe;
++	}
++
++      grub_free (ddp);
++    }
++
++  grub_free (handles);
++}
++
++static void
++set_ip_policy_to_static (void)
++{
++  struct grub_efi_net_device *dev;
++
++  for (dev = net_devices; dev; dev = dev->next)
++    {
++      grub_efi_ip4_config2_policy_t ip4_policy = GRUB_EFI_IP4_CONFIG2_POLICY_STATIC;
++
++      if (efi_call_4 (dev->ip4_config->set_data, dev->ip4_config,
++		    GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY,
++		    sizeof (ip4_policy), &ip4_policy) != GRUB_EFI_SUCCESS)
++	grub_dprintf ("efinetfs", "could not set GRUB_EFI_IP4_CONFIG2_POLICY_STATIC on dev `%s'", dev->card_name);
++
++      if (dev->ip6_config)
++	{
++	  grub_efi_ip6_config_policy_t ip6_policy = GRUB_EFI_IP6_CONFIG_POLICY_MANUAL;
++
++	  if (efi_call_4 (dev->ip6_config->set_data, dev->ip6_config,
++		    GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY,
++		    sizeof (ip6_policy), &ip6_policy) != GRUB_EFI_SUCCESS)
++	    grub_dprintf ("efinetfs", "could not set GRUB_EFI_IP6_CONFIG_POLICY_MANUAL on dev `%s'", dev->card_name);
++	}
++    }
++}
++
++/* FIXME: Do not fail if the card did not support any of the protocol (Eg http) */
++static void
++grub_efi_net_find_cards (void)
++{
++  grub_efi_uintn_t num_handles;
++  grub_efi_handle_t *handles;
++  grub_efi_handle_t *handle;
++  int id;
++
++  handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &ip4_config_guid,
++				    0, &num_handles);
++  if (!handles)
++    return;
++
++  for (id = 0, handle = handles; num_handles--; handle++, id++)
++    {
++      grub_efi_device_path_t *dp;
++      grub_efi_ip4_config2_protocol_t *ip4_config;
++      grub_efi_ip6_config_protocol_t *ip6_config;
++      grub_efi_handle_t http_handle;
++      grub_efi_http_t *http;
++      grub_efi_handle_t dhcp4_handle;
++      grub_efi_dhcp4_protocol_t *dhcp4;
++      grub_efi_handle_t dhcp6_handle;
++      grub_efi_dhcp6_protocol_t *dhcp6;
++
++      struct grub_efi_net_device *d;
++
++      dp = grub_efi_get_device_path (*handle);
++      if (!dp)
++	continue;
++
++      ip4_config = grub_efi_open_protocol (*handle, &ip4_config_guid,
++				    GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++      if (!ip4_config)
++	continue;
++
++      ip6_config = grub_efi_open_protocol (*handle, &ip6_config_guid,
++				    GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++      http_handle = grub_efi_service_binding (*handle, &http_service_binding_guid);
++      grub_errno = GRUB_ERR_NONE;
++      http = (http_handle)
++	? grub_efi_open_protocol (http_handle, &http_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL)
++	: NULL;
++
++      dhcp4_handle = grub_efi_service_binding (*handle, &dhcp4_service_binding_guid);
++      grub_errno = GRUB_ERR_NONE;
++      dhcp4 = (dhcp4_handle)
++	? grub_efi_open_protocol (dhcp4_handle, &dhcp4_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL)
++	: NULL;
++
++
++      dhcp6_handle = grub_efi_service_binding (*handle, &dhcp6_service_binding_guid);
++      grub_errno = GRUB_ERR_NONE;
++      dhcp6 = (dhcp6_handle)
++	? grub_efi_open_protocol (dhcp6_handle, &dhcp6_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL)
++	: NULL;
++
++      d = grub_malloc (sizeof (*d));
++      if (!d)
++	{
++	  grub_free (handles);
++	  while (net_devices)
++	    {
++	      d = net_devices->next;
++	      grub_free (net_devices);
++	      net_devices = d;
++	    }
++	  return;
++	}
++      d->handle = *handle;
++      d->ip4_config = ip4_config;
++      d->ip6_config = ip6_config;
++      d->http_handle = http_handle;
++      d->http = http;
++      d->dhcp4_handle = dhcp4_handle;
++      d->dhcp4 = dhcp4;
++      d->dhcp6_handle = dhcp6_handle;
++      d->dhcp6 = dhcp6;
++      d->next = net_devices;
++      d->card_name = grub_xasprintf ("efinet%d", id);
++      d->net_interfaces = NULL;
++      net_devices = d;
++    }
++
++  grub_efi_net_add_pxebc_to_cards ();
++  grub_free (handles);
++  set_ip_policy_to_static ();
++}
++
++static void
++listroutes_ip4 (struct grub_efi_net_device *netdev)
++{
++  char **routes;
++
++  routes = NULL;
++
++  if ((routes = efi_net_ip4_config->get_route_table (netdev)))
++    {
++      char **r;
++
++      for (r = routes; *r; ++r)
++	grub_printf ("%s\n", *r);
++    }
++
++  if (routes)
++    {
++      char **r;
++
++      for (r = routes; *r; ++r)
++	grub_free (*r);
++      grub_free (routes);
++    }
++}
++
++static void
++listroutes_ip6 (struct grub_efi_net_device *netdev)
++{
++  char **routes;
++
++  routes = NULL;
++
++  if ((routes = efi_net_ip6_config->get_route_table (netdev)))
++    {
++      char **r;
++
++      for (r = routes; *r; ++r)
++	grub_printf ("%s\n", *r);
++    }
++
++  if (routes)
++    {
++      char **r;
++
++      for (r = routes; *r; ++r)
++	grub_free (*r);
++      grub_free (routes);
++    }
++}
++
++static grub_err_t
++grub_cmd_efi_listroutes (struct grub_command *cmd __attribute__ ((unused)),
++		     int argc __attribute__ ((unused)),
++		     char **args __attribute__ ((unused)))
++{
++  struct grub_efi_net_device *netdev;
++
++  for (netdev = net_devices; netdev; netdev = netdev->next)
++    {
++      listroutes_ip4 (netdev);
++      listroutes_ip6 (netdev);
++    }
++
++  return GRUB_ERR_NONE;
++}
++static grub_err_t
++grub_cmd_efi_listcards (struct grub_command *cmd __attribute__ ((unused)),
++		    int argc __attribute__ ((unused)),
++		    char **args __attribute__ ((unused)))
++{
++  struct grub_efi_net_device *dev;
++
++  for (dev = net_devices; dev; dev = dev->next)
++    {
++      char *hw_addr;
++
++      hw_addr = efi_net_ip4_config->get_hw_address (dev);
++
++      if (hw_addr)
++	{
++	  grub_printf ("%s %s\n", dev->card_name, hw_addr);
++	  grub_free (hw_addr);
++	}
++    }
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_cmd_efi_listaddrs (struct grub_command *cmd __attribute__ ((unused)),
++		    int argc __attribute__ ((unused)),
++		    char **args __attribute__ ((unused)))
++{
++  struct grub_efi_net_device *dev;
++  grub_efi_net_interface_t *inf;
++
++  for (dev = net_devices; dev; dev = dev->next)
++    for (inf = dev->net_interfaces; inf; inf = inf->next)
++      {
++	char *hw_addr = NULL;
++	char *addr = NULL;
++
++	if ((hw_addr = efi_net_interface_get_hw_address (inf))
++	    && (addr = efi_net_interface_get_address (inf)))
++	  grub_printf ("%s %s %s\n", inf->name, hw_addr, addr);
++
++	if (hw_addr)
++	  grub_free (hw_addr);
++	if (addr)
++	  grub_free (addr);
++      }
++
++  return GRUB_ERR_NONE;
++}
++
++/* FIXME: support MAC specifying.  */
++static grub_err_t
++grub_cmd_efi_addaddr (struct grub_command *cmd __attribute__ ((unused)),
++                  int argc, char **args)
++{
++  struct grub_efi_net_device *dev;
++  grub_err_t err;
++  grub_efi_ip4_config2_manual_address_t ip4;
++  grub_efi_ip6_config_manual_address_t ip6;
++  grub_efi_net_ip_manual_address_t net_ip;
++  int is_ip6 = 0;
++  int cidr = 0;
++
++  if (argc != 3)
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected"));
++
++  for (dev = net_devices; dev; dev = dev->next)
++    {
++      if (grub_strcmp (dev->card_name, args[1]) == 0)
++	break;
++    }
++
++  if (!dev)
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found"));
++
++  err = grub_efi_net_parse_address (args[2], &ip4, &ip6, &is_ip6, &cidr);
++
++  if (err)
++    return err;
++
++  net_ip.is_ip6 = is_ip6;
++  if (is_ip6)
++    grub_memcpy (&net_ip.ip6, &ip6, sizeof(net_ip.ip6));
++  else
++    grub_memcpy (&net_ip.ip4, &ip4, sizeof(net_ip.ip4));
++
++  if (!grub_efi_net_create_interface (dev,
++		args[0],
++		&net_ip,
++		cidr))
++    return grub_errno;
++
++  return GRUB_ERR_NONE;
++}
++
++static struct grub_fs grub_efi_netfs;
++
++static grub_net_t
++grub_net_open_real (const char *name __attribute__ ((unused)))
++{
++  grub_size_t protnamelen;
++  const char *protname, *server;
++  grub_net_t ret;
++
++  net_interface = NULL;
++
++  if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
++    {
++      protname = "tftp";
++      protnamelen = sizeof ("tftp") - 1;
++      server = name + sizeof ("pxe:") - 1;
++    }
++  else if (grub_strcmp (name, "pxe") == 0)
++    {
++      protname = "tftp";
++      protnamelen = sizeof ("tftp") - 1;
++      server = default_server;
++    }
++  else
++    {
++      const char *comma;
++
++      comma = grub_strchr (name, ',');
++      if (comma)
++	{
++	  protnamelen = comma - name;
++	  server = comma + 1;
++	  protname = name;
++	}
++      else
++	{
++	  protnamelen = grub_strlen (name);
++	  server = default_server;
++	  protname = name;
++	}
++    }
++
++  if (!server)
++    {
++      grub_error (GRUB_ERR_NET_BAD_ADDRESS,
++		  N_("no server is specified"));
++      return NULL;
++    }
++
++  /*FIXME: Use DNS translate name to address */
++  net_interface = match_route (server);
++
++  /*XXX: should we check device with default gateway ? */
++  if (!net_interface && !(net_interface = net_default_interface))
++    {
++      grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' no route found"),
++		  name);
++      return NULL;
++    }
++
++  if ((protnamelen == (sizeof ("https") - 1)
++	&& grub_memcmp ("https", protname, protnamelen) == 0))
++    {
++      net_interface->io = &io_http;
++      net_interface->io_type = 1;
++    }
++  else if ((protnamelen == (sizeof ("http") - 1)
++	&& grub_memcmp ("http", protname, protnamelen) == 0))
++    {
++      net_interface->io = &io_http;
++      net_interface->io_type = 0;
++    }
++  else if (protnamelen == (sizeof ("tftp") - 1)
++	&& grub_memcmp ("tftp", protname, protnamelen) == 0)
++    {
++      net_interface->io = &io_pxe;
++      net_interface->io_type = 0;
++    }
++  else
++    {
++      grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"),
++		  name);
++      return NULL;
++    }
++
++  /*XXX: Should we try to avoid doing excess "reconfigure" here ??? */
++  efi_net_interface (configure);
++
++  ret = grub_zalloc (sizeof (*ret));
++  if (!ret)
++    return NULL;
++
++  ret->server = grub_strdup (server);
++  if (!ret->server)
++    {
++      grub_free (ret);
++      return NULL;
++    }
++
++  ret->fs = &grub_efi_netfs;
++  return ret;
++}
++#if 0
++static grub_command_t cmd_efi_lsaddr;
++static grub_command_t cmd_efi_lscards;
++static grub_command_t cmd_efi_lsroutes;
++static grub_command_t cmd_efi_addaddr;
++#endif
++
++static struct grub_fs grub_efi_netfs =
++  {
++    .name = "efi netfs",
++    .dir = grub_efi_netfs_dir,
++    .open = grub_efi_netfs_open,
++    .read = grub_efi_netfs_read,
++    .close = grub_efi_netfs_close,
++    .label = NULL,
++    .uuid = NULL,
++    .mtime = NULL,
++  };
++
++int
++grub_efi_net_boot_from_https (void)
++{
++  grub_efi_loaded_image_t *image = NULL;
++  grub_efi_device_path_t *dp;
++
++  image = grub_efi_get_loaded_image (grub_efi_image_handle);
++  if (!image)
++    return 0;
++
++  dp = grub_efi_get_device_path (image->device_handle);
++
++  while (1)
++    {
++      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
++      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
++      grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
++
++      if ((type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE)
++	  && (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE))
++	{
++	  grub_efi_uri_device_path_t *uri_dp = (grub_efi_uri_device_path_t *) dp;
++	  return (grub_strncmp ((const char*)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0) ? 1 : 0;
++	}
++
++      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
++        break;
++      dp = (grub_efi_device_path_t *) ((char *) dp + len);
++    }
++
++  return 0;
++}
++
++int
++grub_efi_net_boot_from_opa (void)
++{
++  grub_efi_loaded_image_t *image = NULL;
++  grub_efi_device_path_t *dp;
++
++  image = grub_efi_get_loaded_image (grub_efi_image_handle);
++  if (!image)
++    return 0;
++
++  dp = grub_efi_get_device_path (image->device_handle);
++
++  while (1)
++    {
++      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
++      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
++      grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
++
++      if ((type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE)
++	  && (subtype == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE))
++	{
++	  grub_efi_mac_address_device_path_t *mac_dp  = (grub_efi_mac_address_device_path_t *)dp;
++	  return (mac_dp->if_type == 0xC7) ? 1 : 0;
++	}
++
++      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
++        break;
++      dp = (grub_efi_device_path_t *) ((char *) dp + len);
++    }
++
++  return 0;
++}
++
++static char *
++grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
++			 const char *val __attribute__ ((unused)))
++{
++  return NULL;
++}
++
++grub_command_func_t grub_efi_net_list_routes = grub_cmd_efi_listroutes;
++grub_command_func_t grub_efi_net_list_cards = grub_cmd_efi_listcards;
++grub_command_func_t grub_efi_net_list_addrs = grub_cmd_efi_listaddrs;
++grub_command_func_t grub_efi_net_add_addr = grub_cmd_efi_addaddr;
++
++int
++grub_efi_net_fs_init ()
++{
++  grub_efi_net_find_cards ();
++  grub_efi_net_config = grub_efi_net_config_real;
++  grub_net_open = grub_net_open_real;
++  grub_register_variable_hook ("net_default_server", grub_efi_net_var_get_server,
++			       grub_efi_net_var_set_server);
++  grub_env_export ("net_default_server");
++  grub_register_variable_hook ("pxe_default_server", grub_efi_net_var_get_server,
++			       grub_efi_net_var_set_server);
++  grub_env_export ("pxe_default_server");
++  grub_register_variable_hook ("net_default_interface", 0,
++			       grub_efi_net_var_set_interface);
++  grub_env_export ("net_default_interface");
++  grub_register_variable_hook ("net_default_ip", grub_efi_net_var_get_ip,
++			       0);
++  grub_env_export ("net_default_ip");
++  grub_register_variable_hook ("net_default_mac", grub_efi_net_var_get_mac,
++			       0);
++  grub_env_export ("net_default_mac");
++
++  grub_env_set ("grub_netfs_type", "efi");
++  grub_register_variable_hook ("grub_netfs_type", 0, grub_env_write_readonly);
++  grub_env_export ("grub_netfs_type");
++
++  return 1;
++}
++
++void
++grub_efi_net_fs_fini (void)
++{
++  grub_env_unset ("grub_netfs_type");
++  grub_efi_net_unset_interface_vars ();
++  grub_register_variable_hook ("net_default_server", 0, 0);
++  grub_env_unset ("net_default_server");
++  grub_register_variable_hook ("net_default_interface", 0, 0);
++  grub_env_unset ("net_default_interface");
++  grub_register_variable_hook ("pxe_default_server", 0, 0);
++  grub_env_unset ("pxe_default_server");
++  grub_register_variable_hook ("net_default_ip", 0, 0);
++  grub_env_unset ("net_default_ip");
++  grub_register_variable_hook ("net_default_mac", 0, 0);
++  grub_env_unset ("net_default_mac");
++  grub_efi_net_config = NULL;
++  grub_net_open = NULL;
++  grub_fs_unregister (&grub_efi_netfs);
++}
+diff --git a/grub-core/net/efi/pxe.c b/grub-core/net/efi/pxe.c
+new file mode 100644
+index 00000000000..531949cba5c
+--- /dev/null
++++ b/grub-core/net/efi/pxe.c
+@@ -0,0 +1,424 @@
++
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/misc.h>
++#include <grub/net/efi.h>
++#include <grub/charset.h>
++
++static grub_efi_ip6_config_manual_address_t *
++efi_ip6_config_manual_address (grub_efi_ip6_config_protocol_t *ip6_config)
++{
++  grub_efi_uintn_t sz;
++  grub_efi_status_t status;
++  grub_efi_ip6_config_manual_address_t *manual_address;
++
++  sz = sizeof (*manual_address);
++  manual_address = grub_malloc (sz);
++  if (!manual_address)
++    return NULL;
++
++  status = efi_call_4 (ip6_config->get_data, ip6_config,
++		    GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS,
++		    &sz, manual_address);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (manual_address);
++      return NULL;
++    }
++
++  return manual_address;
++}
++
++static grub_efi_ip4_config2_manual_address_t *
++efi_ip4_config_manual_address (grub_efi_ip4_config2_protocol_t *ip4_config)
++{
++  grub_efi_uintn_t sz;
++  grub_efi_status_t status;
++  grub_efi_ip4_config2_manual_address_t *manual_address;
++
++  sz = sizeof (*manual_address);
++  manual_address = grub_malloc (sz);
++  if (!manual_address)
++    return NULL;
++
++  status = efi_call_4 (ip4_config->get_data, ip4_config,
++		    GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
++		    &sz, manual_address);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (manual_address);
++      return NULL;
++    }
++
++  return manual_address;
++}
++
++static void
++pxe_configure (struct grub_efi_net_device *dev, int prefer_ip6)
++{
++  grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe;
++
++  grub_efi_pxe_mode_t *mode = pxe->mode;
++
++  if (!mode->started)
++    {
++      grub_efi_status_t status;
++      status = efi_call_2 (pxe->start, pxe, prefer_ip6);
++
++      if (status != GRUB_EFI_SUCCESS)
++	  grub_printf ("Couldn't start PXE\n");
++    }
++
++#if 0
++  grub_printf ("PXE STARTED: %u\n", mode->started);
++  grub_printf ("PXE USING IPV6: %u\n", mode->using_ipv6);
++#endif
++
++  if (mode->using_ipv6)
++    {
++      grub_efi_ip6_config_manual_address_t *manual_address;
++      manual_address = efi_ip6_config_manual_address (dev->ip6_config);
++
++      if (manual_address &&
++	  grub_memcmp (manual_address->address, mode->station_ip.v6, sizeof (manual_address->address)) != 0)
++	{
++	  grub_efi_status_t status;
++	  grub_efi_pxe_ip_address_t station_ip;
++
++	  grub_memcpy (station_ip.v6.addr, manual_address->address, sizeof (station_ip.v6.addr));
++	  status = efi_call_3 (pxe->set_station_ip, pxe, &station_ip, NULL);
++
++	  if (status != GRUB_EFI_SUCCESS)
++	      grub_printf ("Couldn't set station ip\n");
++
++	  grub_free (manual_address);
++	}
++    }
++  else
++    {
++      grub_efi_ip4_config2_manual_address_t *manual_address;
++      manual_address = efi_ip4_config_manual_address (dev->ip4_config);
++
++      if (manual_address &&
++	  grub_memcmp (manual_address->address, mode->station_ip.v4, sizeof (manual_address->address)) != 0)
++	{
++	  grub_efi_status_t status;
++	  grub_efi_pxe_ip_address_t station_ip;
++	  grub_efi_pxe_ip_address_t subnet_mask;
++
++	  grub_memcpy (station_ip.v4.addr, manual_address->address, sizeof (station_ip.v4.addr));
++	  grub_memcpy (subnet_mask.v4.addr, manual_address->subnet_mask, sizeof (subnet_mask.v4.addr));
++
++	  status = efi_call_3 (pxe->set_station_ip, pxe, &station_ip, &subnet_mask);
++
++	  if (status != GRUB_EFI_SUCCESS)
++	      grub_printf ("Couldn't set station ip\n");
++
++	  grub_free (manual_address);
++	}
++    }
++
++#if 0
++  if (mode->using_ipv6)
++    {
++      grub_printf ("PXE STATION IP: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
++	mode->station_ip.v6.addr[0],
++	mode->station_ip.v6.addr[1],
++	mode->station_ip.v6.addr[2],
++	mode->station_ip.v6.addr[3],
++	mode->station_ip.v6.addr[4],
++	mode->station_ip.v6.addr[5],
++	mode->station_ip.v6.addr[6],
++	mode->station_ip.v6.addr[7],
++	mode->station_ip.v6.addr[8],
++	mode->station_ip.v6.addr[9],
++	mode->station_ip.v6.addr[10],
++	mode->station_ip.v6.addr[11],
++	mode->station_ip.v6.addr[12],
++	mode->station_ip.v6.addr[13],
++	mode->station_ip.v6.addr[14],
++	mode->station_ip.v6.addr[15]);
++    }
++  else
++    {
++      grub_printf ("PXE STATION IP: %d.%d.%d.%d\n",
++	mode->station_ip.v4.addr[0],
++	mode->station_ip.v4.addr[1],
++	mode->station_ip.v4.addr[2],
++	mode->station_ip.v4.addr[3]);
++      grub_printf ("PXE SUBNET MASK: %d.%d.%d.%d\n",
++	mode->subnet_mask.v4.addr[0],
++	mode->subnet_mask.v4.addr[1],
++	mode->subnet_mask.v4.addr[2],
++	mode->subnet_mask.v4.addr[3]);
++    }
++#endif
++
++  /* TODO: Set The Station IP to the IP2 Config */
++}
++
++static int
++parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
++{
++  grub_uint16_t newip[8];
++  const char *ptr = val;
++  int word, quaddot = -1;
++  int bracketed = 0;
++
++  if (ptr[0] == '[') {
++    bracketed = 1;
++    ptr++;
++  }
++
++  if (ptr[0] == ':' && ptr[1] != ':')
++    return 0;
++  if (ptr[0] == ':')
++    ptr++;
++
++  for (word = 0; word < 8; word++)
++    {
++      unsigned long t;
++      if (*ptr == ':')
++	{
++	  quaddot = word;
++	  word--;
++	  ptr++;
++	  continue;
++	}
++      t = grub_strtoul (ptr, (char **) &ptr, 16);
++      if (grub_errno)
++	{
++	  grub_errno = GRUB_ERR_NONE;
++	  break;
++	}
++      if (t & ~0xffff)
++	return 0;
++      newip[word] = grub_cpu_to_be16 (t);
++      if (*ptr != ':')
++	break;
++      ptr++;
++    }
++  if (quaddot == -1 && word < 7)
++    return 0;
++  if (quaddot != -1)
++    {
++      grub_memmove (&newip[quaddot + 7 - word], &newip[quaddot],
++		    (word - quaddot + 1) * sizeof (newip[0]));
++      grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0]));
++    }
++  grub_memcpy (ip, newip, 16);
++  if (bracketed && *ptr == ']') {
++    ptr++;
++  }
++  if (rest)
++    *rest = ptr;
++  return 1;
++}
++
++static grub_err_t
++pxe_open (struct grub_efi_net_device *dev,
++	  int prefer_ip6,
++	  grub_file_t file,
++	  const char *filename,
++	  int type __attribute__((unused)))
++{
++  int i;
++  char *p;
++  grub_efi_status_t status;
++  grub_efi_pxe_ip_address_t server_ip;
++  grub_efi_uint64_t file_size = 0;
++  grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe;
++
++  if (pxe->mode->using_ipv6)
++    {
++      const char *rest;
++      grub_uint64_t ip6[2];
++      if (parse_ip6 (file->device->net->server, ip6, &rest) && *rest == 0)
++	grub_memcpy (server_ip.v6.addr, ip6, sizeof (server_ip.v6.addr));
++      /* TODO: ERROR Handling Here */
++#if 0
++      grub_printf ("PXE SERVER IP: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
++	server_ip.v6.addr[0],
++	server_ip.v6.addr[1],
++	server_ip.v6.addr[2],
++	server_ip.v6.addr[3],
++	server_ip.v6.addr[4],
++	server_ip.v6.addr[5],
++	server_ip.v6.addr[6],
++	server_ip.v6.addr[7],
++	server_ip.v6.addr[8],
++	server_ip.v6.addr[9],
++	server_ip.v6.addr[10],
++	server_ip.v6.addr[11],
++	server_ip.v6.addr[12],
++	server_ip.v6.addr[13],
++	server_ip.v6.addr[14],
++	server_ip.v6.addr[15]);
++#endif
++    }
++  else
++    {
++      for (i = 0, p = file->device->net->server; i < 4; ++i, ++p)
++	server_ip.v4.addr[i] = grub_strtoul (p, &p, 10);
++    }
++
++  status = efi_call_10 (pxe->mtftp,
++	    pxe,
++	    GRUB_EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
++	    NULL,
++	    0,
++	    &file_size,
++	    NULL,
++	    &server_ip,
++	    (grub_efi_char8_t *)filename,
++	    NULL,
++	    0);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return grub_error (GRUB_ERR_IO, "Couldn't get file size");
++
++  file->size = (grub_off_t)file_size;
++  file->not_easily_seekable = 0;
++  file->data = 0;
++  file->device->net->offset = 0;
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++pxe_close (struct grub_efi_net_device *dev __attribute__((unused)),
++	  int prefer_ip6 __attribute__((unused)),
++	  grub_file_t file __attribute__((unused)))
++{
++  file->offset = 0;
++  file->size = 0;
++  file->device->net->offset = 0;
++
++  if (file->data)
++    {
++      grub_free (file->data);
++      file->data = NULL;
++    }
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_ssize_t
++pxe_read (struct grub_efi_net_device *dev,
++	  int prefer_ip6,
++	  grub_file_t file,
++	  char *buf,
++	  grub_size_t len)
++{
++  int i;
++  char *p;
++  grub_efi_status_t status;
++  grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe;
++  grub_efi_uint64_t bufsz = len;
++  grub_efi_pxe_ip_address_t server_ip;
++  char *buf2 = NULL;
++
++  if (file->data)
++    {
++      /* TODO: RANGE Check for offset and file size */
++      grub_memcpy (buf, (char*)file->data + file->device->net->offset, len);
++      file->device->net->offset += len;
++      return len;
++    }
++
++  if (file->device->net->offset)
++    {
++      grub_error (GRUB_ERR_BUG, "No Offet Read Possible");
++      grub_print_error ();
++      return 0;
++    }
++
++  if (pxe->mode->using_ipv6)
++    {
++      const char *rest;
++      grub_uint64_t ip6[2];
++      if (parse_ip6 (file->device->net->server, ip6, &rest) && *rest == 0)
++	grub_memcpy (server_ip.v6.addr, ip6, sizeof (server_ip.v6.addr));
++      /* TODO: ERROR Handling Here */
++    }
++  else
++    {
++      for (i = 0, p = file->device->net->server; i < 4; ++i, ++p)
++	server_ip.v4.addr[i] = grub_strtoul (p, &p, 10);
++    }
++
++  status = efi_call_10 (pxe->mtftp,
++	    pxe,
++	    GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE,
++	    buf,
++	    0,
++	    &bufsz,
++	    NULL,
++	    &server_ip,
++	    (grub_efi_char8_t *)file->device->net->name,
++	    NULL,
++	    0);
++
++  if (bufsz != file->size)
++    {
++      grub_error (GRUB_ERR_BUG, "Short read should not happen here");
++      grub_print_error ();
++      return 0;
++    }
++
++  if (status == GRUB_EFI_BUFFER_TOO_SMALL)
++    {
++
++      buf2 = grub_malloc (bufsz);
++
++      if (!buf2)
++	{
++	  grub_error (GRUB_ERR_OUT_OF_MEMORY, "ERROR OUT OF MEMORY");
++	  grub_print_error ();
++	  return 0;
++	}
++
++      status = efi_call_10 (pxe->mtftp,
++		pxe,
++		GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE,
++		buf2,
++		0,
++		&bufsz,
++		NULL,
++		&server_ip,
++		(grub_efi_char8_t *)file->device->net->name,
++		NULL,
++		0);
++    }
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      if (buf2)
++	grub_free (buf2);
++
++      grub_error (GRUB_ERR_IO, "Failed to Read File");
++      grub_print_error ();
++      return 0;
++    }
++
++  if (buf2)
++    grub_memcpy (buf, buf2, len);
++
++  file->device->net->offset = len;
++
++  if (buf2)
++    file->data = buf2;
++
++  return len;
++}
++
++struct grub_efi_net_io io_pxe =
++  {
++    .configure = pxe_configure,
++    .open = pxe_open,
++    .read = pxe_read,
++    .close = pxe_close
++  };
++
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index a6566bdb00a..cfe4cb62760 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -32,6 +32,9 @@
+ #include <grub/loader.h>
+ #include <grub/bufio.h>
+ #include <grub/kernel.h>
++#ifdef GRUB_MACHINE_EFI
++#include <grub/net/efi.h>
++#endif
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -1978,8 +1981,49 @@ static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute;
+ static grub_command_t cmd_lsroutes, cmd_lscards;
+ static grub_command_t cmd_lsaddr, cmd_slaac;
+ 
++#ifdef GRUB_MACHINE_EFI
++
++static enum {
++  INIT_MODE_NONE,
++  INIT_MODE_GRUB,
++  INIT_MODE_EFI
++} init_mode;
++
++static grub_command_t cmd_bootp, cmd_bootp6;
++
++#endif
++
+ GRUB_MOD_INIT(net)
+ {
++#ifdef GRUB_MACHINE_EFI
++  if (grub_net_open)
++    return;
++
++  if ((grub_efi_net_boot_from_https () || grub_efi_net_boot_from_opa ())
++      && grub_efi_net_fs_init ())
++    {
++      cmd_lsroutes = grub_register_command ("net_ls_routes", grub_efi_net_list_routes,
++					    "", N_("list network routes"));
++      cmd_lscards = grub_register_command ("net_ls_cards", grub_efi_net_list_cards,
++					   "", N_("list network cards"));
++      cmd_lsaddr = grub_register_command ("net_ls_addr", grub_efi_net_list_addrs,
++					  "", N_("list network addresses"));
++      cmd_addaddr = grub_register_command ("net_add_addr", grub_efi_net_add_addr,
++					    /* TRANSLATORS: HWADDRESS stands for
++					       "hardware address".  */
++					  N_("SHORTNAME CARD ADDRESS [HWADDRESS]"),
++					  N_("Add a network address."));
++      cmd_bootp = grub_register_command ("net_bootp", grub_efi_net_bootp,
++					 N_("[CARD]"),
++					 N_("perform a bootp autoconfiguration"));
++      cmd_bootp6 = grub_register_command ("net_bootp6", grub_efi_net_bootp6,
++					 N_("[CARD]"),
++					 N_("perform a bootp autoconfiguration"));
++      init_mode = INIT_MODE_EFI;
++      return;
++    }
++#endif
++
+   grub_register_variable_hook ("net_default_server", defserver_get_env,
+ 			       defserver_set_env);
+   grub_env_export ("net_default_server");
+@@ -2027,10 +2071,37 @@ GRUB_MOD_INIT(net)
+ 						grub_net_restore_hw,
+ 						GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
+   grub_net_poll_cards_idle = grub_net_poll_cards_idle_real;
++
++#ifdef GRUB_MACHINE_EFI
++  grub_env_set ("grub_netfs_type", "grub");
++  grub_register_variable_hook ("grub_netfs_type", 0, grub_env_write_readonly);
++  grub_env_export ("grub_netfs_type");
++  init_mode = INIT_MODE_GRUB;
++#endif
++
+ }
+ 
+ GRUB_MOD_FINI(net)
+ {
++
++#ifdef GRUB_MACHINE_EFI
++  if (init_mode == INIT_MODE_NONE)
++    return;
++
++  if (init_mode == INIT_MODE_EFI)
++    {
++      grub_unregister_command (cmd_lsroutes);
++      grub_unregister_command (cmd_lscards);
++      grub_unregister_command (cmd_lsaddr);
++      grub_unregister_command (cmd_addaddr);
++      grub_unregister_command (cmd_bootp);
++      grub_unregister_command (cmd_bootp6);
++      grub_efi_net_fs_fini ();
++      init_mode = INIT_MODE_NONE;
++      return;
++    }
++#endif
++
+   grub_register_variable_hook ("net_default_server", 0, 0);
+   grub_register_variable_hook ("pxe_default_server", 0, 0);
+ 
+@@ -2049,4 +2120,7 @@ GRUB_MOD_FINI(net)
+   grub_net_fini_hw (0);
+   grub_loader_unregister_preboot_hook (fini_hnd);
+   grub_net_poll_cards_idle = grub_net_poll_cards_idle_real;
++#ifdef GRUB_MACHINE_EFI
++  init_mode = INIT_MODE_NONE;
++#endif
+ }
+diff --git a/util/grub-mknetdir.c b/util/grub-mknetdir.c
+index 8366a1121a1..8997336e901 100644
+--- a/util/grub-mknetdir.c
++++ b/util/grub-mknetdir.c
+@@ -32,13 +32,15 @@
+ 
+ static char *rootdir = NULL, *subdir = NULL;
+ static char *debug_image = NULL;
++static char efi_netfs = 0;
+ 
+ enum
+   {
+     OPTION_NET_DIRECTORY = 0x301,
+     OPTION_SUBDIR,
+     OPTION_DEBUG,
+-    OPTION_DEBUG_IMAGE
++    OPTION_DEBUG_IMAGE,
++    OPTION_DEBUG_EFI_NETFS
+   };
+ 
+ static struct argp_option options[] = {
+@@ -49,6 +51,7 @@ static struct argp_option options[] = {
+    0, N_("relative subdirectory on network server"), 2},
+   {"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2},
+   {"debug-image", OPTION_DEBUG_IMAGE, N_("STRING"), OPTION_HIDDEN, 0, 2},
++  {"debug-efi-netfs", OPTION_DEBUG_EFI_NETFS, 0, OPTION_HIDDEN, 0, 2},
+   {0, 0, 0, 0, 0, 0}
+ };
+ 
+@@ -67,6 +70,9 @@ argp_parser (int key, char *arg, struct argp_state *state)
+       free (subdir);
+       subdir = xstrdup (arg);
+       return 0;
++    case OPTION_DEBUG_EFI_NETFS:
++      efi_netfs = 1;
++      return 0;
+       /* This is an undocumented feature...  */
+     case OPTION_DEBUG:
+       verbosity++;
+@@ -82,7 +88,6 @@ argp_parser (int key, char *arg, struct argp_state *state)
+     }
+ }
+ 
+-
+ struct argp argp = {
+   options, argp_parser, NULL,
+   "\v"N_("Prepares GRUB network boot images at net_directory/subdir "
+@@ -92,7 +97,7 @@ struct argp argp = {
+ 
+ static char *base;
+ 
+-static const struct
++static struct
+ {
+   const char *mkimage_target;
+   const char *netmodule;
+@@ -153,6 +158,7 @@ process_input_dir (const char *input_dir, enum grub_install_plat platform)
+   grub_install_push_module (targets[platform].netmodule);
+ 
+   output = grub_util_path_concat_ext (2, grubdir, "core", targets[platform].ext);
++
+   grub_install_make_image_wrap (input_dir, prefix, output,
+ 				0, load_cfg,
+ 				targets[platform].mkimage_target, 0);
+@@ -189,7 +195,16 @@ main (int argc, char *argv[])
+ 
+   grub_install_mkdir_p (base);
+ 
+-  grub_install_push_module ("tftp");
++  if (!efi_netfs)
++    {
++      grub_install_push_module ("tftp");
++      grub_install_push_module ("http");
++    }
++  else
++    {
++      targets[GRUB_INSTALL_PLATFORM_I386_EFI].netmodule = "efi_netfs";
++      targets[GRUB_INSTALL_PLATFORM_X86_64_EFI].netmodule = "efi_netfs";
++    }
+ 
+   if (!grub_install_source_directory)
+     {
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 852daddfb0f..fbd1c4b529d 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -549,6 +549,23 @@ typedef union
+ 
+ typedef grub_efi_uint64_t grub_efi_physical_address_t;
+ typedef grub_efi_uint64_t grub_efi_virtual_address_t;
++typedef struct {
++  grub_uint8_t addr[4];
++} grub_efi_pxe_ipv4_address_t;
++
++typedef struct {
++  grub_uint8_t addr[16];
++} grub_efi_pxe_ipv6_address_t;
++
++typedef struct {
++  grub_uint8_t addr[32];
++} grub_efi_pxe_mac_address_t;
++
++typedef union {
++    grub_uint32_t addr[4];
++    grub_efi_pxe_ipv4_address_t v4;
++    grub_efi_pxe_ipv6_address_t v6;
++} grub_efi_pxe_ip_address_t;
+ 
+ struct grub_efi_guid
+ {
+@@ -812,6 +829,8 @@ struct grub_efi_ipv6_device_path
+   grub_efi_uint16_t remote_port;
+   grub_efi_uint16_t protocol;
+   grub_efi_uint8_t static_ip_address;
++  grub_efi_uint8_t prefix_length;
++  grub_efi_ipv6_address_t gateway_ip_address;
+ } GRUB_PACKED;
+ typedef struct grub_efi_ipv6_device_path grub_efi_ipv6_device_path_t;
+ 
+@@ -861,6 +880,15 @@ struct grub_efi_uri_device_path
+ } GRUB_PACKED;
+ typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t;
+ 
++#define GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE                31
++struct grub_efi_dns_device_path
++{
++  grub_efi_device_path_t header;
++  grub_efi_uint8_t is_ipv6;
++  grub_efi_pxe_ip_address_t dns_server_ip[0];
++} GRUB_PACKED;
++typedef struct grub_efi_dns_device_path grub_efi_dns_device_path_t;
++
+ #define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE	10
+ 
+ /* Media Device Path.  */
+@@ -943,6 +971,23 @@ struct grub_efi_bios_device_path
+ } GRUB_PACKED;
+ typedef struct grub_efi_bios_device_path grub_efi_bios_device_path_t;
+ 
++/* Service Binding definitions */
++struct grub_efi_service_binding;
++
++typedef grub_efi_status_t
++(*grub_efi_service_binding_create_child) (struct grub_efi_service_binding *this,
++                                          grub_efi_handle_t *child_handle);
++
++typedef grub_efi_status_t
++(*grub_efi_service_binding_destroy_child) (struct grub_efi_service_binding *this,
++                                           grub_efi_handle_t *child_handle);
++
++typedef struct grub_efi_service_binding
++{
++  grub_efi_service_binding_create_child create_child;
++  grub_efi_service_binding_destroy_child destroy_child;
++} grub_efi_service_binding_t;
++
+ struct grub_efi_open_protocol_information_entry
+ {
+   grub_efi_handle_t agent_handle;
+@@ -1492,23 +1537,27 @@ typedef struct grub_efi_pxe_tftp_error
+   grub_efi_char8_t error_string[127];
+ } grub_efi_pxe_tftp_error_t;
+ 
+-typedef struct {
+-  grub_uint8_t addr[4];
+-} grub_efi_pxe_ipv4_address_t;
++typedef grub_efi_uint16_t grub_efi_pxe_base_code_udp_port_t;
+ 
+-typedef struct {
+-  grub_uint8_t addr[16];
+-} grub_efi_pxe_ipv6_address_t;
++typedef enum {
++  GRUB_EFI_PXE_BASE_CODE_TFTP_FIRST,
++  GRUB_EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
++  GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE,
++  GRUB_EFI_PXE_BASE_CODE_TFTP_WRITE_FILE,
++  GRUB_EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY,
++  GRUB_EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE,
++  GRUB_EFI_PXE_BASE_CODE_MTFTP_READ_FILE,
++  GRUB_EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY,
++  GRUB_EFI_PXE_BASE_CODE_MTFTP_LAST
++} grub_efi_pxe_base_code_tftp_opcode_t;
+ 
+ typedef struct {
+-  grub_uint8_t addr[32];
+-} grub_efi_pxe_mac_address_t;
+-
+-typedef union {
+-  grub_uint32_t addr[4];
+-  grub_efi_pxe_ipv4_address_t v4;
+-  grub_efi_pxe_ipv6_address_t v6;
+-} grub_efi_pxe_ip_address_t;
++  grub_efi_ip_address_t mcast_ip;
++  grub_efi_pxe_base_code_udp_port_t c_port;
++  grub_efi_pxe_base_code_udp_port_t s_port;
++  grub_efi_uint16_t listen_timeout;
++  grub_efi_uint16_t transmit_timeout;
++} grub_efi_pxe_base_code_mtftp_info_t;
+ 
+ #define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8
+ typedef struct grub_efi_pxe_ip_filter
+@@ -1575,17 +1624,31 @@ typedef struct grub_efi_pxe_mode
+ typedef struct grub_efi_pxe
+ {
+   grub_uint64_t rev;
+-  void (*start) (void);
++  grub_efi_status_t (*start) (struct grub_efi_pxe *this, grub_efi_boolean_t use_ipv6);
+   void (*stop) (void);
+-  void (*dhcp) (void);
++  grub_efi_status_t (*dhcp) (struct grub_efi_pxe *this,
++			    grub_efi_boolean_t sort_offers);
+   void (*discover) (void);
+-  void (*mftp) (void);
++  grub_efi_status_t (*mtftp) (struct grub_efi_pxe *this,
++			    grub_efi_pxe_base_code_tftp_opcode_t operation,
++			    void *buffer_ptr,
++			    grub_efi_boolean_t overwrite,
++			    grub_efi_uint64_t *buffer_size,
++			    grub_efi_uintn_t *block_size,
++			    grub_efi_pxe_ip_address_t *server_ip,
++			    //grub_efi_ip_address_t *server_ip,
++			    grub_efi_char8_t *filename,
++			    grub_efi_pxe_base_code_mtftp_info_t *info,
++			    grub_efi_boolean_t dont_use_buffer);
+   void (*udpwrite) (void);
+   void (*udpread) (void);
+   void (*setipfilter) (void);
+   void (*arp) (void);
+   void (*setparams) (void);
+-  void (*setstationip) (void);
++  grub_efi_status_t (*set_station_ip) (struct grub_efi_pxe *this,
++			    grub_efi_pxe_ip_address_t *new_station_ip,
++			    grub_efi_pxe_ip_address_t *new_subnet_mask);
++  //void (*setstationip) (void);
+   void (*setpackets) (void);
+   struct grub_efi_pxe_mode *mode;
+ } grub_efi_pxe_t;
+@@ -1827,6 +1890,44 @@ struct grub_efi_ip4_config2_protocol
+ };
+ typedef struct grub_efi_ip4_config2_protocol grub_efi_ip4_config2_protocol_t;
+ 
++struct grub_efi_ip4_route_table {
++  grub_efi_ipv4_address_t subnet_address;
++  grub_efi_ipv4_address_t subnet_mask;
++  grub_efi_ipv4_address_t gateway_address;
++};
++
++typedef struct grub_efi_ip4_route_table grub_efi_ip4_route_table_t;
++
++#define GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE 32
++
++struct grub_efi_ip4_config2_interface_info {
++  grub_efi_char16_t name[GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE];
++  grub_efi_uint8_t if_type;
++  grub_efi_uint32_t hw_address_size;
++  grub_efi_mac_address_t hw_address;
++  grub_efi_ipv4_address_t station_address;
++  grub_efi_ipv4_address_t subnet_mask;
++  grub_efi_uint32_t route_table_size;
++  grub_efi_ip4_route_table_t *route_table;
++};
++
++typedef struct grub_efi_ip4_config2_interface_info grub_efi_ip4_config2_interface_info_t;
++
++enum grub_efi_ip4_config2_policy {
++  GRUB_EFI_IP4_CONFIG2_POLICY_STATIC,
++  GRUB_EFI_IP4_CONFIG2_POLICY_DHCP,
++  GRUB_EFI_IP4_CONFIG2_POLICY_MAX
++};
++
++typedef enum grub_efi_ip4_config2_policy grub_efi_ip4_config2_policy_t;
++
++struct grub_efi_ip4_config2_manual_address {
++  grub_efi_ipv4_address_t address;
++  grub_efi_ipv4_address_t subnet_mask;
++};
++
++typedef struct grub_efi_ip4_config2_manual_address grub_efi_ip4_config2_manual_address_t;
++
+ enum grub_efi_ip6_config_data_type {
+   GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO,
+   GRUB_EFI_IP6_CONFIG_DATA_TYPE_ALT_INTERFACEID,
+@@ -1861,6 +1962,49 @@ struct grub_efi_ip6_config_protocol
+ };
+ typedef struct grub_efi_ip6_config_protocol grub_efi_ip6_config_protocol_t;
+ 
++enum grub_efi_ip6_config_policy {
++  GRUB_EFI_IP6_CONFIG_POLICY_MANUAL,
++  GRUB_EFI_IP6_CONFIG_POLICY_AUTOMATIC
++};
++typedef enum grub_efi_ip6_config_policy grub_efi_ip6_config_policy_t;
++
++struct grub_efi_ip6_address_info {
++  grub_efi_ipv6_address_t address;
++  grub_efi_uint8_t prefix_length;
++};
++typedef struct grub_efi_ip6_address_info grub_efi_ip6_address_info_t;
++
++struct grub_efi_ip6_route_table {
++  grub_efi_pxe_ipv6_address_t gateway;
++  grub_efi_pxe_ipv6_address_t destination;
++  grub_efi_uint8_t prefix_length;
++};
++typedef struct grub_efi_ip6_route_table grub_efi_ip6_route_table_t;
++
++struct grub_efi_ip6_config_interface_info {
++  grub_efi_char16_t name[32];
++  grub_efi_uint8_t if_type;
++  grub_efi_uint32_t hw_address_size;
++  grub_efi_mac_address_t hw_address;
++  grub_efi_uint32_t address_info_count;
++  grub_efi_ip6_address_info_t *address_info;
++  grub_efi_uint32_t route_count;
++  grub_efi_ip6_route_table_t *route_table;
++};
++typedef struct grub_efi_ip6_config_interface_info grub_efi_ip6_config_interface_info_t;
++
++struct grub_efi_ip6_config_dup_addr_detect_transmits {
++  grub_efi_uint32_t dup_addr_detect_transmits;
++};
++typedef struct grub_efi_ip6_config_dup_addr_detect_transmits grub_efi_ip6_config_dup_addr_detect_transmits_t;
++
++struct grub_efi_ip6_config_manual_address {
++  grub_efi_ipv6_address_t address;
++  grub_efi_boolean_t is_anycast;
++  grub_efi_uint8_t prefix_length;
++};
++typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_address_t;
++
+ #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
+   || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__)
+ 
+diff --git a/include/grub/efi/dhcp.h b/include/grub/efi/dhcp.h
+new file mode 100644
+index 00000000000..fdb88eb810e
+--- /dev/null
++++ b/include/grub/efi/dhcp.h
+@@ -0,0 +1,343 @@
++#ifndef GRUB_EFI_DHCP_HEADER
++#define GRUB_EFI_DHCP_HEADER	1
++
++#define GRUB_EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID \
++  { 0x9d9a39d8, 0xbd42, 0x4a73, \
++    { 0xa4, 0xd5, 0x8e, 0xe9, 0x4b, 0xe1, 0x13, 0x80 } \
++  }
++
++#define GRUB_EFI_DHCP4_PROTOCOL_GUID \
++  { 0x8a219718, 0x4ef5, 0x4761, \
++    { 0x91, 0xc8, 0xc0, 0xf0, 0x4b, 0xda, 0x9e, 0x56 } \
++  }
++
++#define GRUB_EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID \
++  { 0x9fb9a8a1, 0x2f4a, 0x43a6, \
++    { 0x88, 0x9c, 0xd0, 0xf7, 0xb6, 0xc4 ,0x7a, 0xd5 } \
++  }
++
++#define GRUB_EFI_DHCP6_PROTOCOL_GUID \
++  { 0x87c8bad7, 0x595, 0x4053, \
++    { 0x82, 0x97, 0xde, 0xde, 0x39, 0x5f, 0x5d, 0x5b } \
++  }
++
++typedef struct grub_efi_dhcp4_protocol grub_efi_dhcp4_protocol_t;
++
++enum grub_efi_dhcp4_state {
++  GRUB_EFI_DHCP4_STOPPED,
++  GRUB_EFI_DHCP4_INIT,
++  GRUB_EFI_DHCP4_SELECTING,
++  GRUB_EFI_DHCP4_REQUESTING,
++  GRUB_EFI_DHCP4_BOUND,
++  GRUB_EFI_DHCP4_RENEWING,
++  GRUB_EFI_DHCP4_REBINDING,
++  GRUB_EFI_DHCP4_INIT_REBOOT,
++  GRUB_EFI_DHCP4_REBOOTING
++};
++
++typedef enum grub_efi_dhcp4_state grub_efi_dhcp4_state_t;
++
++struct grub_efi_dhcp4_header {
++  grub_efi_uint8_t op_code;
++  grub_efi_uint8_t hw_type;
++  grub_efi_uint8_t hw_addr_len;
++  grub_efi_uint8_t hops;
++  grub_efi_uint32_t xid;
++  grub_efi_uint16_t seconds;
++  grub_efi_uint16_t reserved;
++  grub_efi_ipv4_address_t client_addr;
++  grub_efi_ipv4_address_t your_addr;
++  grub_efi_ipv4_address_t server_addr;
++  grub_efi_ipv4_address_t gateway_addr;
++  grub_efi_uint8_t client_hw_addr[16];
++  grub_efi_char8_t server_name[64];
++  grub_efi_char8_t boot_file_name[128];
++} GRUB_PACKED;
++
++typedef struct grub_efi_dhcp4_header grub_efi_dhcp4_header_t;
++
++struct grub_efi_dhcp4_packet {
++  grub_efi_uint32_t size;
++  grub_efi_uint32_t length;
++  struct {
++    grub_efi_dhcp4_header_t header;
++    grub_efi_uint32_t magik;
++    grub_efi_uint8_t option[1];
++  } dhcp4;
++} GRUB_PACKED;
++
++typedef struct grub_efi_dhcp4_packet grub_efi_dhcp4_packet_t;
++
++struct grub_efi_dhcp4_listen_point {
++  grub_efi_ipv4_address_t listen_address;
++  grub_efi_ipv4_address_t subnet_mask;
++  grub_efi_uint16_t listen_port;
++};
++
++typedef struct grub_efi_dhcp4_listen_point grub_efi_dhcp4_listen_point_t;
++
++struct grub_efi_dhcp4_transmit_receive_token {
++  grub_efi_status_t status;
++  grub_efi_event_t completion_event;
++  grub_efi_ipv4_address_t remote_address;
++  grub_efi_uint16_t remote_port;
++  grub_efi_ipv4_address_t gateway_address;
++  grub_efi_uint32_t listen_point_count;
++  grub_efi_dhcp4_listen_point_t *listen_points;
++  grub_efi_uint32_t timeout_value;
++  grub_efi_dhcp4_packet_t *packet;
++  grub_efi_uint32_t response_count;
++  grub_efi_dhcp4_packet_t *response_list;
++};
++
++typedef struct grub_efi_dhcp4_transmit_receive_token grub_efi_dhcp4_transmit_receive_token_t;
++
++enum grub_efi_dhcp4_event {
++  GRUB_EFI_DHCP4_SEND_DISCOVER = 0X01,
++  GRUB_EFI_DHCP4_RCVD_OFFER,
++  GRUB_EFI_DHCP4_SELECT_OFFER,
++  GRUB_EFI_DHCP4_SEND_REQUEST,
++  GRUB_EFI_DHCP4_RCVD_ACK,
++  GRUB_EFI_DHCP4_RCVD_NAK,
++  GRUB_EFI_DHCP4_SEND_DECLINE,
++  GRUB_EFI_DHCP4_BOUND_COMPLETED,
++  GRUB_EFI_DHCP4_ENTER_RENEWING,
++  GRUB_EFI_DHCP4_ENTER_REBINDING,
++  GRUB_EFI_DHCP4_ADDRESS_LOST,
++  GRUB_EFI_DHCP4_FAIL
++};
++
++typedef enum grub_efi_dhcp4_event grub_efi_dhcp4_event_t;
++
++struct grub_efi_dhcp4_packet_option {
++  grub_efi_uint8_t op_code;
++  grub_efi_uint8_t length;
++  grub_efi_uint8_t data[1];
++} GRUB_PACKED;
++
++typedef struct grub_efi_dhcp4_packet_option grub_efi_dhcp4_packet_option_t;
++
++struct grub_efi_dhcp4_config_data {
++  grub_efi_uint32_t discover_try_count;
++  grub_efi_uint32_t *discover_timeout;
++  grub_efi_uint32_t request_try_count;
++  grub_efi_uint32_t *request_timeout;
++  grub_efi_ipv4_address_t client_address;
++  grub_efi_status_t (*dhcp4_callback) (
++    grub_efi_dhcp4_protocol_t *this,
++    void *context,
++    grub_efi_dhcp4_state_t current_state,
++    grub_efi_dhcp4_event_t dhcp4_event,
++    grub_efi_dhcp4_packet_t *packet,
++    grub_efi_dhcp4_packet_t **new_packet
++  );
++  void *callback_context;
++  grub_efi_uint32_t option_count;
++  grub_efi_dhcp4_packet_option_t **option_list;
++};
++
++typedef struct grub_efi_dhcp4_config_data grub_efi_dhcp4_config_data_t;
++
++struct grub_efi_dhcp4_mode_data {
++  grub_efi_dhcp4_state_t state;
++  grub_efi_dhcp4_config_data_t config_data;
++  grub_efi_ipv4_address_t client_address;
++  grub_efi_mac_address_t client_mac_address;
++  grub_efi_ipv4_address_t server_address;
++  grub_efi_ipv4_address_t router_address;
++  grub_efi_ipv4_address_t subnet_mask;
++  grub_efi_uint32_t lease_time;
++  grub_efi_dhcp4_packet_t *reply_packet;
++};
++
++typedef struct grub_efi_dhcp4_mode_data grub_efi_dhcp4_mode_data_t;
++
++struct grub_efi_dhcp4_protocol {
++  grub_efi_status_t (*get_mode_data) (grub_efi_dhcp4_protocol_t *this,
++	      grub_efi_dhcp4_mode_data_t *dhcp4_mode_data);
++  grub_efi_status_t (*configure) (grub_efi_dhcp4_protocol_t *this,
++	      grub_efi_dhcp4_config_data_t *dhcp4_cfg_data);
++  grub_efi_status_t (*start) (grub_efi_dhcp4_protocol_t *this,
++	      grub_efi_event_t completion_event);
++  grub_efi_status_t (*renew_rebind) (grub_efi_dhcp4_protocol_t *this,
++	      grub_efi_boolean_t rebind_request,
++	      grub_efi_event_t completion_event);
++  grub_efi_status_t (*release) (grub_efi_dhcp4_protocol_t *this);
++  grub_efi_status_t (*stop) (grub_efi_dhcp4_protocol_t *this);
++  grub_efi_status_t (*build) (grub_efi_dhcp4_protocol_t *this,
++	      grub_efi_dhcp4_packet_t *seed_packet,
++	      grub_efi_uint32_t delete_count,
++	      grub_efi_uint8_t *delete_list,
++	      grub_efi_uint32_t append_count,
++	      grub_efi_dhcp4_packet_option_t *append_list[],
++	      grub_efi_dhcp4_packet_t **new_packet);
++  grub_efi_status_t (*transmit_receive) (grub_efi_dhcp4_protocol_t *this,
++	      grub_efi_dhcp4_transmit_receive_token_t *token);
++  grub_efi_status_t (*parse) (grub_efi_dhcp4_protocol_t *this,
++	      grub_efi_dhcp4_packet_t *packet,
++	      grub_efi_uint32_t *option_count,
++	      grub_efi_dhcp4_packet_option_t *packet_option_list[]);
++};
++
++typedef struct grub_efi_dhcp6_protocol grub_efi_dhcp6_protocol_t;
++
++struct grub_efi_dhcp6_retransmission {
++  grub_efi_uint32_t irt;
++  grub_efi_uint32_t mrc;
++  grub_efi_uint32_t mrt;
++  grub_efi_uint32_t mrd;
++};
++
++typedef struct grub_efi_dhcp6_retransmission grub_efi_dhcp6_retransmission_t;
++
++enum grub_efi_dhcp6_event {
++  GRUB_EFI_DHCP6_SEND_SOLICIT,
++  GRUB_EFI_DHCP6_RCVD_ADVERTISE,
++  GRUB_EFI_DHCP6_SELECT_ADVERTISE,
++  GRUB_EFI_DHCP6_SEND_REQUEST,
++  GRUB_EFI_DHCP6_RCVD_REPLY,
++  GRUB_EFI_DHCP6_RCVD_RECONFIGURE,
++  GRUB_EFI_DHCP6_SEND_DECLINE,
++  GRUB_EFI_DHCP6_SEND_CONFIRM,
++  GRUB_EFI_DHCP6_SEND_RELEASE,
++  GRUB_EFI_DHCP6_SEND_RENEW,
++  GRUB_EFI_DHCP6_SEND_REBIND
++};
++
++typedef enum grub_efi_dhcp6_event grub_efi_dhcp6_event_t;
++
++struct grub_efi_dhcp6_packet_option {
++  grub_efi_uint16_t op_code;
++  grub_efi_uint16_t op_len;
++  grub_efi_uint8_t data[1];
++} GRUB_PACKED;
++
++typedef struct grub_efi_dhcp6_packet_option grub_efi_dhcp6_packet_option_t;
++
++struct grub_efi_dhcp6_header {
++  grub_efi_uint32_t transaction_id:24;
++  grub_efi_uint32_t message_type:8;
++} GRUB_PACKED;
++
++typedef struct grub_efi_dhcp6_header grub_efi_dhcp6_header_t;
++
++struct grub_efi_dhcp6_packet {
++  grub_efi_uint32_t size;
++  grub_efi_uint32_t length;
++  struct {
++    grub_efi_dhcp6_header_t header;
++    grub_efi_uint8_t option[1];
++  } dhcp6;
++} GRUB_PACKED;
++
++typedef struct grub_efi_dhcp6_packet grub_efi_dhcp6_packet_t;
++
++struct grub_efi_dhcp6_ia_address {
++  grub_efi_ipv6_address_t ip_address;
++  grub_efi_uint32_t preferred_lifetime;
++  grub_efi_uint32_t valid_lifetime;
++};
++
++typedef struct grub_efi_dhcp6_ia_address grub_efi_dhcp6_ia_address_t;
++
++enum grub_efi_dhcp6_state {
++  GRUB_EFI_DHCP6_INIT,
++  GRUB_EFI_DHCP6_SELECTING,
++  GRUB_EFI_DHCP6_REQUESTING,
++  GRUB_EFI_DHCP6_DECLINING,
++  GRUB_EFI_DHCP6_CONFIRMING,
++  GRUB_EFI_DHCP6_RELEASING,
++  GRUB_EFI_DHCP6_BOUND,
++  GRUB_EFI_DHCP6_RENEWING,
++  GRUB_EFI_DHCP6_REBINDING
++};
++
++typedef enum grub_efi_dhcp6_state grub_efi_dhcp6_state_t;
++
++#define GRUB_EFI_DHCP6_IA_TYPE_NA 3
++#define GRUB_EFI_DHCP6_IA_TYPE_TA 4
++
++struct grub_efi_dhcp6_ia_descriptor {
++  grub_efi_uint16_t type;
++  grub_efi_uint32_t ia_id;
++};
++
++typedef struct grub_efi_dhcp6_ia_descriptor grub_efi_dhcp6_ia_descriptor_t;
++
++struct grub_efi_dhcp6_ia {
++  grub_efi_dhcp6_ia_descriptor_t descriptor;
++  grub_efi_dhcp6_state_t state;
++  grub_efi_dhcp6_packet_t *reply_packet;
++  grub_efi_uint32_t ia_address_count;
++  grub_efi_dhcp6_ia_address_t ia_address[1];
++};
++
++typedef struct grub_efi_dhcp6_ia grub_efi_dhcp6_ia_t;
++
++struct grub_efi_dhcp6_duid {
++  grub_efi_uint16_t length;
++  grub_efi_uint8_t duid[1];
++};
++
++typedef struct grub_efi_dhcp6_duid grub_efi_dhcp6_duid_t;
++
++struct grub_efi_dhcp6_mode_data {
++  grub_efi_dhcp6_duid_t *client_id;
++  grub_efi_dhcp6_ia_t *ia;
++};
++
++typedef struct grub_efi_dhcp6_mode_data grub_efi_dhcp6_mode_data_t;
++
++struct grub_efi_dhcp6_config_data {
++  grub_efi_status_t (*dhcp6_callback) (grub_efi_dhcp6_protocol_t this,
++		void *context,
++		grub_efi_dhcp6_state_t current_state,
++		grub_efi_dhcp6_event_t dhcp6_event,
++		grub_efi_dhcp6_packet_t *packet,
++		grub_efi_dhcp6_packet_t **new_packet);
++  void *callback_context;
++  grub_efi_uint32_t option_count;
++  grub_efi_dhcp6_packet_option_t **option_list;
++  grub_efi_dhcp6_ia_descriptor_t ia_descriptor;
++  grub_efi_event_t ia_info_event;
++  grub_efi_boolean_t reconfigure_accept;
++  grub_efi_boolean_t rapid_commit;
++  grub_efi_dhcp6_retransmission_t *solicit_retransmission;
++};
++
++typedef struct grub_efi_dhcp6_config_data grub_efi_dhcp6_config_data_t;
++
++struct grub_efi_dhcp6_protocol {
++  grub_efi_status_t (*get_mode_data) (grub_efi_dhcp6_protocol_t *this,
++	    grub_efi_dhcp6_mode_data_t *dhcp6_mode_data,
++	    grub_efi_dhcp6_config_data_t *dhcp6_config_data);
++  grub_efi_status_t (*configure) (grub_efi_dhcp6_protocol_t *this,
++	    grub_efi_dhcp6_config_data_t *dhcp6_cfg_data);
++  grub_efi_status_t (*start) (grub_efi_dhcp6_protocol_t *this);
++  grub_efi_status_t (*info_request) (grub_efi_dhcp6_protocol_t *this,
++	    grub_efi_boolean_t send_client_id,
++	    grub_efi_dhcp6_packet_option_t *option_request,
++	    grub_efi_uint32_t option_count,
++	    grub_efi_dhcp6_packet_option_t *option_list[],
++	    grub_efi_dhcp6_retransmission_t *retransmission,
++	    grub_efi_event_t timeout_event,
++	    grub_efi_status_t (*reply_callback) (grub_efi_dhcp6_protocol_t *this,
++		    void *context,
++		    grub_efi_dhcp6_packet_t *packet),
++	    void *callback_context);
++  grub_efi_status_t (*renew_rebind) (grub_efi_dhcp6_protocol_t *this,
++	    grub_efi_boolean_t rebind_request);
++  grub_efi_status_t (*decline) (grub_efi_dhcp6_protocol_t *this,
++	    grub_efi_uint32_t address_count,
++	    grub_efi_ipv6_address_t *addresses);
++  grub_efi_status_t (*release) (grub_efi_dhcp6_protocol_t *this,
++	    grub_efi_uint32_t address_count,
++	    grub_efi_ipv6_address_t *addresses);
++  grub_efi_status_t (*stop) (grub_efi_dhcp6_protocol_t *this);
++  grub_efi_status_t (*parse) (grub_efi_dhcp6_protocol_t *this,
++	    grub_efi_dhcp6_packet_t *packet,
++	    grub_efi_uint32_t *option_count,
++	    grub_efi_dhcp6_packet_option_t *packet_option_list[]);
++};
++
++#endif /* ! GRUB_EFI_DHCP_HEADER */
+diff --git a/include/grub/efi/http.h b/include/grub/efi/http.h
+new file mode 100644
+index 00000000000..c5e9a89f505
+--- /dev/null
++++ b/include/grub/efi/http.h
+@@ -0,0 +1,215 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2006,2007,2008  Free Software Foundation, Inc.
++ *
++ *  GRUB 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 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef GRUB_EFI_HTTP_HEADER
++#define GRUB_EFI_HTTP_HEADER	1
++
++#include <grub/symbol.h>
++#include <grub/net.h>
++#include <grub/efi/api.h>
++
++#define GRUB_EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID \
++  { 0xbdc8e6af, 0xd9bc, 0x4379, \
++      { 0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } \
++  }
++
++#define GRUB_EFI_HTTP_PROTOCOL_GUID \
++  { 0x7A59B29B, 0x910B, 0x4171, \
++      { 0x82, 0x42, 0xA8, 0x5A, 0x0D, 0xF2, 0x5B, 0x5B } \
++  }
++
++#define EFIHTTP_WAIT_TIME 10000 // 10000ms = 10s
++#define EFIHTTP_RX_BUF_LEN 10240
++
++//******************************************
++// Protocol Interface Structure
++//******************************************
++struct grub_efi_http;
++
++//******************************************
++// EFI_HTTP_VERSION
++//******************************************
++typedef enum {
++  GRUB_EFI_HTTPVERSION10,
++  GRUB_EFI_HTTPVERSION11,
++  GRUB_EFI_HTTPVERSIONUNSUPPORTED
++} grub_efi_http_version_t;
++
++//******************************************
++// EFI_HTTPv4_ACCESS_POINT
++//******************************************
++typedef struct {
++  grub_efi_boolean_t use_default_address;
++  grub_efi_ipv4_address_t local_address;
++  grub_efi_ipv4_address_t local_subnet;
++  grub_efi_uint16_t local_port;
++} grub_efi_httpv4_access_point_t;
++
++//******************************************
++// EFI_HTTPv6_ACCESS_POINT
++//******************************************
++typedef struct {
++  grub_efi_ipv6_address_t local_address;
++  grub_efi_uint16_t local_port;
++} grub_efi_httpv6_access_point_t;
++
++//******************************************
++// EFI_HTTP_CONFIG_DATA
++//******************************************
++typedef struct {
++  grub_efi_http_version_t http_version;
++  grub_efi_uint32_t timeout_millisec;
++  grub_efi_boolean_t local_address_is_ipv6;
++  union {
++    grub_efi_httpv4_access_point_t *ipv4_node;
++    grub_efi_httpv6_access_point_t *ipv6_node;
++  } access_point;
++} grub_efi_http_config_data_t;
++
++//******************************************
++// EFI_HTTP_METHOD
++//******************************************
++typedef enum {
++  GRUB_EFI_HTTPMETHODGET,
++  GRUB_EFI_HTTPMETHODPOST,
++  GRUB_EFI_HTTPMETHODPATCH,
++  GRUB_EFI_HTTPMETHODOPTIONS,
++  GRUB_EFI_HTTPMETHODCONNECT,
++  GRUB_EFI_HTTPMETHODHEAD,
++  GRUB_EFI_HTTPMETHODPUT,
++  GRUB_EFI_HTTPMETHODDELETE,
++  GRUB_EFI_HTTPMETHODTRACE,
++} grub_efi_http_method_t;
++
++//******************************************
++// EFI_HTTP_REQUEST_DATA
++//******************************************
++typedef struct {
++  grub_efi_http_method_t method;
++  grub_efi_char16_t *url;
++} grub_efi_http_request_data_t;
++
++typedef enum {
++  GRUB_EFI_HTTP_STATUS_UNSUPPORTED_STATUS = 0,
++  GRUB_EFI_HTTP_STATUS_100_CONTINUE,
++  GRUB_EFI_HTTP_STATUS_101_SWITCHING_PROTOCOLS,
++  GRUB_EFI_HTTP_STATUS_200_OK,
++  GRUB_EFI_HTTP_STATUS_201_CREATED,
++  GRUB_EFI_HTTP_STATUS_202_ACCEPTED,
++  GRUB_EFI_HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION,
++  GRUB_EFI_HTTP_STATUS_204_NO_CONTENT,
++  GRUB_EFI_HTTP_STATUS_205_RESET_CONTENT,
++  GRUB_EFI_HTTP_STATUS_206_PARTIAL_CONTENT,
++  GRUB_EFI_HTTP_STATUS_300_MULTIPLE_CHIOCES,
++  GRUB_EFI_HTTP_STATUS_301_MOVED_PERMANENTLY,
++  GRUB_EFI_HTTP_STATUS_302_FOUND,
++  GRUB_EFI_HTTP_STATUS_303_SEE_OTHER,
++  GRUB_EFI_HTTP_STATUS_304_NOT_MODIFIED,
++  GRUB_EFI_HTTP_STATUS_305_USE_PROXY,
++  GRUB_EFI_HTTP_STATUS_307_TEMPORARY_REDIRECT,
++  GRUB_EFI_HTTP_STATUS_400_BAD_REQUEST,
++  GRUB_EFI_HTTP_STATUS_401_UNAUTHORIZED,
++  GRUB_EFI_HTTP_STATUS_402_PAYMENT_REQUIRED,
++  GRUB_EFI_HTTP_STATUS_403_FORBIDDEN,
++  GRUB_EFI_HTTP_STATUS_404_NOT_FOUND,
++  GRUB_EFI_HTTP_STATUS_405_METHOD_NOT_ALLOWED,
++  GRUB_EFI_HTTP_STATUS_406_NOT_ACCEPTABLE,
++  GRUB_EFI_HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED,
++  GRUB_EFI_HTTP_STATUS_408_REQUEST_TIME_OUT,
++  GRUB_EFI_HTTP_STATUS_409_CONFLICT,
++  GRUB_EFI_HTTP_STATUS_410_GONE,
++  GRUB_EFI_HTTP_STATUS_411_LENGTH_REQUIRED,
++  GRUB_EFI_HTTP_STATUS_412_PRECONDITION_FAILED,
++  GRUB_EFI_HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE,
++  GRUB_EFI_HTTP_STATUS_414_REQUEST_URI_TOO_LARGE,
++  GRUB_EFI_HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE,
++  GRUB_EFI_HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED,
++  GRUB_EFI_HTTP_STATUS_417_EXPECTATION_FAILED,
++  GRUB_EFI_HTTP_STATUS_500_INTERNAL_SERVER_ERROR,
++  GRUB_EFI_HTTP_STATUS_501_NOT_IMPLEMENTED,
++  GRUB_EFI_HTTP_STATUS_502_BAD_GATEWAY,
++  GRUB_EFI_HTTP_STATUS_503_SERVICE_UNAVAILABLE,
++  GRUB_EFI_HTTP_STATUS_504_GATEWAY_TIME_OUT,
++  GRUB_EFI_HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED
++} grub_efi_http_status_code_t;
++
++//******************************************
++// EFI_HTTP_RESPONSE_DATA
++//******************************************
++typedef struct {
++  grub_efi_http_status_code_t status_code;
++} grub_efi_http_response_data_t;
++
++//******************************************
++// EFI_HTTP_HEADER
++//******************************************
++typedef struct {
++  grub_efi_char8_t *field_name;
++  grub_efi_char8_t *field_value;
++} grub_efi_http_header_t;
++
++//******************************************
++// EFI_HTTP_MESSAGE
++//******************************************
++typedef struct {
++  union {
++    grub_efi_http_request_data_t *request;
++    grub_efi_http_response_data_t *response;
++  } data;
++  grub_efi_uint32_t header_count;
++  grub_efi_http_header_t *headers;
++  grub_efi_uint32_t body_length;
++  void *body;
++} grub_efi_http_message_t;
++
++//******************************************
++// EFI_HTTP_TOKEN
++//******************************************
++typedef struct {
++  grub_efi_event_t event;
++  grub_efi_status_t status;
++  grub_efi_http_message_t *message;
++} grub_efi_http_token_t;
++
++struct grub_efi_http {
++  grub_efi_status_t
++  (*get_mode_data) (struct grub_efi_http *this,
++                    grub_efi_http_config_data_t *http_config_data);
++
++  grub_efi_status_t
++  (*configure) (struct grub_efi_http *this,
++                grub_efi_http_config_data_t *http_config_data);
++
++  grub_efi_status_t
++  (*request) (struct grub_efi_http *this,
++              grub_efi_http_token_t *token);
++
++  grub_efi_status_t
++  (*cancel) (struct grub_efi_http *this,
++             grub_efi_http_token_t *token);
++
++  grub_efi_status_t
++  (*response) (struct grub_efi_http *this,
++               grub_efi_http_token_t *token);
++
++  grub_efi_status_t
++  (*poll) (struct grub_efi_http *this);
++};
++typedef struct grub_efi_http grub_efi_http_t;
++
++#endif /* !GRUB_EFI_HTTP_HEADER */
+diff --git a/include/grub/net/efi.h b/include/grub/net/efi.h
+new file mode 100644
+index 00000000000..de90d223e8e
+--- /dev/null
++++ b/include/grub/net/efi.h
+@@ -0,0 +1,144 @@
++#ifndef GRUB_NET_EFI_HEADER
++#define GRUB_NET_EFI_HEADER	1
++
++#include <grub/efi/api.h>
++#include <grub/efi/http.h>
++#include <grub/efi/dhcp.h>
++#include <grub/command.h>
++
++typedef struct grub_efi_net_interface grub_efi_net_interface_t;
++typedef struct grub_efi_net_ip_config grub_efi_net_ip_config_t;
++typedef union grub_efi_net_ip_address grub_efi_net_ip_address_t;
++typedef struct grub_efi_net_ip_manual_address grub_efi_net_ip_manual_address_t;
++
++struct grub_efi_net_interface
++{
++  char *name;
++  int prefer_ip6;
++  struct grub_efi_net_device *dev;
++  struct grub_efi_net_io *io;
++  grub_efi_net_ip_config_t *ip_config;
++  int io_type;
++  struct grub_efi_net_interface *next;
++};
++
++#define efi_net_interface_get_hw_address(inf) inf->ip_config->get_hw_address (inf->dev)
++#define efi_net_interface_get_address(inf) inf->ip_config->get_address (inf->dev)
++#define efi_net_interface_get_route_table(inf) inf->ip_config->get_route_table (inf->dev)
++#define efi_net_interface_set_address(inf, addr, with_subnet) inf->ip_config->set_address (inf->dev, addr, with_subnet)
++#define efi_net_interface_set_gateway(inf, addr) inf->ip_config->set_gateway (inf->dev, addr)
++#define efi_net_interface_set_dns(inf, addr) inf->ip_config->set_dns (inf->dev, addr)
++
++struct grub_efi_net_ip_config
++{
++  char * (*get_hw_address) (struct grub_efi_net_device *dev);
++  char * (*get_address) (struct grub_efi_net_device *dev);
++  char ** (*get_route_table) (struct grub_efi_net_device *dev);
++  grub_efi_net_interface_t * (*best_interface) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *address);
++  int (*set_address) (struct grub_efi_net_device *dev, grub_efi_net_ip_manual_address_t *net_ip, int with_subnet);
++  int (*set_gateway) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *address);
++  int (*set_dns) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *dns);
++};
++
++union grub_efi_net_ip_address
++{
++  grub_efi_ipv4_address_t ip4;
++  grub_efi_ipv6_address_t ip6;
++};
++
++struct grub_efi_net_ip_manual_address
++{
++  int is_ip6;
++  union
++  {
++    grub_efi_ip4_config2_manual_address_t ip4;
++    grub_efi_ip6_config_manual_address_t ip6;
++  };
++};
++
++struct grub_efi_net_device
++{
++  grub_efi_handle_t handle;
++  grub_efi_ip4_config2_protocol_t *ip4_config;
++  grub_efi_ip6_config_protocol_t *ip6_config;
++  grub_efi_handle_t http_handle;
++  grub_efi_http_t *http;
++  grub_efi_handle_t ip4_pxe_handle;
++  grub_efi_pxe_t *ip4_pxe;
++  grub_efi_handle_t ip6_pxe_handle;
++  grub_efi_pxe_t *ip6_pxe;
++  grub_efi_handle_t dhcp4_handle;
++  grub_efi_dhcp4_protocol_t *dhcp4;
++  grub_efi_handle_t dhcp6_handle;
++  grub_efi_dhcp6_protocol_t *dhcp6;
++  char *card_name;
++  grub_efi_net_interface_t *net_interfaces;
++  struct grub_efi_net_device *next;
++};
++
++struct grub_efi_net_io
++{
++  void (*configure) (struct grub_efi_net_device *dev, int prefer_ip6);
++  grub_err_t (*open) (struct grub_efi_net_device *dev,
++		    int prefer_ip6,
++		    grub_file_t file,
++		    const char *filename,
++		    int type);
++  grub_ssize_t (*read) (struct grub_efi_net_device *dev,
++			int prefer_ip6,
++			grub_file_t file,
++			char *buf,
++			grub_size_t len);
++  grub_err_t (*close) (struct grub_efi_net_device *dev,
++		      int prefer_ip6,
++		      grub_file_t file);
++};
++
++extern struct grub_efi_net_device *net_devices;
++
++extern struct grub_efi_net_io io_http;
++extern struct grub_efi_net_io io_pxe;
++
++extern grub_efi_net_ip_config_t *efi_net_ip4_config;
++extern grub_efi_net_ip_config_t *efi_net_ip6_config;
++
++char *
++grub_efi_ip4_address_to_string (grub_efi_ipv4_address_t *address);
++
++char *
++grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address);
++
++char *
++grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address);
++
++int
++grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest);
++
++int
++grub_efi_string_to_ip6_address (const char *val, grub_efi_ipv6_address_t *address, const char **rest);
++
++char *
++grub_efi_ip6_interface_name (struct grub_efi_net_device *dev);
++
++char *
++grub_efi_ip4_interface_name (struct grub_efi_net_device *dev);
++
++grub_efi_net_interface_t *
++grub_efi_net_create_interface (struct grub_efi_net_device *dev,
++		const char *interface_name,
++		grub_efi_net_ip_manual_address_t *net_ip,
++		int has_subnet);
++
++int grub_efi_net_fs_init (void);
++void grub_efi_net_fs_fini (void);
++int grub_efi_net_boot_from_https (void);
++int grub_efi_net_boot_from_opa (void);
++
++extern grub_command_func_t grub_efi_net_list_routes;
++extern grub_command_func_t grub_efi_net_list_cards;
++extern grub_command_func_t grub_efi_net_list_addrs;
++extern grub_command_func_t grub_efi_net_add_addr;
++extern grub_command_func_t grub_efi_net_bootp;
++extern grub_command_func_t grub_efi_net_bootp6;
++
++#endif /* ! GRUB_NET_EFI_HEADER */
diff --git a/SOURCES/0266-efinet-Setting-network-from-UEFI-device-path.patch b/SOURCES/0266-efinet-Setting-network-from-UEFI-device-path.patch
new file mode 100644
index 0000000..1084075
--- /dev/null
+++ b/SOURCES/0266-efinet-Setting-network-from-UEFI-device-path.patch
@@ -0,0 +1,71 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Michael Chang <mchang@suse.com>
+Date: Sun, 10 Jul 2016 23:46:31 +0800
+Subject: [PATCH] efinet: Setting network from UEFI device path
+
+The PXE Base Code protocol used to obtain cached PXE DHCPACK packet is no
+longer provided for HTTP Boot. Instead, we have to get the HTTP boot
+information from the device path nodes defined in following UEFI Specification
+sections.
+
+ 9.3.5.12 IPv4 Device Path
+ 9.3.5.13 IPv6 Device Path
+ 9.3.5.23 Uniform Resource Identifiers (URI) Device Path
+
+This patch basically does:
+
+include/grub/efi/api.h:
+Add new structure of Uniform Resource Identifiers (URI) Device Path
+
+grub-core/net/drivers/efi/efinet.c:
+Check if PXE Base Code is available, if not it will try to obtain the netboot
+information from the device path where the image booted from. The DHCPACK
+packet is recoverd from the information in device patch and feed into the same
+DHCP packet processing functions to ensure the network interface is setting up
+the same way it used to be.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Ken Lin <ken.lin@hpe.com>
+---
+ grub-core/net/drivers/efi/efinet.c | 14 +++++---------
+ 1 file changed, 5 insertions(+), 9 deletions(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 3bea6221745..a161e7a5f26 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -475,9 +475,6 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+   grub_err_t err;
+ 
+   ddp = grub_efi_duplicate_device_path (dp);
+-  if (!ddp)
+-    return NULL;
+-
+   ldp = grub_efi_find_last_device_path (ddp);
+ 
+   if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
+@@ -754,7 +751,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+   {
+     grub_efi_device_path_t *cdp;
+     struct grub_efi_pxe *pxe;
+-    struct grub_efi_pxe_mode *pxe_mode;
++    struct grub_efi_pxe_mode *pxe_mode = NULL;
+     grub_uint8_t *packet_buf;
+     grub_size_t packet_bufsz ;
+     int ipv6;
+@@ -841,11 +838,10 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+     if (ipv6)
+       {
+ 	grub_dprintf ("efinet", "using ipv6 and dhcpv6\n");
+-	grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n",
+-		      pxe_mode->dhcp_ack_received ? "yes" : "no",
+-		      pxe_mode->dhcp_ack_received ? "" : " cannot continue");
+-	if (!pxe_mode->dhcp_ack_received)
+-	  continue;
++	if (pxe_mode)
++	  grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n",
++			pxe_mode->dhcp_ack_received ? "yes" : "no",
++			pxe_mode->dhcp_ack_received ? "" : " cannot continue");
+ 
+ 	grub_net_configure_by_dhcpv6_reply (card->name, card, 0,
+ 					    (struct grub_net_dhcp6_packet *)
diff --git a/SOURCES/0267-AUDIT-0-http-boot-tracker-bug.patch b/SOURCES/0267-AUDIT-0-http-boot-tracker-bug.patch
new file mode 100644
index 0000000..d6b2107
--- /dev/null
+++ b/SOURCES/0267-AUDIT-0-http-boot-tracker-bug.patch
@@ -0,0 +1,62 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Sebastian Krahmer <krahmer@suse.com>
+Date: Tue, 28 Nov 2017 17:24:38 +0800
+Subject: [PATCH] AUDIT-0: http boot tracker bug
+
+Fixing a memory leak in case of error, and a integer overflow, leading to a
+heap overflow due to overly large chunk sizes.
+
+We need to check against some maximum value, otherwise values like 0xffffffff
+will eventually lead in the allocation functions to small sized buffers, since
+the len is rounded up to the next reasonable alignment. The following memcpy
+will then smash the heap, leading to RCE.
+
+This is no big issue for pure http boot, since its going to execute an
+untrusted kernel anyway, but it will break trusted boot scenarios, where only
+signed code is allowed to be executed.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+---
+ grub-core/net/efi/net.c | 4 +++-
+ grub-core/net/http.c    | 5 ++++-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c
+index 9e0078ac1c6..2bf15447fd5 100644
+--- a/grub-core/net/efi/net.c
++++ b/grub-core/net/efi/net.c
+@@ -645,8 +645,10 @@ grub_efihttp_chunk_read (grub_file_t file, char *buf,
+ 
+       rd = efi_net_interface (read, file, chunk, sz);
+ 
+-      if (rd <= 0)
++      if (rd <= 0) {
++	grub_free (chunk);
+ 	return rd;
++      }
+ 
+       if (buf)
+ 	{
+diff --git a/grub-core/net/http.c b/grub-core/net/http.c
+index 2b46e4672fc..82515f352dd 100644
+--- a/grub-core/net/http.c
++++ b/grub-core/net/http.c
+@@ -31,7 +31,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+ enum
+   {
+-    HTTP_PORT = 80
++    HTTP_PORT = 80,
++    HTTP_MAX_CHUNK_SIZE = 0x80000000
+   };
+ 
+ 
+@@ -78,6 +79,8 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len)
+   if (data->in_chunk_len == 2)
+     {
+       data->chunk_rem = grub_strtoul (ptr, 0, 16);
++      if (data->chunk_rem > HTTP_MAX_CHUNK_SIZE)
++	  return GRUB_ERR_NET_PACKET_TOO_BIG;
+       grub_errno = GRUB_ERR_NONE;
+       if (data->chunk_rem == 0)
+ 	{
diff --git a/SOURCES/0268-xfs-accept-filesystem-with-sparse-inodes.patch b/SOURCES/0268-xfs-accept-filesystem-with-sparse-inodes.patch
new file mode 100644
index 0000000..84502ae
--- /dev/null
+++ b/SOURCES/0268-xfs-accept-filesystem-with-sparse-inodes.patch
@@ -0,0 +1,59 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Eric Sandeen <sandeen@sandeen.net>
+Date: Tue, 15 May 2018 14:55:55 -0500
+Subject: [PATCH] xfs: accept filesystem with sparse inodes
+
+The sparse inode metadata format became a mkfs.xfs default in
+xfsprogs-4.16.0, and such filesystems are now rejected by grub as
+containing an incompatible feature.
+
+In essence, this feature allows xfs to allocate inodes into fragmented
+freespace.  (Without this feature, if xfs could not allocate contiguous
+space for 64 new inodes, inode creation would fail.)
+
+In practice, the disk format change is restricted to the inode btree,
+which as far as I can tell is not used by grub.  If all you're doing
+today is parsing a directory, reading an inode number, and converting
+that inode number to a disk location, then ignoring this feature
+should be fine, so I've added it to XFS_SB_FEAT_INCOMPAT_SUPPORTED
+
+I did some brief testing of this patch by hacking up the regression
+tests to completely fragment freespace on the test xfs filesystem, and
+then write a large-ish number of inodes to consume any existing
+contiguous 64-inode chunk.  This way any files the grub tests add and
+traverse would be in such a fragmented inode allocation.  Tests passed,
+but I'm not sure how to cleanly integrate that into the test harness.
+
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+---
+ grub-core/fs/xfs.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
+index 72492915533..852155b1bf3 100644
+--- a/grub-core/fs/xfs.c
++++ b/grub-core/fs/xfs.c
+@@ -76,8 +76,22 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+ /* incompat feature flags */
+ #define XFS_SB_FEAT_INCOMPAT_FTYPE      (1 << 0)        /* filetype in dirent */
++#define XFS_SB_FEAT_INCOMPAT_SPINODES   (1 << 1)        /* sparse inode chunks */
++#define XFS_SB_FEAT_INCOMPAT_META_UUID  (1 << 2)        /* metadata UUID */
++
++/*
++ * Directory entries with ftype are explicitly handled by grub code.
++ *
++ * We do not currently verify metadata UUID, so it is safe to read filesystems
++ * with the XFS_SB_FEAT_INCOMPAT_META_UUID feature.
++ *
++ * We do not currently read the inode btrees, so it is safe to read filesystems
++ * with the XFS_SB_FEAT_INCOMPAT_SPINODES feature.
++ */
+ #define XFS_SB_FEAT_INCOMPAT_SUPPORTED \
+-	(XFS_SB_FEAT_INCOMPAT_FTYPE)
++	(XFS_SB_FEAT_INCOMPAT_FTYPE | \
++	 XFS_SB_FEAT_INCOMPAT_SPINODES | \
++	 XFS_SB_FEAT_INCOMPAT_META_UUID)
+ 
+ struct grub_xfs_sblock
+ {
diff --git a/SOURCES/0269-grub-core-video-efi_gop.c-Add-support-for-BLT_ONLY-a.patch b/SOURCES/0269-grub-core-video-efi_gop.c-Add-support-for-BLT_ONLY-a.patch
new file mode 100644
index 0000000..33cde3b
--- /dev/null
+++ b/SOURCES/0269-grub-core-video-efi_gop.c-Add-support-for-BLT_ONLY-a.patch
@@ -0,0 +1,56 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Alexander Graf <agraf@suse.de>
+Date: Wed, 1 Feb 2017 23:10:45 +0100
+Subject: [PATCH] grub-core/video/efi_gop.c: Add support for BLT_ONLY adapters
+
+EFI GOP has support for multiple different bitness types of frame buffers
+and for a special "BLT only" type which is always defined to be RGBx.
+
+Because grub2 doesn't ever directly access the frame buffer but instead
+only renders graphics via the BLT interface anyway, we can easily support
+these adapters.
+
+The reason this has come up now is the emerging support for virtio-gpu
+in OVMF. That adapter does not have the notion of a memory mapped frame
+buffer and thus is BLT only.
+
+Signed-off-by: Alexander Graf <agraf@suse.de>
+---
+ grub-core/video/efi_gop.c          | 2 ++
+ include/grub/efi/graphics_output.h | 3 ++-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/video/efi_gop.c b/grub-core/video/efi_gop.c
+index 7f9d1c2dfa1..c9e40e8d4e9 100644
+--- a/grub-core/video/efi_gop.c
++++ b/grub-core/video/efi_gop.c
+@@ -121,6 +121,7 @@ grub_video_gop_get_bpp (struct grub_efi_gop_mode_info *in)
+     {
+     case GRUB_EFI_GOT_BGRA8:
+     case GRUB_EFI_GOT_RGBA8:
++    case GRUB_EFI_GOT_BLT_ONLY:
+       return 32;
+ 
+     case GRUB_EFI_GOT_BITMASK:
+@@ -187,6 +188,7 @@ grub_video_gop_fill_real_mode_info (unsigned mode,
+   switch (in->pixel_format)
+     {
+     case GRUB_EFI_GOT_RGBA8:
++    case GRUB_EFI_GOT_BLT_ONLY:
+       out->red_mask_size = 8;
+       out->red_field_pos = 0;
+       out->green_mask_size = 8;
+diff --git a/include/grub/efi/graphics_output.h b/include/grub/efi/graphics_output.h
+index 12977741192..e4388127c66 100644
+--- a/include/grub/efi/graphics_output.h
++++ b/include/grub/efi/graphics_output.h
+@@ -28,7 +28,8 @@ typedef enum
+   {
+     GRUB_EFI_GOT_RGBA8,
+     GRUB_EFI_GOT_BGRA8,
+-    GRUB_EFI_GOT_BITMASK
++    GRUB_EFI_GOT_BITMASK,
++    GRUB_EFI_GOT_BLT_ONLY,
+   }
+   grub_efi_gop_pixel_format_t;
+ 
diff --git a/SOURCES/0270-efi-uga-use-64-bit-for-fb_base.patch b/SOURCES/0270-efi-uga-use-64-bit-for-fb_base.patch
new file mode 100644
index 0000000..391bdb2
--- /dev/null
+++ b/SOURCES/0270-efi-uga-use-64-bit-for-fb_base.patch
@@ -0,0 +1,105 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Wed, 16 May 2018 13:06:04 -0400
+Subject: [PATCH] efi/uga: use 64 bit for fb_base
+
+We get 64 bit from PCI BAR but then truncate by assigning to 32 bit.
+Make sure to check that pointer does not overflow on 32 bit platform.
+
+Closes: 50931
+---
+ grub-core/video/efi_uga.c | 31 ++++++++++++++++---------------
+ 1 file changed, 16 insertions(+), 15 deletions(-)
+
+diff --git a/grub-core/video/efi_uga.c b/grub-core/video/efi_uga.c
+index 464ede874da..1d4091c5631 100644
+--- a/grub-core/video/efi_uga.c
++++ b/grub-core/video/efi_uga.c
+@@ -34,7 +34,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+ static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID;
+ static struct grub_efi_uga_draw_protocol *uga;
+-static grub_uint32_t uga_fb;
++static grub_uint64_t uga_fb;
+ static grub_uint32_t uga_pitch;
+ 
+ static struct
+@@ -52,7 +52,7 @@ static struct
+ #define FBTEST_COUNT	8
+ 
+ static int
+-find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len)
++find_line_len (grub_uint64_t *fb_base, grub_uint32_t *line_len)
+ {
+   grub_uint32_t *base = (grub_uint32_t *) (grub_addr_t) *fb_base;
+   int i;
+@@ -67,7 +67,7 @@ find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len)
+ 	    {
+ 	      if ((base[j] & RGB_MASK) == RGB_MAGIC)
+ 		{
+-		  *fb_base = (grub_uint32_t) (grub_addr_t) base;
++		  *fb_base = (grub_uint64_t) (grub_addr_t) base;
+ 		  *line_len = j << 2;
+ 
+ 		  return 1;
+@@ -84,7 +84,7 @@ find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len)
+ /* Context for find_framebuf.  */
+ struct find_framebuf_ctx
+ {
+-  grub_uint32_t *fb_base;
++  grub_uint64_t *fb_base;
+   grub_uint32_t *line_len;
+   int found;
+ };
+@@ -120,7 +120,9 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
+ 	      if (i == 5)
+ 		break;
+ 
+-	      old_bar2 = grub_pci_read (addr + 4);
++	      i++;
++	      addr += 4;
++	      old_bar2 = grub_pci_read (addr);
+ 	    }
+ 	  else
+ 	    old_bar2 = 0;
+@@ -129,10 +131,15 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
+ 	  base64 <<= 32;
+ 	  base64 |= (old_bar1 & GRUB_PCI_ADDR_MEM_MASK);
+ 
+-	  grub_dprintf ("fb", "%s(%d): 0x%llx\n",
++	  grub_dprintf ("fb", "%s(%d): 0x%" PRIxGRUB_UINT64_T "\n",
+ 			((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) ?
+-			"VMEM" : "MMIO"), i,
+-		       (unsigned long long) base64);
++			"VMEM" : "MMIO"), type == GRUB_PCI_ADDR_MEM_TYPE_64 ? i - 1 : i,
++			base64);
++
++#if GRUB_CPU_SIZEOF_VOID_P == 4
++	  if (old_bar2)
++	    continue;
++#endif
+ 
+ 	  if ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) && (! ctx->found))
+ 	    {
+@@ -140,12 +147,6 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
+ 	      if (find_line_len (ctx->fb_base, ctx->line_len))
+ 		ctx->found++;
+ 	    }
+-
+-	  if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
+-	    {
+-	      i++;
+-	      addr += 4;
+-	    }
+ 	}
+     }
+ 
+@@ -153,7 +154,7 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
+ }
+ 
+ static int
+-find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len)
++find_framebuf (grub_uint64_t *fb_base, grub_uint32_t *line_len)
+ {
+   struct find_framebuf_ctx ctx = {
+     .fb_base = fb_base,
diff --git a/SOURCES/0271-Fix-grub-setpassword-o-s-output-path.patch b/SOURCES/0271-Fix-grub-setpassword-o-s-output-path.patch
new file mode 100644
index 0000000..6bf5751
--- /dev/null
+++ b/SOURCES/0271-Fix-grub-setpassword-o-s-output-path.patch
@@ -0,0 +1,33 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andy Lutomirski <luto@kernel.org>
+Date: Sun, 11 Jun 2017 19:17:40 -0400
+Subject: [PATCH] Fix grub-setpassword -o's output path
+
+The output path is set up in the command line parsing, but completely ignored
+in the code that actually writes the files.  This patch fixes that.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ util/grub-setpassword.in | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/util/grub-setpassword.in b/util/grub-setpassword.in
+index d7924af5192..9ca7114f904 100755
+--- a/util/grub-setpassword.in
++++ b/util/grub-setpassword.in
+@@ -117,11 +117,11 @@ fi
+ 
+ # on the ESP, these will fail to set the permissions, but it's okay because
+ # the directory is protected.
+-install -m 0600 /dev/null "${grubdir}/user.cfg" 2>/dev/null || :
+-chmod 0600 "${grubdir}/user.cfg" 2>/dev/null || :
+-echo "GRUB2_PASSWORD=${MYPASS}" > "${grubdir}/user.cfg"
++install -m 0600 /dev/null "${OUTPUT_PATH}/user.cfg" 2>/dev/null || :
++chmod 0600 "${OUTPUT_PATH}/user.cfg" 2>/dev/null || :
++echo "GRUB2_PASSWORD=${MYPASS}" > "${OUTPUT_PATH}/user.cfg"
+ 
+-if ! grep -q "^### BEGIN /etc/grub.d/01_users ###$" "${grubdir}/grub.cfg"; then
++if ! grep -q "^### BEGIN /etc/grub.d/01_users ###$" "${OUTPUT_PATH}/grub.cfg"; then
+     echo "WARNING: The current configuration lacks password support!"
+     echo "Update your configuration with @grub_mkconfig@ to support this feature."
+ fi
diff --git a/SOURCES/0272-Verify-modules-on-build-time-rather-than-failing-in-.patch b/SOURCES/0272-Verify-modules-on-build-time-rather-than-failing-in-.patch
new file mode 100644
index 0000000..53423db
--- /dev/null
+++ b/SOURCES/0272-Verify-modules-on-build-time-rather-than-failing-in-.patch
@@ -0,0 +1,559 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Thu, 31 Dec 2015 13:09:15 +0100
+Subject: [PATCH] Verify modules on build-time rather than failing in runtime.
+
+---
+ util/grub-module-verifier.c    | 122 ++++++++++++++++
+ util/grub-module-verifier32.c  |   2 +
+ util/grub-module-verifier64.c  |   2 +
+ util/grub-module-verifierXX.c  | 315 +++++++++++++++++++++++++++++++++++++++++
+ include/grub/module_verifier.h |  19 +++
+ grub-core/Makefile.am          |   6 +-
+ grub-core/genmod.sh.in         |   5 +-
+ 7 files changed, 468 insertions(+), 3 deletions(-)
+ create mode 100644 util/grub-module-verifier.c
+ create mode 100644 util/grub-module-verifier32.c
+ create mode 100644 util/grub-module-verifier64.c
+ create mode 100644 util/grub-module-verifierXX.c
+ create mode 100644 include/grub/module_verifier.h
+
+diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c
+new file mode 100644
+index 00000000000..d2d6984033c
+--- /dev/null
++++ b/util/grub-module-verifier.c
+@@ -0,0 +1,122 @@
++#include <stdio.h>
++#include <string.h>
++
++#include <grub/elf.h>
++#include <grub/module_verifier.h>
++#include <grub/misc.h>
++#include <grub/util/misc.h>
++
++struct grub_module_verifier_arch archs[] = {
++  { "i386", 4, 0, EM_386, GRUB_MODULE_VERIFY_SUPPORTS_REL, (int[]){
++      R_386_32,
++      R_386_PC32,
++      -1
++    } },
++  { "x86_64", 8, 0, EM_X86_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
++      R_X86_64_64,
++      R_X86_64_PC64,
++      /* R_X86_64_32, R_X86_64_32S, R_X86_64_PC32 are supported but shouldn't be used because of their limited range.  */
++      -1
++    } },
++  { "powerpc", 4, 1, EM_PPC, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
++      GRUB_ELF_R_PPC_ADDR16_LO,
++      GRUB_ELF_R_PPC_REL24, /* It has limited range but GRUB adds trampolines when necessarry.  */
++      GRUB_ELF_R_PPC_ADDR16_HA,
++      GRUB_ELF_R_PPC_ADDR32,
++      GRUB_ELF_R_PPC_REL32,
++      -1
++    } },
++  { "sparc64", 8, 1, EM_SPARCV9, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
++      R_SPARC_WDISP30, /* It has limited range but GRUB adds trampolines when necessarry. */
++      R_SPARC_HH22,
++      R_SPARC_HM10,
++      R_SPARC_LM22,
++      R_SPARC_LO10,
++      R_SPARC_64,
++      R_SPARC_OLO10,
++      /* R_SPARC_32, R_SPARC_HI22  are supported but shouldn't be used because of their limited range.  */
++      -1
++    } },
++  { "ia64", 8, 0, EM_IA_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
++      R_IA64_PCREL21B, /* We should verify that it's pointing either
++			  to a function or to a section in the same module.  */
++      R_IA64_SEGREL64LSB,
++      R_IA64_FPTR64LSB,
++      R_IA64_DIR64LSB,
++      R_IA64_PCREL64LSB,
++      R_IA64_GPREL22,  /* We should verify that it's pointing  to a section in the same module.  */
++      R_IA64_LTOFF22X,
++      R_IA64_LTOFF22,
++      R_IA64_LTOFF_FPTR22,
++      R_IA64_LDXMOV,
++      -1
++    } },
++  { "mipsel", 4, 0, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
++      R_MIPS_HI16,
++      R_MIPS_LO16,
++      R_MIPS_32,
++      R_MIPS_GPREL32,
++      R_MIPS_26,
++      R_MIPS_GOT16,
++      R_MIPS_CALL16,
++      R_MIPS_JALR,
++      -1
++    } },
++  { "mips", 4, 1, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
++      R_MIPS_HI16,
++      R_MIPS_LO16,
++      R_MIPS_32,
++      R_MIPS_GPREL32,
++      R_MIPS_26,
++      R_MIPS_GOT16,
++      R_MIPS_CALL16,
++      R_MIPS_JALR,
++      -1
++    } },
++  { "arm", 4, 0, EM_ARM, GRUB_MODULE_VERIFY_SUPPORTS_REL, (int[]){
++      /* Some relocations are range-limited but trampolines are added when necessarry. */
++      R_ARM_ABS32,
++      R_ARM_CALL,
++      R_ARM_JUMP24,
++      R_ARM_THM_CALL,
++      R_ARM_THM_JUMP24,
++      R_ARM_V4BX,
++      R_ARM_THM_MOVW_ABS_NC,
++      R_ARM_THM_MOVT_ABS,
++      R_ARM_THM_JUMP19,
++      -1
++    } },
++  { "arm64", 8, 0, EM_AARCH64, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
++      R_AARCH64_ABS64,
++      R_AARCH64_CALL26,
++      R_AARCH64_JUMP26,
++      -1
++    } },
++};
++
++
++int
++main (int argc, char **argv)
++{
++  size_t module_size;
++  unsigned arch;
++  char *module_img;
++  if (argc != 3) {
++    fprintf (stderr, "usage: %s FILE ARCH\n", argv[0]);
++    return 1;
++  }
++
++  for (arch = 0; arch < ARRAY_SIZE(archs); arch++)
++    if (strcmp(archs[arch].name, argv[2]) == 0)
++      break;
++  if (arch == ARRAY_SIZE(archs))
++    grub_util_error("unknown arch: %s", argv[2]);
++
++  module_size = grub_util_get_image_size (argv[1]);
++  module_img = grub_util_read_image (argv[1]);
++  if (archs[arch].voidp_sizeof == 8)
++    grub_module_verify64(module_img, module_size, &archs[arch]);
++  else
++    grub_module_verify32(module_img, module_size, &archs[arch]);
++  return 0;
++}
+diff --git a/util/grub-module-verifier32.c b/util/grub-module-verifier32.c
+new file mode 100644
+index 00000000000..257229f8f08
+--- /dev/null
++++ b/util/grub-module-verifier32.c
+@@ -0,0 +1,2 @@
++#define MODULEVERIFIER_ELF32 1
++#include "grub-module-verifierXX.c"
+diff --git a/util/grub-module-verifier64.c b/util/grub-module-verifier64.c
+new file mode 100644
+index 00000000000..4db6b4bedd1
+--- /dev/null
++++ b/util/grub-module-verifier64.c
+@@ -0,0 +1,2 @@
++#define MODULEVERIFIER_ELF64 1
++#include "grub-module-verifierXX.c"
+diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c
+new file mode 100644
+index 00000000000..904be27d39b
+--- /dev/null
++++ b/util/grub-module-verifierXX.c
+@@ -0,0 +1,315 @@
++#include <string.h>
++
++#include <grub/elf.h>
++#include <grub/module_verifier.h>
++#include <grub/util/misc.h>
++
++#if defined(MODULEVERIFIER_ELF32)
++# define SUFFIX(x)	x ## 32
++# define ELFCLASSXX	ELFCLASS32
++# define Elf_Ehdr	Elf32_Ehdr
++# define Elf_Phdr	Elf32_Phdr
++# define Elf_Nhdr	Elf32_Nhdr
++# define Elf_Addr	Elf32_Addr
++# define Elf_Sym	Elf32_Sym
++# define Elf_Off	Elf32_Off
++# define Elf_Shdr	Elf32_Shdr
++# define Elf_Rela       Elf32_Rela
++# define Elf_Rel        Elf32_Rel
++# define Elf_Word       Elf32_Word
++# define Elf_Half       Elf32_Half
++# define Elf_Section    Elf32_Section
++# define ELF_R_SYM(val)		ELF32_R_SYM(val)
++# define ELF_R_TYPE(val)		ELF32_R_TYPE(val)
++# define ELF_ST_TYPE(val)		ELF32_ST_TYPE(val)
++#elif defined(MODULEVERIFIER_ELF64)
++# define SUFFIX(x)	x ## 64
++# define ELFCLASSXX	ELFCLASS64
++# define Elf_Ehdr	Elf64_Ehdr
++# define Elf_Phdr	Elf64_Phdr
++# define Elf_Nhdr	Elf64_Nhdr
++# define Elf_Addr	Elf64_Addr
++# define Elf_Sym	Elf64_Sym
++# define Elf_Off	Elf64_Off
++# define Elf_Shdr	Elf64_Shdr
++# define Elf_Rela       Elf64_Rela
++# define Elf_Rel        Elf64_Rel
++# define Elf_Word       Elf64_Word
++# define Elf_Half       Elf64_Half
++# define Elf_Section    Elf64_Section
++# define ELF_R_SYM(val)		ELF64_R_SYM(val)
++# define ELF_R_TYPE(val)		ELF64_R_TYPE(val)
++# define ELF_ST_TYPE(val)		ELF64_ST_TYPE(val)
++#else
++#error "I'm confused"
++#endif
++
++#define grub_target_to_host32(x) (grub_target_to_host32_real (arch, (x)))
++#define grub_host_to_target32(x) (grub_host_to_target32_real (arch, (x)))
++#define grub_target_to_host64(x) (grub_target_to_host64_real (arch, (x)))
++#define grub_host_to_target64(x) (grub_host_to_target64_real (arch, (x)))
++#define grub_host_to_target_addr(x) (grub_host_to_target_addr_real (arch, (x)))
++#define grub_target_to_host16(x) (grub_target_to_host16_real (arch, (x)))
++#define grub_host_to_target16(x) (grub_host_to_target16_real (arch, (x)))
++#define grub_target_to_host(val) grub_target_to_host_real(arch, (val))
++
++static inline grub_uint32_t
++grub_target_to_host32_real (const struct grub_module_verifier_arch *arch,
++			    grub_uint32_t in)
++{
++  if (arch->bigendian)
++    return grub_be_to_cpu32 (in);
++  else
++    return grub_le_to_cpu32 (in);
++}
++
++static inline grub_uint64_t
++grub_target_to_host64_real (const struct grub_module_verifier_arch *arch,
++			    grub_uint64_t in)
++{
++  if (arch->bigendian)
++    return grub_be_to_cpu64 (in);
++  else
++    return grub_le_to_cpu64 (in);
++}
++
++static inline grub_uint64_t
++grub_host_to_target64_real (const struct grub_module_verifier_arch *arch,
++			    grub_uint64_t in)
++{
++  if (arch->bigendian)
++    return grub_cpu_to_be64 (in);
++  else
++    return grub_cpu_to_le64 (in);
++}
++
++static inline grub_uint32_t
++grub_host_to_target32_real (const struct grub_module_verifier_arch *arch,
++			    grub_uint32_t in)
++{
++  if (arch->bigendian)
++    return grub_cpu_to_be32 (in);
++  else
++    return grub_cpu_to_le32 (in);
++}
++
++static inline grub_uint16_t
++grub_target_to_host16_real (const struct grub_module_verifier_arch *arch,
++			    grub_uint16_t in)
++{
++  if (arch->bigendian)
++    return grub_be_to_cpu16 (in);
++  else
++    return grub_le_to_cpu16 (in);
++}
++
++static inline grub_uint16_t
++grub_host_to_target16_real (const struct grub_module_verifier_arch *arch,
++			    grub_uint16_t in)
++{
++  if (arch->bigendian)
++    return grub_cpu_to_be16 (in);
++  else
++    return grub_cpu_to_le16 (in);
++}
++
++static inline grub_uint64_t
++grub_host_to_target_addr_real (const struct grub_module_verifier_arch *arch, grub_uint64_t in)
++{
++  if (arch->voidp_sizeof == 8)
++    return grub_host_to_target64_real (arch, in);
++  else
++    return grub_host_to_target32_real (arch, in);
++}
++
++static inline grub_uint64_t
++grub_target_to_host_real (const struct grub_module_verifier_arch *arch, grub_uint64_t in)
++{
++  if (arch->voidp_sizeof == 8)
++    return grub_target_to_host64_real (arch, in);
++  else
++    return grub_target_to_host32_real (arch, in);
++}
++
++
++static Elf_Shdr *
++find_section (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, const char *name)
++{
++  Elf_Shdr *s;
++  const char *str;
++  unsigned i;
++
++  s = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff) + grub_target_to_host16 (e->e_shstrndx) * grub_target_to_host16 (e->e_shentsize));
++  str = (char *) e + grub_target_to_host (s->sh_offset);
++
++  for (i = 0, s = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff));
++       i < grub_target_to_host16 (e->e_shnum);
++       i++, s = (Elf_Shdr *) ((char *) s + grub_target_to_host16 (e->e_shentsize)))
++    if (strcmp (str + grub_target_to_host32 (s->sh_name), name) == 0)
++      return s;
++  return NULL;
++}
++
++static void
++check_license (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
++{
++  Elf_Shdr *s = find_section (arch, e, ".module_license");
++  if (s && (strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv3") == 0
++	    || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv3+") == 0
++	    || strcmp ((char *) e + grub_target_to_host(s->sh_offset), "LICENSE=GPLv2+") == 0))
++    return;
++  grub_util_error ("incompatible license");
++}
++
++static void
++check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
++{
++  unsigned i;
++  Elf_Shdr *s, *sections;
++  Elf_Sym *sym;
++  const char *str;
++  Elf_Word size, entsize;
++
++  sections = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff));
++  for (i = 0, s = sections;
++       i < grub_target_to_host16 (e->e_shnum);
++       i++, s = (Elf_Shdr *) ((char *) s + grub_target_to_host16 (e->e_shentsize)))
++    if (grub_target_to_host32 (s->sh_type) == SHT_SYMTAB)
++      break;
++
++  if (i == grub_target_to_host16 (e->e_shnum))
++    grub_util_error ("no symbol table");
++
++  sym = (Elf_Sym *) ((char *) e + grub_target_to_host (s->sh_offset));
++  size = grub_target_to_host (s->sh_size);
++  entsize = grub_target_to_host (s->sh_entsize);
++
++  s = (Elf_Shdr *) ((char *) sections + grub_target_to_host16 (e->e_shentsize) * grub_target_to_host32 (s->sh_link));
++  str = (char *) e + grub_target_to_host (s->sh_offset);
++
++  for (i = 0;
++       i < size / entsize;
++       i++, sym = (Elf_Sym *) ((char *) sym + entsize))
++    {
++      unsigned char type = ELF_ST_TYPE (sym->st_info);
++
++      switch (type)
++	{
++	case STT_NOTYPE:
++	case STT_OBJECT:
++	case STT_FUNC:
++	case STT_SECTION:
++	case STT_FILE:
++	  break;
++
++	default:
++	  return grub_util_error ("unknown symbol type `%d'", (int) type);
++	}
++    }
++}
++
++/* Relocate symbols.  */
++static void
++section_check_relocations (const struct grub_module_verifier_arch *arch, void *ehdr,
++			   Elf_Shdr *s, size_t target_seg_size)
++{
++  Elf_Rel *rel, *max;
++
++  for (rel = (Elf_Rel *) ((char *) ehdr + grub_target_to_host (s->sh_offset)),
++	 max = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_size));
++       rel < max;
++       rel = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_entsize)))
++    {
++      Elf_Word *addr;
++      Elf_Sym *sym;
++      unsigned i;
++
++      if (target_seg_size < grub_target_to_host (rel->r_offset))
++	grub_util_error ("reloc offset is out of the segment");
++
++      grub_uint32_t type = ELF_R_TYPE (grub_target_to_host (rel->r_info));
++
++      if (arch->machine == EM_SPARCV9)
++	type &= 0xff;
++
++      for (i = 0; arch->supported_relocations[i] != -1; i++)
++	if (type == arch->supported_relocations[i])
++	  break;
++      if (arch->supported_relocations[i] == -1)
++	grub_util_error ("unsupported relocation 0x%x", type);
++    }
++}
++
++static void
++check_relocations (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
++{
++  Elf_Shdr *s;
++  unsigned i;
++
++  for (i = 0, s = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff));
++       i < grub_target_to_host16 (e->e_shnum);
++       i++, s = (Elf_Shdr *) ((char *) s + grub_target_to_host16 (e->e_shentsize)))
++    if (grub_target_to_host32 (s->sh_type) == SHT_REL || grub_target_to_host32 (s->sh_type) == SHT_RELA)
++      {
++	Elf_Shdr *ts;
++
++	if (grub_target_to_host32 (s->sh_type) == SHT_REL && !(arch->flags & GRUB_MODULE_VERIFY_SUPPORTS_REL))
++	  grub_util_error ("unsupported SHT_REL");
++	if (grub_target_to_host32 (s->sh_type) == SHT_RELA && !(arch->flags & GRUB_MODULE_VERIFY_SUPPORTS_RELA))
++	  grub_util_error ("unsupported SHT_RELA");
++
++	/* Find the target segment.  */
++	if (grub_target_to_host32 (s->sh_info) >= grub_target_to_host16 (e->e_shnum))
++	  grub_util_error ("orphaned reloc section");
++	ts = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff) + grub_target_to_host32 (s->sh_info) * grub_target_to_host16 (e->e_shentsize));
++
++	section_check_relocations (arch, e, s, grub_target_to_host (ts->sh_size));
++      }
++}
++
++void
++SUFFIX(grub_module_verify) (void *module_img, size_t size, const struct grub_module_verifier_arch *arch)
++{
++  Elf_Ehdr *e = module_img;
++
++  /* Check the header size.  */
++  if (size < sizeof (Elf_Ehdr))
++    grub_util_error ("ELF header smaller than expected");
++
++  /* Check the magic numbers.  */
++  if (e->e_ident[EI_MAG0] != ELFMAG0
++      || e->e_ident[EI_MAG1] != ELFMAG1
++      || e->e_ident[EI_MAG2] != ELFMAG2
++      || e->e_ident[EI_MAG3] != ELFMAG3
++      || e->e_ident[EI_VERSION] != EV_CURRENT
++      || grub_target_to_host32 (e->e_version) != EV_CURRENT)
++    grub_util_error ("invalid arch-independent ELF magic");
++
++  if (e->e_ident[EI_CLASS] != ELFCLASSXX
++      || e->e_ident[EI_DATA] != (arch->bigendian ? ELFDATA2MSB : ELFDATA2LSB)
++      || grub_target_to_host16 (e->e_machine) != arch->machine)
++    grub_util_error ("invalid arch-dependent ELF magic");
++
++  if (grub_target_to_host16 (e->e_type) != ET_REL)
++    {
++      grub_util_error ("this ELF file is not of the right type");
++    }
++
++  /* Make sure that every section is within the core.  */
++  if (size < grub_target_to_host (e->e_shoff)
++      + grub_target_to_host16 (e->e_shentsize) * grub_target_to_host16(e->e_shnum))
++    {
++      grub_util_error ("ELF sections outside core");
++    }
++
++  check_license (arch, e);
++
++  Elf_Shdr *s;
++
++  s = find_section (arch, e, ".modname");
++  if (!s)
++    grub_util_error ("no module name found");
++
++  check_symbols(arch, e);
++  check_relocations(arch, e);
++}
+diff --git a/include/grub/module_verifier.h b/include/grub/module_verifier.h
+new file mode 100644
+index 00000000000..9e3a2ba720f
+--- /dev/null
++++ b/include/grub/module_verifier.h
+@@ -0,0 +1,19 @@
++#include <stdint.h>
++#include <stdlib.h>
++
++#include <grub/types.h>
++
++#define GRUB_MODULE_VERIFY_SUPPORTS_REL 1
++#define GRUB_MODULE_VERIFY_SUPPORTS_RELA 2
++
++struct grub_module_verifier_arch {
++  const char *name;
++  int voidp_sizeof;
++  int bigendian;
++  int machine;
++  int flags;
++  const int *supported_relocations;
++};
++
++void grub_module_verify64(void *module_img, size_t module_size, const struct grub_module_verifier_arch *arch);
++void grub_module_verify32(void *module_img, size_t module_size, const struct grub_module_verifier_arch *arch);
+diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
+index be29e327f77..77205f16358 100644
+--- a/grub-core/Makefile.am
++++ b/grub-core/Makefile.am
+@@ -39,6 +39,10 @@ gentrigtables$(BUILD_EXEEXT): gentrigtables.c
+ 	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $< $(BUILD_LIBM)
+ CLEANFILES += gentrigtables$(BUILD_EXEEXT)
+ 
++build-grub-module-verifier$(BUILD_EXEEXT): $(top_srcdir)/util/grub-module-verifier.c $(top_srcdir)/util/grub-module-verifier32.c $(top_srcdir)/util/grub-module-verifier64.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
++	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-module-verifier\" $^
++CLEANFILES += build-grub-module-verifier$(BUILD_EXEEXT)
++
+ # trigtables.c
+ trigtables.c: gentrigtables$(BUILD_EXEEXT) gentrigtables.c $(top_srcdir)/configure.ac
+ 	./gentrigtables$(BUILD_EXEEXT) > $@
+@@ -387,7 +391,7 @@ moddep.lst: syminfo.lst genmoddep.awk video.lst
+ platform_DATA += moddep.lst
+ CLEANFILES += config.log syminfo.lst moddep.lst
+ 
+-$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT)
++$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-grub-module-verifier
+ 	TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@
+ platform_DATA += $(MOD_FILES)
+ platform_DATA += modinfo.sh
+diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in
+index 789732b108b..7dcafd9d370 100644
+--- a/grub-core/genmod.sh.in
++++ b/grub-core/genmod.sh.in
+@@ -15,12 +15,12 @@ set -e
+ #
+ # Example:
+ #
+-# genmod.sh moddep.lst normal.module normal.mod
++# genmod.sh moddep.lst normal.module build-grub-module-verifier normal.mod
+ #
+ 
+ moddep=$1
+ infile=$2
+-outfile=$3
++outfile=$4
+ 
+ tmpfile=${outfile}.tmp
+ modname=`echo $infile | sed -e 's@\.module.*$@@'`
+@@ -93,4 +93,5 @@ else
+ 	    -wd1106 -nu -nd $tmpfile.bin $tmpfile || exit 1
+ 	rm -f $name.bin
+ fi
++./build-grub-module-verifier $tmpfile @target_cpu@
+ mv $tmpfile $outfile
diff --git a/SOURCES/0273-module-verifier-Check-range-limited-relative-relocat.patch b/SOURCES/0273-module-verifier-Check-range-limited-relative-relocat.patch
new file mode 100644
index 0000000..9d23811
--- /dev/null
+++ b/SOURCES/0273-module-verifier-Check-range-limited-relative-relocat.patch
@@ -0,0 +1,183 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Thu, 31 Dec 2015 15:29:28 +0100
+Subject: [PATCH] module-verifier: Check range-limited relative relocations.
+
+Check that they point to the same module, so will end up in the same
+chunk of memory.
+---
+ util/grub-module-verifier.c    | 19 ++++++++++---
+ util/grub-module-verifierXX.c  | 62 ++++++++++++++++++++++++++++++++++--------
+ include/grub/module_verifier.h |  1 +
+ 3 files changed, 67 insertions(+), 15 deletions(-)
+
+diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c
+index d2d6984033c..c027f0a0fb1 100644
+--- a/util/grub-module-verifier.c
++++ b/util/grub-module-verifier.c
+@@ -15,9 +15,13 @@ struct grub_module_verifier_arch archs[] = {
+   { "x86_64", 8, 0, EM_X86_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
+       R_X86_64_64,
+       R_X86_64_PC64,
+-      /* R_X86_64_32, R_X86_64_32S, R_X86_64_PC32 are supported but shouldn't be used because of their limited range.  */
++      /* R_X86_64_32, R_X86_64_32S are supported but shouldn't be used because of their limited range.  */
+       -1
+-    } },
++    }, (int[]){
++      R_X86_64_PC32,
++      -1
++    }
++  },
+   { "powerpc", 4, 1, EM_PPC, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
+       GRUB_ELF_R_PPC_ADDR16_LO,
+       GRUB_ELF_R_PPC_REL24, /* It has limited range but GRUB adds trampolines when necessarry.  */
+@@ -39,17 +43,24 @@ struct grub_module_verifier_arch archs[] = {
+     } },
+   { "ia64", 8, 0, EM_IA_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
+       R_IA64_PCREL21B, /* We should verify that it's pointing either
+-			  to a function or to a section in the same module.  */
++			  to a function or to a section in the same module.
++			  Checking that external symbol is a function is
++			  non-trivial and I have never seen this relocation used
++			  for anything else, so assume that it always points to a
++			  function.
++		       */
+       R_IA64_SEGREL64LSB,
+       R_IA64_FPTR64LSB,
+       R_IA64_DIR64LSB,
+       R_IA64_PCREL64LSB,
+-      R_IA64_GPREL22,  /* We should verify that it's pointing  to a section in the same module.  */
+       R_IA64_LTOFF22X,
+       R_IA64_LTOFF22,
+       R_IA64_LTOFF_FPTR22,
+       R_IA64_LDXMOV,
+       -1
++    }, (int[]){
++      R_IA64_GPREL22,
++      -1
+     } },
+   { "mipsel", 4, 0, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
+       R_MIPS_HI16,
+diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c
+index 904be27d39b..25988ebc21d 100644
+--- a/util/grub-module-verifierXX.c
++++ b/util/grub-module-verifierXX.c
+@@ -161,14 +161,12 @@ check_license (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
+   grub_util_error ("incompatible license");
+ }
+ 
+-static void
+-check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
++static Elf_Sym *
++get_symtab (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, Elf_Word *size, Elf_Word *entsize)
+ {
+   unsigned i;
+   Elf_Shdr *s, *sections;
+   Elf_Sym *sym;
+-  const char *str;
+-  Elf_Word size, entsize;
+ 
+   sections = (Elf_Shdr *) ((char *) e + grub_target_to_host (e->e_shoff));
+   for (i = 0, s = sections;
+@@ -181,11 +179,19 @@ check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
+     grub_util_error ("no symbol table");
+ 
+   sym = (Elf_Sym *) ((char *) e + grub_target_to_host (s->sh_offset));
+-  size = grub_target_to_host (s->sh_size);
+-  entsize = grub_target_to_host (s->sh_entsize);
++  *size = grub_target_to_host (s->sh_size);
++  *entsize = grub_target_to_host (s->sh_entsize);
++  return sym;
++}
+ 
+-  s = (Elf_Shdr *) ((char *) sections + grub_target_to_host16 (e->e_shentsize) * grub_target_to_host32 (s->sh_link));
+-  str = (char *) e + grub_target_to_host (s->sh_offset);
++static void
++check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
++{
++  Elf_Sym *sym;
++  Elf_Word size, entsize;
++  unsigned i;
++
++  sym = get_symtab (arch, e, &size, &entsize);
+ 
+   for (i = 0;
+        i < size / entsize;
+@@ -208,19 +214,41 @@ check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
+     }
+ }
+ 
+-/* Relocate symbols.  */
++static int
++is_symbol_local(Elf_Sym *sym)
++{
++  switch (ELF_ST_TYPE (sym->st_info))
++    {
++    case STT_NOTYPE:
++    case STT_OBJECT:
++      if (sym->st_name != 0 && sym->st_shndx == 0)
++	return 0;
++      return 1;
++
++    case STT_FUNC:
++    case STT_SECTION:
++      return 1;
++
++    default:
++      return 0;
++    }
++}
++
+ static void
+ section_check_relocations (const struct grub_module_verifier_arch *arch, void *ehdr,
+ 			   Elf_Shdr *s, size_t target_seg_size)
+ {
+   Elf_Rel *rel, *max;
++  Elf_Sym *symtab;
++  Elf_Word symtabsize, symtabentsize;
++
++  symtab = get_symtab (arch, ehdr, &symtabsize, &symtabentsize);
+ 
+   for (rel = (Elf_Rel *) ((char *) ehdr + grub_target_to_host (s->sh_offset)),
+ 	 max = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_size));
+        rel < max;
+        rel = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_entsize)))
+     {
+-      Elf_Word *addr;
+       Elf_Sym *sym;
+       unsigned i;
+ 
+@@ -235,8 +263,20 @@ section_check_relocations (const struct grub_module_verifier_arch *arch, void *e
+       for (i = 0; arch->supported_relocations[i] != -1; i++)
+ 	if (type == arch->supported_relocations[i])
+ 	  break;
+-      if (arch->supported_relocations[i] == -1)
++      if (arch->supported_relocations[i] != -1)
++	continue;
++      if (!arch->short_relocations)
+ 	grub_util_error ("unsupported relocation 0x%x", type);
++      for (i = 0; arch->short_relocations[i] != -1; i++)
++	if (type == arch->short_relocations[i])
++	  break;
++      if (arch->short_relocations[i] == -1)
++	grub_util_error ("unsupported relocation 0x%x", type);
++      sym = (Elf_Sym *) ((char *) symtab + symtabentsize * ELF_R_SYM (grub_target_to_host (rel->r_info)));
++
++      if (is_symbol_local (sym))
++	continue;
++      grub_util_error ("relocation 0x%x is not module-local", type);
+     }
+ }
+ 
+diff --git a/include/grub/module_verifier.h b/include/grub/module_verifier.h
+index 9e3a2ba720f..6cddff30f2e 100644
+--- a/include/grub/module_verifier.h
++++ b/include/grub/module_verifier.h
+@@ -13,6 +13,7 @@ struct grub_module_verifier_arch {
+   int machine;
+   int flags;
+   const int *supported_relocations;
++  const int *short_relocations;
+ };
+ 
+ void grub_module_verify64(void *module_img, size_t module_size, const struct grub_module_verifier_arch *arch);
diff --git a/SOURCES/0274-Strip-.ARM.exidx.patch b/SOURCES/0274-Strip-.ARM.exidx.patch
new file mode 100644
index 0000000..aed2f16
--- /dev/null
+++ b/SOURCES/0274-Strip-.ARM.exidx.patch
@@ -0,0 +1,39 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Thu, 31 Dec 2015 18:13:59 +0100
+Subject: [PATCH] Strip .ARM.exidx
+
+This section is generated by clang and is useful only for debugging.
+It contains exotic relocations, so strip them to avoid them interferring
+with module loading.
+---
+ gentpl.py              | 2 +-
+ grub-core/genmod.sh.in | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gentpl.py b/gentpl.py
+index 889cc91d39c..58430fcd236 100644
+--- a/gentpl.py
++++ b/gentpl.py
+@@ -753,7 +753,7 @@ def image(defn, platform):
+ if test x$(TARGET_APPLE_LINKER) = x1; then \
+   $(MACHO2IMG) $< $@; \
+ else \
+-  $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; \
++  $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version -R .ARM.exidx $< $@; \
+ fi
+ """)
+ 
+diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in
+index 7dcafd9d370..005cb198504 100644
+--- a/grub-core/genmod.sh.in
++++ b/grub-core/genmod.sh.in
+@@ -58,7 +58,7 @@ if test x@TARGET_APPLE_LINKER@ != x1; then
+ 		-K grub_mod_init -K grub_mod_fini \
+ 		-K _grub_mod_init -K _grub_mod_fini \
+ 		-R .note.gnu.gold-version -R .note.GNU-stack \
+-		-R .note -R .comment $tmpfile || exit 1
++		-R .note -R .comment -R .ARM.exidx $tmpfile || exit 1
+ 	fi
+ 	if ! test -z "${TARGET_OBJ2ELF}"; then
+ 	    "${TARGET_OBJ2ELF}" $tmpfile || exit 1
diff --git a/SOURCES/0275-Disable-build-time-module-check-on-emu.patch b/SOURCES/0275-Disable-build-time-module-check-on-emu.patch
new file mode 100644
index 0000000..51c4d4e
--- /dev/null
+++ b/SOURCES/0275-Disable-build-time-module-check-on-emu.patch
@@ -0,0 +1,26 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Thu, 31 Dec 2015 18:20:11 +0100
+Subject: [PATCH] Disable build-time module check on emu.
+
+On emu some checks can be laxer like check for relocation range. Additionally
+module loading in emu is rarely used. So skip this check rather than making
+it laxer for all platforms. In ideal we may want to have slightly different
+check for emu but for now this is good enough.
+---
+ grub-core/genmod.sh.in | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in
+index 005cb198504..f74edd55181 100644
+--- a/grub-core/genmod.sh.in
++++ b/grub-core/genmod.sh.in
+@@ -93,5 +93,7 @@ else
+ 	    -wd1106 -nu -nd $tmpfile.bin $tmpfile || exit 1
+ 	rm -f $name.bin
+ fi
+-./build-grub-module-verifier $tmpfile @target_cpu@
++if test x@platform@ != xemu; then
++    ./build-grub-module-verifier $tmpfile @target_cpu@
++fi
+ mv $tmpfile $outfile
diff --git a/SOURCES/0276-module-verifier-allow-limited-range-relocations-on-s.patch b/SOURCES/0276-module-verifier-allow-limited-range-relocations-on-s.patch
new file mode 100644
index 0000000..c1791b3
--- /dev/null
+++ b/SOURCES/0276-module-verifier-allow-limited-range-relocations-on-s.patch
@@ -0,0 +1,29 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Thu, 31 Dec 2015 18:30:39 +0100
+Subject: [PATCH] module-verifier: allow limited-range relocations on sparc64.
+
+clang as incomplete mcmodel=large support. As we don't currently need full
+mcmodel=large support for sparc64, relax those checks.
+---
+ util/grub-module-verifier.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c
+index c027f0a0fb1..e217dcddc07 100644
+--- a/util/grub-module-verifier.c
++++ b/util/grub-module-verifier.c
+@@ -38,7 +38,12 @@ struct grub_module_verifier_arch archs[] = {
+       R_SPARC_LO10,
+       R_SPARC_64,
+       R_SPARC_OLO10,
+-      /* R_SPARC_32, R_SPARC_HI22  are supported but shouldn't be used because of their limited range.  */
++      /* Following 2 relocations have limited range but unfortunately
++	 clang generates them, as it doesn't implement mcmodel=large properly.
++	 At least our heap and core are under 4G, so it's not a problem
++	 usually. */
++      R_SPARC_HI22,
++      R_SPARC_32,
+       -1
+     } },
+   { "ia64", 8, 0, EM_IA_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
diff --git a/SOURCES/0277-remove-temporary-.bin-files-kernel-and-modules.patch b/SOURCES/0277-remove-temporary-.bin-files-kernel-and-modules.patch
new file mode 100644
index 0000000..632f137
--- /dev/null
+++ b/SOURCES/0277-remove-temporary-.bin-files-kernel-and-modules.patch
@@ -0,0 +1,39 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrey Borzenkov <arvidjaar@gmail.com>
+Date: Thu, 31 Dec 2015 23:00:25 +0300
+Subject: [PATCH] remove temporary .bin files (kernel and modules)
+
+---
+ gentpl.py              | 2 ++
+ grub-core/genmod.sh.in | 2 +-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/gentpl.py b/gentpl.py
+index 58430fcd236..c17a18b0ea0 100644
+--- a/gentpl.py
++++ b/gentpl.py
+@@ -723,9 +723,11 @@ def kernel(defn, platform):
+ """if test x$(TARGET_APPLE_LINKER) = x1; then \
+   $(TARGET_STRIP) -S -x $(""" + cname(defn) + """) -o $@.bin $<; \
+   $(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -ed2016 -wd1106 -nu -nd $@.bin $@; \
++  rm -f $@.bin; \
+    elif test ! -z '$(TARGET_OBJ2ELF)'; then \
+      """  + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@.bin $< && \
+      $(TARGET_OBJ2ELF) $@.bin $@ || (rm -f $@; rm -f $@.bin; exit 1); \
++     rm -f $@.bin; \
+ else """  + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@ $<; \
+ fi"""))
+ 
+diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in
+index f74edd55181..ca2e59d5c42 100644
+--- a/grub-core/genmod.sh.in
++++ b/grub-core/genmod.sh.in
+@@ -91,7 +91,7 @@ else
+ 	    -nr:_grub_mod_init:grub_mod_init \
+ 	    -nr:_grub_mod_fini:grub_mod_fini \
+ 	    -wd1106 -nu -nd $tmpfile.bin $tmpfile || exit 1
+-	rm -f $name.bin
++	rm -f $tmpfile.bin
+ fi
+ if test x@platform@ != xemu; then
+     ./build-grub-module-verifier $tmpfile @target_cpu@
diff --git a/SOURCES/0278-Add-missing-BUILD_EXEEXT.patch b/SOURCES/0278-Add-missing-BUILD_EXEEXT.patch
new file mode 100644
index 0000000..afcd89c
--- /dev/null
+++ b/SOURCES/0278-Add-missing-BUILD_EXEEXT.patch
@@ -0,0 +1,111 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Fri, 1 Jan 2016 11:13:54 +0300
+Subject: [PATCH] Add missing BUILD_EXEEXT
+
+---
+ Makefile.am            | 45 +++++++++++++++++++++++++--------------------
+ grub-core/Makefile.am  |  2 +-
+ grub-core/genmod.sh.in |  2 +-
+ 3 files changed, 27 insertions(+), 22 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index f02ae0a393c..335a268ea9f 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -85,16 +85,21 @@ CLEANFILES += build-grub-gen-widthspec$(BUILD_EXEEXT)
+ 
+ if COND_STARFIELD
+ starfield_DATA = dejavu_10.pf2 dejavu_12.pf2 dejavu_bold_14.pf2 dejavu_14.pf2 dejavu_16.pf2 $(starfield_theme_files)
+-dejavu_10.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont
+-	./build-grub-mkfont -s 10 -o $@ $(DJVU_FONT_SOURCE)
+-dejavu_12.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont
+-	./build-grub-mkfont -s 12 -o $@ $(DJVU_FONT_SOURCE)
+-dejavu_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont
+-	./build-grub-mkfont -s 14 -o $@ $(DJVU_FONT_SOURCE)
+-dejavu_bold_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont
+-	./build-grub-mkfont -b -s 14 -o $@ $(DJVU_FONT_SOURCE)
+-dejavu_16.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont
+-	./build-grub-mkfont -s 16 -o $@ $(DJVU_FONT_SOURCE)
++dejavu_10.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
++	./build-grub-mkfont$(BUILD_EXEEXT) -s 10 -o $@ $(DJVU_FONT_SOURCE)
++CLEANFILES += dejavu_10.pf2
++dejavu_12.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
++	./build-grub-mkfont$(BUILD_EXEEXT) -s 12 -o $@ $(DJVU_FONT_SOURCE)
++CLEANFILES += dejavu_12.pf2
++dejavu_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
++	./build-grub-mkfont$(BUILD_EXEEXT) -s 14 -o $@ $(DJVU_FONT_SOURCE)
++CLEANFILES += dejavu_14.pf2
++dejavu_bold_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
++	./build-grub-mkfont$(BUILD_EXEEXT) -b -s 14 -o $@ $(DJVU_FONT_SOURCE)
++CLEANFILES += dejavu_bold_14.pf2
++dejavu_16.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
++	./build-grub-mkfont$(BUILD_EXEEXT) -s 16 -o $@ $(DJVU_FONT_SOURCE)
++CLEANFILES += dejavu_16.pf2
+ else
+ starfield_DATA =
+ endif
+@@ -102,28 +107,28 @@ endif
+ EXTRA_DIST += $(starfield_theme_files)
+ EXTRA_DIST += $(srcdir)/themes/starfield/src/slider_s.xcf $(srcdir)/themes/starfield/src/slider_n.xcf $(srcdir)/themes/starfield/src/slider_c.xcf $(srcdir)/themes/starfield/src/blob_nw.xcf $(srcdir)/themes/starfield/src/bootmenu/center.xcf $(srcdir)/themes/starfield/src/bootmenu/corner.xcf $(srcdir)/themes/starfield/src/bootmenu/side.xcf $(srcdir)/themes/starfield/src/terminalbox/side.xcf $(srcdir)/themes/starfield/src/terminalbox/corner.xcf $(srcdir)/themes/starfield/src/terminalbox/center.xcf
+ 
+-unicode.pf2: $(FONT_SOURCE) build-grub-mkfont
+-	./build-grub-mkfont -o $@ $(FONT_SOURCE) || (rm -f $@; exit 1)
++unicode.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
++	./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) || (rm -f $@; exit 1)
+ CLEANFILES += unicode.pf2
+ 
+ # Arrows and lines are needed to draw the menu, so always include them
+ UNICODE_ARROWS=0x2190-0x2193
+ UNICODE_LINES=0x2501-0x251B
+ 
+-ascii.pf2: $(FONT_SOURCE) build-grub-mkfont
+-	./build-grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1)
++ascii.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
++	./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1)
+ CLEANFILES += ascii.pf2
+ 
+-euro.pf2: $(FONT_SOURCE) build-grub-mkfont
+-	./build-grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x4ff,0x1e00-0x1fff,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1)
++euro.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
++	./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) -r 0x0-0x4ff,0x1e00-0x1fff,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1)
+ CLEANFILES += euro.pf2
+ 
+-ascii.h: $(FONT_SOURCE) build-grub-gen-asciih
+-	./build-grub-gen-asciih $(FONT_SOURCE) $@ || (rm -f $@; exit 1)
++ascii.h: $(FONT_SOURCE) build-grub-gen-asciih$(BUILD_EXEEXT)
++	./build-grub-gen-asciih$(BUILD_EXEEXT) $(FONT_SOURCE) $@ || (rm -f $@; exit 1)
+ CLEANFILES += ascii.h
+ 
+-widthspec.h: $(FONT_SOURCE) build-grub-gen-widthspec
+-	./build-grub-gen-widthspec $(FONT_SOURCE) $@ || (rm -f $@; exit 1)
++widthspec.h: $(FONT_SOURCE) build-grub-gen-widthspec$(BUILD_EXEEXT)
++	./build-grub-gen-widthspec$(BUILD_EXEEXT) $(FONT_SOURCE) $@ || (rm -f $@; exit 1)
+ CLEANFILES += widthspec.h
+ 
+ # Install config.h into platformdir
+diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
+index 77205f16358..59a00f11fab 100644
+--- a/grub-core/Makefile.am
++++ b/grub-core/Makefile.am
+@@ -391,7 +391,7 @@ moddep.lst: syminfo.lst genmoddep.awk video.lst
+ platform_DATA += moddep.lst
+ CLEANFILES += config.log syminfo.lst moddep.lst
+ 
+-$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-grub-module-verifier
++$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-grub-module-verifier$(BUILD_EXEEXT)
+ 	TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@
+ platform_DATA += $(MOD_FILES)
+ platform_DATA += modinfo.sh
+diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in
+index ca2e59d5c42..045817b1534 100644
+--- a/grub-core/genmod.sh.in
++++ b/grub-core/genmod.sh.in
+@@ -94,6 +94,6 @@ else
+ 	rm -f $tmpfile.bin
+ fi
+ if test x@platform@ != xemu; then
+-    ./build-grub-module-verifier $tmpfile @target_cpu@
++    ./build-grub-module-verifier@BUILD_EXEEXT@ $tmpfile @target_cpu@
+ fi
+ mv $tmpfile $outfile
diff --git a/SOURCES/0279-grub-module-verifier-fix-unintended-sign-extension.patch b/SOURCES/0279-grub-module-verifier-fix-unintended-sign-extension.patch
new file mode 100644
index 0000000..3284408
--- /dev/null
+++ b/SOURCES/0279-grub-module-verifier-fix-unintended-sign-extension.patch
@@ -0,0 +1,24 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Fri, 8 Jan 2016 11:05:16 +0300
+Subject: [PATCH] grub-module-verifier: fix unintended sign extension
+
+Found by: Coverity scan.
+CID: 156533, 156532
+---
+ util/grub-module-verifierXX.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c
+index 25988ebc21d..f612d51f389 100644
+--- a/util/grub-module-verifierXX.c
++++ b/util/grub-module-verifierXX.c
+@@ -337,7 +337,7 @@ SUFFIX(grub_module_verify) (void *module_img, size_t size, const struct grub_mod
+ 
+   /* Make sure that every section is within the core.  */
+   if (size < grub_target_to_host (e->e_shoff)
+-      + grub_target_to_host16 (e->e_shentsize) * grub_target_to_host16(e->e_shnum))
++      + (grub_uint32_t) grub_target_to_host16 (e->e_shentsize) * grub_target_to_host16(e->e_shnum))
+     {
+       grub_util_error ("ELF sections outside core");
+     }
diff --git a/SOURCES/0280-mkimage-fix-unintended-sign-extension.patch b/SOURCES/0280-mkimage-fix-unintended-sign-extension.patch
new file mode 100644
index 0000000..f151b7f
--- /dev/null
+++ b/SOURCES/0280-mkimage-fix-unintended-sign-extension.patch
@@ -0,0 +1,24 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Sat, 9 Jan 2016 21:05:44 +0300
+Subject: [PATCH] mkimage: fix unintended sign extension
+
+Found by: Coverity scan.
+CID: 73691, 73717
+---
+ util/grub-mkimagexx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
+index 0a1ac9e517c..66e8576411e 100644
+--- a/util/grub-mkimagexx.c
++++ b/util/grub-mkimagexx.c
+@@ -1465,7 +1465,7 @@ SUFFIX (load_image) (const char *kernel_path, size_t *exec_size,
+   section_entsize = grub_target_to_host16 (e->e_shentsize);
+   num_sections = grub_target_to_host16 (e->e_shnum);
+ 
+-  if (kernel_size < section_offset + section_entsize * num_sections)
++  if (kernel_size < section_offset + (grub_uint32_t) section_entsize * num_sections)
+     grub_util_error (_("premature end of file %s"), kernel_path);
+ 
+   sections = (Elf_Shdr *) (kernel_img + section_offset);
diff --git a/SOURCES/0281-arm64-Add-support-for-relocations-needed-for-linaro-.patch b/SOURCES/0281-arm64-Add-support-for-relocations-needed-for-linaro-.patch
new file mode 100644
index 0000000..030ecc7
--- /dev/null
+++ b/SOURCES/0281-arm64-Add-support-for-relocations-needed-for-linaro-.patch
@@ -0,0 +1,212 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 22 Jan 2016 19:09:37 +0100
+Subject: [PATCH] arm64: Add support for relocations needed for linaro gcc
+
+---
+ grub-core/kern/arm64/dl.c        | 18 ++++++++++++++++++
+ grub-core/kern/arm64/dl_helper.c | 40 ++++++++++++++++++++++++++++++++++++++++
+ util/grub-mkimagexx.c            | 31 +++++++++++++++++++++++++++++++
+ util/grub-module-verifier.c      |  8 +++++++-
+ include/grub/arm64/reloc.h       |  8 ++++++++
+ include/grub/elf.h               |  3 +++
+ 6 files changed, 107 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/arm64/dl.c b/grub-core/kern/arm64/dl.c
+index e19ba6a0d58..cf50d7250d9 100644
+--- a/grub-core/kern/arm64/dl.c
++++ b/grub-core/kern/arm64/dl.c
+@@ -132,6 +132,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
+ 	    *abs_place = (grub_uint64_t) sym_addr;
+ 	  }
+ 	  break;
++	case R_AARCH64_ADD_ABS_LO12_NC:
++	  grub_arm64_set_abs_lo12 (place, sym_addr);
++	  break;
++	case R_AARCH64_LDST64_ABS_LO12_NC:
++	  grub_arm64_set_abs_lo12_ldst64 (place, sym_addr);
++	  break;
+ 	case R_AARCH64_CALL26:
+ 	case R_AARCH64_JUMP26:
+ 	  {
+@@ -154,6 +160,18 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
+ 	    grub_arm64_set_xxxx26_offset (place, offset);
+ 	  }
+ 	  break;
++	case R_AARCH64_ADR_PREL_PG_HI21:
++	  {
++	    grub_int64_t offset = (sym_addr & ~0xfffULL) - (((grub_uint64_t) place) & ~0xfffULL);
++
++	    if (!grub_arm64_check_hi21_signed (offset))
++		return grub_error (GRUB_ERR_BAD_MODULE,
++				   "HI21 out of range");
++
++	    grub_arm64_set_hi21 (place, offset);
++	  }
++	  break;
++
+ 	default:
+ 	  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ 			     N_("relocation 0x%x is not implemented yet"),
+diff --git a/grub-core/kern/arm64/dl_helper.c b/grub-core/kern/arm64/dl_helper.c
+index d213ab93e88..f031b1ae921 100644
+--- a/grub-core/kern/arm64/dl_helper.c
++++ b/grub-core/kern/arm64/dl_helper.c
+@@ -53,3 +53,43 @@ grub_arm64_set_xxxx26_offset (grub_uint32_t *place, grub_int64_t offset)
+   *place &= insmask;
+   *place |= grub_cpu_to_le32 (offset >> 2) & ~insmask;
+ }
++
++int
++grub_arm64_check_hi21_signed (grub_int64_t offset)
++{
++  if (offset != (grub_int64_t)(grub_int32_t)offset)
++    return 0;
++  return 1;
++}
++
++void
++grub_arm64_set_hi21 (grub_uint32_t *place, grub_int64_t offset)
++{
++  const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0x9f00001f);
++  grub_uint32_t val;
++
++  offset >>= 12;
++  
++  val = ((offset & 3) << 29) | (((offset >> 2) & 0x7ffff) << 5);
++  
++  *place &= insmask;
++  *place |= grub_cpu_to_le32 (val) & ~insmask;
++}
++
++void
++grub_arm64_set_abs_lo12 (grub_uint32_t *place, grub_int64_t target)
++{
++  const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff);
++
++  *place &= insmask;
++  *place |= grub_cpu_to_le32 (target << 10) & ~insmask;
++}
++
++void
++grub_arm64_set_abs_lo12_ldst64 (grub_uint32_t *place, grub_int64_t target)
++{
++  const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfff803ff);
++
++  *place &= insmask;
++  *place |= grub_cpu_to_le32 (target << 7) & ~insmask;
++}
+diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
+index 66e8576411e..d1bc95e350d 100644
+--- a/util/grub-mkimagexx.c
++++ b/util/grub-mkimagexx.c
+@@ -836,6 +836,14 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
+ 		       *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
+ 		     }
+ 		     break;
++		   case R_AARCH64_ADD_ABS_LO12_NC:
++		     grub_arm64_set_abs_lo12 ((grub_uint32_t *) target,
++					      sym_addr);
++		     break;
++		   case R_AARCH64_LDST64_ABS_LO12_NC:
++		     grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) target,
++						     sym_addr);
++		     break;
+ 		   case R_AARCH64_JUMP26:
+ 		   case R_AARCH64_CALL26:
+ 		     {
+@@ -848,6 +856,17 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
+ 						     sym_addr);
+ 		     }
+ 		     break;
++		   case R_AARCH64_ADR_PREL_PG_HI21:
++		     {
++		       sym_addr &= ~0xfffULL;
++		       sym_addr -= (offset + SUFFIX (entry_point)) & ~0xfffULL;
++		       if (!grub_arm64_check_hi21_signed (sym_addr))
++			 grub_util_error ("%s", "CALL26 Relocation out of range");
++
++		       grub_arm64_set_hi21((grub_uint32_t *)target,
++					   sym_addr);
++		     }
++		     break;
+ 		   default:
+ 		     grub_util_error (_("relocation 0x%x is not implemented yet"),
+ 				      (unsigned int) ELF_R_TYPE (info));
+@@ -1200,6 +1219,15 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out,
+ 		  case R_AARCH64_CALL26:
+ 		  case R_AARCH64_JUMP26:
+ 		    break;
++		    /* Page-relative relocations do not require fixup entries. */
++		  case R_AARCH64_ADR_PREL_PG_HI21:
++		     /* We page-align the whole kernel, so no need
++			for fixup entries.
++		      */
++		  case R_AARCH64_ADD_ABS_LO12_NC:
++		  case R_AARCH64_LDST64_ABS_LO12_NC:
++		    break;
++
+ 		  default:
+ 		    grub_util_error (_("relocation 0x%x is not implemented yet"),
+ 				     (unsigned int) ELF_R_TYPE (info));
+@@ -1343,6 +1371,9 @@ SUFFIX (locate_sections) (const char *kernel_path,
+   Elf_Shdr *s;
+ 
+   *all_align = 1;
++  /* Page-aligning simplifies relocation handling.  */
++  if (image_target->elf_target == EM_AARCH64)
++    *all_align = 4096;
+ 
+   section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
+   memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
+diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c
+index e217dcddc07..405c9117051 100644
+--- a/util/grub-module-verifier.c
++++ b/util/grub-module-verifier.c
+@@ -107,7 +107,13 @@ struct grub_module_verifier_arch archs[] = {
+       R_AARCH64_CALL26,
+       R_AARCH64_JUMP26,
+       -1
+-    } },
++    }, (int[]){
++      R_AARCH64_ADR_PREL_PG_HI21,
++      R_AARCH64_ADD_ABS_LO12_NC,
++      R_AARCH64_LDST64_ABS_LO12_NC,
++      -1
++    }
++  },
+ };
+ 
+ 
+diff --git a/include/grub/arm64/reloc.h b/include/grub/arm64/reloc.h
+index 4aed3d715e0..452c148226d 100644
+--- a/include/grub/arm64/reloc.h
++++ b/include/grub/arm64/reloc.h
+@@ -22,5 +22,13 @@
+ int grub_arm_64_check_xxxx26_offset (grub_int64_t offset);
+ void
+ grub_arm64_set_xxxx26_offset (grub_uint32_t *place, grub_int64_t offset);
++int
++grub_arm64_check_hi21_signed (grub_int64_t offset);
++void
++grub_arm64_set_hi21 (grub_uint32_t *place, grub_int64_t offset);
++void
++grub_arm64_set_abs_lo12 (grub_uint32_t *place, grub_int64_t target);
++void
++grub_arm64_set_abs_lo12_ldst64 (grub_uint32_t *place, grub_int64_t target);
+ 
+ #endif
+diff --git a/include/grub/elf.h b/include/grub/elf.h
+index caa79639082..db15acecf9f 100644
+--- a/include/grub/elf.h
++++ b/include/grub/elf.h
+@@ -2068,6 +2068,9 @@ typedef Elf32_Addr Elf32_Conflict;
+ #define R_AARCH64_NONE			0	/* No relocation.  */
+ #define R_AARCH64_ABS64			257	/* Direct 64 bit. */
+ #define R_AARCH64_ABS32			258	/* Direct 32 bit.  */
++#define R_AARCH64_ADR_PREL_PG_HI21	275
++#define R_AARCH64_ADD_ABS_LO12_NC	277
++#define R_AARCH64_LDST64_ABS_LO12_NC	286
+ #define R_AARCH64_JUMP26		282	/* 26-bit relative. */
+ #define R_AARCH64_CALL26		283	/* 26-bit relative. */
+ #define R_AARCH64_COPY			1024	/* Copy symbol at runtime.  */
diff --git a/SOURCES/0282-support-modules-without-symbol-table.patch b/SOURCES/0282-support-modules-without-symbol-table.patch
new file mode 100644
index 0000000..326deb6
--- /dev/null
+++ b/SOURCES/0282-support-modules-without-symbol-table.patch
@@ -0,0 +1,106 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Wed, 3 Feb 2016 20:34:55 +0300
+Subject: [PATCH] support modules without symbol table
+
+all_video module does not have any code or data and exists solely for
+.moddeps section to pull in dependencies. This makes all symbols unneeded.
+
+While in current binutils (last released version as of this commit is 2.26)
+``strip --strip-unneeded'' unintentionally adds section symbols for each
+existing section, this behavior was considered a bug and changed in commit
+14f2c699ddca1e2f706342dffc59a6c7e23e844c to completely strip symbol table
+in this case.
+
+Older binutils (verified with 2.17) and some other toolchains (at least
+elftoolchain r3223M), both used in FreeBSD, remove symbol table in all_video
+as well.
+
+Relax run-time check and do not return error for modules without symbol table.
+Add additional checks to module verifier to make sure such modules
+
+a) have non-empty .moddeps section. Without either externally visible symbols
+or .moddeps modules are completely useless and should not be built.
+
+b) do not have any relocations.
+
+Closes: 46986
+
+v2: add run-time check for empty symbol table if relocations are present as
+    suggested by Vladimir.
+---
+ grub-core/kern/dl.c           |  8 +++++++-
+ util/grub-module-verifierXX.c | 18 +++++++++++++++++-
+ 2 files changed, 24 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
+index b0b0405fcbe..c45afc64950 100644
+--- a/grub-core/kern/dl.c
++++ b/grub-core/kern/dl.c
+@@ -341,8 +341,11 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
+     if (s->sh_type == SHT_SYMTAB)
+       break;
+ 
++  /* Module without symbol table may still be used to pull in dependencies.
++     We verify at build time that such modules do not contain any relocations
++     that may reference symbol table. */
+   if (i == e->e_shnum)
+-    return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table"));
++    return GRUB_ERR_NONE;
+ 
+ #ifdef GRUB_MODULES_MACHINE_READONLY
+   mod->symtab = grub_malloc (s->sh_size);
+@@ -584,6 +587,9 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
+ 
+ 	if (seg)
+ 	  {
++	    if (!mod->symtab)
++	      return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table");
++
+ 	    err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg);
+ 	    if (err)
+ 	      return err;
+diff --git a/util/grub-module-verifierXX.c b/util/grub-module-verifierXX.c
+index f612d51f389..9c04caa63b4 100644
+--- a/util/grub-module-verifierXX.c
++++ b/util/grub-module-verifierXX.c
+@@ -176,7 +176,7 @@ get_symtab (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e, Elf_Word
+       break;
+ 
+   if (i == grub_target_to_host16 (e->e_shnum))
+-    grub_util_error ("no symbol table");
++    return NULL;
+ 
+   sym = (Elf_Sym *) ((char *) e + grub_target_to_host (s->sh_offset));
+   *size = grub_target_to_host (s->sh_size);
+@@ -191,7 +191,21 @@ check_symbols (const struct grub_module_verifier_arch *arch, Elf_Ehdr *e)
+   Elf_Word size, entsize;
+   unsigned i;
+ 
++  /* Module without symbol table and without .moddeps section is useless
++     at boot time, so catch it early to prevent build errors */
+   sym = get_symtab (arch, e, &size, &entsize);
++  if (!sym)
++    {
++      Elf_Shdr *s = find_section (arch, e, ".moddeps");
++
++      if (!s)
++	grub_util_error ("no symbol table and no .moddeps section");
++
++      if (!s->sh_size)
++	grub_util_error ("no symbol table and empty .moddeps section");
++
++      return;
++    }
+ 
+   for (i = 0;
+        i < size / entsize;
+@@ -243,6 +257,8 @@ section_check_relocations (const struct grub_module_verifier_arch *arch, void *e
+   Elf_Word symtabsize, symtabentsize;
+ 
+   symtab = get_symtab (arch, ehdr, &symtabsize, &symtabentsize);
++  if (!symtab)
++    grub_util_error ("relocation without symbol table");
+ 
+   for (rel = (Elf_Rel *) ((char *) ehdr + grub_target_to_host (s->sh_offset)),
+ 	 max = (Elf_Rel *) ((char *) rel + grub_target_to_host (s->sh_size));
diff --git a/SOURCES/0283-cacheinfo-Add-missing-license-information.patch b/SOURCES/0283-cacheinfo-Add-missing-license-information.patch
new file mode 100644
index 0000000..fd6c6d6
--- /dev/null
+++ b/SOURCES/0283-cacheinfo-Add-missing-license-information.patch
@@ -0,0 +1,22 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Fri, 20 Mar 2015 11:13:58 +0100
+Subject: [PATCH] cacheinfo: Add missing license information.
+
+---
+ grub-core/commands/cacheinfo.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/grub-core/commands/cacheinfo.c b/grub-core/commands/cacheinfo.c
+index ead6ff82cfc..d34a346964c 100644
+--- a/grub-core/commands/cacheinfo.c
++++ b/grub-core/commands/cacheinfo.c
+@@ -23,6 +23,8 @@
+ #include <grub/i18n.h>
+ #include <grub/disk.h>
+ 
++GRUB_MOD_LICENSE ("GPLv3+");
++
+ static grub_err_t
+ grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)),
+     int argc __attribute__ ((unused)),
diff --git a/SOURCES/0284-arm64-setjmp-Add-missing-license-macro.patch b/SOURCES/0284-arm64-setjmp-Add-missing-license-macro.patch
new file mode 100644
index 0000000..0424f79
--- /dev/null
+++ b/SOURCES/0284-arm64-setjmp-Add-missing-license-macro.patch
@@ -0,0 +1,31 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: dann frazier <dann.frazier@canonical.com>
+Date: Thu, 21 May 2015 10:28:48 -0600
+Subject: [PATCH] arm64/setjmp: Add missing license macro
+
+Including the setjmp module in an arm64-efi image will cause it to
+immediately exit with an "incompatible license" error.
+
+The source file includes a GPLv3+ boilerplate, so fix this by declaring a
+GPLv3+ license using the GRUB_MOD_LICENSE macro.
+
+Signed-off-by: dann frazier <dann.frazier@canonical.com>
+---
+ grub-core/lib/arm64/setjmp.S | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/grub-core/lib/arm64/setjmp.S b/grub-core/lib/arm64/setjmp.S
+index adaafe40f71..eabfd99b296 100644
+--- a/grub-core/lib/arm64/setjmp.S
++++ b/grub-core/lib/arm64/setjmp.S
+@@ -17,8 +17,10 @@
+  */
+ 
+ #include <grub/symbol.h>
++#include <grub/dl.h>
+ 
+ 	.file	"setjmp.S"
++GRUB_MOD_LICENSE "GPLv3+"
+ 	.text
+ 
+ /*
diff --git a/SOURCES/0285-editenv-handle-relative-symlinks.patch b/SOURCES/0285-editenv-handle-relative-symlinks.patch
new file mode 100644
index 0000000..20e1686
--- /dev/null
+++ b/SOURCES/0285-editenv-handle-relative-symlinks.patch
@@ -0,0 +1,50 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jonathan Lebon <jlebon@redhat.com>
+Date: Mon, 14 Aug 2017 14:37:20 -0400
+Subject: [PATCH] editenv: handle relative symlinks
+
+Handle symlinks with targets relative to the containing dir. This
+ensures that the rename operation does not depend on the cwd.
+
+Resolves: rhbz#1479960
+
+Signed-off-by: Jonathan Lebon <jlebon@redhat.com>
+---
+ util/editenv.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/util/editenv.c b/util/editenv.c
+index d8d1dad6ab9..41bc7cb1c9a 100644
+--- a/util/editenv.c
++++ b/util/editenv.c
+@@ -28,6 +28,7 @@
+ 
+ #include <errno.h>
+ #include <string.h>
++#include <libgen.h>
+ 
+ #define DEFAULT_ENVBLK_SIZE	1024
+ 
+@@ -87,9 +88,20 @@ grub_util_create_envblk_file (const char *name)
+ 	  continue;
+ 	}
+ 
+-      free (rename_target);
+       linkbuf[retsize] = '\0';
+-      rename_target = linkbuf;
++      if (linkbuf[0] == '/')
++        {
++          free (rename_target);
++          rename_target = linkbuf;
++        }
++      else
++        {
++          char *dbuf = xstrdup (rename_target);
++          const char *dir = dirname (dbuf);
++          free (rename_target);
++          rename_target = xasprintf("%s/%s", dir, linkbuf);
++          free (dbuf);
++        }
+     }
+ 
+   int rc = grub_util_rename (namenew, rename_target);
diff --git a/SOURCES/0286-efinet-also-use-the-firmware-acceleration-for-http.patch b/SOURCES/0286-efinet-also-use-the-firmware-acceleration-for-http.patch
new file mode 100644
index 0000000..5771c8a
--- /dev/null
+++ b/SOURCES/0286-efinet-also-use-the-firmware-acceleration-for-http.patch
@@ -0,0 +1,25 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 30 Jul 2018 14:06:42 -0400
+Subject: [PATCH] efinet: also use the firmware acceleration for http
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/net/efi/net.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c
+index 2bf15447fd5..f208d1b180c 100644
+--- a/grub-core/net/efi/net.c
++++ b/grub-core/net/efi/net.c
+@@ -1324,7 +1324,9 @@ grub_efi_net_boot_from_https (void)
+ 	  && (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE))
+ 	{
+ 	  grub_efi_uri_device_path_t *uri_dp = (grub_efi_uri_device_path_t *) dp;
+-	  return (grub_strncmp ((const char*)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0) ? 1 : 0;
++	  grub_dprintf ("efinet", "url:%s\n", (const char *)uri_dp->uri);
++	  return (grub_strncmp ((const char *)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0 ||
++	          grub_strncmp ((const char *)uri_dp->uri, "http://", sizeof ("http://") - 1) == 0);
+ 	}
+ 
+       if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
diff --git a/SOURCES/0287-Make-root_url-reflect-the-protocol-hostname-of-our-b.patch b/SOURCES/0287-Make-root_url-reflect-the-protocol-hostname-of-our-b.patch
new file mode 100644
index 0000000..2a5ffcd
--- /dev/null
+++ b/SOURCES/0287-Make-root_url-reflect-the-protocol-hostname-of-our-b.patch
@@ -0,0 +1,47 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 30 Jul 2018 16:39:57 -0400
+Subject: [PATCH] Make root_url reflect the protocol+hostname of our boot url.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/net/efi/http.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c
+index 3f61fd2fa5b..243acbaa35b 100644
+--- a/grub-core/net/efi/http.c
++++ b/grub-core/net/efi/http.c
+@@ -4,6 +4,7 @@
+ #include <grub/misc.h>
+ #include <grub/net/efi.h>
+ #include <grub/charset.h>
++#include <grub/env.h>
+ 
+ static void
+ http_configure (struct grub_efi_net_device *dev, int prefer_ip6)
+@@ -351,6 +352,24 @@ grub_efihttp_open (struct grub_efi_net_device *dev,
+   grub_err_t err;
+   grub_off_t size;
+   char *buf;
++  char *root_url;
++  grub_efi_ipv6_address_t address;
++  const char *rest;
++
++  if (grub_efi_string_to_ip6_address (file->device->net->server, &address, &rest) && *rest == 0)
++    root_url = grub_xasprintf ("%s://[%s]", type ? "https" : "http", file->device->net->server);
++  else
++    root_url = grub_xasprintf ("%s://%s", type ? "https" : "http", file->device->net->server);
++  if (root_url)
++    {
++      grub_env_unset ("root_url");
++      grub_env_set ("root_url", root_url);
++      grub_free (root_url);
++    }
++  else
++    {
++      return grub_errno;
++    }
+ 
+   err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 1, 0);
+   if (err != GRUB_ERR_NONE)
diff --git a/SOURCES/0288-efi-uga-Fix-PCIe-LER-when-GRUB2-accesses-non-enabled.patch b/SOURCES/0288-efi-uga-Fix-PCIe-LER-when-GRUB2-accesses-non-enabled.patch
new file mode 100644
index 0000000..7101637
--- /dev/null
+++ b/SOURCES/0288-efi-uga-Fix-PCIe-LER-when-GRUB2-accesses-non-enabled.patch
@@ -0,0 +1,50 @@
+From a897321d9c318c18c92c6431115fd9be71fedba1 Mon Sep 17 00:00:00 2001
+From: "mike.travis@hpe.com" <mike.travis@hpe.com>
+Date: Wed, 28 Mar 2018 11:42:18 -0500
+Subject: [PATCH 288/288] efi/uga: Fix PCIe LER when GRUB2 accesses non-enabled
+ MMIO data from VGA
+
+A GPU inserted into a PCIe I/O slot disappears during system startup.
+The problem centers around GRUB and a specific VGA init function in
+efi_uga.c. This causes an LER (Link Error Recorvery) because the MMIO
+memory has not been enabled before attempting access.
+
+The fix is to add the same coding used in other VGA drivers, specifically
+to add a check to insure that it is indeed a VGA controller. And then
+enable the MMIO address space with the specific bits.
+
+Signed-off-by: Mike Travis <mike.travis@hpe.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/efi_uga.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/video/efi_uga.c b/grub-core/video/efi_uga.c
+index 1d4091c5631..97a607c01a5 100644
+--- a/grub-core/video/efi_uga.c
++++ b/grub-core/video/efi_uga.c
+@@ -94,10 +94,19 @@ static int
+ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
+ {
+   struct find_framebuf_ctx *ctx = data;
+-  grub_pci_address_t addr;
++  grub_pci_address_t addr, rcaddr;
++  grub_uint32_t subclass;
+ 
+   addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
+-  if (grub_pci_read (addr) >> 24 == 0x3)
++  subclass = (grub_pci_read (addr) >> 16) & 0xffff;
++
++  if (subclass != GRUB_PCI_CLASS_SUBCLASS_VGA)
++    return 0;
++
++  /* Enable MEM address spaces */
++  rcaddr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
++  grub_pci_write_word (rcaddr, grub_pci_read_word (rcaddr) | GRUB_PCI_COMMAND_MEM_ENABLED);
++
+     {
+       int i;
+ 
+-- 
+2.17.1
+
diff --git a/SOURCES/0289-efidisk-prevent-errors-from-diskfilter-scan-of-remov.patch b/SOURCES/0289-efidisk-prevent-errors-from-diskfilter-scan-of-remov.patch
new file mode 100644
index 0000000..70abdb9
--- /dev/null
+++ b/SOURCES/0289-efidisk-prevent-errors-from-diskfilter-scan-of-remov.patch
@@ -0,0 +1,54 @@
+From 8f4dc1510c0f42a549b91c28eda74fe8a1e2a5d4 Mon Sep 17 00:00:00 2001
+From: Andrei Borzenkov <arvidjaar@gmail.com>
+Date: Fri, 26 Feb 2016 21:44:37 +0300
+Subject: [PATCH] efidisk: prevent errors from diskfilter scan of removable
+ drives
+
+Map EFI_NO_MEDIA to GRUB_ERR_OUT_OF_RANGE that is ignored by diskfilter. This
+actually matches pretty close (we obviously attempt to read outside of media)
+and avoids adding more error codes.
+
+This affects only internally initiated scans. If read/write from removable is
+explicitly requested, we still return an error and text explanation is more
+clear for user than generic error.
+
+Reported and tested by Andreas Loew <Andreas.Loew@gmx.net>
+---
+ grub-core/disk/efi/efidisk.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c
+index f04f20b84ff..41adc1b0421 100644
+--- a/grub-core/disk/efi/efidisk.c
++++ b/grub-core/disk/efi/efidisk.c
+@@ -575,9 +575,11 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector,
+ 
+   status = grub_efidisk_readwrite (disk, sector, size, buf, 0);
+ 
+-  if (status != GRUB_EFI_SUCCESS)
++  if (status == GRUB_EFI_NO_MEDIA)
++    return grub_error (GRUB_ERR_OUT_OF_RANGE, "no media in `%s'", disk->name);
++  else if (status != GRUB_EFI_SUCCESS)
+     return grub_error (GRUB_ERR_READ_ERROR,
+-		       N_("failure reading sector 0x%llx from `%s'"),
++		       "failure reading sector 0x%llx from `%s'",
+ 		       (unsigned long long) sector,
+ 		       disk->name);
+ 
+@@ -596,9 +598,11 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector,
+ 
+   status = grub_efidisk_readwrite (disk, sector, size, (char *) buf, 1);
+ 
+-  if (status != GRUB_EFI_SUCCESS)
++  if (status == GRUB_EFI_NO_MEDIA)
++    return grub_error (GRUB_ERR_OUT_OF_RANGE, "no media in `%s'", disk->name);
++  else if (status != GRUB_EFI_SUCCESS)
+     return grub_error (GRUB_ERR_WRITE_ERROR,
+-		       N_("failure writing sector 0x%llx to `%s'"),
++		       "failure writing sector 0x%llx to `%s'",
+ 		       (unsigned long long) sector, disk->name);
+ 
+   return GRUB_ERR_NONE;
+-- 
+2.20.1
+
diff --git a/SOURCES/gitignore b/SOURCES/gitignore
new file mode 100644
index 0000000..f318bf1
--- /dev/null
+++ b/SOURCES/gitignore
@@ -0,0 +1,243 @@
+00_header
+10_*
+20_linux_xen
+30_os-prober
+40_custom
+41_custom
+*.1
+*.8
+aclocal.m4
+ahci_test
+ascii.bitmaps
+ascii.h
+autom4te.cache
+build-grub-gen-asciih
+build-grub-gen-widthspec
+build-grub-mkfont
+cdboot_test
+cmp_test
+config.cache
+config.guess
+config.h
+config-util.h
+config-util.h.in
+config.log
+config.status
+config.sub
+configure
+core_compress_test
+DISTLIST
+docs/*.info
+docs/stamp-vti
+docs/version.texi
+ehci_test
+example_grub_script_test
+example_scripted_test
+example_unit_test
+*.exec
+*.exec.exe
+fddboot_test
+genkernsyms.sh
+gensymlist.sh
+gentrigtables
+gentrigtables.exe
+gettext_strings_test
+grub-bin2h
+/grub-bios-setup
+/grub-bios-setup.exe
+grub_cmd_date
+grub_cmd_echo
+grub_cmd_regexp
+grub_cmd_set_date
+grub_cmd_sleep
+/grub-editenv
+/grub-editenv.exe
+grub-emu
+grub-emu-lite
+grub-emu.exe
+grub-emu-lite.exe
+grub_emu_init.c
+grub_emu_init.h
+grub-fstest
+grub-fstest.exe
+grub_fstest_init.c
+grub_fstest_init.h
+grub_func_test
+grub-install
+grub-install.exe
+grub-kbdcomp
+grub-macho2img
+/grub-menulst2cfg
+/grub-menulst2cfg.exe
+/grub-mk*
+grub-mount
+/grub-ofpathname
+/grub-ofpathname.exe
+grub-core/build-grub-pe2elf.exe
+/grub-probe
+/grub-probe.exe
+grub_probe_init.c
+grub_probe_init.h
+/grub-reboot
+grub_script_blanklines
+grub_script_blockarg
+grub_script_break
+grub-script-check
+grub-script-check.exe
+grub_script_check_init.c
+grub_script_check_init.h
+grub_script_comments
+grub_script_continue
+grub_script_dollar
+grub_script_echo1
+grub_script_echo_keywords
+grub_script_escape_comma
+grub_script_eval
+grub_script_expansion
+grub_script_final_semicolon
+grub_script_for1
+grub_script_functions
+grub_script_gettext
+grub_script_if
+grub_script_leading_whitespace
+grub_script_no_commands
+grub_script_not
+grub_script_return
+grub_script_setparams
+grub_script_shift
+grub_script_strcmp
+grub_script_test
+grub_script_vars1
+grub_script_while1
+grub_script.tab.c
+grub_script.tab.h
+grub_script.yy.c
+grub_script.yy.h
+grub-set-default
+grub_setup_init.c
+grub_setup_init.h
+grub-shell
+grub-shell-tester
+grub-sparc64-setup
+grub-sparc64-setup.exe
+gzcompress_test
+hddboot_test
+help_test
+*.img
+*.image
+*.image.exe
+include/grub/cpu
+include/grub/machine
+install-sh
+lib/libgcrypt-grub
+libgrub_a_init.c
+*.log
+*.lst
+lzocompress_test
+*.marker
+Makefile
+*.mod
+mod-*.c
+missing
+netboot_test
+*.o
+*.a
+ohci_test
+partmap_test
+pata_test
+*.pf2
+*.pp
+po/*.mo
+po/grub.pot
+po/POTFILES
+po/stamp-po
+printf_test
+priority_queue_unit_test
+pseries_test
+stamp-h
+stamp-h1
+stamp-h.in
+symlist.c
+symlist.h
+trigtables.c
+*.trs
+uhci_test
+update-grub_lib
+unidata.c
+xzcompress_test
+Makefile.in
+GPATH
+GRTAGS
+GSYMS
+GTAGS
+compile
+depcomp
+mdate-sh
+texinfo.tex
+grub-core/lib/libgcrypt-grub
+.deps
+.deps-util
+.deps-core
+.dirstamp
+Makefile.util.am
+contrib
+grub-core/bootinfo.txt
+grub-core/Makefile.core.am
+grub-core/Makefile.gcry.def
+grub-core/contrib
+grub-core/gdb_grub
+grub-core/genmod.sh
+grub-core/gensyminfo.sh
+grub-core/gmodule.pl
+grub-core/grub.chrp
+grub-core/modinfo.sh
+grub-core/*.module
+grub-core/*.module.exe
+grub-core/*.pp
+util/bash-completion.d/grub
+grub-core/gnulib/alloca.h
+grub-core/gnulib/arg-nonnull.h
+grub-core/gnulib/c++defs.h
+grub-core/gnulib/charset.alias
+grub-core/gnulib/configmake.h
+grub-core/gnulib/float.h
+grub-core/gnulib/getopt.h
+grub-core/gnulib/langinfo.h
+grub-core/gnulib/ref-add.sed
+grub-core/gnulib/ref-del.sed
+grub-core/gnulib/stdio.h
+grub-core/gnulib/stdlib.h
+grub-core/gnulib/string.h
+grub-core/gnulib/strings.h
+grub-core/gnulib/sys
+grub-core/gnulib/unistd.h
+grub-core/gnulib/warn-on-use.h
+grub-core/gnulib/wchar.h
+grub-core/gnulib/wctype.h
+grub-core/rs_decoder.h
+widthspec.bin
+widthspec.h
+docs/stamp-1
+docs/version-dev.texi
+Makefile.utilgcry.def
+po/*.po
+po/*.gmo
+po/LINGUAS
+po/remove-potcdate.sed
+include/grub/gcrypt/gcrypt.h
+include/grub/gcrypt/g10lib.h
+po/POTFILES.in
+po/POTFILES-shell.in
+/grub-glue-efi
+/grub-render-label
+/grub-glue-efi.exe
+/grub-render-label.exe
+grub-core/gnulib/locale.h
+grub-core/gnulib/unitypes.h
+grub-core/gnulib/uniwidth.h
+build-aux/test-driver
+/garbage-gen
+/garbage-gen.exe
+/grub-fs-tester
+!util/grub.d/[[:digit:]][[:digit:]]*.in
+!util/*.[[:digit:]]
diff --git a/SOURCES/grub.macros b/SOURCES/grub.macros
new file mode 100644
index 0000000..20a2f97
--- /dev/null
+++ b/SOURCES/grub.macros
@@ -0,0 +1,510 @@
+# vim:filetype=spec
+
+%global flagday 1:2.02-0.65.el7_4
+
+# Modules always contain just 32-bit code
+%global _libdir %{_exec_prefix}/lib
+%global _binaries_in_noarch_packages_terminate_build 0
+#%%undefine _missing_build_ids_terminate_build
+%{expand:%%{!?buildsubdir:%%global buildsubdir grub-%{tarversion}}}
+%{expand:%%{!?_licensedir:%%global license %%%%doc}}
+
+%if %{?_with_ccache: 1}%{?!_with_ccache: 0}
+%global cc_equals CC=/usr/%{_lib}/ccache/gcc
+%else
+%global cc_equals %{nil}
+%endif
+
+%global efi_cflags %(echo %{optflags} | 			\\\
+	sed							\\\
+		-e 's/-O./-g3/g'				\\\
+		-e 's/-fstack-protector[[:alpha:]-]\\+//g'	\\\
+		-e 's/-Wp,-D_FORTIFY_SOURCE=[[:digit:]]\\+//g'	\\\
+		-e 's/--param=ssp-buffer-size=4//g'		\\\
+		-e 's/-mregparm=3/-mregparm=4/g'		\\\
+		-e 's/-fexceptions//g'				\\\
+		-e 's/-fasynchronous-unwind-tables//g'		\\\
+		-e 's/^/ -fno-strict-aliasing /' ) %{nil}
+%global legacy_cflags %(echo %{efi_cflags} |			\\\
+	sed							\\\
+		-e 's/-m64//g'					\\\
+		-e 's/-mcpu=power[[:alnum:]]\\+/-mcpu=power6/g'	\\\
+		) %{nil}
+
+
+%global with_efi_arch 0
+%global with_alt_efi_arch 0
+%global with_legacy_arch 0
+%global with_legacy_utils 0
+%global grubefiarch %{nil}
+%global grublegacyarch %{nil}
+
+# sparc is always compiled 64 bit
+%ifarch %{sparc}
+%global target_cpu_name sparc64
+%global _target_platform %{target_cpu_name}-%{_vendor}-%{_target_os}%{?_gnu}
+%global legacy_target_cpu_name %{_arch}
+%global legacy_package_arch ieee1275
+%global platform ieee1275
+%endif
+# ppc is always compiled 64 bit
+%ifarch ppc ppc64 ppc64le
+%global target_cpu_name %{_arch}
+%global legacy_target_cpu_name powerpc
+%global legacy_package_arch %{_arch}
+%global legacy_grub_dir powerpc-ieee1275
+%global _target_platform %{target_cpu_name}-%{_vendor}-%{_target_os}%{?_gnu}
+%global platform ieee1275
+%endif
+
+%global efi_only aarch64 %{arm}
+%global efi_arch x86_64 ia64 %{efi_only}
+%ifarch %{efi_arch}
+%global with_efi_arch 1
+%else
+%global with_efi_arch 0
+%endif
+%ifarch %{efi_only}
+%global with_efi_only 1
+%else
+%global with_efi_only 0
+%endif
+%{!?with_efi_arch:%global without_efi_arch 0}
+%{?with_efi_arch:%global without_efi_arch 1}
+%{!?with_efi_only:%global without_efi_only 0}
+%{?with_efi_only:%global without_efi_only 1}
+
+### fixme
+%ifarch aarch64 %{arm}
+%global efi_modules " http linux "
+%else
+%global efi_modules " backtrace http linuxefi usb usbserial_common usbserial_pl2303 usbserial_ftdi usbserial_usbdebug "
+%endif
+
+%ifarch x86_64
+%global efiarch x64
+%global target_cpu_name %{_arch}
+%global grub_target_name %{_arch}-efi
+%global package_arch efi-x64
+
+%global legacy_target_cpu_name i386
+%global legacy_package_arch pc
+%global platform pc
+
+%global alt_efi_arch ia32
+%global alt_target_cpu_name i386
+%global alt_grub_target_name i386-efi
+%global alt_platform efi
+%global alt_package_arch efi-ia32
+%global alt_efi_cflags %(echo %{efi_cflags} |			\\\
+	sed							\\\
+		-e 's/-m64//g'				\\\
+	) %{nil}
+%endif
+%ifarch %{ix86}
+%global target_cpu_name %{_arch}
+%global grub_target_name %{_arch}-pc
+
+%global legacy_target_cpu_name i386
+%global legacy_package_arch pc
+%global platform pc
+
+%global with_legacy_arch 0
+%endif
+
+%ifarch aarch64
+%global efiarch aa64
+%global target_cpu_name aarch64
+%global grub_target_name arm64-efi
+%global package_arch efi-aa64
+%endif
+
+%ifarch %{arm}
+%global efiarch arm
+%global target_cpu_name arm
+%global grub_target_name arm-efi
+%global package_arch efi-arm
+%endif
+
+%global _target_platform %{target_cpu_name}-%{_vendor}-%{_target_os}%{?_gnu}
+%global _alt_target_platform %{alt_target_cpu_name}-%{_vendor}-%{_target_os}%{?_gnu}
+
+%ifarch %{efi_arch}
+%global with_efi_arch 1
+%global grubefiname grub%{efiarch}.efi
+%global grubeficdname gcd%{efiarch}.efi
+%global grubefiarch %{target_cpu_name}-efi
+%endif
+
+%if 0%{?alt_efi_arch:1}
+%global with_alt_efi_arch 1
+%global grubaltefiname grub%{alt_efi_arch}.efi
+%global grubalteficdname gcd%{alt_efi_arch}.efi
+%global grubaltefiarch %{alt_target_cpu_name}-efi
+%endif
+
+# Figure out the right file path to use
+%global efidir %(eval echo $(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/'))
+
+%ifnarch %{efi_only}
+%global with_legacy_arch 1
+%global with_legacy_utils 1
+%global grublegacyarch %{legacy_target_cpu_name}-%{platform}
+%global moduledir %{legacy_target_cpu_name}-%{platform}
+%endif
+
+%global evr %{epoch}:%{version}-%{release}
+
+%if %{with_legacy_arch}
+%global with_efi_common 0
+%global with_legacy_common 1
+%else
+%global with_efi_common 1
+%global with_legacy_common 0
+%endif
+%ifarch %{ix86}
+%global with_efi_arch 0
+%global with_alt_efi_arch 0
+%global with_efi_common 0
+%global with_legacy_common 1
+%global with_legacy_utils 1
+%global with_legacy_arch 0
+%endif
+
+%if 0%{with_efi_common}
+%global common_srcdir grub-%{grubefiarch}-%{tarversion}
+%endif
+%if 0%{with_legacy_common}
+%global common_srcdir grub-%{grublegacyarch}-%{tarversion}
+%endif
+
+%define define_legacy_variant()						\
+%{expand:%%package %{1}}						\
+Summary:	Bootloader with support for Linux, Multiboot, and more	\
+Group:		System Environment/Base					\
+Requires:	%{name}-common = %{evr}					\
+Requires:	%{name}-tools-minimal = %{evr}				\
+Requires:	%{name}-%{1}-modules = %{evr}				\
+Requires:	gettext which file					\
+Requires:	%{name}-tools-extra = %{evr}				\
+Requires:	%{name}-tools = %{evr}					\
+Requires(pre):	dracut							\
+Requires(post): dracut							\
+%{expand:%%description %{1}}						\
+%{desc}									\
+This subpackage provides support for %{1} systems.			\
+									\
+%{expand:%%{?!buildsubdir:%%define buildsubdir grub-%{1}-%{tarversion}}}\
+%{expand:%%package %{1}-modules}					\
+Summary:	Modules used to build custom grub images		\
+Group:		System Environment/Base					\
+BuildArch:	noarch							\
+Requires:	%{name}-common = %{evr}					\
+%{expand:%%description %{1}-modules}					\
+%{desc}									\
+This subpackage provides support for rebuilding your own grub.efi.	\
+									\
+%{expand:%%{?!buildsubdir:%%define buildsubdir grub-%{1}-%{tarversion}}}\
+%{expand:%%package %{1}-tools}						\
+Summary:	Support tools for GRUB.					\
+Group:		System Environment/Base					\
+Requires:	gettext os-prober which file system-logos		\
+Requires:	%{name}-common = %{evr}					\
+Requires:	%{name}-tools-minimal = %{evr}				\
+Requires:	os-prober >= 1.58-11					\
+Requires:	gettext which file					\
+									\
+%{expand:%%description %{1}-tools}					\
+%{desc}									\
+This subpackage provides tools for support of %{1} platforms.		\
+%{nil}
+
+%define define_efi_variant(p)						\
+%{expand:%%package %{1}}						\
+Summary:	GRUB for EFI systems.					\
+Group:		System Environment/Base					\
+Requires:	%{name}-common = %{evr}					\
+Requires:	%{name}-tools-minimal >= %{evr}				\
+Requires:	%{name}-tools-extra = %{evr}				\
+Requires:	%{name}-tools = %{evr}					\
+%{-p:Provides:	%{name}-efi = %{evr}}					\
+%{-p:Obsoletes:	%{name}-efi <= %{flagday}}				\
+									\
+%{expand:%%description %{1}}						\
+%{desc}									\
+This subpackage provides support for %{1} systems.			\
+									\
+%{expand:%%{?!buildsubdir:%%define buildsubdir grub-%{1}-%{tarversion}}}\
+%{expand:%%package %{1}-modules}					\
+Summary:	Modules used to build custom grub.efi images		\
+Group:		System Environment/Base					\
+BuildArch:	noarch							\
+Requires:	%{name}-common = %{evr}					\
+%{-p:Provides:	%{name}-efi-modules = %{evr}}				\
+%{-p:Obsoletes:	%{name}-efi-modules <= %{flagday}}			\
+%{expand:%%description %{1}-modules}					\
+%{desc}									\
+This subpackage provides support for rebuilding your own grub.efi.	\
+									\
+%{expand:%%package %{1}-cdboot}						\
+Summary:	Files used to boot removeable media with EFI		\
+Group:		System Environment/Base					\
+Requires:	%{name}-common = %{evr}					\
+%{expand:%%description %{1}-cdboot}					\
+%{desc}									\
+This subpackage provides optional components of grub used with removeable media on %{1} systems.\
+%{nil}
+
+%global do_common_setup()					\
+%setup -D -q -T -a 0 -n grub-%{tarversion}			\
+cd grub-%{tarversion}						\
+rm -fv docs/*.info						\
+cp %{SOURCE5} unifont.pcf.gz					\
+cp %{SOURCE6} .gitignore					\
+git init							\
+echo '![[:digit:]][[:digit:]]_*.in' > util/grub.d/.gitignore	\
+echo '!*.[[:digit:]]' > util/.gitignore				\
+git config user.email "%{name}-owner@fedoraproject.org"		\
+git config user.name "Fedora Ninjas"				\
+git config gc.auto 0						\
+git add .							\
+git commit -a -q -m "%{tarversion} baseline."			\
+git am %%{patches} </dev/null					\
+git config --unset user.email					\
+git config --unset user.name					\
+cd ..								\
+%{nil}
+
+%global do_setup()						\
+cp -al grub-%{tarversion} grub-%{1}-%{tarversion}		\
+%{nil}
+
+%global do_common_build()					\
+cd %{common_srcdir}						\
+makeinfo --info --no-split -I docs -o docs/grub-dev.info	\\\
+	docs/grub-dev.texi					\
+makeinfo --info --no-split -I docs -o docs/grub.info		\\\
+	docs/grub.texi						\
+makeinfo --html --no-split -I docs -o docs/grub-dev.html	\\\
+	docs/grub-dev.texi					\
+makeinfo --html --no-split -I docs -o docs/grub.html		\\\
+	docs/grub.texi						\
+cd ..								\
+%{nil}
+
+%define do_efi_configure()					\
+./autogen.sh							\
+%configure							\\\
+	%{cc_equals}						\\\
+	CFLAGS="%{2}"						\\\
+	TARGET_LDFLAGS=-static					\\\
+        --with-platform=efi					\\\
+	--target=%{1}						\\\
+	--with-grubdir=%{name}					\\\
+        --program-transform-name=s,grub,%{name},		\\\
+	--disable-grub-mount					\\\
+	--disable-werror					\
+%{nil}
+
+%define do_efi_build_modules()					\
+make %{?_smp_mflags} ascii.h widthspec.h			\
+make %{?_smp_mflags} -C grub-core				\
+%{nil}
+
+%define do_efi_build_all()					\
+make %{?_smp_mflags}						\
+%{nil}
+
+%define do_efi_link_utils()					\
+for x in grub-mkimage ; do					\\\
+	ln ../grub-%{1}-%{tarversion}/${x} ./ ;			\\\
+done								\
+%{nil}
+
+%ifarch x86_64 aarch64
+%define mkimage()						\
+%{4}./grub-mkimage -O %{1} -o %{2}.orig				\\\
+	-p /EFI/%{efidir} -d grub-core ${GRUB_MODULES}		\
+%{4}./grub-mkimage -O %{1} -o %{3}.orig				\\\
+	-p /EFI/BOOT -d grub-core ${GRUB_MODULES}		\
+%{expand:%%{pesign -s -i %{2}.orig -o %{2} -a %{5} -c %{6} -n %{7}}}	\
+%{expand:%%{pesign -s -i %{3}.orig -o %{3} -a %{5} -c %{6} -n %{7}}}	\
+%{nil}
+%else
+%define mkimage()						\
+%{4}./grub-mkimage -O %{1} -o %{2}				\\\
+	-p /EFI/%{efidir} -d grub-core ${GRUB_MODULES}		\
+%{4}./grub-mkimage -O %{1} -o %{3}				\\\
+	-p /EFI/BOOT -d grub-core ${GRUB_MODULES}		\
+%{nil}
+%endif
+
+%define do_efi_build_images()					\
+GRUB_MODULES="	all_video boot btrfs cat chain configfile echo	\\\
+		efifwsetup efinet ext2 fat font gfxmenu gfxterm \\\
+		gzio halt hfsplus iso9660 jpeg loadenv loopback \\\
+		lvm mdraid09 mdraid1x minicmd normal part_apple \\\
+		part_msdos part_gpt password_pbkdf2 png reboot	\\\
+		regexp search search_fs_uuid search_fs_file	\\\
+		search_label serial sleep syslinuxcfg test tftp \\\
+		video xfs"					\
+GRUB_MODULES+=%{efi_modules}					\
+%{expand:%%{mkimage %{1} %{2} %{3} %{4} %{5} %{6} %{7}}}	\
+%{nil}
+
+%define do_primary_efi_build()					\
+cd grub-%{1}-%{tarversion}					\
+%{expand:%%do_efi_configure %%{4} %%{5}}			\
+%do_efi_build_all						\
+%{expand:%%do_efi_build_images %{grub_target_name} %{2} %{3} ./ %{6} %{7} %{8}}\
+cd ..								\
+%{nil}
+
+%define do_alt_efi_build()					\
+cd grub-%{1}-%{tarversion}					\
+%{expand:%%do_efi_configure %%{4} %%{5}}			\
+%do_efi_build_modules						\
+%{expand:%%do_efi_link_utils %{grubefiarch}}			\
+%{expand:%%do_efi_build_images %{alt_grub_target_name} %{2} %{3} ../grub-%{grubefiarch}-%{tarversion}/ %{6} %{7} %{8}}	\
+cd ..								\
+%{nil}
+
+%define do_legacy_build()					\
+cd grub-%{1}-%{tarversion}					\
+./autogen.sh							\
+%configure							\\\
+	%{cc_equals}						\\\
+	CFLAGS="%{legacy_cflags}"				\\\
+	TARGET_LDFLAGS=-static					\\\
+        --with-platform=%{platform}				\\\
+	--target=%{_target_platform}				\\\
+	--with-grubdir=%{name}					\\\
+        --program-transform-name=s,grub,%{name},		\\\
+	--disable-grub-mount					\\\
+	--disable-werror					\
+make %{?_smp_mflags}						\
+cd ..								\
+%{nil}
+
+%define do_alt_efi_install()					\
+cd grub-%{1}-%{tarversion}					\
+install -d -m 755 $RPM_BUILD_ROOT/usr/lib/grub/%{grubaltefiarch}/ \
+find . '(' -iname gdb_grub					\\\
+	-o -iname kernel.exec					\\\
+	-o -iname kernel.img					\\\
+	-o -iname config.h					\\\
+	-o -iname gmodule.pl					\\\
+	-o -iname modinfo.sh					\\\
+	-o -iname '*.lst'					\\\
+	-o -iname '*.mod'					\\\
+	')'							\\\
+	-exec cp {} $RPM_BUILD_ROOT/usr/lib/grub/%{grubaltefiarch}/ \\\; \
+find $RPM_BUILD_ROOT -iname "*.mod*" -exec chmod a-x {} '\;'	\
+install -m 700 %{2} $RPM_BUILD_ROOT/boot/efi/EFI/%{efidir}/%{2}	\
+install -m 700 %{3} $RPM_BUILD_ROOT/boot/efi/EFI/%{efidir}/%{3} \
+cd ..								\
+%{nil}
+
+%define do_efi_install()					\
+cd grub-%{1}-%{tarversion}					\
+install -m 700 -d $RPM_BUILD_ROOT/boot/efi/EFI/%{efidir}/	\
+install -m 700 -d $RPM_BUILD_ROOT/boot/grub2/			\
+make DESTDIR=$RPM_BUILD_ROOT install				\
+if [ -f $RPM_BUILD_ROOT%{_infodir}/grub.info ]; then		\
+	rm -f $RPM_BUILD_ROOT%{_infodir}/grub.info		\
+fi								\
+if [ -f $RPM_BUILD_ROOT%{_infodir}/grub-dev.info ]; then	\
+	rm -f $RPM_BUILD_ROOT%{_infodir}/grub-dev.info		\
+fi								\
+find $RPM_BUILD_ROOT -iname "*.module" -exec chmod a-x {} '\;'	\
+touch $RPM_BUILD_ROOT/boot/efi/EFI/%{efidir}/grub.cfg		\
+ln -sf ../boot/efi/EFI/%{efidir}/grub.cfg			\\\
+	$RPM_BUILD_ROOT%{_sysconfdir}/%{name}-efi.cfg		\
+install -m 700 %{2} $RPM_BUILD_ROOT/boot/efi/EFI/%{efidir}/%{2}	\
+install -m 700 %{3} $RPM_BUILD_ROOT/boot/efi/EFI/%{efidir}/%{3} \
+install -D -m 700 unicode.pf2					\\\
+	$RPM_BUILD_ROOT/boot/efi/EFI/%{efidir}/fonts/unicode.pf2\
+cd ..								\
+%{nil}
+
+%define do_legacy_install()					\
+cd grub-%{1}-%{tarversion}					\
+make DESTDIR=$RPM_BUILD_ROOT install				\
+if [ -f $RPM_BUILD_ROOT%{_infodir}/grub.info ]; then		\
+	rm -f $RPM_BUILD_ROOT%{_infodir}/grub.info		\
+fi								\
+if [ -f $RPM_BUILD_ROOT%{_infodir}/grub-dev.info ]; then	\
+	rm -f $RPM_BUILD_ROOT%{_infodir}/grub-dev.info		\
+fi								\
+touch ${RPM_BUILD_ROOT}/boot/%{name}/grub.cfg			\
+ln -s ../boot/%{name}/grub.cfg					\\\
+	${RPM_BUILD_ROOT}%{_sysconfdir}/grub2.cfg		\
+cd ..								\
+if [ -f $RPM_BUILD_ROOT/%{_libdir}/grub/%{1}/grub2.chrp ]; then \
+	mv $RPM_BUILD_ROOT/%{_libdir}/grub/%{1}/grub2.chrp	\\\
+	   $RPM_BUILD_ROOT/%{_libdir}/grub/%{1}/grub.chrp	\
+fi								\
+%{nil}
+
+%define do_common_install()					\
+cd %{common_srcdir}						\
+install -d -m 0755 						\\\
+	$RPM_BUILD_ROOT%{_datarootdir}/locale/en\@quot		\\\
+	$RPM_BUILD_ROOT%{_datarootdir}/locale/en		\\\
+	$RPM_BUILD_ROOT%{_infodir}/				\
+cp -a $RPM_BUILD_ROOT%{_datarootdir}/locale/en\@quot		\\\
+	$RPM_BUILD_ROOT%{_datarootdir}/locale/en		\
+cp docs/grub.info $RPM_BUILD_ROOT%{_infodir}/%{name}.info	\
+cp docs/grub-dev.info						\\\
+	$RPM_BUILD_ROOT%{_infodir}/%{name}-dev.info		\
+# Ghost config file						\
+install -d -m 0700 ${RPM_BUILD_ROOT}/boot/efi/EFI/%{efidir}/	\
+install -d -m 0700 ${RPM_BUILD_ROOT}/boot/grub2/		\
+install -d -m 0755 ${RPM_BUILD_ROOT}/boot/%{name}/themes/system	\
+install -d -m 0755 ${RPM_BUILD_ROOT}%{_sysconfdir}/default	\
+install -d -m 0755 ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig	\
+touch ${RPM_BUILD_ROOT}%{_sysconfdir}/default/grub		\
+ln -sf ../default/grub						\\\
+	${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/grub		\
+ln -sf ../efi/EFI/%{efidir}/grubenv				\\\
+	$RPM_BUILD_ROOT/boot/grub2/grubenv			\
+cd ..								\
+%{nil}
+
+%define define_legacy_variant_files()				\
+%{expand:%%files %{1}}						\
+%defattr(-,root,root,-)						\
+%config(noreplace) %{_sysconfdir}/%{name}.cfg			\
+%ghost %config(noreplace) /boot/%{name}/grub.cfg		\
+								\
+%{expand:%%files %{1}-modules}					\
+%defattr(-,root,root)						\
+%dir %{_libdir}/grub/%{2}/					\
+%{_libdir}/grub/%{2}/*						\
+%exclude %{_libdir}/grub/%{2}/*.module				\
+%exclude %{_libdir}/grub/%{2}/{boot,boot_hybrid,cdboot,diskboot,lzma_decompress,pxeboot}.{image,img}						\
+%exclude %{_libdir}/grub/%{2}/*.o				\
+%{nil}
+
+%define define_efi_variant_files()				\
+%{expand:%%files %{1}}						\
+%defattr(-,root,root,-)						\
+%config(noreplace) %{_sysconfdir}/%{name}-efi.cfg		\
+%verify(not mtime) %dir %attr(0700,root,root)/boot/efi/EFI/%{efidir} \
+%verify(not mtime) %attr(0700,root,root)/boot/efi/EFI/%{efidir}/%{2} \
+%verify(not mtime) %attr(0700,root,root)/boot/efi/EFI/%{efidir}/fonts \
+%ghost %config(noreplace) %verify(not mtime) %attr(0700,root,root)/boot/efi/EFI/%{efidir}/grub.cfg \
+%config(noreplace) /boot/grub2/grubenv						\
+%ghost %config(noreplace) %attr(0700,root,root)/boot/efi/EFI/%{efidir}/grubenv \
+								\
+%{expand:%%files %{1}-modules}					\
+%defattr(-,root,root,-)						\
+%dir %{_libdir}/grub/%{6}/					\
+%{_libdir}/grub/%{6}/*						\
+%exclude %{_libdir}/grub/%{6}/*.module				\
+								\
+%{expand:%%files %{1}-cdboot}					\
+%defattr(-,root,root,-)						\
+%verify(not mtime) %attr(0700,root,root)/boot/efi/EFI/%{efidir}/%{3} \
+%verify(not mtime) %attr(0700,root,root)/boot/efi/EFI/%{efidir}/fonts \
+%{nil}
diff --git a/SOURCES/grub.patches b/SOURCES/grub.patches
new file mode 100644
index 0000000..5fda75b
--- /dev/null
+++ b/SOURCES/grub.patches
@@ -0,0 +1,289 @@
+Patch0001: 0001-fix-EFI-detection-on-Windows.patch
+Patch0002: 0002-grub-core-kern-arm-cache_armv6.S-Remove-.arch-direct.patch
+Patch0003: 0003-INSTALL-Cross-compiling-the-GRUB-Fix-some-spelling-m.patch
+Patch0004: 0004-NEWS-First-draft-of-2.02-entry.patch
+Patch0005: 0005-Merge-branch-master-of-git.sv.gnu.org-srv-git-grub.patch
+Patch0006: 0006-NEWS-The-cmosclean-command-in-fact-dates-back-to-1.9.patch
+Patch0007: 0007-remove-unused-error.h-from-kern-emu-misc.c.patch
+Patch0008: 0008-Don-t-abort-on-unavailable-coreboot-tables-if-not-ru.patch
+Patch0009: 0009-NEWS-Add-few-missing-entries.-Correct-existing-ones.patch
+Patch0010: 0010-strip-.eh_frame-section-from-arm64-efi-kernel.patch
+Patch0011: 0011-use-grub-boot-aa64.efi-for-boot-images-on-AArch64.patch
+Patch0012: 0012-fix-32-bit-compilation-on-MinGW-w64.patch
+Patch0013: 0013-Change-grub-mkrescue-to-use-bootaa64.efi-too.patch
+Patch0014: 0014-arm64-set-correct-length-of-device-path-end-entry.patch
+Patch0015: 0015-Makefile.util.def-grub-macbless-Change-mansection-to.patch
+Patch0016: 0016-add-part_apple-to-EFI-rescue-image-to-fix-missing-pr.patch
+Patch0017: 0017-freebsd-hostdisk.c-is-only-ever-compiled-on-FreeBSD.patch
+Patch0018: 0018-Prefer-more-portable-test-1-constructs.patch
+Patch0019: 0019-NEWS-Add-few-missing-entries.patch
+Patch0020: 0020-grub-core-kern-efi-efi.c-Ensure-that-the-result-star.patch
+Patch0021: 0021-util-grub-mount.c-Extend-GCC-warning-workaround-to-g.patch
+Patch0022: 0022-reintroduce-BUILD_LDFLAGS-for-the-cross-compile-case.patch
+Patch0023: 0023-grub-core-term-terminfo.c-Recognize-keys-F1-F12.patch
+Patch0024: 0024-Fix-ChangeLog-date.patch
+Patch0025: 0025-Use-_W64-to-detect-MinGW-W64-32-instead-of-_FILE_OFF.patch
+Patch0026: 0026-add-BUILD_EXEEXT-support-to-fix-make-clean-on-Window.patch
+Patch0027: 0027-fix-include-loop-on-MinGW-due-to-libintl.h-pulling-s.patch
+Patch0028: 0028-grub-core-commands-macbless.c-Rename-FILE-and-DIR-to.patch
+Patch0029: 0029-Makefile.util.def-Link-grub-ofpathname-with-zfs-libs.patch
+Patch0030: 0030-Makefile.am-default_payload.elf-Add-modules-multiboo.patch
+Patch0031: 0031-fix-removal-of-cpu-machine-links-on-mingw-msys.patch
+Patch0032: 0032-grub-core-normal-main.c-read_config_file-Buffer-conf.patch
+Patch0033: 0033-util-grub-install.c-Fix-a-typo.patch
+Patch0034: 0034-use-MODULE_FILES-for-genemuinit-instead-of-MOD_FILES.patch
+Patch0035: 0035-Ignore-EPERM-when-modifying-kern.geom.debugflags.patch
+Patch0036: 0036-change-stop-condition-to-avoid-infinite-loops.patch
+Patch0037: 0037-increase-network-try-interval-gradually.patch
+Patch0038: 0038-look-for-DejaVu-also-in-usr-share-fonts-truetype.patch
+Patch0039: 0039-Show-detected-path-to-DejaVuSans-in-configure-summar.patch
+Patch0040: 0040-add-GRUB_WINDOWS_EXTRA_DIST-to-allow-shipping-runtim.patch
+Patch0041: 0041-util-grub-install.c-write_to_disk-Add-an-info-messag.patch
+Patch0042: 0042-util-grub-install.c-List-available-targets.patch
+Patch0043: 0043-Fix-several-translatable-strings.patch
+Patch0044: 0044-do-not-set-default-prefix-in-grub-mkimage.patch
+Patch0045: 0045-fix-Mingw-W64-32-cross-compile-failure-due-to-printf.patch
+Patch0046: 0046-grub-core-term-serial.c-grub_serial_register-Fix-inv.patch
+Patch0047: 0047-grub-install-support-for-partitioned-partx-loop-devi.patch
+Patch0048: 0048-grub-core-term-at_keyboard.c-Tolerate-missing-keyboa.patch
+Patch0049: 0049-.gitignore-add-missing-files-and-.exe-variants.patch
+Patch0050: 0050-util-grub-mkfont.c-Downgrade-warnings-about-unhandle.patch
+Patch0051: 0051-grub-core-disk-ahci.c-Do-not-enable-I-O-decoding-and.patch
+Patch0052: 0052-grub-core-disk-ahci.c-Allocate-and-clean-space-for-a.patch
+Patch0053: 0053-grub-core-disk-ahci.c-Add-safety-cleanups.patch
+Patch0054: 0054-grub-core-disk-ahci.c-Properly-handle-transactions-w.patch
+Patch0055: 0055-grub-core-disk-ahci.c-Increase-timeout.-Some-SSDs-ta.patch
+Patch0056: 0056-util-grub-mkfont.c-Build-fix-for-argp.h-with-older-g.patch
+Patch0057: 0057-util-grub-mkrescue.c-Build-fix-for-argp.h-with-older.patch
+Patch0058: 0058-add-grub_env_set_net_property-function.patch
+Patch0059: 0059-add-bootpath-parser-for-open-firmware.patch
+Patch0060: 0060-grub-core-disk-ahci.c-Ignore-NPORTS-field-and-rely-o.patch
+Patch0061: 0061-grub-core-kern-i386-coreboot-mmap.c-Filter-out-0xa00.patch
+Patch0062: 0062-grub-core-loader-i386-multiboot_mbi.c-grub_multiboot.patch
+Patch0063: 0063-grub-core-mmap-i386-uppermem.c-lower_hook-COREBOOT-I.patch
+Patch0064: 0064-grub-core-kern-i386-pc-mmap.c-Fallback-to-EISA-memor.patch
+Patch0065: 0065-include-grub-i386-openbsd_bootarg.h-Add-addr-and-fre.patch
+Patch0066: 0066-ieee1275-check-for-IBM-pseries-emulated-machine.patch
+Patch0067: 0067-grub-core-loader-arm64-linux.c-Remove-redundant-0x.patch
+Patch0068: 0068-grub-core-lib-relocator.c-Fix-the-case-when-end-of-l.patch
+Patch0069: 0069-Fix-grub-probe-0-option.patch
+Patch0070: 0070-Fix-partmap-cryptodisk-and-abstraction-handling-in-g.patch
+Patch0071: 0071-btrfs-fix-get_root-key-comparison-failures-due-to-en.patch
+Patch0072: 0072-grub-core-osdep-linux-getroot.c-grub_util_part_to_di.patch
+Patch0073: 0073-Replace-few-instances-of-memcmp-memcpy-in-the-code-t.patch
+Patch0074: 0074-include-grub-libgcc.h-Remove-ctzsi2-and-ctzdi2.-They.patch
+Patch0075: 0075-Add-missing-endif.patch
+Patch0076: 0076-grub-core-lib-syslinux_parse.c-Fix-timeout-quoting.patch
+Patch0077: 0077-Improve-LVM-logical_volumes-string-matching.patch
+Patch0078: 0078-Tolerate-devices-with-no-filesystem-UUID-returned-by.patch
+Patch0079: 0079-Allow-loading-old-kernels-by-placing-GDT-in-conventi.patch
+Patch0080: 0080-grub-core-kern-misc.c-__bzero-Don-t-compile-in-GRUB_.patch
+Patch0081: 0081-grub-core-commands-verify.c-grub_pubkey_open-Fix-mem.patch
+Patch0082: 0082-grub-core-commands-verify.c-grub_pubkey_open-Trust-p.patch
+Patch0083: 0083-util-grub-gen-asciih.c-add_glyph-Fix-uninitialised-v.patch
+Patch0084: 0084-grub-core-commands-efi-lsefisystab.c-grub_cmd_lsefis.patch
+Patch0085: 0085-grub-core-loader-i386-bsd.c-grub_netbsd_boot-Pass-po.patch
+Patch0086: 0086-util-grub-install.c-Fix-handling-of-disk-module.patch
+Patch0087: 0087-grub-core-commands-loadenv.c-check_blocklists-Fix-ov.patch
+Patch0088: 0088-NEWS-The-cmosclean-command-in-fact-dates-back-to-1.9.patch
+Patch0089: 0089-Migrate-PPC-from-Yaboot-to-Grub2.patch
+Patch0090: 0090-Add-fw_path-variable-revised.patch
+Patch0091: 0091-Add-support-for-linuxefi.patch
+Patch0092: 0092-Use-linuxefi-and-initrdefi-where-appropriate.patch
+Patch0093: 0093-Don-t-allow-insmod-when-secure-boot-is-enabled.patch
+Patch0094: 0094-Pass-x-hex-hex-straight-through-unmolested.patch
+Patch0095: 0095-Fix-crash-on-http.patch
+Patch0096: 0096-IBM-client-architecture-CAS-reboot-support.patch
+Patch0097: 0097-Add-vlan-tag-support.patch
+Patch0098: 0098-Add-X-option-to-printf-functions.patch
+Patch0099: 0099-DHCP-client-ID-and-UUID-options-added.patch
+Patch0100: 0100-Search-for-specific-config-file-for-netboot.patch
+Patch0101: 0101-blscfg-add-blscfg-module-to-parse-Boot-Loader-Specif.patch
+Patch0102: 0102-Move-bash-completion-script-922997.patch
+Patch0103: 0103-for-ppc-reset-console-display-attr-when-clear-screen.patch
+Patch0104: 0104-Don-t-write-messages-to-the-screen.patch
+Patch0105: 0105-Don-t-print-GNU-GRUB-header.patch
+Patch0106: 0106-Don-t-add-to-highlighted-row.patch
+Patch0107: 0107-Message-string-cleanups.patch
+Patch0108: 0108-Fix-border-spacing-now-that-we-aren-t-displaying-it.patch
+Patch0109: 0109-Use-the-correct-indentation-for-the-term-help-text.patch
+Patch0110: 0110-Indent-menu-entries.patch
+Patch0111: 0111-Fix-margins.patch
+Patch0112: 0112-Add-support-for-UEFI-operating-systems-returned-by-o.patch
+Patch0113: 0113-Disable-GRUB-video-support-for-IBM-power-machines.patch
+Patch0114: 0114-Use-2-instead-of-1-for-our-right-hand-margin-so-line.patch
+Patch0115: 0115-Use-linux16-when-appropriate-880840.patch
+Patch0116: 0116-Enable-pager-by-default.-985860.patch
+Patch0117: 0117-F10-doesn-t-work-on-serial-so-don-t-tell-the-user-to.patch
+Patch0118: 0118-Don-t-say-GNU-Linux-in-generated-menus.patch
+Patch0119: 0119-Don-t-draw-a-border-around-the-menu.patch
+Patch0120: 0120-Use-the-standard-margin-for-the-timeout-string.patch
+Patch0121: 0121-Fix-grub_script_execute_sourcecode-usage-on-ppc.patch
+Patch0122: 0122-Add-.eh_frame-to-list-of-relocations-stripped.patch
+Patch0123: 0123-Make-10_linux-work-with-our-changes-for-linux16-and-.patch
+Patch0124: 0124-Don-t-print-during-fdt-loading-method.patch
+Patch0125: 0125-Honor-a-symlink-when-generating-configuration-by-gru.patch
+Patch0126: 0126-Don-t-munge-raw-spaces-when-we-re-doing-our-cmdline-.patch
+Patch0127: 0127-Don-t-require-a-password-to-boot-entries-generated-b.patch
+Patch0128: 0128-Don-t-emit-Booting-.-message.patch
+Patch0129: 0129-Make-CTRL-and-ALT-keys-work-as-expected-on-EFI-syste.patch
+Patch0130: 0130-May-as-well-try-it.patch
+Patch0131: 0131-use-fw_path-prefix-when-fallback-searching-for-grub-.patch
+Patch0132: 0132-Try-mac-guid-etc-before-grub.cfg-on-tftp-config-file.patch
+Patch0133: 0133-trim-arp-packets-with-abnormal-size.patch
+Patch0134: 0134-Fix-convert-function-to-support-NVMe-devices.patch
+Patch0135: 0135-Fix-bad-test-on-GRUB_DISABLE_SUBMENU.patch
+Patch0136: 0136-Switch-to-use-APM-Mustang-device-tree-for-hardware-t.patch
+Patch0137: 0137-Use-the-default-device-tree-from-the-grub-default-fi.patch
+Patch0138: 0138-reopen-SNP-protocol-for-exclusive-use-by-grub.patch
+Patch0139: 0139-Reduce-timer-event-frequency-by-10.patch
+Patch0140: 0140-always-return-error-to-UEFI.patch
+Patch0141: 0141-Add-powerpc-little-endian-ppc64le-flags.patch
+Patch0142: 0142-Files-reorganization-and-include-some-libgcc-fuction.patch
+Patch0143: 0143-Suport-for-bi-endianess-in-elf-file.patch
+Patch0144: 0144-Fix-exit-back-to-EFI-firmware.patch
+Patch0145: 0145-Add-grub_util_readlink.patch
+Patch0146: 0146-Make-editenv-chase-symlinks-including-those-across-d.patch
+Patch0147: 0147-Generate-OS-and-CLASS-in-10_linux-from-etc-os-releas.patch
+Patch0148: 0148-Minimize-the-sort-ordering-for-.debug-and-rescue-ker.patch
+Patch0149: 0149-Add-GRUB_DISABLE_UUID.patch
+Patch0150: 0150-Allow-fallback-to-include-entries-by-title-not-just-.patch
+Patch0151: 0151-Initialized-initrd_ctx-so-we-don-t-free-a-random-poi.patch
+Patch0152: 0152-Load-arm-with-SB-enabled.patch
+Patch0153: 0153-Fix-up-some-man-pages-rpmdiff-noticed.patch
+Patch0154: 0154-Try-prefix-if-fw_path-doesn-t-work.patch
+Patch0155: 0155-Update-info-with-grub.cfg-netboot-selection-order-11.patch
+Patch0156: 0156-Use-Distribution-Package-Sort-for-grub2-mkconfig-112.patch
+Patch0157: 0157-efidisk-move-device-path-helpers-in-core-for-efinet.patch
+Patch0158: 0158-efinet-Check-for-immediate-completition.patch
+Patch0159: 0159-efinet-memory-leak-on-module-removal.patch
+Patch0160: 0160-efinet-cannot-free-const-char-pointer.patch
+Patch0161: 0161-Revert-efinet-memory-leak-on-module-removal.patch
+Patch0162: 0162-efinet-skip-virtual-IPv4-and-IPv6-devices-when-enume.patch
+Patch0163: 0163-efinet-open-Simple-Network-Protocol-exclusively.patch
+Patch0164: 0164-efinet-enable-hardware-filters-when-opening-interfac.patch
+Patch0165: 0165-efinet-handle-get_status-on-buggy-firmware-properly.patch
+Patch0166: 0166-Handle-rssd-storage-devices.patch
+Patch0167: 0167-xfs-Fix-termination-loop-for-directory-iteration.patch
+Patch0168: 0168-xfs-Convert-inode-numbers-to-cpu-endianity-immediate.patch
+Patch0169: 0169-xfs-Add-helpers-for-inode-size.patch
+Patch0170: 0170-xfs-V5-filesystem-format-support.patch
+Patch0171: 0171-xfs-silence-Coverity-overflow-warning.patch
+Patch0172: 0172-send-router-solicitation-for-ipv6-address-autoconf-v.patch
+Patch0173: 0173-icmp6-fix-no-respond-to-neighbor-solicit-message.patch
+Patch0174: 0174-calibrate_tsc-use-the-Stall-EFI-boot-service-on-GRUB.patch
+Patch0175: 0175-fix-memory-corruption-in-pubkey-filter-over-network.patch
+Patch0176: 0176-Make-grub2-mkconfig-construct-titles-that-look-like-.patch
+Patch0177: 0177-don-t-strip-fw_path-twice-for-EFI-network-boot.patch
+Patch0178: 0178-Add-friendly-grub2-password-config-tool-985962.patch
+Patch0179: 0179-Try-to-make-sure-configure.ac-and-grub-rpm-sort-play.patch
+Patch0180: 0180-ppc64le-sync-mkconfig-to-disk-1212114.patch
+Patch0181: 0181-tcp-ack-when-we-get-an-OOO-lost-packet.patch
+Patch0182: 0182-tcp-add-window-scaling-support.patch
+Patch0183: 0183-efinet-retransmit-if-our-device-is-busy.patch
+Patch0184: 0184-efinet-add-filter-for-the-first-exclusive-reopen-of-.patch
+Patch0185: 0185-Fix-security-issue-when-reading-username-and-passwor.patch
+Patch0186: 0186-01_users-Handle-GRUB_PASSWORD-better.patch
+Patch0187: 0187-Failed-config-now-returns-exit-code-1252311.patch
+Patch0188: 0188-Warn-if-grub-password-will-not-be-read-1290803.patch
+Patch0189: 0189-Clean-up-grub-setpassword-documentation-1290799.patch
+Patch0190: 0190-Fix-locale-issue-in-grub-setpassword-1294243.patch
+Patch0191: 0191-efi-really-mark-memory-of-unknown-type-as-reserved.patch
+Patch0192: 0192-Translate-UEFI-persistent-memory-type.patch
+Patch0193: 0193-lsefimmap-support-persistent-memory-and-other-UEFI-2.patch
+Patch0194: 0194-efiemu-Handle-persistent-RAM-and-unknown-possible-fu.patch
+Patch0195: 0195-efiemu-Fix-compilation-failure.patch
+Patch0196: 0196-devmapper-getroot-use-makedev-instead-of-direct-shif.patch
+Patch0197: 0197-loader-linux-do-not-pad-initrd-with-zeroes-at-the-en.patch
+Patch0198: 0198-Revert-reopen-SNP-protocol-for-exclusive-use-by-grub.patch
+Patch0199: 0199-Add-a-url-parser.patch
+Patch0200: 0200-efinet-and-bootp-add-support-for-dhcpv6.patch
+Patch0201: 0201-ppc64le-has-no-separate-boot-mount-1261926.patch
+Patch0202: 0202-Add-grub-get-kernel-settings-and-use-it-in-10_linux.patch
+Patch0203: 0203-Fix-coverity-issues-in-shell-scripts-1226325.patch
+Patch0204: 0204-Fix-compiler-warning-1154226.patch
+Patch0205: 0205-Fix-CLANG-error-from-Coverity-1154226.patch
+Patch0206: 0206-grub_ipv6_get_masksize-fix-loop-iteration-error.patch
+Patch0207: 0207-efinet-fix-some-coverity-gripes.patch
+Patch0208: 0208-Fix-another-coverity-gripe-about-a-missing-typecast.patch
+Patch0209: 0209-Fix-duplicate-shell-entries-1226325.patch
+Patch0210: 0210-Coverity-rightly-noticed-that-grub_ipv6_get_masksize.patch
+Patch0211: 0211-Export-grub-get-kernel-settings-variables.patch
+Patch0212: 0212-Normalize-slashes-in-tftp-paths.patch
+Patch0213: 0213-bz1374141-fix-incorrect-mask-for-ppc64.patch
+Patch0214: 0214-Make-efi-machines-load-an-env-block-from-a-variable.patch
+Patch0215: 0215-Fix-race-in-EFI-validation.patch
+Patch0216: 0216-efi-chainloader-fix-use-after-free.patch
+Patch0217: 0217-chainloader-fix-resoource-leak.patch
+Patch0218: 0218-efi-properly-terminate-filepath-with-NULL-in-chainlo.patch
+Patch0219: 0219-Use-device-part-of-chainloader-target-if-present.patch
+Patch0220: 0220-Add-secureboot-support-on-efi-chainloader.patch
+Patch0221: 0221-Make-any-of-the-loaders-that-link-in-efi-mode-honor-.patch
+Patch0222: 0222-Rework-linux-command.patch
+Patch0223: 0223-Rework-linux16-command.patch
+Patch0224: 0224-Re-work-some-intricacies-of-PE-loading.patch
+Patch0225: 0225-Rework-even-more-of-efi-chainload-so-non-sb-cases-wo.patch
+Patch0226: 0226-linuxefi-fix-double-free-on-verification-failure.patch
+Patch0227: 0227-efi-chainloader-fix-wrong-sanity-check-in-relocate_c.patch
+Patch0228: 0228-efi-chainloader-truncate-overlong-relocation-section.patch
+Patch0229: 0229-Add-some-grub_dprintf-in-the-linuxefi-path.patch
+Patch0230: 0230-linuxefi-minor-cleanups.patch
+Patch0231: 0231-Handle-multi-arch-64-on-32-boot-in-linuxefi-loader.patch
+Patch0232: 0232-efidisk-Respect-block_io_protocol-buffer-alignment.patch
+Patch0233: 0233-loader-linux-Make-trailer-initrd-entry-aligned-again.patch
+Patch0234: 0234-Make-exit-take-a-return-code.patch
+Patch0235: 0235-efi-fix-memory-leak-in-variable-handling.patch
+Patch0236: 0236-efi-fix-GetVariable-return-status-check-in-81ca24a.patch
+Patch0237: 0237-linux.c-Ensure-that-initrd-is-page-aligned.patch
+Patch0238: 0238-arm64-make-sure-fdt-has-address-cells-and-size-cells.patch
+Patch0239: 0239-Don-t-guess-boot-efi-as-on-ppc-machines.patch
+Patch0240: 0240-Clean-up-some-errors-in-the-linuxefi-loader.patch
+Patch0241: 0241-Revert-trim-arp-packets-with-abnormal-size.patch
+Patch0242: 0242-cleanup-grub_cpu_to_XXX_compile_time-for-constants.patch
+Patch0243: 0243-arp-icmp-Fix-handling-in-case-of-oversized-or-invali.patch
+Patch0244: 0244-net-trivial-grub_cpu_to_XX_compile_time-cleanup.patch
+Patch0245: 0245-bootp-ignore-gateway_ip-relay-field.patch
+Patch0246: 0246-bootp-check-that-interface-is-not-NULL-in-configure_.patch
+Patch0247: 0247-Use-xid-to-match-DHCP-replies.patch
+Patch0248: 0248-Add-support-for-non-Ethernet-network-cards.patch
+Patch0249: 0249-misc-fix-invalid-character-recongition-in-strto-l.patch
+Patch0250: 0250-net-read-bracketed-ipv6-addrs-and-port-numbers.patch
+Patch0251: 0251-net-read-bracketed-ipv6-addrs-and-port-numbers-pjone.patch
+Patch0252: 0252-tftp-Fix-a-minor-const-error.patch
+Patch0253: 0253-bootp-New-net_bootp6-command.patch
+Patch0254: 0254-Put-back-our-code-to-add-a-local-route.patch
+Patch0255: 0255-efinet-UEFI-IPv6-PXE-support.patch
+Patch0256: 0256-grub.texi-Add-net_bootp6-doument.patch
+Patch0257: 0257-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch
+Patch0258: 0258-efinet-Setting-network-from-UEFI-device-path.patch
+Patch0259: 0259-efinet-Setting-DNS-server-from-UEFI-protocol.patch
+Patch0260: 0260-set-rootpath.patch
+Patch0261: 0261-Fix-one-more-coverity-complaint.patch
+Patch0262: 0262-Fix-up-linux-params-usage.patch
+Patch0263: 0263-Fix-grub_net_hwaddr_to_str.patch
+Patch0264: 0264-Fixup-for-newer-compiler.patch
+Patch0265: 0265-Support-UEFI-networking-protocols.patch
+Patch0266: 0266-efinet-Setting-network-from-UEFI-device-path.patch
+Patch0267: 0267-AUDIT-0-http-boot-tracker-bug.patch
+Patch0268: 0268-xfs-accept-filesystem-with-sparse-inodes.patch
+Patch0269: 0269-grub-core-video-efi_gop.c-Add-support-for-BLT_ONLY-a.patch
+Patch0270: 0270-efi-uga-use-64-bit-for-fb_base.patch
+Patch0271: 0271-Fix-grub-setpassword-o-s-output-path.patch
+Patch0272: 0272-Verify-modules-on-build-time-rather-than-failing-in-.patch
+Patch0273: 0273-module-verifier-Check-range-limited-relative-relocat.patch
+Patch0274: 0274-Strip-.ARM.exidx.patch
+Patch0275: 0275-Disable-build-time-module-check-on-emu.patch
+Patch0276: 0276-module-verifier-allow-limited-range-relocations-on-s.patch
+Patch0277: 0277-remove-temporary-.bin-files-kernel-and-modules.patch
+Patch0278: 0278-Add-missing-BUILD_EXEEXT.patch
+Patch0279: 0279-grub-module-verifier-fix-unintended-sign-extension.patch
+Patch0280: 0280-mkimage-fix-unintended-sign-extension.patch
+Patch0281: 0281-arm64-Add-support-for-relocations-needed-for-linaro-.patch
+Patch0282: 0282-support-modules-without-symbol-table.patch
+Patch0283: 0283-cacheinfo-Add-missing-license-information.patch
+Patch0284: 0284-arm64-setjmp-Add-missing-license-macro.patch
+Patch0285: 0285-editenv-handle-relative-symlinks.patch
+Patch0286: 0286-efinet-also-use-the-firmware-acceleration-for-http.patch
+Patch0287: 0287-Make-root_url-reflect-the-protocol-hostname-of-our-b.patch
+Patch0288: 0288-efi-uga-Fix-PCIe-LER-when-GRUB2-accesses-non-enabled.patch
+Patch0289: 0289-efidisk-prevent-errors-from-diskfilter-scan-of-remov.patch
diff --git a/SOURCES/secureboot.cer b/SOURCES/secureboot.cer
new file mode 100644
index 0000000..4ff8b79
Binary files /dev/null and b/SOURCES/secureboot.cer differ
diff --git a/SOURCES/securebootca.cer b/SOURCES/securebootca.cer
new file mode 100644
index 0000000..b235400
Binary files /dev/null and b/SOURCES/securebootca.cer differ
diff --git a/SPECS/grub2.spec b/SPECS/grub2.spec
new file mode 100644
index 0000000..44ba5ea
--- /dev/null
+++ b/SPECS/grub2.spec
@@ -0,0 +1,1295 @@
+%undefine _hardened_build
+
+%global tarversion 2.02~beta2
+%undefine _missing_build_ids_terminate_build
+
+Name:           grub2
+Epoch:          1
+Version:        2.02
+Release:        0.81%{?dist}%{?buildid}
+Summary:        Bootloader with support for Linux, Multiboot and more
+Group:          System Environment/Base
+License:        GPLv3+
+URL:            http://www.gnu.org/software/grub/
+Source0:        ftp://alpha.gnu.org/gnu/grub/grub-%{tarversion}.tar.xz
+#Source0:	ftp://ftp.gnu.org/gnu/grub/grub-%%{tarversion}.tar.xz
+Source1:	grub.macros
+Source2:	grub.patches
+Source3:	securebootca.cer
+Source4:	secureboot.cer
+Source5:	http://unifoundry.com/unifont-5.1.20080820.pcf.gz
+Source6:	gitignore
+
+%include %{SOURCE1}
+
+# generate with do-rebase
+%include %{SOURCE2}
+
+BuildRequires:  flex bison binutils python
+BuildRequires:  ncurses-devel xz-devel bzip2-devel
+BuildRequires:  freetype-devel libusb-devel
+BuildRequires:	rpm-devel rpm-libs
+%ifarch %{sparc} aarch64 ppc64le
+# sparc builds need 64 bit glibc-devel - also for 32 bit userland
+BuildRequires:  /usr/lib64/crt1.o glibc-static glibc-devel
+%else
+%ifarch x86_64
+BuildRequires:  /usr/lib64/crt1.o glibc-static(x86-64) glibc-devel(x86-64)
+%else
+# ppc64 builds need the ppc crt1.o
+BuildRequires:  /usr/lib/crt1.o glibc-static glibc-devel
+%endif
+%endif
+BuildRequires:  autoconf automake autogen device-mapper-devel
+BuildRequires:	freetype-devel gettext-devel git
+BuildRequires:	texinfo
+BuildRequires:	dejavu-sans-fonts
+BuildRequires:	help2man
+%ifarch %{efi_arch}
+BuildRequires:	pesign >= 0.99-8
+%endif
+%if %{?_with_ccache: 1}%{?!_with_ccache: 0}
+BuildRequires:  ccache
+%endif
+
+ExcludeArch:	s390 s390x %{arm} %{?ix86}
+Obsoletes:	%{name} <= %{flagday}
+
+%if 0%{with_legacy_arch}
+Requires:	%{name}-%{legacy_package_arch} = %{evr}
+%else
+Requires:	%{name}-%{package_arch} = %{evr}
+%endif
+
+%global desc \
+The GRand Unified Bootloader (GRUB) is a highly configurable and \
+customizable bootloader with modular architecture.  It supports a rich \
+variety of kernel formats, file systems, computer architectures and \
+hardware devices.\
+%{nil}
+
+%description
+%{desc}
+
+%ifarch x86_64
+%package common
+Summary:	grub2 common layout
+Group:		System Environment/Base
+BuildArch:	noarch
+
+%description common
+This package provides some directories which are required by various grub2
+subpackages.
+%endif
+
+%package tools
+Summary:	Support tools for GRUB.
+Group:		System Environment/Base
+Obsoletes:	%{name}-tools <= %{flagday}
+%ifarch x86_64
+Obsoletes:	%{name}-tools-efi <= %{flagday}
+Provides:	%{name}-tools-efi = %{evr}
+%endif
+Requires:	%{name}-tools-minimal = %{evr}
+Requires:	%{name}-common = %{evr}
+Requires:	gettext os-prober which file
+Requires(pre):  dracut
+Requires(post): dracut
+
+%description tools
+%{desc}
+This subpackage provides tools for support of all platforms.
+
+%package tools-minimal
+Summary:	Support tools for GRUB.
+Group:		System Environment/Base
+Requires:	gettext
+Requires:	%{name}-common = %{evr}
+Obsoletes:	%{name}-tools <= %{flagday}
+
+%description tools-minimal
+%{desc}
+This subpackage provides tools for support of all platforms.
+
+%package tools-extra
+Summary:	Support tools for GRUB.
+Group:		System Environment/Base
+Requires:	gettext os-prober which file
+Requires:	%{name}-tools-minimal = %{epoch}:%{version}-%{release}
+Requires:	%{name}-common = %{epoch}:%{version}-%{release}
+Requires:	%{name}-tools = %{evr}
+Obsoletes:	%{name}-tools <= %{flagday}
+
+%description tools-extra
+%{desc}
+This subpackage provides tools for support of all platforms.
+
+%if 0%{with_efi_arch}
+%define_efi_variant %{package_arch} -p
+%endif
+%if 0%{with_alt_efi_arch}
+%define_efi_variant %{alt_package_arch}
+%endif
+%if 0%{with_legacy_arch}
+%define_legacy_variant %{legacy_package_arch}
+%endif
+
+%prep
+%setup -T -c -n grub-%{tarversion}
+%do_common_setup
+%if 0%{with_efi_arch}
+%do_setup %{grubefiarch}
+%endif
+%if 0%{with_alt_efi_arch}
+%do_setup %{grubaltefiarch}
+%endif
+%if 0%{with_legacy_arch}%{with_legacy_utils}
+%do_setup %{grublegacyarch}
+%endif
+
+%build
+%if 0%{with_efi_arch}
+%do_primary_efi_build %{grubefiarch} %{grubefiname} %{grubeficdname} %{_target_platform} "'%{efi_cflags}'" %{SOURCE3} %{SOURCE4} redhatsecureboot301
+%endif
+%if 0%{with_alt_efi_arch}
+%do_alt_efi_build %{grubaltefiarch} %{grubaltefiname} %{grubalteficdname} %{_alt_target_platform} "'%{alt_efi_cflags}'" %{SOURCE3} %{SOURCE4} redhatsecureboot301
+%endif
+%if 0%{with_legacy_arch}%{with_legacy_utils}
+%do_legacy_build %{grublegacyarch}
+%endif
+%do_common_build
+
+%install
+set -e
+rm -fr $RPM_BUILD_ROOT
+
+%do_common_install
+%if 0%{with_efi_arch}
+%do_efi_install %{grubefiarch} %{grubefiname} %{grubeficdname}
+%endif
+%if 0%{with_alt_efi_arch}
+%do_alt_efi_install %{grubaltefiarch} %{grubaltefiname} %{grubalteficdname}
+%endif
+%if 0%{with_legacy_arch}%{with_legacy_utils}
+%do_legacy_install %{grublegacyarch} %{alt_grub_target_name}
+%endif
+${RPM_BUILD_ROOT}/%{_bindir}/%{name}-editenv ${RPM_BUILD_ROOT}/boot/efi/EFI/%{efidir}/grubenv create
+rm -f $RPM_BUILD_ROOT%{_infodir}/dir
+
+%find_lang grub
+
+# Make selinux happy with exec stack binaries.
+mkdir ${RPM_BUILD_ROOT}%{_sysconfdir}/prelink.conf.d/
+cat << EOF > ${RPM_BUILD_ROOT}%{_sysconfdir}/prelink.conf.d/grub2.conf
+# these have execstack, and break under selinux
+-b /usr/bin/grub2-script-check
+-b /usr/bin/grub2-mkrelpath
+-b /usr/bin/grub2-fstest
+-b /usr/sbin/grub2-bios-setup
+-b /usr/sbin/grub2-probe
+-b /usr/sbin/grub2-sparc64-setup
+EOF
+
+# Don't run debuginfo on all the grub modules and whatnot; it just
+# rejects them, complains, and slows down extraction.
+%global finddebugroot "%{_builddir}/%{?buildsubdir}/debug"
+
+%global dip RPM_BUILD_ROOT=%{finddebugroot} %{__debug_install_post}
+%define __debug_install_post (						\
+	mkdir -p %{finddebugroot}/usr					\
+	mv ${RPM_BUILD_ROOT}/usr/bin %{finddebugroot}/usr/bin		\
+	mv ${RPM_BUILD_ROOT}/usr/sbin %{finddebugroot}/usr/sbin		\
+	%{dip}								\
+	install -m 0755 -d %{buildroot}/usr/lib/ %{buildroot}/usr/src/	\
+	cp -al %{finddebugroot}/usr/lib/debug/				\\\
+		%{buildroot}/usr/lib/debug/				\
+	cp -al %{finddebugroot}/usr/src/debug/				\\\
+		%{buildroot}/usr/src/debug/ )				\
+	mv %{finddebugroot}/usr/bin %{buildroot}/usr/bin		\
+	mv %{finddebugroot}/usr/sbin %{buildroot}/usr/sbin		\
+	%{nil}
+
+%clean    
+rm -rf $RPM_BUILD_ROOT
+
+%pre tools
+if [ -f /boot/grub2/user.cfg ]; then
+    if grep -q '^GRUB_PASSWORD=' /boot/grub2/user.cfg ; then
+	sed -i 's/^GRUB_PASSWORD=/GRUB2_PASSWORD=/' /boot/grub2/user.cfg
+    fi
+elif [ -f /boot/efi/EFI/%{efidir}/user.cfg ]; then
+    if grep -q '^GRUB_PASSWORD=' /boot/efi/EFI/%{efidir}/user.cfg ; then
+	sed -i 's/^GRUB_PASSWORD=/GRUB2_PASSWORD=/' \
+	    /boot/efi/EFI/%{efidir}/user.cfg
+    fi
+elif [ -f /etc/grub.d/01_users ] && \
+	grep -q '^password_pbkdf2 root' /etc/grub.d/01_users ; then
+    if [ -f /boot/efi/EFI/%{efidir}/grub.cfg ]; then
+	# on EFI we don't get permissions on the file, but
+	# the directory is protected.
+	grep '^password_pbkdf2 root' /etc/grub.d/01_users | \
+		sed 's/^password_pbkdf2 root \(.*\)$/GRUB2_PASSWORD=\1/' \
+	    > /boot/efi/EFI/%{efidir}/user.cfg
+    fi
+    if [ -f /boot/grub2/grub.cfg ]; then
+	install -m 0600 /dev/null /boot/grub2/user.cfg
+	chmod 0600 /boot/grub2/user.cfg
+	grep '^password_pbkdf2 root' /etc/grub.d/01_users | \
+		sed 's/^password_pbkdf2 root \(.*\)$/GRUB2_PASSWORD=\1/' \
+	    > /boot/grub2/user.cfg
+    fi
+fi
+if [ -f /boot/grub2/grubenv ] && ! [ -f /boot/efi/EFI/%{efidir}/grubenv ] ; then
+	if [ -e /boot/efi/EFI/%{efidir}/grubenv ] ; then
+		rm /boot/efi/EFI/%{efidir}/grubenv
+		mv /boot/grub2/grubenv /boot/efi/EFI/%{efidir}/grubenv
+		ln -sf ../efi/EFI/%{efidir}/grubenv /boot/grub2/grubenv
+	fi
+fi
+
+%post tools
+if [ "$1" = 1 ]; then
+	/sbin/install-info --info-dir=%{_infodir} %{_infodir}/%{name}.info.gz || :
+	/sbin/install-info --info-dir=%{_infodir} %{_infodir}/%{name}-dev.info.gz || :
+fi
+
+%triggerun -- grub2 < 1:1.99-4
+# grub2 < 1.99-4 removed a number of essential files in postun. To fix upgrades
+# from the affected grub2 packages, we first back up the files in triggerun and
+# later restore them in triggerpostun.
+# https://bugzilla.redhat.com/show_bug.cgi?id=735259
+
+# Back up the files before uninstalling old grub2
+mkdir -p /boot/grub2.tmp &&
+mv -f /boot/grub2/*.mod \
+      /boot/grub2/*.img \
+      /boot/grub2/*.lst \
+      /boot/grub2/device.map \
+      /boot/grub2.tmp/ || :
+
+%triggerpostun -- grub2 < 1:1.99-4
+# ... and restore the files.
+test ! -f /boot/grub2/device.map &&
+test -d /boot/grub2.tmp &&
+mv -f /boot/grub2.tmp/*.mod \
+      /boot/grub2.tmp/*.img \
+      /boot/grub2.tmp/*.lst \
+      /boot/grub2.tmp/device.map \
+      /boot/grub2/ &&
+rm -r /boot/grub2.tmp/ || :
+
+%preun tools
+if [ "$1" = 0 ]; then
+	/sbin/install-info --delete --info-dir=%{_infodir} %{_infodir}/%{name}.info.gz || :
+	/sbin/install-info --delete --info-dir=%{_infodir} %{_infodir}/%{name}-dev.info.gz || :
+fi
+
+%files
+%ifnarch x86_64 %{ix86}
+%exclude %{_bindir}/%{name}-render-label
+%exclude %{_sbindir}/%{name}-bios-setup
+%exclude %{_sbindir}/%{name}-macbless
+%endif
+%ifnarch x86_64
+%exclude /boot/grub2/grubenv
+%exclude /boot/efi/EFI/*/grubenv
+%exclude %{_datadir}/locale
+%endif
+
+%ifarch x86_64
+%files common -f grub.lang
+%dir %{_libdir}/grub/
+%dir %{_datarootdir}/grub/
+%dir %{_datarootdir}/grub/themes/
+%exclude %{_datarootdir}/grub/themes/*
+%attr(0700,root,root) %dir %{_sysconfdir}/grub.d
+%dir %{_datarootdir}/grub
+%exclude %{_datarootdir}/grub/*
+%dir /boot/%{name}
+%dir /boot/%{name}/themes/
+%dir /boot/%{name}/themes/system
+%exclude /boot/%{name}/themes/system/*
+%attr(0700,root,root) %dir /boot/grub2
+%exclude /boot/grub2/*
+%dir %verify(not mtime) %attr(0700,root,root)/boot/efi/EFI/%{efidir}
+%exclude /boot/efi/EFI/%{efidir}/*
+%license %{common_srcdir}/COPYING
+%ghost %config(noreplace) /boot/grub2/grubenv
+%doc %{common_srcdir}/INSTALL
+%doc %{common_srcdir}/NEWS
+%doc %{common_srcdir}/README
+%doc %{common_srcdir}/THANKS
+%doc %{common_srcdir}/TODO
+%doc %{common_srcdir}/docs/grub.html
+%doc %{common_srcdir}/docs/grub-dev.html
+%doc %{common_srcdir}/docs/font_char_metrics.png
+%endif
+
+%files tools-minimal
+%defattr(-,root,root,-)
+%{_sysconfdir}/prelink.conf.d/grub2.conf
+%{_sbindir}/%{name}-get-kernel-settings
+%{_sbindir}/%{name}-set-default
+%{_sbindir}/%{name}-setpassword
+%{_bindir}/%{name}-editenv
+%{_bindir}/%{name}-mkpasswd-pbkdf2
+
+%{_datadir}/man/man3/%{name}-get-kernel-settings*
+%{_datadir}/man/man8/%{name}-set-default*
+%{_datadir}/man/man8/%{name}-setpassword*
+%{_datadir}/man/man1/%{name}-editenv*
+%{_datadir}/man/man1/%{name}-mkpasswd-*
+
+%files tools
+%defattr(-,root,root,-)
+%attr(0644,root,root) %ghost %config(noreplace) %{_sysconfdir}/default/grub
+%config %{_sysconfdir}/grub.d/??_*
+%{_sysconfdir}/grub.d/README
+%{_infodir}/%{name}*
+%{_datarootdir}/grub/*
+%exclude %{_datarootdir}/grub/themes
+%exclude %{_datarootdir}/grub/*.h
+%{_datarootdir}/bash-completion/completions/grub
+%{_sbindir}/%{name}-install
+%{_sbindir}/%{name}-mkconfig
+%{_sbindir}/%{name}-probe
+%{_sbindir}/%{name}-rpm-sort
+%{_sbindir}/%{name}-reboot
+%{_bindir}/%{name}-file
+%{_bindir}/%{name}-menulst2cfg
+%{_bindir}/%{name}-mkrelpath
+%{_bindir}/%{name}-script-check
+%{_datadir}/man/man?/*
+
+# exclude man pages from tools-extra
+%exclude %{_datadir}/man/man8/%{name}-sparc64-setup*
+%exclude %{_datadir}/man/man8/%{name}-install*
+%exclude %{_datadir}/man/man1/%{name}-fstest*
+%exclude %{_datadir}/man/man1/%{name}-glue-efi*
+%exclude %{_datadir}/man/man1/%{name}-kbdcomp*
+%exclude %{_datadir}/man/man1/%{name}-mkfont*
+%exclude %{_datadir}/man/man1/%{name}-mkimage*
+%exclude %{_datadir}/man/man1/%{name}-mklayout*
+%exclude %{_datadir}/man/man1/%{name}-mknetdir*
+%exclude %{_datadir}/man/man1/%{name}-mkrescue*
+%exclude %{_datadir}/man/man1/%{name}-mkstandalone*
+%exclude %{_datadir}/man/man1/%{name}-syslinux2cfg*
+
+# exclude man pages from tools-minimal
+%exclude %{_datadir}/man/man3/%{name}-get-kernel-settings*
+%exclude %{_datadir}/man/man8/%{name}-set-default*
+%exclude %{_datadir}/man/man8/%{name}-setpassword*
+%exclude %{_datadir}/man/man1/%{name}-editenv*
+%exclude %{_datadir}/man/man1/%{name}-mkpasswd-*
+
+%ifarch x86_64 %{?ix86}
+%{_sbindir}/%{name}-macbless
+%{_bindir}/%{name}-render-label
+%{_datadir}/man/man8/%{name}-macbless*
+%{_datadir}/man/man1/%{name}-render-label*
+%else
+%exclude %{_sbindir}/%{name}-macbless
+%exclude %{_bindir}/%{name}-render-label
+%exclude %{_datadir}/man/man8/%{name}-macbless*
+%exclude %{_datadir}/man/man1/%{name}-render-label*
+%endif
+
+%if %{with_legacy_utils}
+%{_sbindir}/%{name}-install
+%ifarch %{ix86} x86_64
+%{_sbindir}/%{name}-bios-setup
+%else
+%exclude %{_sbindir}/%{name}-bios-setup
+%exclude %{_datadir}/man/man8/%{name}-bios-setup*
+%endif
+%ifarch %{sparc}
+%{_sbindir}/%{name}-sparc64-setup
+%else
+%exclude %{_sbindir}/%{name}-sparc64-setup
+%exclude %{_datadir}/man/man8/%{name}-sparc64-setup*
+%endif
+%ifarch %{sparc} ppc ppc64 ppc64le
+%{_sbindir}/%{name}-ofpathname
+%else
+%exclude %{_sbindir}/%{name}-ofpathname
+%exclude %{_datadir}/man/man8/%{name}-ofpathname*
+%endif
+%endif
+
+%files tools-extra
+%{_sbindir}/%{name}-sparc64-setup
+%{_sbindir}/%{name}-ofpathname
+%{_bindir}/%{name}-fstest
+%{_bindir}/%{name}-glue-efi
+%{_bindir}/%{name}-kbdcomp
+%{_bindir}/%{name}-mkfont
+%{_bindir}/%{name}-mkimage
+%{_bindir}/%{name}-mklayout
+%{_bindir}/%{name}-mknetdir
+%ifnarch %{sparc}
+%{_bindir}/%{name}-mkrescue
+%endif
+%{_bindir}/%{name}-mkstandalone
+%{_bindir}/%{name}-syslinux2cfg
+%{_sysconfdir}/sysconfig/grub
+%{_datadir}/man/man8/%{name}-sparc64-setup*
+%{_datadir}/man/man8/%{name}-install*
+%{_datadir}/man/man1/%{name}-fstest*
+%{_datadir}/man/man1/%{name}-glue-efi*
+%{_datadir}/man/man1/%{name}-kbdcomp*
+%{_datadir}/man/man1/%{name}-mkfont*
+%{_datadir}/man/man1/%{name}-mkimage*
+%{_datadir}/man/man1/%{name}-mklayout*
+%{_datadir}/man/man1/%{name}-mknetdir*
+%{_datadir}/man/man1/%{name}-mkrescue*
+%{_datadir}/man/man1/%{name}-mkstandalone*
+%{_datadir}/man/man8/%{name}-ofpathname*
+%{_datadir}/man/man1/%{name}-syslinux2cfg*
+%exclude %{_datarootdir}/grub/themes/starfield
+
+%if 0%{with_efi_arch}
+%define_efi_variant_files %{package_arch} %{grubefiname} %{grubeficdname} %{grubefiarch} %{target_cpu_name} %{grub_target_name}
+%endif
+%if 0%{with_alt_efi_arch}
+%define_efi_variant_files %{alt_package_arch} %{grubaltefiname} %{grubalteficdname} %{grubaltefiarch} %{alt_target_cpu_name} %{alt_grub_target_name}
+%endif
+%if 0%{with_legacy_arch}
+%define_legacy_variant_files %{legacy_package_arch} %{grublegacyarch}
+%else
+%if 0%{with_legacy_utils}
+%exclude %{_sysconfdir}/%{name}.cfg
+%exclude %{_libdir}/grub/%{grublegacyarch}/*
+%exclude %{_libdir}/grub/%{grublegacyarch}/
+%endif
+%endif
+
+%changelog
+* Fri Sep 13 2019 Javier Martinez Canillas <javierm@redhat.com> - 2.02-0.81
+- Only make grub2-tools Obsoletes and Provides grub2-tools-efi for x86_64
+  Resolves: rhbz#1748019
+
+* Wed Mar 27 2019 Javier Martinez Canillas <javierm@redhat.com> - 2.02-0.80
+- Rebuild with correct build target for signing
+  Resolves: rhbz#1693213
+
+* Tue Mar 26 2019 Javier Martinez Canillas <javierm@redhat.com> - 2.02-0.79
+- Ignore the modification time when doing RPM verification of /boot/efi files
+  Resolves: rhbz#1496952
+
+* Wed Mar 20 2019 Javier Martinez Canillas <javierm@redhat.com> - 2.02-0.78
+- Prevent errors from diskfilter scan of removable drives
+  Resolves: rhbz#1446418
+- Avoid grub2-efi package to overwrite existing /boot/grub2/grubenv file
+  Resolves: rhbz#1497918
+- Remove glibc32 and glibc-static(x86-32) BuildRequires
+  Resolves: rhbz#1614259
+
+* Thu Oct 25 2018 Javier Martinez Canillas <javierm@redhat.com> - 2.02-0.77
+- Re-enable regexp module
+  Resolves: rhbz#1630678
+
+* Mon Jul 30 2018 pjones <pjones@redhat.com> - 2.02.0.76
+- Fix PCIe probing in EFI UGA driver.
+  Resolves: rhbz#1583708
+
+* Wed Jul 18 2018 Peter Jones <pjones@redhat.com> - 2.02-0.74
+- Fix symlink issues with grubenv
+  Resolves: rhbz#1602773
+  Related: rhbz#1497918
+- Make the common subpackage only build on x86_64 to avoid timestamp
+  mismatches.
+  Related: rhbz#1602773
+  Related: rhbz#1497918
+
+* Fri Jun 29 2018 Peter Jones <pjones@redhat.com> - 2.02-0.73
+- Fix loading grub modules with no symbols defined.
+  Related: rhbz#1490981
+
+* Thu Jun 28 2018 Peter Jones <pjones@redhat.com> - 2.02-0.72
+- Revert module dir fix; it still doesn't work.
+  Resolves: rhbz#1594703
+
+* Mon Jun 25 2018 Peter Jones <pjones@redhat.com> - 2.02-0.71
+- The change from 2.02-0.65.el7_4.2 never made it onto the main branch,
+  so one more build to avoid the regression.
+  Related: rhbz#1340893
+
+* Mon Jun 25 2018 Peter Jones <pjones@redhat.com> 2.02-0.70
+- ... and once more, because I built for the wrong target.
+  Related: rhbz#1340893
+
+* Mon Jun 25 2018 Peter Jones <pjones@redhat.com> - 2.02-0.69
+- Build utilities on i686 as well, so grubby can build-dep it there.
+  Related: rhbz#1340893
+
+* Fri Jun 22 2018 Peter Jones <pjones@redhat.com> - 2.02-0.68
+- More work on /boot/efi/... permissions
+  Resolves: rhbz#1496952
+- Rework grubenv symlinks and handle them on upgrades
+  Resolves: rhbz#1497918
+- Make grub2-setpassword -o work
+  Resolves: rhbz#1512749
+
+* Thu Jun 21 2018 Peter Jones <pjones@redhat.com> - 2.02-0.67
+- Make the permissions on /boot/efi/... match the filesystem's requirements.
+  Resolves: rhbz#1496952
+
+* Thu Jun 21 2018 Peter Jones <pjones@redhat.com> - 2.02-0.66
+- Fix EFI UGA driver when the framebuffer is above 4G
+  Resolves: rhbz#1457988
+- Handle XFS filesystems with sparse inodes
+  Resolves: rhbz#1402716
+- Support HTTP booting
+  Resolves: rhbz#1490981
+
+* Mon Oct 09 2017 Peter Jones <pjones@redhat.com> - 2.02-0.65.el7_4.2
+- Fix an incorrect man page exclusion on x86_64.
+
+* Fri Oct 06 2017 Peter Jones <pjones@redhat.com> - 2.02-0.65.1
+- More precise requires and obsoletes on the -tools* subpackages to avoid
+  issues with mixing and matching repos the subpackages are split between.
+
+* Fri Sep 22 2017 Peter Jones <pjones@redhat.com> - 2.02-0.65
+- Fix spurious : at the end of the mac address netboot paths.
+  Resolves: rhbz#1483740
+
+* Wed May 31 2017 Peter Jones <pjones@redhat.com> - 2.02-0.64
+- Revert pkglibdir usage; we have to coordinate this with Lorax.
+  Related: rhbz#1455243
+
+* Tue May 30 2017 pjones <pjones@redhat.com> - 2.02-0.63
+- Fix grub2-mkimage on ppc* to *also* deal with pkglibdir changing.
+  Related: rhbz#1455243
+
+* Tue May 30 2017 Peter Jones <pjones@redhat.com> - 2.02-0.62
+- Fix grub2-mkimage on ppc* to *also* deal with pkglibdir changing.
+  Related: rhbz#1455243
+
+* Wed May 24 2017 Peter Jones <pjones@redhat.com> - 2.02-0.61
+- Fix some minor ia32 booting bugs
+  Related: rhbz#1310763
+  Related: rhbz#1411748
+  Related: rhbz#1300009
+- Add support for non-Ethernet network cards
+  Related: rhbz#1232432
+- Add support for http booting
+  Resolves: rhbz#1232432
+- Fix efi module subpackage obsoletes/provides
+  Resolves: rhbz#1447723
+- Make ppc modules subpackages use different directories on the filesystem.
+  Resolves: rhbz#1455243
+
+* Thu Apr 20 2017 Peter Jones <pjones@redhat.com> - 2.02-0.60
+- Fix ppc64 deciding /boot/efi might somehow be the CHRP partition if it
+  exists.  This is also why the bug we fixed in 0.59 showed up at all.
+  Resolves: rhbz#1443809
+  Resolves: rhbz#1442970
+- Fix a regexp problem where rpm spec parser un-escapes things that
+  don't need escaping, which causes our s/-mcpu=power8/-mcpu=power6/
+  to fail.
+  Related: rhbz#1443809
+
+* Wed Apr 19 2017 Peter Jones <pjones@redhat.com> - 2.02-0.59
+- Fix ppc64 "grub2.chrp" to be "grub.chrp" harder
+  Resolves: rhbz#1442970
+
+* Wed Apr 19 2017 Peter Jones <pjones@redhat.com> - 2.02-0.58
+- Add Aarch64 FDT #address-cells and #size-cells support
+  Resolves: rhbz#1436745
+- Fix ppc64 "grub2.chrp" to be "grub.chrp"
+  Resolves: rhbz#1442970
+
+* Wed Apr 12 2017 Peter Jones <pjones@redhat.com> - 2.02-0.57
+- Make "grub2" require the grub2-efi-... package on arches where there's no
+  legacy build.
+  Related: rhbz#1440787
+
+* Tue Apr 11 2017 Peter Jones <pjones@redhat.com> - 2.02-0.56
+- Rebuild in the right build root.
+  Related: rhbz#1437450
+
+* Tue Apr 11 2017 Peter Jones <pjones@redhat.com> - 2.02-0.55
+- Make a "grub2" top-level package to help solve Jira RCM-14929.
+  Related: rhbz#1437450
+
+* Mon Apr 10 2017 Peter Jones <pjones@redhat.com> - 2.02-0.54
+- Make grub2-pc, grub2-ppc64le, etc, also have an Obsoletes for the old grub2
+  packages.  Hoping this will solve Jira RCM-14929.
+  Related: rhbz#1437450
+
+* Thu Mar 30 2017 Peter Jones <pjones@redhat.com> - 2.02-0.53
+- Don't manually put an arch in a requires.
+  The automatically generated provides won't have it, and all of the
+  tools display the packages as if it were there, so you can't ever see
+  that they never match up. Meanwhile the auto generator *will* add
+  $name($arch)=$evr provides, which aren't quite the same.  We probably
+  don't need it anyway.  Maybe.
+  Resolves: rhbz#1437450
+
+* Thu Mar 30 2017 Peter Jones <pjones@redhat.com> - 2.02-0.52
+- Fix our debuginfo filter to not accidentally discard the stripped versions of
+  userland binaries.
+  Related: rhbz#1310763
+
+* Tue Mar 28 2017 Peter Jones <pjones@redhat.com> - 2.02-0.51
+- Also be sure to pull in grub2-tools-extras for now, to make upgrades work.
+  Related: rhbz#1310763
+
+* Tue Mar 28 2017 Peter Jones <pjones@redhat.com> - 2.02-0.50
+- Fix where the grub2-ofpathname man page lands
+  Related: rhbz#1310763
+- Fix stripping of userland binaries
+  Related: rhbz#1310763
+
+* Tue Mar 21 2017 Peter Jones <pjones@redhat.com> - 2.02-0.49
+- Include unicode.pf2 in the grub-efi-ARCH-cdboot images
+  Related: rhbz#1310763
+  Related: rhbz#1411748
+  Related: rhbz#1300009
+
+* Tue Mar 21 2017 Peter Jones <pjones@redhat.com> - 2.02-0.48
+- grub2-efi-* don't actually need to require grub2-tools-efi (i.e. the mac
+  tools), anaconda and lorax can know how to do that.
+  Related: rhbz#1310763
+  Related: rhbz#1411748
+  Related: rhbz#1300009
+
+* Mon Mar 20 2017 Peter Jones <pjones@redhat.com> - 2.02-0.47
+- Fix ia32 booting.
+  Related: rhbz#1310763
+  Related: rhbz#1411748
+  Related: rhbz#1300009
+
+* Fri Mar 17 2017 Peter Jones <pjones@redhat.com> - 2.02-0.46
+- Fix ppc* package names.
+  Related: rhbz#1310763
+  Related: rhbz#1411748
+  Related: rhbz#1300009
+
+* Wed Mar 15 2017 Peter Jones <pjones@redhat.com> - 2.02-0.45
+- Rework package to make multi-arch EFI easier.
+  Resolves: rhbz#1310763
+  Related: rhbz#1411748
+- Honor IO alignment on EFI systems
+  Resolves: rhbz#1300009
+
+* Mon Aug 29 2016 Peter Jones <pjones@redhat.com> - 2.02-0.44
+- Work around tftp servers that don't work with multiple consecutive slashes in
+  file paths.
+  Resolves: rhbz#1217243
+
+* Thu Aug 25 2016 Peter Jones <pjones@redhat.com> - 2.02-0.42
+- Make grub2-mkconfig export grub2-get-kernel-settings variables correctly.
+  Related: rhbz#1226325
+
+* Tue Aug 23 2016 Peter Jones <pjones@redhat.com> - 2.02-0.42
+- Rebuild in the right build root.  Again.
+  Related: rhbz#1273974
+
+* Wed Jul 13 2016 Peter Jones <pjones@redhat.com> - 2.02-0.41
+- Build with coverity patch I missed last time.
+  Related: rhbz#1226325
+
+* Wed Jul 13 2016 rmarshall@redhat.com - 2.02-0.40
+- Build with coverity patches.
+  Related: rhbz#1226325
+
+* Wed Jul 13 2016 Peter Jones <pjones@redhat.com>
+- Remove our patch to force a paricular uefi network interface
+  Related: rhbz#1273974
+  Related: rhbz#1277599
+  Related: rhbz#1298765
+- Update some more coverity issues
+  Related: rhbz#1226325
+  Related: rhbz#1154226
+
+* Mon Jul 11 2016 rmarshall@redhat.com - 2.02-0.39
+- Fix all issues discovered during coverity scan. 
+  Related: rhbz#1154226
+- Fix a couple compiler and CLANG issues discovered during coverity scan.
+  Related: rhbz#1154226
+- Fix the last few CLANG issues and a deadcode issue discovered by the
+  coverity scan.
+  Related: rhbz#1154226
+
+* Fri Jul 01 2016 Peter Jones <pjones@redhat.com> - 2.02-0.38
+- Pick the right build target.  Again.
+  Related: rhbz#1226325
+
+* Tue Jun 21 2016 rmarshall@redhat.com - 2.02-0.37
+- Update fix for rhbz#1212114 to reflect the move to handling this case
+  in anaconda.
+  Related: rhbz#1315468
+  Resolves: rhbz#1261926
+- Add grub2-get-kernel-settings to allow grub2-mkconfig to take grubby
+  configuration changes into account.
+  Resolves: rhbz#1226325
+
+* Fri Jun 17 2016 Peter Jones <pjones@redhat.com> - 2.02-0.36
+- Better support for EFI network booting with dhcpv6.
+  Resolves: rhbz#1154226
+- Back out a duplicate change resulting in some EFI network firmware drivers
+  not working properly.
+  Related: rhbz#1273974
+  Related: rhbz#1277599
+  Related: rhbz#1298765
+
+* Mon Jun 06 2016 Peter Jones <pjones@redhat.com> - 2.02-0.35
+- Don't use legacy methods to make device node variables.
+  Resolves: rhbz#1279599
+- Don't pad initramfs with zeros
+  Resolves: rhbz#1219864
+
+* Thu Apr 28 2016 rmarshall@redhat.com 2.02-0.34
+- Exit grub-mkconfig with a proper code when the new configuration would be
+  invalid.
+  Resolves: rhbz#1252311
+- Warn users if grub-mkconfig needs to be run to add support for GRUB
+  passwords.
+  Resolves: rhbz#1290803
+- Fix the information in the --help and man pages for grub-setpassword
+  Resolves: rhbz#1290799
+- Fix issue where shell substitution expected non-translated output when
+  setting a bootloader password.
+  Resolves: rhbz#1294243
+- Fix an issue causing memory regions with unknown types to be marked available
+  through a series of backports from upstream.
+  Resolves: rhbz#1288608
+
+* Thu Dec 10 2015 Peter Jones <pjones@redhat.com> - 2.02-0.33
+- Don't remove 01_users, it's the wrong thing to do.
+  Related: rhbz#1284370
+
+* Wed Dec 09 2015 Peter Jones <pjones@redhat.com> - 2.02-0.32
+- Rebuild for .z so the release number is different.
+  Related: rhbz#1284370
+
+* Wed Dec 09 2015 Peter Jones <pjones@redhat.com> - 2.02-0.31
+- More work on handling of GRUB2_PASSWORD
+  Resolves: rhbz#1284370
+
+* Tue Dec 08 2015 Peter Jones <pjones@redhat.com> - 2.02-0.30
+- Fix security issue when reading username and password
+  Resolves: CVE-2015-8370
+- Do a better job of handling GRUB_PASSWORD
+  Resolves: rhbz#1284370
+
+* Fri Oct 09 2015 Peter Jones <pjones@redhat.com> - 2.02-0.29
+- Fix DHCP6 timeouts due to failed network stack once more.
+  Resolves: rhbz#1267139
+
+* Thu Sep 17 2015 Peter Jones <pjones@redhat.com> - 2.02-0.28
+- Once again, rebuild for the right build target.
+  Resolves: CVE-2015-5281
+
+* Thu Sep 17 2015 Peter Jones <pjones@redhat.com> - 2.02-0.27
+- Remove multiboot and multiboot2 modules from the .efi builds; they
+  should never have been there.
+  Resolves: CVE-2015-5281
+
+* Mon Sep 14 2015 Peter Jones <pjones@redhat.com> - 2.02-0.26
+- Be more aggressive about trying to make sure we use the configured SNP
+  device in UEFI.
+  Resolves: rhbz#1257475
+
+* Wed Aug 05 2015 Robert Marshall <rmarshall@redhat.com> - 2.02-0.25
+- Force file sync to disk on ppc64le machines.
+  Resolves: rhbz#1212114
+
+* Mon Aug 03 2015 Peter Jones <pjones@redhat.com> - 2.02-0.24
+- Undo 0.23 and fix it a different way.
+  Resolves: rhbz#1124074
+
+* Thu Jul 30 2015 Peter Jones <pjones@redhat.com> - 2.02-0.23
+- Reverse kernel sort order so they're displayed correctly.
+  Resolves: rhbz#1124074
+
+* Wed Jul 08 2015 Peter Jones <pjones@redhat.com> - 2.02-0.22
+- Make upgrades work reasonably well with grub2-setpassword .
+  Related: rhbz#985962
+
+* Tue Jul 07 2015 Peter Jones <pjones@redhat.com> - 2.02-0.21
+- Add a simpler grub2 password config tool
+  Related: rhbz#985962
+- Some more coverity nits.
+
+* Mon Jul 06 2015 Peter Jones <pjones@redhat.com> - 2.02-0.20
+- Deal with some coverity nits.
+  Related: rhbz#1215839
+  Related: rhbz#1124074
+
+* Mon Jul 06 2015 Peter Jones <pjones@redhat.com> - 2.02-0.19
+- Rebuild for Aarch64
+- Deal with some coverity nits.
+  Related: rhbz#1215839
+  Related: rhbz#1124074
+
+* Thu Jul 02 2015 Peter Jones <pjones@redhat.com> - 2.02-0.18
+- Update for an rpmdiff problem with one of the man pages.
+  Related: rhbz#1124074
+
+* Tue Jun 30 2015 Peter Jones <pjones@redhat.com> - 2.02-0.17
+- Handle ipv6 better
+  Resolves: rhbz#1154226
+- On UEFI, use SIMPLE_NETWORK_PROTOCOL when we can.
+  Resolves: rhbz#1233378
+- Handle rssd disk drives in grub2 utilities.
+  Resolves: rhbz#1087962
+- Handle xfs CRC disk format.
+  Resolves: rhbz#1001279
+- Calibrate TCS using the EFI Stall service
+  Resolves: rhbz#1150698
+- Fix built-in gpg verification when using TFTP
+  Resolves: rhbz#1167977
+- Generate better stanza titles so grubby can find them easier.
+  Resolves: rhbz#1177003
+- Don't strip the fw_path variable twice when we're using EFI networking.
+  Resolves: rhbz#1211101
+
+* Mon May 11 2015 Peter Jones <pjones@redhat.com> - 2.02-0.17
+- Document network boot paths better
+  Resolves: rhbz#1148650
+- Use an rpm-based version sorted in grub2-mkconfig
+  Resolves: rhbz#1124074
+
+* Thu Oct 09 2014 Peter Jones <pjones@redhat.com> - 2.02-0.16
+- ... and build it on the right target.
+  Related: rhbz#1148652
+
+* Thu Oct 09 2014 Peter Jones <pjones@redhat.com> - 2.02-0.15
+- Make netbooting do a better job of picking the config path *again*.
+  Resolves: rhbz#1148652
+
+* Sat Oct 04 2014 Peter Jones <pjones@redhat.com> - 2.02-0.14
+- Be sure to *install* gcdaa64.efi
+  Related: rhbz#1100048
+
+* Fri Sep 26 2014 Peter Jones <pjones@redhat.com> - 2.02-0.13
+- Make sure to build a gcdaa64.efi
+  Related: rhbz#1100048
+
+* Tue Sep 23 2014 Peter Jones <pjones@redhat.com> - 2.02-0.12
+- Fix minor problems rpmdiff found.
+  Related: rhbz#1125540
+
+* Mon Sep 22 2014 Peter Jones <pjones@redhat.com> - 2.02-0.11
+- Fix grub2 segfault when root isn't set.
+  Resolves: rhbz#1084536
+- Make the aarch64 loader be SB-aware.
+  Related: rhbz#1100048
+- Enable regexp module
+  Resolves: rhbz#1125916
+
+* Thu Sep 04 2014 Peter Jones <pjones@redhat.com> - 2.02-0.10
+- Make editenv utilities (grub2-editenv, grub2-set-default, etc.) from
+  non-UEFI builds work with UEFI builds as well, since they're shared
+  from grub2-tools.
+  Resolves: rhbz#1119943
+- Make more grub2-mkconfig generate menu entries with the OS name and version
+  included.
+  Resolves: rhbz#996794
+- Minimize the sort ordering for .debug and -rescue- kernels.
+  Resolves: rhbz#1065360
+- Add GRUB_DISABLE_UUID to disable filesystem searching by UUID.
+  Resolves: rhbz#1027833
+- Allow "fallback" to specify titles like the documentation says
+  Resolves: rhbz#1026084
+
+* Wed Aug 27 2014 Peter Jones <pjones@redhat.com> - 2.02-0.9.1
+- A couple of patches for aarch64 got missed.
+  Related: rhbz#967937
+
+* Wed Aug 27 2014 Peter Jones <pjones@redhat.com> - 2.02-0.9
+- Once again, I have built with the wrong target.
+  Related: rhbz#1125540
+  Resolves: rhbz#967937
+
+* Fri Aug 22 2014 Peter Jones <pjones@redhat.com> - 2.02-0.8
+- Add patches for ppc64le
+  Related: rhbz#1125540
+
+* Thu Mar 20 2014 Peter Jones <pjones@redhat.com> - 2.02-0.2.10
+- Fix GRUB_DISABLE_SUBMENU one more time.
+  Resolves: rhbz#1063414
+
+* Tue Mar 18 2014 Peter Jones <pjones@redhat.com> - 2.02-0.2.9
+- Not sure why the right build target wasn't used *again*.
+  Resolves: rhbz#1073337
+
+* Wed Mar 12 2014 Peter Jones <pjones@redhat.com> - 2.02-0.2.8
+- Make GRUB_DISABLE_SUBMENU work again.
+  Resolves: rhbz#1063414
+
+* Thu Mar 06 2014 Peter Jones <pjones@redhat.com> - 2.02-0.2.7
+- Build on the right target.
+  Resolves: rhbz#1073337
+
+* Wed Mar 05 2014 Peter Jones <pjones@redhat.com> - 2.02-0.2.6
+- Fix minor man page install bug
+  Related: rhbz#948847
+
+* Tue Mar 04 2014 Peter Jones <pjones@redhat.com> - 2.02-0.2.5
+- Add man pages for common grub utilities.
+  Resolves: rhbz#948847
+- Fix shift key behavior on UEFI.
+  Resolves: rhbz#1068215
+
+* Tue Feb 18 2014 Peter Jones <pjones@redhat.com> - 2.02-0.2.4
+- Build against the right target.
+  Related: rhbz#1064424
+
+* Tue Feb 18 2014 Peter Jones <pjones@redhat.com> - 2.02-0.2.3
+- Don't emit "Booting <foo>" message.
+  Resolves: rhbz#1023142
+- Don't require a password for booting, only for editing entries.
+  Resolves: rhbz#1030176
+- Several network fixes from IBM
+  Resolves: rhbz#1056324
+- Support NVMe device names
+  Resolves: rhbz#1019660
+- Make control keys work on UEFI systems.
+  Resolves: rhbz#1056035
+
+* Fri Jan 31 2014 Peter Jones <pjones@redhat.com> - 2.02-0.2.2
+- Fix FORTIFY_SOURCE for util/
+  Related: rhbz#1049047
+
+* Tue Jan 21 2014 Peter Jones <pjones@redhat.com> - 2.02-0.2.1
+- Don't destroy symlinks when re-writing grub.cfg
+  Resolves: rhbz#1032182
+
+* Mon Jan 06 2014 Peter Jones <pjones@redhat.com> - 2.02-0.2
+- Update to grub-2.02~beta2
+
+* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 1:2.00-23
+- Mass rebuild 2013-12-27
+
+* Wed Nov 20 2013 Peter Jones <pjones@redhat.com> - 2.00-22.10
+- Rebuild with correct release number and with correct target.
+  Related: rhbz#1032530
+
+* Wed Nov 20 2013 Daniel Mach <dmach@redhat.com> - 2.00-22.9.1
+- Enable tftp module
+  Resolves: rhbz#1032530
+
+* Thu Nov 14 2013 Peter Jones <pjones@redhat.com> - 2.00-22.9
+- Make "linux16" happen on x86_64 machines as well.
+  Resolves: rhbz#880840
+
+* Wed Nov 06 2013 Peter Jones <pjones@redhat.com> - 2.00-22.8
+- Rebuild with correct build target for signing.
+  Related: rhbz#996863
+
+* Tue Nov 05 2013 Peter Jones <pjones@redhat.com> - 2.00-22.7
+- Build with -mcpu=power6 as we did before redhat-rpm-config changed
+  Resolves: rhbz#1026368
+
+* Thu Oct 31 2013 Peter Jones <pjones@redhat.com> - 2.00-22.6
+- Make linux16 work with the shell better.
+  Resolves: rhbz#880840
+
+* Thu Oct 31 2013 Peter Jones <pjones@redhat.com> - 2.00-22.5
+- Rebuild because we were clobbering signing in the spec file...
+  Related: rhbz#1017855
+
+* Thu Oct 31 2013 Peter Jones <pjones@redhat.com> - 2.00-22.4
+- Rebuild because signing didn't work.
+  Related: rhbz#1017855
+
+* Mon Oct 28 2013 Peter Jones <pjones@redhat.com> - 2.00-22.3
+- Use linux16 when appropriate:
+  Resolves: rhbz#880840
+- Enable pager by default:
+  Resolves: rhbz#985860
+- Don't ask the user to hit keys that won't work.
+  Resolves: rhbz#987443
+- Sign grub2 during builds
+  Resolves: rhbz#1017855
+
+* Thu Aug 29 2013 Peter Jones <pjones@redhat.com> - 2.00-22.2
+- Fix minor rpmdiff complaints.
+
+* Wed Aug 07 2013 Peter Jones <pjones@redhat.com> - 2.00-22.1
+- Fix url so PkgWrangler doesn't go crazy.
+
+* Fri Jun 21 2013 Peter Jones <pjones@redhat.com> - 2.00-22
+- Fix linewrapping in edit menu.
+  Resolves: rhbz #976643
+
+* Thu Jun 20 2013 Peter Jones <pjones@redhat.com> - 2.00-21
+- Fix obsoletes to pull in -starfield-theme subpackage when it should.
+
+* Fri Jun 14 2013 Peter Jones <pjones@redhat.com> - 2.00-20
+- Put the theme entirely ento the subpackage where it belongs (#974667)
+
+* Wed Jun 12 2013 Peter Jones <pjones@redhat.com> - 2.00-19
+- Rebase to upstream snapshot.
+- Fix PPC build error (#967862)
+- Fix crash on net_bootp command (#960624)
+- Reset colors on ppc when appropriate (#908519)
+- Left align "Loading..." messages (#908492)
+- Fix probing of SAS disks on PPC (#953954)
+- Add support for UEFI OSes returned by os-prober
+- Disable "video" mode on PPC for now (#973205)
+- Make grub fit better into the boot sequence, visually (#966719)
+
+* Fri May 10 2013 Matthias Clasen <mclasen@redhat.com> - 2.00-18
+- Move the starfield theme to a subpackage (#962004)
+- Don't allow SSE or MMX on UEFI builds (#949761)
+
+* Wed Apr 24 2013 Peter Jones <pjones@redhat.com> - 2.00-17.pj0
+- Rebase to upstream snapshot.
+
+* Thu Apr 04 2013 Peter Jones <pjones@redhat.com> - 2.00-17
+- Fix booting from drives with 4k sectors on UEFI.
+- Move bash completion to new location (#922997)
+- Include lvm support for /boot (#906203)
+
+* Thu Feb 14 2013 Peter Jones <pjones@redhat.com> - 2.00-16
+- Allow the user to disable submenu generation
+- (partially) support BLS-style configuration stanzas.
+
+* Tue Feb 12 2013 Peter Jones <pjones@redhat.com> - 2.00-15.pj0
+- Add various config file related changes.
+
+* Thu Dec 20 2012 Dennis Gilmore <dennis@ausil.us> - 2.00-15
+- bump nvr
+
+* Mon Dec 17 2012 Karsten Hopp <karsten@redhat.com> 2.00-14
+- add bootpath device to the device list (pfsmorigo, #886685)
+
+* Tue Nov 27 2012 Peter Jones <pjones@redhat.com> - 2.00-13
+- Add vlan tag support (pfsmorigo, #871563)
+- Follow symlinks during PReP installation in grub2-install (pfsmorigo, #874234)
+- Improve search paths for config files on network boot (pfsmorigo, #873406)
+
+* Tue Oct 23 2012 Peter Jones <pjones@redhat.com> - 2.00-12
+- Don't load modules when grub transitions to "normal" mode on UEFI.
+
+* Mon Oct 22 2012 Peter Jones <pjones@redhat.com> - 2.00-11
+- Rebuild with newer pesign so we'll get signed with the final signing keys.
+
+* Thu Oct 18 2012 Peter Jones <pjones@redhat.com> - 2.00-10
+- Various PPC fixes.
+- Fix crash fetching from http (gustavold, #860834)
+- Issue separate dns queries for ipv4 and ipv6 (gustavold, #860829)
+- Support IBM CAS reboot (pfsmorigo, #859223)
+- Include all modules in the core image on ppc (pfsmorigo, #866559)
+
+* Mon Oct 01 2012 Peter Jones <pjones@redhat.com> - 1:2.00-9
+- Work around bug with using "\x20" in linux command line.
+  Related: rhbz#855849
+
+* Thu Sep 20 2012 Peter Jones <pjones@redhat.com> - 2.00-8
+- Don't error on insmod on UEFI/SB, but also don't do any insmodding.
+- Increase device path size for ieee1275
+  Resolves: rhbz#857936
+- Make network booting work on ieee1275 machines.
+  Resolves: rhbz#857936
+
+* Wed Sep 05 2012 Matthew Garrett <mjg@redhat.com> - 2.00-7
+- Add Apple partition map support for EFI
+
+* Thu Aug 23 2012 David Cantrell <dcantrell@redhat.com> - 2.00-6
+- Only require pesign on EFI architectures (#851215)
+
+* Tue Aug 14 2012 Peter Jones <pjones@redhat.com> - 2.00-5
+- Work around AHCI firmware bug in efidisk driver.
+- Move to newer pesign macros
+- Don't allow insmod if we're in secure-boot mode.
+
+* Wed Aug 08 2012 Peter Jones <pjones@redhat.com>
+- Split module lists for UEFI boot vs UEFI cd images.
+- Add raid modules for UEFI image (related: #750794)
+- Include a prelink whitelist for binaries that need execstack (#839813)
+- Include fix efi memory map fix from upstream (#839363)
+
+* Wed Aug 08 2012 Peter Jones <pjones@redhat.com> - 2.00-4
+- Correct grub-mkimage invocation to use efidir RPM macro (jwb)
+- Sign with test keys on UEFI systems.
+- PPC - Handle device paths with commas correctly.
+  Related: rhbz#828740
+
+* Wed Jul 25 2012 Peter Jones <pjones@redhat.com> - 2.00-3
+- Add some more code to support Secure Boot, and temporarily disable
+  some other bits that don't work well enough yet.
+  Resolves: rhbz#836695
+
+* Wed Jul 11 2012 Matthew Garrett <mjg@redhat.com> - 2.00-2
+- Set a prefix for the image - needed for installer work
+- Provide the font in the EFI directory for the same reason
+
+* Thu Jun 28 2012 Peter Jones <pjones@redhat.com> - 2.00-1
+- Rebase to grub-2.00 release.
+
+* Mon Jun 18 2012 Peter Jones <pjones@redhat.com> - 2.0-0.37.beta6
+- Fix double-free in grub-probe.
+
+* Wed Jun 06 2012 Peter Jones <pjones@redhat.com> - 2.0-0.36.beta6
+- Build with patch19 applied.
+
+* Wed Jun 06 2012 Peter Jones <pjones@redhat.com> - 2.0-0.35.beta6
+- More ppc fixes.
+
+* Wed Jun 06 2012 Peter Jones <pjones@redhat.com> - 2.0-0.34.beta6
+- Add IBM PPC fixes.
+
+* Mon Jun 04 2012 Peter Jones <pjones@redhat.com> - 2.0-0.33.beta6
+- Update to beta6.
+- Various fixes from mads.
+
+* Fri May 25 2012 Peter Jones <pjones@redhat.com> - 2.0-0.32.beta5
+- Revert builddep change for crt1.o; it breaks ppc build.
+
+* Fri May 25 2012 Peter Jones <pjones@redhat.com> - 2.0-0.31.beta5
+- Add fwsetup command (pjones)
+- More ppc fixes (IBM)
+
+* Tue May 22 2012 Peter Jones <pjones@redhat.com> - 2.0-0.30.beta5
+- Fix the /other/ grub2-tools require to include epoch.
+
+* Mon May 21 2012 Peter Jones <pjones@redhat.com> - 2.0-0.29.beta5
+- Get rid of efi_uga and efi_gop, favoring all_video instead.
+
+* Mon May 21 2012 Peter Jones <pjones@redhat.com> - 2.0-0.28.beta5
+- Name grub.efi something that's arch-appropriate (kiilerix, pjones)
+- use EFI/$SOMETHING_DISTRO_BASED/ not always EFI/redhat/grub2-efi/ .
+- move common stuff to -tools (kiilerix)
+- spec file cleanups (kiilerix)
+
+* Mon May 14 2012 Peter Jones <pjones@redhat.com> - 2.0-0.27.beta5
+- Fix module trampolining on ppc (benh)
+
+* Thu May 10 2012 Peter Jones <pjones@redhat.com> - 2.0-0.27.beta5
+- Fix license of theme (mizmo)
+  Resolves: rhbz#820713
+- Fix some PPC bootloader detection IBM problem
+  Resolves: rhbz#820722
+
+* Thu May 10 2012 Peter Jones <pjones@redhat.com> - 2.0-0.26.beta5
+- Update to beta5.
+- Update how efi building works (kiilerix)
+- Fix theme support to bring in fonts correctly (kiilerix, pjones)
+
+* Wed May 09 2012 Peter Jones <pjones@redhat.com> - 2.0-0.25.beta4
+- Include theme support (mizmo)
+- Include locale support (kiilerix)
+- Include html docs (kiilerix)
+
+* Thu Apr 26 2012 Peter Jones <pjones@redhat.com> - 2.0-0.24
+- Various fixes from Mads Kiilerich
+
+* Thu Apr 19 2012 Peter Jones <pjones@redhat.com> - 2.0-0.23
+- Update to 2.00~beta4
+- Make fonts work so we can do graphics reasonably
+
+* Thu Mar 29 2012 David Aquilina <dwa@redhat.com> - 2.0-0.22
+- Fix ieee1275 platform define for ppc
+
+* Thu Mar 29 2012 Peter Jones <pjones@redhat.com> - 2.0-0.21
+- Remove ppc excludearch lines (dwa)
+- Update ppc terminfo patch (hamzy)
+
+* Wed Mar 28 2012 Peter Jones <pjones@redhat.com> - 2.0-0.20
+- Fix ppc64 vs ppc exclude according to what dwa tells me they need
+- Fix version number to better match policy.
+
+* Tue Mar 27 2012 Dan Horák <dan[at]danny.cz> - 1.99-19.2
+- Add support for serial terminal consoles on PPC by Mark Hamzy
+
+* Sun Mar 25 2012 Dan Horák <dan[at]danny.cz> - 1.99-19.1
+- Use Fix-tests-of-zeroed-partition patch by Mark Hamzy
+
+* Thu Mar 15 2012 Peter Jones <pjones@redhat.com> - 1.99-19
+- Use --with-grubdir= on configure to make it behave like -17 did.
+
+* Wed Mar 14 2012 Peter Jones <pjones@redhat.com> - 1.99-18
+- Rebase from 1.99 to 2.00~beta2
+
+* Wed Mar 07 2012 Peter Jones <pjones@redhat.com> - 1.99-17
+- Update for newer autotools and gcc 4.7.0
+  Related: rhbz#782144
+- Add /etc/sysconfig/grub link to /etc/default/grub
+  Resolves: rhbz#800152
+- ExcludeArch s390*, which is not supported by this package.
+  Resolves: rhbz#758333
+
+* Fri Feb 17 2012 Orion Poplawski <orion@cora.nwra.com> - 1:1.99-16
+- Build with -Os (bug 782144)
+
+* Fri Jan 13 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1:1.99-15
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
+
+* Wed Dec 14 2011 Matthew Garrett <mjg@redhat.com> - 1.99-14
+- fix up various grub2-efi issues
+
+* Thu Dec 08 2011 Adam Williamson <awilliam@redhat.com> - 1.99-13
+- fix hardwired call to grub-probe in 30_os-prober (rhbz#737203)
+
+* Mon Nov 07 2011 Peter Jones <pjones@redhat.com> - 1.99-12
+- Lots of .spec fixes from Mads Kiilerich:
+  Remove comment about update-grub - it isn't run in any scriptlets
+  patch info pages so they can be installed and removed correctly when renamed
+  fix references to grub/grub2 renames in info pages (#743964)
+  update README.Fedora (#734090)
+  fix comments for the hack for upgrading from grub2 < 1.99-4
+  fix sed syntax error preventing use of $RPM_OPT_FLAGS (#704820)
+  make /etc/grub2*.cfg %config(noreplace)
+  make grub.cfg %ghost - an empty file is of no use anyway
+  create /etc/default/grub more like anaconda would create it (#678453)
+  don't create rescue entries by default - grubby will not maintain them anyway
+  set GRUB_SAVEDEFAULT=true so saved defaults works (rbhz#732058)
+  grub2-efi should have its own bash completion
+  don't set gfxpayload in efi mode - backport upstream r3402
+- Handle dmraid better. Resolves: rhbz#742226
+
+* Wed Oct 26 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1:1.99-11
+- Rebuilt for glibc bug#747377
+
+* Wed Oct 19 2011 Adam Williamson <awilliam@redhat.com> - 1.99-10
+- /etc/default/grub is explicitly intended for user customization, so
+  mark it as config(noreplace)
+
+* Tue Oct 11 2011 Peter Jones <pjones@redhat.com> - 1.99-9
+- grub has an epoch, so we need that expressed in the obsolete as well.
+  Today isn't my day.
+
+* Tue Oct 11 2011 Peter Jones <pjones@redhat.com> - 1.99-8
+- Fix my bad obsoletes syntax.
+
+* Thu Oct 06 2011 Peter Jones <pjones@redhat.com> - 1.99-7
+- Obsolete grub
+  Resolves: rhbz#743381
+
+* Wed Sep 14 2011 Peter Jones <pjones@redhat.com> - 1.99-6
+- Use mv not cp to try to avoid moving disk blocks around for -5 fix
+  Related: rhbz#735259
+- handle initramfs on xen better (patch from Marko Ristola)
+  Resolves: rhbz#728775
+
+* Sat Sep 03 2011 Kalev Lember <kalevlember@gmail.com> - 1.99-5
+- Fix upgrades from grub2 < 1.99-4 (#735259)
+
+* Fri Sep 02 2011 Peter Jones <pjones@redhat.com> - 1.99-4
+- Don't do sysadminny things in %preun or %post ever. (#735259)
+- Actually include the changelog in this build (sorry about -3)
+
+* Thu Sep 01 2011 Peter Jones <pjones@redhat.com> - 1.99-2
+- Require os-prober (#678456) (patch from Elad Alfassa)
+- Require which (#734959) (patch from Elad Alfassa)
+
+* Thu Sep 01 2011 Peter Jones <pjones@redhat.com> - 1.99-1
+- Update to grub-1.99 final.
+- Fix crt1.o require on x86-64 (fix from Mads Kiilerich)
+- Various CFLAGS fixes (from Mads Kiilerich)
+  - -fexceptions and -m64
+- Temporarily ignore translations (from Mads Kiilerich)
+
+* Thu Jul 21 2011 Peter Jones <pjones@redhat.com> - 1.99-0.3
+- Use /sbin not /usr/sbin .
+
+* Thu Jun 23 2011 Peter Lemenkov <lemenkov@gmail.com> - 1:1.99-0.2
+- Fixes for ppc and ppc64
+
+* Wed Feb 09 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1:1.98-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild