Blob Blame History Raw
diff --git a/configure.ac b/configure.ac
index edd184154f7e9aad556b6437b8ec22bc79d5a057..c7888e40f6695ee23a43fb98420d6cbcd3d86622 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,7 +31,7 @@ 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],[bug-grub@gnu.org])
+AC_INIT([GRUB],[2.03],[bug-grub@gnu.org])
 
 AC_CONFIG_AUX_DIR([build-aux])
 
@@ -167,6 +167,7 @@ case "$target_cpu"-"$platform" in
   mipsel-fuloong) platform=loongson ;;
   mipsel-loongson) ;;
   arm-uboot) ;;
+  arm-coreboot) ;;
   arm-efi) ;;
   arm64-efi) ;;
   *-emu) ;;
@@ -203,7 +204,8 @@ case "$host_os" in
 esac
 
 case "$host_os" in
-  cygwin | windows* | mingw32*)	have_exec=n ;;
+  cygwin) have_exec=y ;;
+  windows* | mingw32*) have_exec=n ;;
   aros*) have_exec=n ;;
   *) have_exec=y;;
 esac
@@ -373,7 +375,10 @@ case "$host_os" in
      ;;
   *)
      AC_CHECK_SIZEOF(off_t)
-     test x"$ac_cv_sizeof_off_t" = x8 || AC_MSG_ERROR([Large file support is required]);;
+     if test x"$ac_cv_sizeof_off_t" != x8 ; then
+       AC_CHECK_SIZEOF(off64_t)
+       test x"$ac_cv_sizeof_off64_t" = x8 || AC_MSG_ERROR([Large file support is required])
+     fi;;
 esac
 
 if test x$USE_NLS = xno; then
@@ -456,6 +461,16 @@ case "$build_os" in
 esac
 AC_SUBST(BUILD_EXEEXT)
 
+# In some build environments like termux /bin/sh is not a valid
+# shebang. Use $SHELL instead if it's executable and /bin/sh isn't
+BUILD_SHEBANG=/bin/sh
+for she in /bin/sh "$SHELL"; do
+  if test -x "$she" ; then
+    BUILD_SHEBANG="$she"
+  fi
+done
+AC_SUBST(BUILD_SHEBANG)
+
 # For gnulib.
 gl_INIT
 
@@ -1905,6 +1920,7 @@ AM_CONDITIONAL([COND_mipsel], [test x$target_cpu = xmipsel])
 AM_CONDITIONAL([COND_mipseb], [test x$target_cpu = xmips])
 AM_CONDITIONAL([COND_arm], [test x$target_cpu = xarm ])
 AM_CONDITIONAL([COND_arm_uboot], [test x$target_cpu = xarm -a x$platform = xuboot])
+AM_CONDITIONAL([COND_arm_coreboot], [test x$target_cpu = xarm -a x$platform = xcoreboot])
 AM_CONDITIONAL([COND_arm_efi], [test x$target_cpu = xarm -a x$platform = xefi])
 AM_CONDITIONAL([COND_arm64], [test x$target_cpu = xarm64 ])
 AM_CONDITIONAL([COND_arm64_efi], [test x$target_cpu = xarm64 -a x$platform = xefi])
diff --git a/Makefile.util.def b/Makefile.util.def
index f9caccb9780ffe8d4b31c8a19399ba7bbd308e56..3180ac880a9aa86e94fb47a7386bfa324425bff0 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -99,6 +99,7 @@ library = {
   common = grub-core/fs/ext2.c;
   common = grub-core/fs/fat.c;
   common = grub-core/fs/exfat.c;
+  common = grub-core/fs/f2fs.c;
   common = grub-core/fs/fshelp.c;
   common = grub-core/fs/hfs.c;
   common = grub-core/fs/hfsplus.c;
@@ -774,6 +775,12 @@ script = {
   common = tests/xfs_test.in;
 };
 
+script = {
+  testcase;
+  name = f2fs_test;
+  common = tests/f2fs_test.in;
+};
+
 script = {
   testcase;
   name = nilfs2_test;
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 2dfa22a9271bd6624fad9b91ce051ac12202dfbd..9590e87d9c080d6675a9521d91ef6a47d39f2751 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -68,11 +68,11 @@ kernel = {
   i386_pc_ldflags          = '$(TARGET_IMG_LDFLAGS)';
   i386_pc_ldflags          = '$(TARGET_IMG_BASE_LDOPT),0x9000';
   i386_qemu_ldflags        = '$(TARGET_IMG_LDFLAGS)';
-  i386_qemu_ldflags        = '$(TARGET_IMG_BASE_LDOPT),0x8200';
+  i386_qemu_ldflags        = '$(TARGET_IMG_BASE_LDOPT),0x9000';
   i386_coreboot_ldflags    = '$(TARGET_IMG_LDFLAGS)';
-  i386_coreboot_ldflags    = '$(TARGET_IMG_BASE_LDOPT),0x8200';
+  i386_coreboot_ldflags    = '$(TARGET_IMG_BASE_LDOPT),0x9000';
   i386_multiboot_ldflags   = '$(TARGET_IMG_LDFLAGS)';
-  i386_multiboot_ldflags   = '$(TARGET_IMG_BASE_LDOPT),0x8200';
+  i386_multiboot_ldflags   = '$(TARGET_IMG_BASE_LDOPT),0x9000';
   i386_ieee1275_ldflags    = '$(TARGET_IMG_LDFLAGS)';
   i386_ieee1275_ldflags    = '$(TARGET_IMG_BASE_LDOPT),0x10000';
   i386_xen_ldflags         = '$(TARGET_IMG_LDFLAGS)';
@@ -92,6 +92,8 @@ kernel = {
   emu_cppflags = '$(CPPFLAGS_GNULIB)';
   arm_uboot_ldflags       = '-Wl,-r,-d';
   arm_uboot_stripflags    = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
+  arm_coreboot_ldflags       = '-Wl,-r,-d';
+  arm_coreboot_stripflags    = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
 
   i386_pc_startup = kern/i386/pc/startup.S;
   i386_efi_startup = kern/i386/efi/startup.S;
@@ -105,7 +107,8 @@ kernel = {
   mips_startup = kern/mips/startup.S;
   sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S;
   powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S;
-  arm_uboot_startup = kern/arm/uboot/startup.S;
+  arm_uboot_startup = kern/arm/startup.S;
+  arm_coreboot_startup = kern/arm/startup.S;
   arm_efi_startup = kern/arm/efi/startup.S;
   arm64_efi_startup = kern/arm64/efi/startup.S;
 
@@ -149,6 +152,21 @@ kernel = {
   uboot = kern/uboot/init.c;
   uboot = kern/uboot/hw.c;
   uboot = term/uboot/console.c;
+  arm_uboot = kern/arm/uboot/init.c;
+  arm_uboot = kern/arm/uboot/uboot.S;
+
+  arm_coreboot = kern/arm/coreboot/init.c;
+  arm_coreboot = kern/arm/coreboot/timer.c;
+  arm_coreboot = kern/arm/coreboot/coreboot.S;
+  arm_coreboot = lib/fdt.c;
+  arm_coreboot = bus/fdt.c;
+  arm_coreboot = term/ps2.c;
+  arm_coreboot = term/arm/pl050.c;
+  arm_coreboot = term/arm/cros.c;
+  arm_coreboot = term/arm/cros_ec.c;
+  arm_coreboot = bus/spi/rk3288_spi.c;
+  arm_coreboot = commands/keylayouts.c;
+  arm_coreboot = kern/arm/coreboot/dma.c;
 
   terminfoinkernel = term/terminfo.c;
   terminfoinkernel = term/tparm.c;
@@ -164,7 +182,7 @@ kernel = {
   i386_multiboot = kern/i386/coreboot/init.c;
   i386_qemu = kern/i386/qemu/init.c;
   i386_coreboot_multiboot_qemu = term/i386/pc/vga_text.c;
-  i386_coreboot = video/i386/coreboot/cbfb.c;
+  coreboot = video/coreboot/cbfb.c;
 
   efi = disk/efi/efidisk.c;
   efi = kern/efi/efi.c;
@@ -211,7 +229,6 @@ kernel = {
   ia64_efi = kern/ia64/cache.c;
 
   arm_efi = kern/arm/efi/init.c;
-  arm_efi = kern/arm/efi/misc.c;
   arm_efi = kern/efi/fdt.c;
 
   arm64_efi = kern/arm64/efi/init.c;
@@ -225,8 +242,10 @@ kernel = {
   i386_qemu = kern/vga_init.c;
   i386_qemu = kern/i386/qemu/mmap.c;
 
-  i386_coreboot = kern/i386/coreboot/mmap.c;
+  coreboot = kern/coreboot/mmap.c;
   i386_coreboot = kern/i386/coreboot/cbtable.c;
+  coreboot = kern/coreboot/cbtable.c;
+  arm_coreboot = kern/arm/coreboot/cbtable.c;
 
   i386_multiboot = kern/i386/multiboot_mmap.c;
 
@@ -238,6 +257,7 @@ kernel = {
   mips_qemu_mips = term/ns8250.c;
   mips_qemu_mips = term/serial.c;
   mips_qemu_mips = term/at_keyboard.c;
+  mips_qemu_mips = term/ps2.c;
   mips_qemu_mips = commands/boot.c;
   mips_qemu_mips = commands/keylayouts.c;
   mips_qemu_mips = term/i386/pc/vga_text.c;
@@ -253,6 +273,7 @@ kernel = {
   mips_loongson = bus/pci.c;
   mips_loongson = kern/mips/loongson/init.c;
   mips_loongson = term/at_keyboard.c;
+  mips_loongson = term/ps2.c;
   mips_loongson = commands/boot.c;
   mips_loongson = term/serial.c;
   mips_loongson = video/sm712.c;
@@ -574,7 +595,10 @@ module = {
 module = {
   name = ehci;
   common = bus/usb/ehci.c;
+  arm_coreboot = bus/usb/ehci-fdt.c;
+  pci = bus/usb/ehci-pci.c;
   enable = pci;
+  enable = arm_coreboot;
 };
 
 module = {
@@ -641,6 +665,7 @@ module = {
 module = {
   name = cbtable;
   common = kern/i386/coreboot/cbtable.c;
+  common = kern/coreboot/cbtable.c;
   enable = i386_pc;
   enable = i386_efi;
   enable = i386_qemu;
@@ -754,6 +779,7 @@ module = {
   enable = arm_efi;
   enable = arm64_efi;
   enable = arm_uboot;
+  enable = arm_coreboot;
 };
 
 module = {
@@ -837,17 +863,14 @@ module = {
   efi = lib/efi/halt.c;
   ieee1275 = lib/ieee1275/halt.c;
   emu = lib/emu/halt.c;
-  uboot = lib/uboot/halt.c;
+  uboot = lib/dummy/halt.c;
+  arm_coreboot = lib/dummy/halt.c;
 };
 
 module = {
   name = reboot;
   i386 = lib/i386/reboot.c;
   i386 = lib/i386/reboot_trampoline.S;
-  ia64_efi = lib/efi/reboot.c;
-  x86_64_efi = lib/efi/reboot.c;
-  arm_efi = lib/efi/reboot.c;
-  arm64_efi = lib/efi/reboot.c;
   powerpc_ieee1275 = lib/ieee1275/reboot.c;
   sparc64_ieee1275 = lib/ieee1275/reboot.c;
   mips_arc = lib/mips/arc/reboot.c;
@@ -855,6 +878,7 @@ module = {
   mips_qemu_mips = lib/mips/qemu_mips/reboot.c;
   xen = lib/xen/reboot.c;
   uboot = lib/uboot/reboot.c;
+  arm_coreboot = lib/dummy/reboot.c;
   common = commands/reboot.c;
 };
 
@@ -873,7 +897,6 @@ module = {
 module = {
   name = hdparm;
   common = commands/hdparm.c;
-  common = lib/hexdump.c;
   enable = pci;
   enable = mips_qemu_mips;
 };
@@ -1290,6 +1313,11 @@ module = {
   common = fs/exfat.c;
 };
 
+module = {
+  name = f2fs;
+  common = fs/f2fs.c;
+};
+
 module = {
   name = fshelp;
   common = fs/fshelp.c;
@@ -1548,7 +1576,8 @@ module = {
   name = datetime;
   cmos = lib/cmos_datetime.c;
   efi = lib/efi/datetime.c;
-  uboot = lib/uboot/datetime.c;
+  uboot = lib/dummy/datetime.c;
+  arm_coreboot = lib/dummy/datetime.c;
   sparc64_ieee1275 = lib/ieee1275/datetime.c;
   powerpc_ieee1275 = lib/ieee1275/datetime.c;
   sparc64_ieee1275 = lib/ieee1275/cmos.c;
@@ -1601,8 +1630,6 @@ module = {
 module = {
   name = linux16;
   common = loader/i386/pc/linux.c;
-  common = loader/linux.c;
-  common = lib/cmdline.c;
   enable = x86;
 };
 
@@ -1637,7 +1664,6 @@ module = {
   cppflags = "-DGRUB_USE_MULTIBOOT2";
 
   common = loader/multiboot.c;
-  common = lib/cmdline.c;
   common = loader/multiboot_mbi2.c;
   enable = x86;
   enable = mips;
@@ -1646,7 +1672,6 @@ module = {
 module = {
   name = multiboot;
   common = loader/multiboot.c;
-  common = lib/cmdline.c;
   x86 = loader/i386/multiboot_mbi.c;
   extra_dist = loader/multiboot_elfxx.c;
   enable = x86;
@@ -1654,7 +1679,6 @@ module = {
 
 module = {
   name = xen_boot;
-  common = lib/cmdline.c;
   arm64 = loader/arm64/xen_boot.c;
   enable = arm64;
 };
@@ -1668,7 +1692,9 @@ module = {
   powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c;
   sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c;
   ia64_efi = loader/ia64/efi/linux.c;
-  arm = loader/arm/linux.c;
+  arm_coreboot = loader/arm/linux.c;
+  arm_efi = loader/arm64/linux.c;
+  arm_uboot = loader/arm/linux.c;
   arm64 = loader/arm64/linux.c;
   common = loader/linux.c;
   common = lib/cmdline.c;
@@ -1677,7 +1703,7 @@ module = {
 
 module = {
   name = fdt;
-  arm64 = loader/arm64/fdt.c;
+  efi = loader/efi/fdt.c;
   common = lib/fdt.c;
   enable = fdt;
 };
@@ -1869,6 +1895,7 @@ module = {
 module = {
   name = at_keyboard;
   common = term/at_keyboard.c;
+  common = term/ps2.c;
   enable = x86;
 };
 
@@ -1961,6 +1988,11 @@ module = {
   common = tests/example_functional_test.c;
 };
 
+module = {
+  name = strtoull_test;
+  common = tests/strtoull_test.c;
+};
+
 module = {
   name = setjmp_test;
   common = tests/setjmp_test.c;
diff --git a/grub-core/bus/fdt.c b/grub-core/bus/fdt.c
new file mode 100644
index 0000000000000000000000000000000000000000..135da497ba67e7545490e0e73ee3a1fa676a6069
--- /dev/null
+++ b/grub-core/bus/fdt.c
@@ -0,0 +1,256 @@
+/*
+ *  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/>.
+ */
+
+#include <grub/fdtbus.h>
+#include <grub/fdt.h>
+#include <grub/term.h>
+
+static const void *dtb;
+static grub_size_t root_address_cells, root_size_cells;
+/* Pointer to this symbol signals invalid mapping.  */
+char grub_fdtbus_invalid_mapping[1];
+
+struct grub_fdtbus_dev *devs;
+struct grub_fdtbus_driver *drivers;
+
+int
+grub_fdtbus_is_compatible (const char *compat_string,
+			   const struct grub_fdtbus_dev *dev)
+{
+  grub_size_t compatible_size;
+  const char *compatible = grub_fdt_get_prop (dtb, dev->node, "compatible",
+					      &compatible_size);
+  if (!compatible)
+    return 0;
+  const char *compatible_end = compatible + compatible_size;
+  while (compatible < compatible_end)
+    {
+      if (grub_strcmp (compat_string, compatible) == 0)
+	return 1;
+      compatible += grub_strlen (compatible) + 1;
+    }
+  return 0;
+}
+
+static void
+fdtbus_scan (struct grub_fdtbus_dev *parent)
+{
+  int node;
+  for (node = grub_fdt_first_node (dtb, parent ? parent->node : 0); node >= 0;
+       node = grub_fdt_next_node (dtb, node))
+    {
+      struct grub_fdtbus_dev *dev;
+      struct grub_fdtbus_driver *driver;
+      dev = grub_zalloc (sizeof (*dev));
+      if (!dev)
+	{
+	  grub_print_error ();
+	  return;
+	}
+      dev->node = node;
+      dev->next = devs;
+      dev->parent = parent;
+      devs = dev;
+      FOR_LIST_ELEMENTS(driver, drivers)
+	if (!dev->driver && grub_fdtbus_is_compatible (driver->compatible, dev))
+	  {
+	    grub_dprintf ("fdtbus", "Attaching %s\n", driver->compatible);
+	    if (driver->attach (dev) == GRUB_ERR_NONE)
+	      {
+		grub_dprintf ("fdtbus", "Attached %s\n", driver->compatible);
+		dev->driver = driver;
+		break;
+	      }
+	    grub_print_error ();
+	  }
+      fdtbus_scan (dev);
+    }
+}
+
+void
+grub_fdtbus_register (struct grub_fdtbus_driver *driver)
+{
+  struct grub_fdtbus_dev *dev;
+  grub_dprintf ("fdtbus", "Registering %s\n", driver->compatible);
+  grub_list_push (GRUB_AS_LIST_P (&drivers),
+		  GRUB_AS_LIST (driver));
+  for (dev = devs; dev; dev = dev->next)
+    if (!dev->driver && grub_fdtbus_is_compatible (driver->compatible, dev))
+      {
+	grub_dprintf ("fdtbus", "Attaching %s (%p)\n", driver->compatible, dev);
+	if (driver->attach (dev) == GRUB_ERR_NONE)
+	  {
+	    grub_dprintf ("fdtbus", "Attached %s\n", driver->compatible);
+	    dev->driver = driver;
+	  }
+	grub_print_error ();
+      }
+}
+
+void
+grub_fdtbus_unregister (struct grub_fdtbus_driver *driver)
+{
+  grub_list_remove (GRUB_AS_LIST (driver));
+  struct grub_fdtbus_dev *dev;
+  for (dev = devs; dev; dev = dev->next)
+    if (dev->driver == driver)
+      {
+	if (driver->detach)
+	  driver->detach(dev);
+	dev->driver = 0;
+      }
+}
+
+void
+grub_fdtbus_init (const void *dtb_in, grub_size_t size)
+{
+  if (!dtb_in || grub_fdt_check_header (dtb_in, size) < 0)
+    grub_fatal ("invalid FDT");
+  dtb = dtb_in;
+  const grub_uint32_t *prop = grub_fdt_get_prop (dtb, 0, "#address-cells", 0);
+  if (prop)
+    root_address_cells = grub_be_to_cpu32 (*prop);
+  else
+    root_address_cells = 1;
+
+  prop = grub_fdt_get_prop (dtb, 0, "#size-cells", 0);
+  if (prop)
+    root_size_cells = grub_be_to_cpu32 (*prop);
+  else
+    root_size_cells = 1;
+
+  fdtbus_scan (0);
+}
+
+static int
+get_address_cells (const struct grub_fdtbus_dev *dev)
+{
+  const grub_uint32_t *prop;
+  if (!dev)
+    return root_address_cells;
+  prop = grub_fdt_get_prop (dtb, dev->node, "#address-cells", 0);
+  if (prop)
+    return grub_be_to_cpu32 (*prop);
+  return 1;
+}
+
+static int
+get_size_cells (const struct grub_fdtbus_dev *dev)
+{
+  const grub_uint32_t *prop;
+  if (!dev)
+    return root_size_cells;
+  prop = grub_fdt_get_prop (dtb, dev->node, "#size-cells", 0);
+  if (prop)
+    return grub_be_to_cpu32 (*prop);
+  return 1;
+}
+
+static grub_uint64_t
+get64 (const grub_uint32_t *reg, grub_size_t cells)
+{
+  grub_uint64_t val = 0;
+  if (cells >= 1)
+    val = grub_be_to_cpu32 (reg[cells - 1]);
+  if (cells >= 2)
+    val |= ((grub_uint64_t) grub_be_to_cpu32 (reg[cells - 2])) << 32;
+  return val;
+}
+
+static volatile void *
+translate (const struct grub_fdtbus_dev *dev, const grub_uint32_t *reg)
+{
+  volatile void *ret;
+  const grub_uint32_t *ranges;
+  grub_size_t ranges_size, cells_per_mapping;
+  grub_size_t parent_address_cells, child_address_cells, child_size_cells;
+  grub_size_t nmappings, i;
+  if (dev == 0)
+    {
+      grub_uint64_t val;
+      val = get64 (reg, root_address_cells);
+      if (sizeof (void *) == 4 && (val >> 32))
+	return grub_fdtbus_invalid_mapping;
+      return (void *) (grub_addr_t) val;
+    }
+  ranges = grub_fdt_get_prop (dtb, dev->node, "ranges", &ranges_size);
+  if (!ranges)
+    return grub_fdtbus_invalid_mapping;
+  if (ranges_size == 0)
+    return translate (dev->parent, reg);
+  parent_address_cells = get_address_cells (dev->parent);
+  child_address_cells = get_address_cells (dev);
+  child_size_cells = get_size_cells (dev);
+  cells_per_mapping = parent_address_cells + child_address_cells + child_size_cells;
+  nmappings = ranges_size / 4 / cells_per_mapping;
+  for (i = 0; i < nmappings; i++)
+    {
+      const grub_uint32_t *child_addr = &ranges[i * cells_per_mapping];
+      const grub_uint32_t *parent_addr = child_addr + child_address_cells;
+      grub_uint64_t child_size = get64 (parent_addr + parent_address_cells, child_size_cells);
+
+      if (child_address_cells > 2 && grub_memcmp (reg, child_addr, (child_address_cells - 2) * 4) != 0)
+	continue;
+      if (get64 (reg, child_address_cells) < get64 (child_addr, child_address_cells))
+	continue;
+
+      grub_uint64_t offset = get64 (reg, child_address_cells) - get64 (child_addr, child_address_cells);
+      if (offset >= child_size)
+	continue;
+
+      ret = translate (dev->parent, parent_addr);
+      if (grub_fdtbus_is_mapping_valid (ret))
+	ret = (volatile char *) ret + offset;
+      return ret;
+    }
+  return grub_fdtbus_invalid_mapping;
+}
+
+volatile void *
+grub_fdtbus_map_reg (const struct grub_fdtbus_dev *dev, int regno, grub_size_t *size)
+{
+  grub_size_t address_cells, size_cells;
+  address_cells = get_address_cells (dev->parent);
+  size_cells = get_size_cells (dev->parent);
+  const grub_uint32_t *reg = grub_fdt_get_prop (dtb, dev->node, "reg", 0);
+  if (size && size_cells)
+    *size = reg[(address_cells + size_cells) * regno + address_cells];
+  if (size && !size_cells)
+    *size = 0;
+  return translate (dev->parent, reg + (address_cells + size_cells) * regno);
+}
+
+const char *
+grub_fdtbus_get_name (const struct grub_fdtbus_dev *dev)
+{
+  return grub_fdt_get_nodename (dtb, dev->node);
+}
+
+const void *
+grub_fdtbus_get_prop (const struct grub_fdtbus_dev *dev,
+		      const char *name,
+		      grub_uint32_t *len)
+{
+  return grub_fdt_get_prop (dtb, dev->node, name, len);
+}
+
+const void *
+grub_fdtbus_get_fdt (void)
+{
+  return dtb;
+}
diff --git a/grub-core/bus/spi/rk3288_spi.c b/grub-core/bus/spi/rk3288_spi.c
new file mode 100644
index 0000000000000000000000000000000000000000..aacb79ffef103bdbff1bb66dd70229b85b1e8030
--- /dev/null
+++ b/grub-core/bus/spi/rk3288_spi.c
@@ -0,0 +1,103 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *
+ *  Copyright (C) 2012  Google Inc.
+ *  Copyright (C) 2016  Free Software Foundation, Inc.
+ *
+ *  This is based on depthcharge code.
+ *
+ *  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/mm.h>
+#include <grub/time.h>
+#include <grub/misc.h>
+#include <grub/fdtbus.h>
+#include <grub/machine/kernel.h>
+
+static grub_err_t
+spi_send (const struct grub_fdtbus_dev *dev, const void *data, grub_size_t sz)
+{
+  const grub_uint8_t *ptr = data, *end = ptr + sz;
+  volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0);
+  spi[2] = 0;
+  spi[1] = sz - 1;
+  spi[0] = ((1 << 18) | spi[0]) & ~(1 << 19);
+  spi[2] = 1;
+  while (ptr < end)
+    {
+      while (spi[9] & 2);
+      spi[256] = *ptr++;
+    }
+  while (spi[9] & 1);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+spi_receive (const struct grub_fdtbus_dev *dev, void *data, grub_size_t sz)
+{
+  grub_uint8_t *ptr = data, *end = ptr + sz;
+  volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0);
+  spi[2] = 0;
+  spi[1] = sz - 1;
+  spi[0] = ((1 << 19) | spi[0]) & ~(1 << 18);
+  spi[2] = 1;
+  while (ptr < end)
+    {
+      while (spi[9] & 8);
+      *ptr++ = spi[512];
+    }
+  while (spi[9] & 1);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+spi_start (const struct grub_fdtbus_dev *dev)
+{
+  volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0);
+  spi[3] = 1;
+  return GRUB_ERR_NONE;
+}
+
+static void
+spi_stop (const struct grub_fdtbus_dev *dev)
+{
+  volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0);
+  spi[3] = 0;
+}
+
+static grub_err_t
+spi_attach(const struct grub_fdtbus_dev *dev)
+{
+  if (!grub_fdtbus_is_mapping_valid (grub_fdtbus_map_reg (dev, 0, 0)))
+    return GRUB_ERR_IO;
+
+  return GRUB_ERR_NONE;
+}
+
+static struct grub_fdtbus_driver spi =
+{
+  .compatible = "rockchip,rk3288-spi",
+  .attach = spi_attach,
+  .send = spi_send,
+  .receive = spi_receive,
+  .start = spi_start,
+  .stop = spi_stop,
+};
+
+void
+grub_rk3288_spi_init (void)
+{
+  grub_fdtbus_register (&spi);
+}
diff --git a/grub-core/bus/usb/ehci-fdt.c b/grub-core/bus/usb/ehci-fdt.c
new file mode 100644
index 0000000000000000000000000000000000000000..29b50bdd5c30d192cc3cba1d7f466a9bcf321d92
--- /dev/null
+++ b/grub-core/bus/usb/ehci-fdt.c
@@ -0,0 +1,45 @@
+/* ehci.c - EHCI Support.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2011  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/misc.h>
+#include <grub/mm.h>
+#include <grub/time.h>
+#include <grub/usb.h>
+#include <grub/fdtbus.h>
+
+static grub_err_t
+ehci_attach(const struct grub_fdtbus_dev *dev)
+{
+  grub_dprintf ("ehci", "Found generic-ehci\n");
+
+  grub_ehci_init_device (grub_fdtbus_map_reg (dev, 0, 0));
+  return 0;
+}
+
+struct grub_fdtbus_driver ehci =
+{
+  .compatible = "generic-ehci",
+  .attach = ehci_attach
+};
+
+void
+grub_ehci_pci_scan (void)
+{
+  grub_fdtbus_register (&ehci);
+}
diff --git a/grub-core/bus/usb/ehci-pci.c b/grub-core/bus/usb/ehci-pci.c
new file mode 100644
index 0000000000000000000000000000000000000000..65e6cb57438b7dfa35b80bbbe36a1e50629f025f
--- /dev/null
+++ b/grub-core/bus/usb/ehci-pci.c
@@ -0,0 +1,208 @@
+/* ehci.c - EHCI Support.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2011  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/pci.h>
+#include <grub/cpu/pci.h>
+#include <grub/cs5536.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/time.h>
+#include <grub/usb.h>
+
+#define GRUB_EHCI_PCI_SBRN_REG  0x60
+#define GRUB_EHCI_ADDR_MEM_MASK	(~0xff)
+
+/* USBLEGSUP bits and related OS OWNED byte offset */
+enum
+{
+  GRUB_EHCI_BIOS_OWNED = (1 << 16),
+  GRUB_EHCI_OS_OWNED = (1 << 24)
+};
+
+/* PCI iteration function... */
+static int
+grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
+		    void *data __attribute__ ((unused)))
+{
+  volatile grub_uint32_t *regs;
+  grub_uint32_t base, base_h;
+  grub_uint32_t eecp_offset;
+  grub_uint32_t usblegsup = 0;
+  grub_uint64_t maxtime;
+  grub_uint32_t interf;
+  grub_uint32_t subclass;
+  grub_uint32_t class;
+  grub_uint8_t release;
+  grub_uint32_t class_code;
+
+  grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: begin\n");
+
+  if (pciid == GRUB_CS5536_PCIID)
+    {
+      grub_uint64_t basereg;
+
+      basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE);
+      if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE))
+	{
+	  /* Shouldn't happen.  */
+	  grub_dprintf ("ehci", "No EHCI address is assigned\n");
+	  return 0;
+	}
+      base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK);
+      basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER;
+      basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED;
+      basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS;
+      basereg &= ~GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE;
+      grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE, basereg);
+    }
+  else
+    {
+      grub_pci_address_t addr;
+      addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
+      class_code = grub_pci_read (addr) >> 8;
+      interf = class_code & 0xFF;
+      subclass = (class_code >> 8) & 0xFF;
+      class = class_code >> 16;
+
+      /* If this is not an EHCI controller, just return.  */
+      if (class != 0x0c || subclass != 0x03 || interf != 0x20)
+	return 0;
+
+      grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: class OK\n");
+
+      /* Check Serial Bus Release Number */
+      addr = grub_pci_make_address (dev, GRUB_EHCI_PCI_SBRN_REG);
+      release = grub_pci_read_byte (addr);
+      if (release != 0x20)
+	{
+	  grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: Wrong SBRN: %0x\n",
+			release);
+	  return 0;
+	}
+      grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: bus rev. num. OK\n");
+  
+      /* Determine EHCI EHCC registers base address.  */
+      addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
+      base = grub_pci_read (addr);
+      addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
+      base_h = grub_pci_read (addr);
+      /* Stop if registers are mapped above 4G - GRUB does not currently
+       * work with registers mapped above 4G */
+      if (((base & GRUB_PCI_ADDR_MEM_TYPE_MASK) != GRUB_PCI_ADDR_MEM_TYPE_32)
+	  && (base_h != 0))
+	{
+	  grub_dprintf ("ehci",
+			"EHCI grub_ehci_pci_iter: registers above 4G are not supported\n");
+	  return 0;
+	}
+      base &= GRUB_PCI_ADDR_MEM_MASK;
+      if (!base)
+	{
+	  grub_dprintf ("ehci",
+			"EHCI: EHCI is not mapped\n");
+	  return 0;
+	}
+
+      /* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */
+      addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
+      grub_pci_write_word(addr,
+			  GRUB_PCI_COMMAND_MEM_ENABLED
+			  | GRUB_PCI_COMMAND_BUS_MASTER
+			  | grub_pci_read_word(addr));
+      
+      grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: 32-bit EHCI OK\n");
+    }
+
+  grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: iobase of EHCC: %08x\n",
+		(base & GRUB_EHCI_ADDR_MEM_MASK));
+
+  regs = grub_pci_device_map_range (dev,
+				    (base & GRUB_EHCI_ADDR_MEM_MASK),
+				    0x100);
+
+  /* Is there EECP ? */
+  eecp_offset = (grub_le_to_cpu32 (regs[2]) >> 8) & 0xff;
+
+    /* Determine and change ownership. */
+  /* EECP offset valid in HCCPARAMS */
+  /* Ownership can be changed via EECP only */
+  if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40)	
+    {
+      grub_pci_address_t pciaddr_eecp;
+      pciaddr_eecp = grub_pci_make_address (dev, eecp_offset);
+
+      usblegsup = grub_pci_read (pciaddr_eecp);
+      if (usblegsup & GRUB_EHCI_BIOS_OWNED)
+	{
+	  grub_boot_time ("Taking ownership of EHCI controller");
+	  grub_dprintf ("ehci",
+			"EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n");
+	  /* Ownership change - set OS_OWNED bit */
+	  grub_pci_write (pciaddr_eecp, usblegsup | GRUB_EHCI_OS_OWNED);
+	  /* Ensure PCI register is written */
+	  grub_pci_read (pciaddr_eecp);
+
+	  /* Wait for finish of ownership change, EHCI specification
+	   * doesn't say how long it can take... */
+	  maxtime = grub_get_time_ms () + 1000;
+	  while ((grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
+		 && (grub_get_time_ms () < maxtime));
+	  if (grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
+	    {
+	      grub_dprintf ("ehci",
+			    "EHCI grub_ehci_pci_iter: EHCI change ownership timeout");
+	      /* Change ownership in "hard way" - reset BIOS ownership */
+	      grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
+	      /* Ensure PCI register is written */
+	      grub_pci_read (pciaddr_eecp);
+	    }
+	}
+      else if (usblegsup & GRUB_EHCI_OS_OWNED)
+	/* XXX: What to do in this case - nothing ? Can it happen ? */
+	grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: OS\n");
+      else
+	{
+	  grub_dprintf ("ehci",
+			"EHCI grub_ehci_pci_iter: EHCI owned by: NONE\n");
+	  /* XXX: What to do in this case ? Can it happen ?
+	   * Is code below correct ? */
+	  /* Ownership change - set OS_OWNED bit */
+	  grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
+	  /* Ensure PCI register is written */
+	  grub_pci_read (pciaddr_eecp);
+	}
+
+      /* Disable SMI, just to be sure.  */
+      pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4);
+      grub_pci_write (pciaddr_eecp, 0);
+      /* Ensure PCI register is written */
+      grub_pci_read (pciaddr_eecp);
+    }
+
+  grub_dprintf ("ehci", "inithw: EHCI grub_ehci_pci_iter: ownership OK\n");
+
+  grub_ehci_init_device (regs);
+  return 0;
+}
+
+void
+grub_ehci_pci_scan (void)
+{
+  grub_pci_iterate (grub_ehci_pci_iter, NULL);
+}
diff --git a/grub-core/bus/usb/ehci.c b/grub-core/bus/usb/ehci.c
index 5f4297bb21ec4c28824abb0c442a87a3dd4a872e..d966fc21002602fab3f1b68668ddcb5bfa639442 100644
--- a/grub-core/bus/usb/ehci.c
+++ b/grub-core/bus/usb/ehci.c
@@ -22,13 +22,10 @@
 #include <grub/usb.h>
 #include <grub/usbtrans.h>
 #include <grub/misc.h>
-#include <grub/pci.h>
-#include <grub/cpu/pci.h>
-#include <grub/cpu/io.h>
 #include <grub/time.h>
 #include <grub/loader.h>
-#include <grub/cs5536.h>
 #include <grub/disk.h>
+#include <grub/dma.h>
 #include <grub/cache.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
@@ -39,8 +36,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
  *      - is not supporting interrupt transfers
  */
 
-#define GRUB_EHCI_PCI_SBRN_REG  0x60
-
 /* Capability registers offsets */
 enum
 {
@@ -54,7 +49,6 @@ enum
 #define GRUB_EHCI_EECP_MASK     (0xff << 8)
 #define GRUB_EHCI_EECP_SHIFT    8
 
-#define GRUB_EHCI_ADDR_MEM_MASK	(~0xff)
 #define GRUB_EHCI_POINTER_MASK	(~0x1f)
 
 /* Capability register SPARAMS bits */
@@ -85,13 +79,6 @@ enum
 
 #define GRUB_EHCI_QH_EMPTY 1
 
-/* USBLEGSUP bits and related OS OWNED byte offset */
-enum
-{
-  GRUB_EHCI_BIOS_OWNED = (1 << 16),
-  GRUB_EHCI_OS_OWNED = (1 << 24)
-};
-
 /* Operational registers offsets */
 enum
 {
@@ -455,9 +442,10 @@ grub_ehci_reset (struct grub_ehci *e)
 
   sync_all_caches (e);
 
+  grub_dprintf ("ehci", "reset\n");
+
   grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
-			  GRUB_EHCI_CMD_HC_RESET
-			  | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
+			  GRUB_EHCI_CMD_HC_RESET);
   /* Ensure command is written */
   grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
   /* XXX: How long time could take reset of HC ? */
@@ -473,116 +461,24 @@ grub_ehci_reset (struct grub_ehci *e)
 }
 
 /* PCI iteration function... */
-static int
-grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
-		    void *data __attribute__ ((unused)))
+void
+grub_ehci_init_device (volatile void *regs)
 {
-  grub_uint8_t release;
-  grub_uint32_t class_code;
-  grub_uint32_t interf;
-  grub_uint32_t subclass;
-  grub_uint32_t class;
-  grub_uint32_t base, base_h;
   struct grub_ehci *e;
-  grub_uint32_t eecp_offset;
   grub_uint32_t fp;
   int i;
-  grub_uint32_t usblegsup = 0;
-  grub_uint64_t maxtime;
   grub_uint32_t n_ports;
   grub_uint8_t caplen;
 
-  grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: begin\n");
-
-  if (pciid == GRUB_CS5536_PCIID)
-    {
-      grub_uint64_t basereg;
-
-      basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE);
-      if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE))
-	{
-	  /* Shouldn't happen.  */
-	  grub_dprintf ("ehci", "No EHCI address is assigned\n");
-	  return 0;
-	}
-      base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK);
-      basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER;
-      basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED;
-      basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS;
-      basereg &= ~GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE;
-      grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE, basereg);
-    }
-  else
-    {
-      grub_pci_address_t addr;
-      addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
-      class_code = grub_pci_read (addr) >> 8;
-      interf = class_code & 0xFF;
-      subclass = (class_code >> 8) & 0xFF;
-      class = class_code >> 16;
-
-      /* If this is not an EHCI controller, just return.  */
-      if (class != 0x0c || subclass != 0x03 || interf != 0x20)
-	return 0;
-
-      grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: class OK\n");
-
-      /* Check Serial Bus Release Number */
-      addr = grub_pci_make_address (dev, GRUB_EHCI_PCI_SBRN_REG);
-      release = grub_pci_read_byte (addr);
-      if (release != 0x20)
-	{
-	  grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: Wrong SBRN: %0x\n",
-			release);
-	  return 0;
-	}
-      grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: bus rev. num. OK\n");
-  
-      /* Determine EHCI EHCC registers base address.  */
-      addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
-      base = grub_pci_read (addr);
-      addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
-      base_h = grub_pci_read (addr);
-      /* Stop if registers are mapped above 4G - GRUB does not currently
-       * work with registers mapped above 4G */
-      if (((base & GRUB_PCI_ADDR_MEM_TYPE_MASK) != GRUB_PCI_ADDR_MEM_TYPE_32)
-	  && (base_h != 0))
-	{
-	  grub_dprintf ("ehci",
-			"EHCI grub_ehci_pci_iter: registers above 4G are not supported\n");
-	  return 0;
-	}
-      base &= GRUB_PCI_ADDR_MEM_MASK;
-      if (!base)
-	{
-	  grub_dprintf ("ehci",
-			"EHCI: EHCI is not mapped\n");
-	  return 0;
-	}
-
-      /* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */
-      addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
-      grub_pci_write_word(addr,
-			  GRUB_PCI_COMMAND_MEM_ENABLED
-			  | GRUB_PCI_COMMAND_BUS_MASTER
-			  | grub_pci_read_word(addr));
-      
-      grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: 32-bit EHCI OK\n");
-    }
-
   /* Allocate memory for the controller and fill basic values. */
   e = grub_zalloc (sizeof (*e));
   if (!e)
-    return 1;
+    return;
   e->framelist_chunk = NULL;
   e->td_chunk = NULL;
   e->qh_chunk = NULL;
-  e->iobase_ehcc = grub_pci_device_map_range (dev,
-					      (base & GRUB_EHCI_ADDR_MEM_MASK),
-					      0x100);
+  e->iobase_ehcc = regs;
 
-  grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: iobase of EHCC: %08x\n",
-		(base & GRUB_EHCI_ADDR_MEM_MASK));
   grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CAPLEN: %02x\n",
 		grub_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN));
   grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: VERSION: %04x\n",
@@ -598,7 +494,7 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
   if (caplen & (sizeof (grub_uint32_t) - 1))
     {
       grub_dprintf ("ehci", "Unaligned caplen\n");
-      return 0;
+      return;
     }
   e->iobase = ((volatile grub_uint32_t *) e->iobase_ehcc
 	       + (caplen / sizeof (grub_uint32_t)));
@@ -608,8 +504,8 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
 #endif
 
   grub_dprintf ("ehci",
-		"EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n",
-		(base & GRUB_EHCI_ADDR_MEM_MASK) + caplen);
+		"EHCI grub_ehci_pci_iter: iobase of oper. regs: %08llxx\n",
+		(unsigned long long) (grub_addr_t) e->iobase_ehcc + caplen);
   grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n",
 		grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
   grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n",
@@ -625,10 +521,6 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
   grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n",
 		grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG));
 
-  /* Is there EECP ? */
-  eecp_offset = (grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS)
-		 & GRUB_EHCI_EECP_MASK) >> GRUB_EHCI_EECP_SHIFT;
-
   /* Check format of data structures requested by EHCI */
   /* XXX: In fact it is not used at any place, it is prepared for future
    * This implementation uses 32-bits pointers only */
@@ -732,65 +624,6 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
 
   grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: QH/TD init. OK\n");
 
-  /* Determine and change ownership. */
-  /* EECP offset valid in HCCPARAMS */
-  /* Ownership can be changed via EECP only */
-  if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40)	
-    {
-      grub_pci_address_t pciaddr_eecp;
-      pciaddr_eecp = grub_pci_make_address (dev, eecp_offset);
-
-      usblegsup = grub_pci_read (pciaddr_eecp);
-      if (usblegsup & GRUB_EHCI_BIOS_OWNED)
-	{
-	  grub_boot_time ("Taking ownership of EHCI controller");
-	  grub_dprintf ("ehci",
-			"EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n");
-	  /* Ownership change - set OS_OWNED bit */
-	  grub_pci_write (pciaddr_eecp, usblegsup | GRUB_EHCI_OS_OWNED);
-	  /* Ensure PCI register is written */
-	  grub_pci_read (pciaddr_eecp);
-
-	  /* Wait for finish of ownership change, EHCI specification
-	   * doesn't say how long it can take... */
-	  maxtime = grub_get_time_ms () + 1000;
-	  while ((grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
-		 && (grub_get_time_ms () < maxtime));
-	  if (grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
-	    {
-	      grub_dprintf ("ehci",
-			    "EHCI grub_ehci_pci_iter: EHCI change ownership timeout");
-	      /* Change ownership in "hard way" - reset BIOS ownership */
-	      grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
-	      /* Ensure PCI register is written */
-	      grub_pci_read (pciaddr_eecp);
-	    }
-	}
-      else if (usblegsup & GRUB_EHCI_OS_OWNED)
-	/* XXX: What to do in this case - nothing ? Can it happen ? */
-	grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: OS\n");
-      else
-	{
-	  grub_dprintf ("ehci",
-			"EHCI grub_ehci_pci_iter: EHCI owned by: NONE\n");
-	  /* XXX: What to do in this case ? Can it happen ?
-	   * Is code below correct ? */
-	  /* Ownership change - set OS_OWNED bit */
-	  grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
-	  /* Ensure PCI register is written */
-	  grub_pci_read (pciaddr_eecp);
-	}
-
-    /* Disable SMI, just to be sure.  */
-    pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4);
-    grub_pci_write (pciaddr_eecp, 0);
-    /* Ensure PCI register is written */
-    grub_pci_read (pciaddr_eecp);
-
-    }
-
-  grub_dprintf ("ehci", "inithw: EHCI grub_ehci_pci_iter: ownership OK\n");
-
   /* Now we can setup EHCI (maybe...) */
 
   /* Check if EHCI is halted and halt it if not */
@@ -863,8 +696,8 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
   grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n");
 
   grub_dprintf ("ehci",
-		"EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n",
-		(base & GRUB_EHCI_ADDR_MEM_MASK));
+		"EHCI grub_ehci_pci_iter: iobase of oper. regs: %08llx\n",
+		(unsigned long long) (grub_addr_t) regs);
   grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n",
 		grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
   grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n",
@@ -880,7 +713,7 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
   grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n",
 		grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG));
 
-  return 0;
+  return;
 
 fail:
   if (e)
@@ -894,7 +727,7 @@ fail:
     }
   grub_free (e);
 
-  return 0;
+  return;
 }
 
 static int
@@ -1891,12 +1724,6 @@ grub_ehci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
     }
 }
 
-static void
-grub_ehci_inithw (void)
-{
-  grub_pci_iterate (grub_ehci_pci_iter, NULL);
-}
-
 static grub_err_t
 grub_ehci_restore_hw (void)
 {
@@ -1997,7 +1824,7 @@ GRUB_MOD_INIT (ehci)
   grub_stop_disk_firmware ();
 
   grub_boot_time ("Initing EHCI hardware");
-  grub_ehci_inithw ();
+  grub_ehci_pci_scan ();
   grub_boot_time ("Registering EHCI driver");
   grub_usb_controller_dev_register (&usb_controller);
   grub_boot_time ("EHCI driver registered");
diff --git a/grub-core/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c
index 9266e49311c4471d0915aebf9fae05509d0fa5c7..85f081fffb3a2aa7354816c79977ae45a79b1c80 100644
--- a/grub-core/bus/usb/usbtrans.c
+++ b/grub-core/bus/usb/usbtrans.c
@@ -18,7 +18,7 @@
  */
 
 #include <grub/dl.h>
-#include <grub/pci.h>
+#include <grub/dma.h>
 #include <grub/mm.h>
 #include <grub/misc.h>
 #include <grub/usb.h>
diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c
index d901c3892630f2500eda9822c712aae278017907..d1ce99af438914692d1b71b0017050689dd73db9 100644
--- a/grub-core/commands/efi/lsefi.c
+++ b/grub-core/commands/efi/lsefi.c
@@ -109,8 +109,10 @@ grub_cmd_lsefi (grub_command_t cmd __attribute__ ((unused)),
 
       status = efi_call_3 (grub_efi_system_table->boot_services->protocols_per_handle,
 			   handle, &protocols, &num_protocols);
-      if (status != GRUB_EFI_SUCCESS)
+      if (status != GRUB_EFI_SUCCESS) {
 	grub_printf ("Unable to retrieve protocols\n");
+	continue;
+      }
       for (j = 0; j < num_protocols; j++)
 	{
 	  for (k = 0; k < ARRAY_SIZE (known_protocols); k++)
diff --git a/grub-core/commands/file.c b/grub-core/commands/file.c
index 12fba99e06a23cb72af67fc4bfb758d97bfa0e67..3ff6d5522d2d572c2af16fec371faeb8e4b28f9d 100644
--- a/grub-core/commands/file.c
+++ b/grub-core/commands/file.c
@@ -27,6 +27,8 @@
 #include <grub/elf.h>
 #include <grub/xen_file.h>
 #include <grub/efi/pe32.h>
+#include <grub/arm/linux.h>
+#include <grub/arm64/linux.h>
 #include <grub/i386/linux.h>
 #include <grub/xnu.h>
 #include <grub/machoload.h>
@@ -383,21 +385,19 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
       }
     case IS_ARM_LINUX:
       {
-	grub_uint32_t sig, sig_pi;
-	if (grub_file_read (file, &sig_pi, 4) != 4)
+	struct linux_arm_kernel_header lh;
+
+	if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
 	  break;
-	/* Raspberry pi.  */
-	if (sig_pi == grub_cpu_to_le32_compile_time (0xea000006))
+	/* Short forward branch in A32 state (for Raspberry pi kernels). */
+	if (lh.code0 == grub_cpu_to_le32_compile_time (0xea000006))
 	  {
 	    ret = 1;
 	    break;
 	  }
 
-	if (grub_file_seek (file, 0x24) == (grub_size_t) -1)
-	  break;
-	if (grub_file_read (file, &sig, 4) != 4)
-	  break;
-	if (sig == grub_cpu_to_le32_compile_time (0x016f2818))
+	if (lh.magic ==
+	    grub_cpu_to_le32_compile_time (GRUB_LINUX_ARM_MAGIC_SIGNATURE))
 	  {
 	    ret = 1;
 	    break;
@@ -406,13 +406,13 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
       }
     case IS_ARM64_LINUX:
       {
-	grub_uint32_t sig;
+	struct linux_arm64_kernel_header lh;
 
-	if (grub_file_seek (file, 0x38) == (grub_size_t) -1)
+	if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
 	  break;
-	if (grub_file_read (file, &sig, 4) != 4)
-	  break;
-	if (sig == grub_cpu_to_le32_compile_time (0x644d5241))
+
+	if (lh.magic ==
+	    grub_cpu_to_le32_compile_time (GRUB_LINUX_ARM64_MAGIC_SIGNATURE))
 	  {
 	    ret = 1;
 	    break;
@@ -497,7 +497,7 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
     case IS_X86_LINUX32:
     case IS_X86_LINUX:
       {
-	struct linux_kernel_header lh;
+	struct linux_i386_kernel_header lh;
 	if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
 	  break;
 	if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
@@ -508,7 +508,7 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
 
 	/* FIXME: some really old kernels (< 1.3.73) will fail this.  */
 	if (lh.header !=
-	    grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+	    grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
 	    || grub_le_to_cpu16 (lh.version) < 0x0200)
 	  break;
 
@@ -521,7 +521,7 @@ grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args)
 	/* 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_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+	    grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
 	    || grub_le_to_cpu16 (lh.version) < 0x0203)
 	  break;
 
diff --git a/grub-core/commands/i386/coreboot/cb_timestamps.c b/grub-core/commands/i386/coreboot/cb_timestamps.c
index e72f38d6e057dccfb981d6bbc483d2bdd8a06c98..e97ea6bed98b42d4f03f06ab5bc076fadbfee67f 100644
--- a/grub-core/commands/i386/coreboot/cb_timestamps.c
+++ b/grub-core/commands/i386/coreboot/cb_timestamps.c
@@ -20,7 +20,7 @@
 #include <grub/misc.h>
 #include <grub/command.h>
 #include <grub/i18n.h>
-#include <grub/i386/coreboot/lbio.h>
+#include <grub/coreboot/lbio.h>
 #include <grub/i386/tsc.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
diff --git a/grub-core/commands/i386/coreboot/cbls.c b/grub-core/commands/i386/coreboot/cbls.c
index e0a10596fe279331cca94172e1f452fdfe18394f..102291f424ab782c6cd3bcd4ae1effd836cd832e 100644
--- a/grub-core/commands/i386/coreboot/cbls.c
+++ b/grub-core/commands/i386/coreboot/cbls.c
@@ -20,7 +20,7 @@
 #include <grub/misc.h>
 #include <grub/command.h>
 #include <grub/i18n.h>
-#include <grub/i386/coreboot/lbio.h>
+#include <grub/coreboot/lbio.h>
 #include <grub/i386/tsc.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
diff --git a/grub-core/commands/keylayouts.c b/grub-core/commands/keylayouts.c
index f4b7730208ab8ffafb1b0283294a140248839d7a..f35d3a369bad7125cb04e25f0e32c01c00c673b0 100644
--- a/grub-core/commands/keylayouts.c
+++ b/grub-core/commands/keylayouts.c
@@ -40,7 +40,7 @@ static struct grub_keyboard_layout layout_us = {
     /* 0x10 */ 'm',  'n',  'o',  'p',  'q', 'r', 's', 't',
     /* 0x18 */ 'u',  'v',  'w',  'x',  'y', 'z', '1', '2',
     /* 0x20 */ '3',  '4',  '5',  '6',  '7', '8', '9', '0',
-    /* 0x28 */ '\n', '\e', '\b', '\t', ' ', '-', '=', '[',
+    /* 0x28 */ '\n', GRUB_TERM_ESC, GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, ' ', '-', '=', '[',
     /* According to usage table 0x31 should be mapped to '/'
        but testing with real keyboard shows that 0x32 is remapped to '/'.
        Map 0x31 to 0. 
@@ -82,8 +82,8 @@ static struct grub_keyboard_layout layout_us = {
     /* 0x10 */ 'M',  'N',  'O',  'P',  'Q', 'R', 'S', 'T',
     /* 0x18 */ 'U',  'V',  'W',  'X',  'Y', 'Z', '!', '@',
     /* 0x20 */ '#',  '$',  '%',  '^',  '&', '*', '(', ')',
-    /* 0x28 */ '\n' | GRUB_TERM_SHIFT, '\e' | GRUB_TERM_SHIFT, 
-    /* 0x2a */ '\b' | GRUB_TERM_SHIFT, '\t' | GRUB_TERM_SHIFT, 
+    /* 0x28 */ '\n' | GRUB_TERM_SHIFT, GRUB_TERM_ESC | GRUB_TERM_SHIFT,
+    /* 0x2a */ GRUB_TERM_BACKSPACE | GRUB_TERM_SHIFT, GRUB_TERM_TAB | GRUB_TERM_SHIFT,
     /* 0x2c */ ' '  | GRUB_TERM_SHIFT,  '_', '+', '{',
     /* According to usage table 0x31 should be mapped to '/'
        but testing with real keyboard shows that 0x32 is remapped to '/'.
diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c
index 0eaf836527944ba69d499050ad080f919d3e57ef..c25161cc4f2c6d4fce6781bfac9bf7796fceb0c7 100644
--- a/grub-core/commands/ls.c
+++ b/grub-core/commands/ls.c
@@ -201,6 +201,15 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
       if (grub_errno == GRUB_ERR_UNKNOWN_FS)
 	grub_errno = GRUB_ERR_NONE;
 
+#ifdef GRUB_MACHINE_IEEE1275
+      /*
+       * Close device to prevent a double open in grub_normal_print_device_info().
+       * Otherwise it may lead to hangs on some IEEE 1275 platforms.
+       */
+      grub_device_close (dev);
+      dev = NULL;
+#endif
+
       grub_normal_print_device_info (device_name);
     }
   else if (fs)
diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c
index 58d4dadf6ee4ec392a09d433802803520704cd7b..2c5363da7f549b85ae04d1d88a78db0b85504c51 100644
--- a/grub-core/commands/menuentry.c
+++ b/grub-core/commands/menuentry.c
@@ -52,8 +52,8 @@ static struct
   int key;
 } hotkey_aliases[] =
   {
-    {"backspace", '\b'},
-    {"tab", '\t'},
+    {"backspace", GRUB_TERM_BACKSPACE},
+    {"tab", GRUB_TERM_TAB},
     {"delete", GRUB_TERM_KEY_DC},
     {"insert", GRUB_TERM_KEY_INSERT},
     {"f1", GRUB_TERM_KEY_F1},
diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c
index 494a1b7734ef44fef6e887f62b6eb30d0a494284..f2f606423aca4f842f5b16b797a1084cc5791cbb 100644
--- a/grub-core/disk/ahci.c
+++ b/grub-core/disk/ahci.c
@@ -82,6 +82,20 @@ enum grub_ahci_hba_port_command
     GRUB_AHCI_HBA_PORT_CMD_FR = 0x4000,
   };
 
+enum grub_ahci_hba_port_int_status
+  {
+    GRUB_AHCI_HBA_PORT_IS_IFS  = (1UL << 27),
+    GRUB_AHCI_HBA_PORT_IS_HBDS = (1UL << 28),
+    GRUB_AHCI_HBA_PORT_IS_HBFS = (1UL << 29),
+    GRUB_AHCI_HBA_PORT_IS_TFES = (1UL << 30),
+  };
+
+#define GRUB_AHCI_HBA_PORT_IS_FATAL_MASK ( \
+	GRUB_AHCI_HBA_PORT_IS_IFS | \
+	GRUB_AHCI_HBA_PORT_IS_HBDS | \
+	GRUB_AHCI_HBA_PORT_IS_HBFS | \
+	GRUB_AHCI_HBA_PORT_IS_TFES)
+
 struct grub_ahci_hba
 {
   grub_uint32_t cap;
@@ -1026,7 +1040,8 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
 
   endtime = grub_get_time_ms () + (spinup ? 20000 : 20000);
   while ((dev->hba->ports[dev->port].command_issue & 1))
-    if (grub_get_time_ms () > endtime)
+    if (grub_get_time_ms () > endtime ||
+	(dev->hba->ports[dev->port].intstatus & GRUB_AHCI_HBA_PORT_IS_FATAL_MASK))
       {
 	grub_dprintf ("ahci", "AHCI status <%x %x %x %x>\n",
 		      dev->hba->ports[dev->port].command_issue,
@@ -1034,7 +1049,10 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
 		      dev->hba->ports[dev->port].intstatus,
 		      dev->hba->ports[dev->port].task_file_data);
 	dev->hba->ports[dev->port].command_issue = 0;
-	err = grub_error (GRUB_ERR_IO, "AHCI transfer timed out");
+	if (dev->hba->ports[dev->port].intstatus & GRUB_AHCI_HBA_PORT_IS_FATAL_MASK)
+	  err = grub_error (GRUB_ERR_IO, "AHCI transfer error");
+	else
+	  err = grub_error (GRUB_ERR_IO, "AHCI transfer timed out");
 	if (!reset)
 	  grub_ahci_reset_port (dev, 1);
 	break;
diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
index 0f978ad05079c9535d7ef9bb16462c7d7adeb80e..2a22d2d6c1c3121ec889f33f2aaaf3077723a6c1 100644
--- a/grub-core/disk/ldm.c
+++ b/grub-core/disk/ldm.c
@@ -135,7 +135,7 @@ msdos_has_ldm_partition (grub_disk_t dsk)
   return has_ldm;
 }
 
-static const grub_gpt_part_type_t ldm_type = GRUB_GPT_PARTITION_TYPE_LDM;
+static const grub_gpt_part_guid_t ldm_type = GRUB_GPT_PARTITION_TYPE_LDM;
 
 /* Helper for gpt_ldm_sector.  */
 static int
diff --git a/grub-core/efiemu/i386/loadcore64.c b/grub-core/efiemu/i386/loadcore64.c
index e49d0b6ff17e02e22e09b306d0a6a32a3b083b78..18facf47fd7678007deb730fb71256edff6292ad 100644
--- a/grub-core/efiemu/i386/loadcore64.c
+++ b/grub-core/efiemu/i386/loadcore64.c
@@ -98,6 +98,7 @@ grub_arch_efiemu_relocate_symbols64 (grub_efiemu_segment_t segs,
 		    break;
 
 		  case R_X86_64_PC32:
+		  case R_X86_64_PLT32:
 		    err = grub_efiemu_write_value (addr,
 						   *addr32 + rel->r_addend
 						   + sym.off
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 4849c1ceb6533c1b19eb64d754d45d44282b5acb..be195448dbeb55abcfb117723cd2fc6d75e6e344 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -175,7 +175,7 @@ struct grub_btrfs_time
 {
   grub_int64_t sec;
   grub_uint32_t nanosec;
-} __attribute__ ((aligned (4)));
+} GRUB_PACKED;
 
 struct grub_btrfs_inode
 {
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
index cdce63bcc9d57e82b7a4f6a644803a1d8320935d..b8ad75a0ff7c4f72b67bef123510d99231531daf 100644
--- a/grub-core/fs/ext2.c
+++ b/grub-core/fs/ext2.c
@@ -102,6 +102,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
 #define EXT4_FEATURE_INCOMPAT_64BIT		0x0080
 #define EXT4_FEATURE_INCOMPAT_MMP		0x0100
 #define EXT4_FEATURE_INCOMPAT_FLEX_BG		0x0200
+#define EXT4_FEATURE_INCOMPAT_ENCRYPT          0x10000
 
 /* The set of back-incompatible features this driver DOES support. Add (OR)
  * flags here as the related features are implemented into the driver.  */
@@ -109,7 +110,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
                                        | EXT4_FEATURE_INCOMPAT_EXTENTS  \
                                        | EXT4_FEATURE_INCOMPAT_FLEX_BG \
                                        | EXT2_FEATURE_INCOMPAT_META_BG \
-                                       | EXT4_FEATURE_INCOMPAT_64BIT)
+                                       | EXT4_FEATURE_INCOMPAT_64BIT \
+                                       | EXT4_FEATURE_INCOMPAT_ENCRYPT)
 /* List of rationales for the ignored "incompatible" features:
  * needs_recovery: Not really back-incompatible - was added as such to forbid
  *                 ext2 drivers from mounting an ext3 volume with a dirty
@@ -138,6 +140,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
 #define EXT3_JOURNAL_FLAG_DELETED	4
 #define EXT3_JOURNAL_FLAG_LAST_TAG	8
 
+#define EXT4_ENCRYPT_FLAG              0x800
 #define EXT4_EXTENTS_FLAG		0x80000
 
 /* The ext2 superblock.  */
@@ -706,6 +709,12 @@ grub_ext2_read_symlink (grub_fshelp_node_t node)
       grub_ext2_read_inode (diro->data, diro->ino, &diro->inode);
       if (grub_errno)
 	return 0;
+
+      if (diro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG))
+       {
+         grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "symlink is encrypted");
+         return 0;
+       }
     }
 
   symlink = grub_malloc (grub_le_to_cpu32 (diro->inode.size) + 1);
@@ -749,6 +758,12 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir,
 	return 0;
     }
 
+  if (diro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG))
+    {
+      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "directory is encrypted");
+      return 0;
+    }
+
   /* Search the file.  */
   while (fpos < grub_le_to_cpu32 (diro->inode.size))
     {
@@ -859,6 +874,12 @@ grub_ext2_open (struct grub_file *file, const char *name)
 	goto fail;
     }
 
+  if (fdiro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG))
+    {
+      err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "file is encrypted");
+      goto fail;
+    }
+
   grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_ext2_inode));
   grub_free (fdiro);
 
diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
new file mode 100644
index 0000000000000000000000000000000000000000..1cad2615f3c9e65e57a12d18b76f4ecc1caa31d8
--- /dev/null
+++ b/grub-core/fs/f2fs.c
@@ -0,0 +1,1314 @@
+/*
+ *  f2fs.c - Flash-Friendly File System
+ *
+ *  Written by Jaegeuk Kim <jaegeuk@kernel.org>
+ *
+ *  Copyright (C) 2015  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/file.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/types.h>
+#include <grub/charset.h>
+#include <grub/fshelp.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+/* F2FS Magic Number. */
+#define F2FS_SUPER_MAGIC          0xf2f52010
+
+#define CHECKSUM_OFFSET           4092  /* Must be aligned 4 bytes. */
+#define U32_CHECKSUM_OFFSET       (CHECKSUM_OFFSET >> 2)
+#define CRCPOLY_LE                0xedb88320
+
+/* Byte-size offset. */
+#define F2FS_SUPER_OFFSET         ((grub_disk_addr_t)1024)
+#define F2FS_SUPER_OFFSET0        (F2FS_SUPER_OFFSET >> GRUB_DISK_SECTOR_BITS)
+#define F2FS_SUPER_OFFSET1        ((F2FS_SUPER_OFFSET + F2FS_BLKSIZE) >> \
+                                        GRUB_DISK_SECTOR_BITS)
+
+/* 9 bits for 512 bytes. */
+#define F2FS_MIN_LOG_SECTOR_SIZE  9
+
+/* Support only 4KB block. */
+#define F2FS_BLK_BITS             12
+#define F2FS_BLKSIZE              (1 << F2FS_BLK_BITS)
+#define F2FS_BLK_SEC_BITS         (F2FS_BLK_BITS - GRUB_DISK_SECTOR_BITS)
+
+#define VERSION_LEN               256
+#define F2FS_MAX_EXTENSION        64
+
+#define CP_COMPACT_SUM_FLAG       0x00000004
+#define CP_UMOUNT_FLAG            0x00000001
+
+#define MAX_ACTIVE_LOGS           16
+#define MAX_ACTIVE_NODE_LOGS      8
+#define MAX_ACTIVE_DATA_LOGS      8
+#define NR_CURSEG_DATA_TYPE       3
+#define NR_CURSEG_NODE_TYPE       3
+#define NR_CURSEG_TYPE            (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
+
+#define ENTRIES_IN_SUM            512
+#define SUMMARY_SIZE              7
+#define SUM_FOOTER_SIZE           5
+#define JENTRY_SIZE               (sizeof(struct grub_f2fs_nat_jent))
+#define SUM_ENTRIES_SIZE          (SUMMARY_SIZE * ENTRIES_IN_SUM)
+#define SUM_JOURNAL_SIZE          (F2FS_BLKSIZE - SUM_FOOTER_SIZE - SUM_ENTRIES_SIZE)
+#define NAT_JOURNAL_ENTRIES       ((SUM_JOURNAL_SIZE - 2) / JENTRY_SIZE)
+#define NAT_JOURNAL_RESERVED      ((SUM_JOURNAL_SIZE - 2) % JENTRY_SIZE)
+
+#define NAT_ENTRY_SIZE            (sizeof(struct grub_f2fs_nat_entry))
+#define NAT_ENTRY_PER_BLOCK       (F2FS_BLKSIZE / NAT_ENTRY_SIZE)
+
+#define F2FS_NAME_LEN             255
+#define F2FS_SLOT_LEN             8
+#define NR_DENTRY_IN_BLOCK        214
+#define SIZE_OF_DIR_ENTRY         11    /* By byte. */
+#define BITS_PER_BYTE             8
+#define SIZE_OF_DENTRY_BITMAP     ((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \
+                                        BITS_PER_BYTE)
+#define SIZE_OF_RESERVED          (F2FS_BLKSIZE - \
+                                        ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
+                                        NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP))
+
+#define F2FS_INLINE_XATTR_ADDRS   50    /* 200 bytes for inline xattrs. */
+#define DEF_ADDRS_PER_INODE       923   /* Address Pointers in an Inode. */
+
+#define ADDRS_PER_BLOCK           1018  /* Address Pointers in a Direct Block. */
+#define NIDS_PER_BLOCK            1018  /* Node IDs in an Indirect Block. */
+#define NODE_DIR1_BLOCK           (DEF_ADDRS_PER_INODE + 1)
+#define NODE_DIR2_BLOCK           (DEF_ADDRS_PER_INODE + 2)
+#define NODE_IND1_BLOCK           (DEF_ADDRS_PER_INODE + 3)
+#define NODE_IND2_BLOCK           (DEF_ADDRS_PER_INODE + 4)
+#define NODE_DIND_BLOCK           (DEF_ADDRS_PER_INODE + 5)
+
+#define MAX_INLINE_DATA           (4 * (DEF_ADDRS_PER_INODE - \
+                                        F2FS_INLINE_XATTR_ADDRS - 1))
+#define NR_INLINE_DENTRY          (MAX_INLINE_DATA * BITS_PER_BYTE / \
+                                        ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
+                                        BITS_PER_BYTE + 1))
+#define INLINE_DENTRY_BITMAP_SIZE ((NR_INLINE_DENTRY + BITS_PER_BYTE - 1) / \
+                                        BITS_PER_BYTE)
+#define INLINE_RESERVED_SIZE      (MAX_INLINE_DATA - \
+                                        ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \
+                                        NR_INLINE_DENTRY + \
+                                        INLINE_DENTRY_BITMAP_SIZE))
+#define CURSEG_HOT_DATA           0
+
+#define CKPT_FLAG_SET(ckpt, f)    (ckpt)->ckpt_flags & \
+                                        grub_cpu_to_le32_compile_time (f)
+
+#define F2FS_INLINE_XATTR         0x01  /* File inline xattr flag. */
+#define F2FS_INLINE_DATA          0x02  /* File inline data flag. */
+#define F2FS_INLINE_DENTRY        0x04  /* File inline dentry flag. */
+#define F2FS_DATA_EXIST           0x08  /* File inline data exist flag. */
+#define F2FS_INLINE_DOTS          0x10  /* File having implicit dot dentries. */
+
+#define MAX_VOLUME_NAME           512
+
+enum FILE_TYPE
+{
+  F2FS_FT_UNKNOWN,
+  F2FS_FT_REG_FILE                = 1,
+  F2FS_FT_DIR                     = 2,
+  F2FS_FT_SYMLINK                 = 7
+};
+
+struct grub_f2fs_superblock
+{
+  grub_uint32_t                   magic;
+  grub_uint16_t                   dummy1[2];
+  grub_uint32_t                   log_sectorsize;
+  grub_uint32_t                   log_sectors_per_block;
+  grub_uint32_t                   log_blocksize;
+  grub_uint32_t                   log_blocks_per_seg;
+  grub_uint32_t                   segs_per_sec;
+  grub_uint32_t                   secs_per_zone;
+  grub_uint32_t                   checksum_offset;
+  grub_uint8_t                    dummy2[40];
+  grub_uint32_t                   cp_blkaddr;
+  grub_uint32_t                   sit_blkaddr;
+  grub_uint32_t                   nat_blkaddr;
+  grub_uint32_t                   ssa_blkaddr;
+  grub_uint32_t                   main_blkaddr;
+  grub_uint32_t                   root_ino;
+  grub_uint32_t                   node_ino;
+  grub_uint32_t                   meta_ino;
+  grub_uint8_t                    uuid[16];
+  grub_uint16_t                   volume_name[MAX_VOLUME_NAME];
+  grub_uint32_t                   extension_count;
+  grub_uint8_t                    extension_list[F2FS_MAX_EXTENSION][8];
+  grub_uint32_t                   cp_payload;
+  grub_uint8_t                    version[VERSION_LEN];
+  grub_uint8_t                    init_version[VERSION_LEN];
+} GRUB_PACKED;
+
+struct grub_f2fs_checkpoint
+{
+  grub_uint64_t                   checkpoint_ver;
+  grub_uint64_t                   user_block_count;
+  grub_uint64_t                   valid_block_count;
+  grub_uint32_t                   rsvd_segment_count;
+  grub_uint32_t                   overprov_segment_count;
+  grub_uint32_t                   free_segment_count;
+  grub_uint32_t                   cur_node_segno[MAX_ACTIVE_NODE_LOGS];
+  grub_uint16_t                   cur_node_blkoff[MAX_ACTIVE_NODE_LOGS];
+  grub_uint32_t                   cur_data_segno[MAX_ACTIVE_DATA_LOGS];
+  grub_uint16_t                   cur_data_blkoff[MAX_ACTIVE_DATA_LOGS];
+  grub_uint32_t                   ckpt_flags;
+  grub_uint32_t                   cp_pack_total_block_count;
+  grub_uint32_t                   cp_pack_start_sum;
+  grub_uint32_t                   valid_node_count;
+  grub_uint32_t                   valid_inode_count;
+  grub_uint32_t                   next_free_nid;
+  grub_uint32_t                   sit_ver_bitmap_bytesize;
+  grub_uint32_t                   nat_ver_bitmap_bytesize;
+  grub_uint32_t                   checksum_offset;
+  grub_uint64_t                   elapsed_time;
+  grub_uint8_t                    alloc_type[MAX_ACTIVE_LOGS];
+  grub_uint8_t                    sit_nat_version_bitmap[3900];
+  grub_uint32_t                   checksum;
+} GRUB_PACKED;
+
+struct grub_f2fs_nat_entry {
+  grub_uint8_t                    version;
+  grub_uint32_t                   ino;
+  grub_uint32_t                   block_addr;
+} GRUB_PACKED;
+
+struct grub_f2fs_nat_jent
+{
+  grub_uint32_t                   nid;
+  struct grub_f2fs_nat_entry      ne;
+} GRUB_PACKED;
+
+struct grub_f2fs_nat_journal {
+  grub_uint16_t                   n_nats;
+  struct grub_f2fs_nat_jent       entries[NAT_JOURNAL_ENTRIES];
+  grub_uint8_t                    reserved[NAT_JOURNAL_RESERVED];
+} GRUB_PACKED;
+
+struct grub_f2fs_nat_block {
+  struct grub_f2fs_nat_entry      ne[NAT_ENTRY_PER_BLOCK];
+} GRUB_PACKED;
+
+struct grub_f2fs_dir_entry
+{
+  grub_uint32_t                   hash_code;
+  grub_uint32_t                   ino;
+  grub_uint16_t                   name_len;
+  grub_uint8_t                    file_type;
+} GRUB_PACKED;
+
+struct grub_f2fs_inline_dentry
+{
+  grub_uint8_t                    dentry_bitmap[INLINE_DENTRY_BITMAP_SIZE];
+  grub_uint8_t                    reserved[INLINE_RESERVED_SIZE];
+  struct grub_f2fs_dir_entry      dentry[NR_INLINE_DENTRY];
+  grub_uint8_t                    filename[NR_INLINE_DENTRY][F2FS_SLOT_LEN];
+} GRUB_PACKED;
+
+struct grub_f2fs_dentry_block {
+  grub_uint8_t                    dentry_bitmap[SIZE_OF_DENTRY_BITMAP];
+  grub_uint8_t                    reserved[SIZE_OF_RESERVED];
+  struct grub_f2fs_dir_entry      dentry[NR_DENTRY_IN_BLOCK];
+  grub_uint8_t                    filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN];
+} GRUB_PACKED;
+
+struct grub_f2fs_inode
+{
+  grub_uint16_t                   i_mode;
+  grub_uint8_t                    i_advise;
+  grub_uint8_t                    i_inline;
+  grub_uint32_t                   i_uid;
+  grub_uint32_t                   i_gid;
+  grub_uint32_t                   i_links;
+  grub_uint64_t                   i_size;
+  grub_uint64_t                   i_blocks;
+  grub_uint64_t                   i_atime;
+  grub_uint64_t                   i_ctime;
+  grub_uint64_t                   i_mtime;
+  grub_uint32_t                   i_atime_nsec;
+  grub_uint32_t                   i_ctime_nsec;
+  grub_uint32_t                   i_mtime_nsec;
+  grub_uint32_t                   i_generation;
+  grub_uint32_t                   i_current_depth;
+  grub_uint32_t                   i_xattr_nid;
+  grub_uint32_t                   i_flags;
+  grub_uint32_t                   i_pino;
+  grub_uint32_t                   i_namelen;
+  grub_uint8_t                    i_name[F2FS_NAME_LEN];
+  grub_uint8_t                    i_dir_level;
+  grub_uint8_t                    i_ext[12];
+  grub_uint32_t                   i_addr[DEF_ADDRS_PER_INODE];
+  grub_uint32_t                   i_nid[5];
+} GRUB_PACKED;
+
+struct grub_direct_node {
+  grub_uint32_t                   addr[ADDRS_PER_BLOCK];
+} GRUB_PACKED;
+
+struct grub_indirect_node {
+  grub_uint32_t                   nid[NIDS_PER_BLOCK];
+} GRUB_PACKED;
+
+struct grub_f2fs_node
+{
+  union
+  {
+    struct grub_f2fs_inode        i;
+    struct grub_direct_node       dn;
+    struct grub_indirect_node     in;
+    /* Should occupy F2FS_BLKSIZE totally. */
+    char                          buf[F2FS_BLKSIZE - 40];
+  };
+  grub_uint8_t                    dummy[40];
+} GRUB_PACKED;
+
+struct grub_fshelp_node
+{
+  struct grub_f2fs_data           *data;
+  struct grub_f2fs_node           inode;
+  grub_uint32_t                   ino;
+  int inode_read;
+};
+
+struct grub_f2fs_data
+{
+  struct grub_f2fs_superblock     sblock;
+  struct grub_f2fs_checkpoint     ckpt;
+
+  grub_uint32_t                   root_ino;
+  grub_uint32_t                   blocks_per_seg;
+  grub_uint32_t                   cp_blkaddr;
+  grub_uint32_t                   nat_blkaddr;
+
+  struct grub_f2fs_nat_journal    nat_j;
+  char                            *nat_bitmap;
+
+  grub_disk_t                     disk;
+  struct grub_f2fs_node           *inode;
+  struct grub_fshelp_node         diropen;
+};
+
+struct grub_f2fs_dir_iter_ctx
+{
+  struct grub_f2fs_data           *data;
+  grub_fshelp_iterate_dir_hook_t  hook;
+  void                            *hook_data;
+  grub_uint8_t                    *bitmap;
+  grub_uint8_t                    (*filename)[F2FS_SLOT_LEN];
+  struct grub_f2fs_dir_entry      *dentry;
+  int                             max;
+};
+
+struct grub_f2fs_dir_ctx
+{
+  grub_fs_dir_hook_t              hook;
+  void                            *hook_data;
+  struct grub_f2fs_data           *data;
+};
+
+static grub_dl_t my_mod;
+
+static int
+grub_f2fs_test_bit_le (int nr, const grub_uint8_t *addr)
+{
+  return addr[nr >> 3] & (1 << (nr & 7));
+}
+
+static char *
+get_inline_addr (struct grub_f2fs_inode *inode)
+{
+  return (char *) &inode->i_addr[1];
+}
+
+static grub_uint64_t
+grub_f2fs_file_size (struct grub_f2fs_inode *inode)
+{
+  return grub_le_to_cpu64 (inode->i_size);
+}
+
+static grub_uint32_t
+start_cp_addr (struct grub_f2fs_data *data)
+{
+  struct grub_f2fs_checkpoint *ckpt = &data->ckpt;
+  grub_uint32_t start_addr = data->cp_blkaddr;
+
+  if (!(ckpt->checkpoint_ver & grub_cpu_to_le64_compile_time(1)))
+    return start_addr + data->blocks_per_seg;
+
+  return start_addr;
+}
+
+static grub_uint32_t
+start_sum_block (struct grub_f2fs_data *data)
+{
+  struct grub_f2fs_checkpoint *ckpt = &data->ckpt;
+
+  return start_cp_addr (data) + grub_le_to_cpu32 (ckpt->cp_pack_start_sum);
+}
+
+static grub_uint32_t
+sum_blk_addr (struct grub_f2fs_data *data, int base, int type)
+{
+  struct grub_f2fs_checkpoint *ckpt = &data->ckpt;
+
+  return start_cp_addr (data) +
+           grub_le_to_cpu32 (ckpt->cp_pack_total_block_count) -
+           (base + 1) + type;
+}
+
+static void *
+nat_bitmap_ptr (struct grub_f2fs_data *data)
+{
+  struct grub_f2fs_checkpoint *ckpt = &data->ckpt;
+  grub_uint32_t offset;
+
+  if (grub_le_to_cpu32 (data->sblock.cp_payload) > 0)
+    return ckpt->sit_nat_version_bitmap;
+
+  offset = grub_le_to_cpu32 (ckpt->sit_ver_bitmap_bytesize);
+
+  return ckpt->sit_nat_version_bitmap + offset;
+}
+
+static grub_uint32_t
+get_node_id (struct grub_f2fs_node *rn, int off, int inode_block)
+{
+  if (inode_block)
+    return grub_le_to_cpu32 (rn->i.i_nid[off - NODE_DIR1_BLOCK]);
+
+  return grub_le_to_cpu32 (rn->in.nid[off]);
+}
+
+static grub_err_t
+grub_f2fs_block_read (struct grub_f2fs_data *data, grub_uint32_t blkaddr,
+                      void *buf)
+{
+  return grub_disk_read (data->disk,
+                         ((grub_disk_addr_t)blkaddr) << F2FS_BLK_SEC_BITS,
+                         0, F2FS_BLKSIZE, buf);
+}
+
+/* CRC32 */
+static grub_uint32_t
+grub_f2fs_cal_crc32 (const void *buf, const grub_uint32_t len)
+{
+  grub_uint32_t crc = F2FS_SUPER_MAGIC;
+  unsigned char *p = (unsigned char *)buf;
+  grub_uint32_t tmp = len;
+  int i;
+
+  while (tmp--)
+    {
+      crc ^= *p++;
+      for (i = 0; i < 8; i++)
+        crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
+    }
+
+  return crc;
+}
+
+static int
+grub_f2fs_crc_valid (grub_uint32_t blk_crc, void *buf, const grub_uint32_t len)
+{
+  grub_uint32_t cal_crc = 0;
+
+  cal_crc = grub_f2fs_cal_crc32 (buf, len);
+
+  return (cal_crc == blk_crc) ? 1 : 0;
+}
+
+static int
+grub_f2fs_test_bit (grub_uint32_t nr, const char *p)
+{
+  int mask;
+
+  p += (nr >> 3);
+  mask = 1 << (7 - (nr & 0x07));
+
+  return mask & *p;
+}
+
+static int
+grub_f2fs_sanity_check_sb (struct grub_f2fs_superblock *sb)
+{
+  grub_uint32_t log_sectorsize, log_sectors_per_block;
+
+  if (sb->magic != grub_cpu_to_le32_compile_time (F2FS_SUPER_MAGIC))
+    return -1;
+
+  if (sb->log_blocksize != grub_cpu_to_le32_compile_time (F2FS_BLK_BITS))
+    return -1;
+
+  log_sectorsize = grub_le_to_cpu32 (sb->log_sectorsize);
+  log_sectors_per_block = grub_le_to_cpu32 (sb->log_sectors_per_block);
+
+  if (log_sectorsize > F2FS_BLK_BITS)
+    return -1;
+
+  if (log_sectorsize < F2FS_MIN_LOG_SECTOR_SIZE)
+    return -1;
+
+  if (log_sectors_per_block + log_sectorsize != F2FS_BLK_BITS)
+    return -1;
+
+  return 0;
+}
+
+static int
+grub_f2fs_read_sb (struct grub_f2fs_data *data, grub_disk_addr_t offset)
+{
+  grub_disk_t disk = data->disk;
+  grub_err_t err;
+
+  /* Read first super block. */
+  err = grub_disk_read (disk, offset, 0, sizeof (data->sblock), &data->sblock);
+  if (err)
+    return -1;
+
+  return grub_f2fs_sanity_check_sb (&data->sblock);
+}
+
+static void *
+validate_checkpoint (struct grub_f2fs_data *data, grub_uint32_t cp_addr,
+                     grub_uint64_t *version)
+{
+  grub_uint32_t *cp_page_1, *cp_page_2;
+  struct grub_f2fs_checkpoint *cp_block;
+  grub_uint64_t cur_version = 0, pre_version = 0;
+  grub_uint32_t crc = 0;
+  grub_uint32_t crc_offset;
+  grub_err_t err;
+
+  /* Read the 1st cp block in this CP pack. */
+  cp_page_1 = grub_malloc (F2FS_BLKSIZE);
+  if (!cp_page_1)
+    return NULL;
+
+  err = grub_f2fs_block_read (data, cp_addr, cp_page_1);
+  if (err)
+    goto invalid_cp1;
+
+  cp_block = (struct grub_f2fs_checkpoint *)cp_page_1;
+  crc_offset = grub_le_to_cpu32 (cp_block->checksum_offset);
+  if (crc_offset != CHECKSUM_OFFSET)
+    goto invalid_cp1;
+
+  crc = grub_le_to_cpu32 (*(cp_page_1 + U32_CHECKSUM_OFFSET));
+  if (!grub_f2fs_crc_valid (crc, cp_block, crc_offset))
+    goto invalid_cp1;
+
+  pre_version = grub_le_to_cpu64 (cp_block->checkpoint_ver);
+
+  /* Read the 2nd cp block in this CP pack. */
+  cp_page_2 = grub_malloc (F2FS_BLKSIZE);
+  if (!cp_page_2)
+    goto invalid_cp1;
+
+  cp_addr += grub_le_to_cpu32 (cp_block->cp_pack_total_block_count) - 1;
+
+  err = grub_f2fs_block_read (data, cp_addr, cp_page_2);
+  if (err)
+    goto invalid_cp2;
+
+  cp_block = (struct grub_f2fs_checkpoint *)cp_page_2;
+  crc_offset = grub_le_to_cpu32 (cp_block->checksum_offset);
+  if (crc_offset != CHECKSUM_OFFSET)
+    goto invalid_cp2;
+
+  crc = grub_le_to_cpu32 (*(cp_page_2 + U32_CHECKSUM_OFFSET));
+  if (!grub_f2fs_crc_valid (crc, cp_block, crc_offset))
+    goto invalid_cp2;
+
+  cur_version = grub_le_to_cpu64 (cp_block->checkpoint_ver);
+  if (cur_version == pre_version)
+    {
+      *version = cur_version;
+      grub_free (cp_page_2);
+
+      return cp_page_1;
+    }
+
+ invalid_cp2:
+  grub_free (cp_page_2);
+
+ invalid_cp1:
+  grub_free (cp_page_1);
+
+  return NULL;
+}
+
+static grub_err_t
+grub_f2fs_read_cp (struct grub_f2fs_data *data)
+{
+  void *cp1, *cp2, *cur_page;
+  grub_uint64_t cp1_version = 0, cp2_version = 0;
+  grub_uint64_t cp_start_blk_no;
+
+  /*
+   * Finding out valid cp block involves read both
+   * sets (cp pack1 and cp pack 2).
+   */
+  cp_start_blk_no = data->cp_blkaddr;
+  cp1 = validate_checkpoint (data, cp_start_blk_no, &cp1_version);
+  if (!cp1 && grub_errno)
+    return grub_errno;
+
+  /* The second checkpoint pack should start at the next segment. */
+  cp_start_blk_no += data->blocks_per_seg;
+  cp2 = validate_checkpoint (data, cp_start_blk_no, &cp2_version);
+  if (!cp2 && grub_errno)
+    {
+      grub_free (cp1);
+      return grub_errno;
+    }
+
+  if (cp1 && cp2)
+    cur_page = (cp2_version > cp1_version) ? cp2 : cp1;
+  else if (cp1)
+    cur_page = cp1;
+  else if (cp2)
+    cur_page = cp2;
+  else
+    return grub_error (GRUB_ERR_BAD_FS, "no checkpoints");
+
+  grub_memcpy (&data->ckpt, cur_page, F2FS_BLKSIZE);
+
+  grub_free (cp1);
+  grub_free (cp2);
+
+  return 0;
+}
+
+static grub_err_t
+get_nat_journal (struct grub_f2fs_data *data)
+{
+  grub_uint32_t block;
+  char *buf;
+  grub_err_t err;
+
+  buf = grub_malloc (F2FS_BLKSIZE);
+  if (!buf)
+    return grub_errno;
+
+  if (CKPT_FLAG_SET(&data->ckpt, CP_COMPACT_SUM_FLAG))
+    block = start_sum_block (data);
+  else if (CKPT_FLAG_SET (&data->ckpt, CP_UMOUNT_FLAG))
+    block = sum_blk_addr (data, NR_CURSEG_TYPE, CURSEG_HOT_DATA);
+  else
+    block = sum_blk_addr (data, NR_CURSEG_DATA_TYPE, CURSEG_HOT_DATA);
+
+  err = grub_f2fs_block_read (data, block, buf);
+  if (err)
+    goto fail;
+
+  if (CKPT_FLAG_SET (&data->ckpt, CP_COMPACT_SUM_FLAG))
+    grub_memcpy (&data->nat_j, buf, SUM_JOURNAL_SIZE);
+  else
+    grub_memcpy (&data->nat_j, buf + SUM_ENTRIES_SIZE, SUM_JOURNAL_SIZE);
+
+ fail:
+  grub_free (buf);
+
+  return err;
+}
+
+static grub_uint32_t
+get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid)
+{
+  grub_uint16_t n = grub_le_to_cpu16 (data->nat_j.n_nats);
+  grub_uint32_t blkaddr = 0;
+  grub_uint16_t i;
+
+  for (i = 0; i < n; i++)
+    {
+      if (grub_le_to_cpu32 (data->nat_j.entries[i].nid) == nid)
+        {
+          blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr);
+          break;
+        }
+    }
+
+  return blkaddr;
+}
+
+static grub_uint32_t
+get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid)
+{
+  struct grub_f2fs_nat_block *nat_block;
+  grub_uint32_t seg_off, block_off, entry_off, block_addr;
+  grub_uint32_t blkaddr;
+  grub_err_t err;
+
+  blkaddr = get_blkaddr_from_nat_journal (data, nid);
+  if (blkaddr)
+    return blkaddr;
+
+  nat_block = grub_malloc (F2FS_BLKSIZE);
+  if (!nat_block)
+    return 0;
+
+  block_off = nid / NAT_ENTRY_PER_BLOCK;
+  entry_off = nid % NAT_ENTRY_PER_BLOCK;
+
+  seg_off = block_off / data->blocks_per_seg;
+  block_addr = data->nat_blkaddr +
+        ((seg_off * data->blocks_per_seg) << 1) +
+        (block_off & (data->blocks_per_seg - 1));
+
+  if (grub_f2fs_test_bit (block_off, data->nat_bitmap))
+    block_addr += data->blocks_per_seg;
+
+  err = grub_f2fs_block_read (data, block_addr, nat_block);
+  if (err)
+    {
+      grub_free (nat_block);
+      return 0;
+    }
+
+  blkaddr = grub_le_to_cpu32 (nat_block->ne[entry_off].block_addr);
+
+  grub_free (nat_block);
+
+  return blkaddr;
+}
+
+static int
+grub_get_node_path (struct grub_f2fs_inode *inode, grub_uint32_t block,
+                    grub_uint32_t offset[4], grub_uint32_t noffset[4])
+{
+  grub_uint32_t direct_blks = ADDRS_PER_BLOCK;
+  grub_uint32_t dptrs_per_blk = NIDS_PER_BLOCK;
+  grub_uint32_t indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
+  grub_uint32_t dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
+  grub_uint32_t direct_index = DEF_ADDRS_PER_INODE;
+  int n = 0;
+  int level = 0;
+
+  if (inode->i_inline & F2FS_INLINE_XATTR)
+    direct_index -= F2FS_INLINE_XATTR_ADDRS;
+
+  noffset[0] = 0;
+
+  if (block < direct_index)
+    {
+      offset[n] = block;
+      goto got;
+    }
+
+  block -= direct_index;
+  if (block < direct_blks)
+    {
+      offset[n++] = NODE_DIR1_BLOCK;
+      noffset[n] = 1;
+      offset[n] = block;
+      level = 1;
+      goto got;
+    }
+
+  block -= direct_blks;
+  if (block < direct_blks)
+    {
+      offset[n++] = NODE_DIR2_BLOCK;
+      noffset[n] = 2;
+      offset[n] = block;
+      level = 1;
+      goto got;
+    }
+
+  block -= direct_blks;
+  if (block < indirect_blks)
+    {
+      offset[n++] = NODE_IND1_BLOCK;
+      noffset[n] = 3;
+      offset[n++] = block / direct_blks;
+      noffset[n] = 4 + offset[n - 1];
+      offset[n] = block % direct_blks;
+      level = 2;
+      goto got;
+    }
+
+  block -= indirect_blks;
+  if (block < indirect_blks)
+    {
+      offset[n++] = NODE_IND2_BLOCK;
+      noffset[n] = 4 + dptrs_per_blk;
+      offset[n++] = block / direct_blks;
+      noffset[n] = 5 + dptrs_per_blk + offset[n - 1];
+      offset[n] = block % direct_blks;
+      level = 2;
+      goto got;
+    }
+
+  block -= indirect_blks;
+  if (block < dindirect_blks)
+    {
+      offset[n++] = NODE_DIND_BLOCK;
+      noffset[n] = 5 + (dptrs_per_blk * 2);
+      offset[n++] = block / indirect_blks;
+      noffset[n] = 6 + (dptrs_per_blk * 2) +
+      offset[n - 1] * (dptrs_per_blk + 1);
+      offset[n++] = (block / direct_blks) % dptrs_per_blk;
+      noffset[n] = 7 + (dptrs_per_blk * 2) +
+      offset[n - 2] * (dptrs_per_blk + 1) + offset[n - 1];
+      offset[n] = block % direct_blks;
+      level = 3;
+      goto got;
+    }
+
+ got:
+  return level;
+}
+
+static grub_err_t
+grub_f2fs_read_node (struct grub_f2fs_data *data,
+                     grub_uint32_t nid, struct grub_f2fs_node *np)
+{
+  grub_uint32_t blkaddr;
+
+  blkaddr = get_node_blkaddr (data, nid);
+  if (!blkaddr)
+    return grub_errno;
+
+  return grub_f2fs_block_read (data, blkaddr, np);
+}
+
+static struct grub_f2fs_data *
+grub_f2fs_mount (grub_disk_t disk)
+{
+  struct grub_f2fs_data *data;
+  grub_err_t err;
+
+  data = grub_malloc (sizeof (*data));
+  if (!data)
+    return NULL;
+
+  data->disk = disk;
+
+  if (grub_f2fs_read_sb (data, F2FS_SUPER_OFFSET0))
+    {
+      if (grub_f2fs_read_sb (data, F2FS_SUPER_OFFSET1))
+        {
+          if (grub_errno == GRUB_ERR_NONE)
+            grub_error (GRUB_ERR_BAD_FS,
+                        "not a F2FS filesystem (no superblock)");
+          goto fail;
+        }
+    }
+
+  data->root_ino = grub_le_to_cpu32 (data->sblock.root_ino);
+  data->cp_blkaddr = grub_le_to_cpu32 (data->sblock.cp_blkaddr);
+  data->nat_blkaddr = grub_le_to_cpu32 (data->sblock.nat_blkaddr);
+  data->blocks_per_seg = 1 <<
+    grub_le_to_cpu32 (data->sblock.log_blocks_per_seg);
+
+  err = grub_f2fs_read_cp (data);
+  if (err)
+    goto fail;
+
+  data->nat_bitmap = nat_bitmap_ptr (data);
+
+  err = get_nat_journal (data);
+  if (err)
+    goto fail;
+
+  data->diropen.data = data;
+  data->diropen.ino = data->root_ino;
+  data->diropen.inode_read = 1;
+  data->inode = &data->diropen.inode;
+
+  err = grub_f2fs_read_node (data, data->root_ino, data->inode);
+  if (err)
+    goto fail;
+
+  return data;
+
+ fail:
+  grub_free (data);
+
+  return NULL;
+}
+
+/* Guarantee inline_data was handled by caller. */
+static grub_disk_addr_t
+grub_f2fs_get_block (grub_fshelp_node_t node, grub_disk_addr_t block_ofs)
+{
+  struct grub_f2fs_data *data = node->data;
+  struct grub_f2fs_inode *inode = &node->inode.i;
+  grub_uint32_t offset[4], noffset[4], nids[4];
+  struct grub_f2fs_node *node_block;
+  grub_uint32_t block_addr = -1;
+  int level, i;
+
+  level = grub_get_node_path (inode, block_ofs, offset, noffset);
+  if (level == 0)
+    return grub_le_to_cpu32 (inode->i_addr[offset[0]]);
+
+  node_block = grub_malloc (F2FS_BLKSIZE);
+  if (!node_block)
+    return -1;
+
+  nids[1] = get_node_id (&node->inode, offset[0], 1);
+
+  /* Get indirect or direct nodes. */
+  for (i = 1; i <= level; i++)
+    {
+      grub_f2fs_read_node (data, nids[i], node_block);
+      if (grub_errno)
+        goto fail;
+
+      if (i < level)
+        nids[i + 1] = get_node_id (node_block, offset[i], 0);
+    }
+
+  block_addr = grub_le_to_cpu32 (node_block->dn.addr[offset[level]]);
+
+ fail:
+  grub_free (node_block);
+
+  return block_addr;
+}
+
+static grub_ssize_t
+grub_f2fs_read_file (grub_fshelp_node_t node,
+                     grub_disk_read_hook_t read_hook, void *read_hook_data,
+                     grub_off_t pos, grub_size_t len, char *buf)
+{
+  struct grub_f2fs_inode *inode = &node->inode.i;
+  grub_off_t filesize = grub_f2fs_file_size (inode);
+  char *inline_addr = get_inline_addr (inode);
+
+  if (inode->i_inline & F2FS_INLINE_DATA)
+    {
+      if (filesize > MAX_INLINE_DATA)
+        return -1;
+
+      if (len > filesize - pos)
+        len = filesize - pos;
+
+      grub_memcpy (buf, inline_addr + pos, len);
+      return len;
+    }
+
+  return grub_fshelp_read_file (node->data->disk, node,
+                                read_hook, read_hook_data,
+                                pos, len, buf, grub_f2fs_get_block,
+                                filesize,
+                                F2FS_BLK_SEC_BITS, 0);
+}
+
+static char *
+grub_f2fs_read_symlink (grub_fshelp_node_t node)
+{
+  char *symlink;
+  struct grub_fshelp_node *diro = node;
+  grub_uint64_t filesize;
+
+  if (!diro->inode_read)
+    {
+      grub_f2fs_read_node (diro->data, diro->ino, &diro->inode);
+      if (grub_errno)
+        return 0;
+    }
+
+  filesize = grub_f2fs_file_size(&diro->inode.i);
+
+  symlink = grub_malloc (filesize + 1);
+  if (!symlink)
+    return 0;
+
+  grub_f2fs_read_file (diro, 0, 0, 0, filesize, symlink);
+  if (grub_errno)
+    {
+      grub_free (symlink);
+      return 0;
+    }
+
+  symlink[filesize] = '\0';
+
+  return symlink;
+}
+
+static int
+grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx)
+{
+  struct grub_fshelp_node *fdiro;
+  int i;
+
+  for (i = 0; i < ctx->max;)
+    {
+      char *filename;
+      enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
+      enum FILE_TYPE ftype;
+      int name_len;
+      int ret;
+
+      if (grub_f2fs_test_bit_le (i, ctx->bitmap) == 0)
+        {
+          i++;
+          continue;
+        }
+
+      ftype = ctx->dentry[i].file_type;
+      name_len = grub_le_to_cpu16 (ctx->dentry[i].name_len);
+      filename = grub_malloc (name_len + 1);
+      if (!filename)
+        return 0;
+
+      grub_memcpy (filename, ctx->filename[i], name_len);
+      filename[name_len] = 0;
+
+      fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
+      if (!fdiro)
+        {
+          grub_free(filename);
+          return 0;
+        }
+
+      if (ftype == F2FS_FT_DIR)
+        type = GRUB_FSHELP_DIR;
+      else if (ftype == F2FS_FT_SYMLINK)
+        type = GRUB_FSHELP_SYMLINK;
+      else if (ftype == F2FS_FT_REG_FILE)
+        type = GRUB_FSHELP_REG;
+
+      fdiro->data = ctx->data;
+      fdiro->ino = grub_le_to_cpu32 (ctx->dentry[i].ino);
+      fdiro->inode_read = 0;
+
+      ret = ctx->hook (filename, type, fdiro, ctx->hook_data);
+      grub_free(filename);
+      if (ret)
+        return 1;
+
+      i += (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN;
+    }
+
+    return 0;
+}
+
+static int
+grub_f2fs_iterate_inline_dir (struct grub_f2fs_inode *dir,
+                              struct grub_f2fs_dir_iter_ctx *ctx)
+{
+  struct grub_f2fs_inline_dentry *de_blk;
+
+  de_blk = (struct grub_f2fs_inline_dentry *) get_inline_addr (dir);
+
+  ctx->bitmap = de_blk->dentry_bitmap;
+  ctx->dentry = de_blk->dentry;
+  ctx->filename = de_blk->filename;
+  ctx->max = NR_INLINE_DENTRY;
+
+  return grub_f2fs_check_dentries (ctx);
+}
+
+static int
+grub_f2fs_iterate_dir (grub_fshelp_node_t dir,
+                       grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
+{
+  struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
+  struct grub_f2fs_inode *inode;
+  struct grub_f2fs_dir_iter_ctx ctx = {
+    .data = diro->data,
+    .hook = hook,
+    .hook_data = hook_data
+  };
+  grub_off_t fpos = 0;
+
+  if (!diro->inode_read)
+    {
+      grub_f2fs_read_node (diro->data, diro->ino, &diro->inode);
+      if (grub_errno)
+        return 0;
+    }
+
+  inode = &diro->inode.i;
+
+  if (inode->i_inline & F2FS_INLINE_DENTRY)
+    return grub_f2fs_iterate_inline_dir (inode, &ctx);
+
+  while (fpos < grub_f2fs_file_size (inode))
+    {
+      struct grub_f2fs_dentry_block *de_blk;
+      char *buf;
+      int ret;
+
+      buf = grub_zalloc (F2FS_BLKSIZE);
+      if (!buf)
+        return 0;
+
+      grub_f2fs_read_file (diro, 0, 0, fpos, F2FS_BLKSIZE, buf);
+      if (grub_errno)
+        {
+          grub_free (buf);
+          return 0;
+        }
+
+      de_blk = (struct grub_f2fs_dentry_block *) buf;
+
+      ctx.bitmap = de_blk->dentry_bitmap;
+      ctx.dentry = de_blk->dentry;
+      ctx.filename = de_blk->filename;
+      ctx.max = NR_DENTRY_IN_BLOCK;
+
+      ret = grub_f2fs_check_dentries (&ctx);
+      grub_free (buf);
+      if (ret)
+        return 1;
+
+      fpos += F2FS_BLKSIZE;
+    }
+
+  return 0;
+}
+
+static int
+grub_f2fs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype,
+                    grub_fshelp_node_t node, void *data)
+{
+  struct grub_f2fs_dir_ctx *ctx = data;
+  struct grub_dirhook_info info;
+
+  grub_memset (&info, 0, sizeof (info));
+  if (!node->inode_read)
+    {
+      grub_f2fs_read_node (ctx->data, node->ino, &node->inode);
+      if (!grub_errno)
+        node->inode_read = 1;
+      grub_errno = GRUB_ERR_NONE;
+    }
+  if (node->inode_read)
+    {
+      info.mtimeset = 1;
+      info.mtime = grub_le_to_cpu64 (node->inode.i.i_mtime);
+    }
+
+  info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
+  grub_free (node);
+
+  return ctx->hook (filename, &info, ctx->hook_data);
+}
+
+static grub_err_t
+grub_f2fs_dir (grub_device_t device, const char *path,
+               grub_fs_dir_hook_t hook, void *hook_data)
+{
+  struct grub_f2fs_dir_ctx ctx = {
+    .hook = hook,
+    .hook_data = hook_data
+  };
+  struct grub_fshelp_node *fdiro = 0;
+
+  grub_dl_ref (my_mod);
+
+  ctx.data = grub_f2fs_mount (device->disk);
+  if (!ctx.data)
+    goto fail;
+
+  grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro,
+                         grub_f2fs_iterate_dir, grub_f2fs_read_symlink,
+                         GRUB_FSHELP_DIR);
+  if (grub_errno)
+    goto fail;
+
+  grub_f2fs_iterate_dir (fdiro, grub_f2fs_dir_iter, &ctx);
+
+ fail:
+  if (fdiro != &ctx.data->diropen)
+    grub_free (fdiro);
+  grub_free (ctx.data);
+  grub_dl_unref (my_mod);
+
+  return grub_errno;
+}
+
+/* Open a file named NAME and initialize FILE. */
+static grub_err_t
+grub_f2fs_open (struct grub_file *file, const char *name)
+{
+  struct grub_f2fs_data *data = NULL;
+  struct grub_fshelp_node *fdiro = 0;
+  struct grub_f2fs_inode *inode;
+
+  grub_dl_ref (my_mod);
+
+  data = grub_f2fs_mount (file->device->disk);
+  if (!data)
+    goto fail;
+
+  grub_fshelp_find_file (name, &data->diropen, &fdiro,
+                         grub_f2fs_iterate_dir, grub_f2fs_read_symlink,
+                         GRUB_FSHELP_REG);
+  if (grub_errno)
+    goto fail;
+
+  if (!fdiro->inode_read)
+    {
+      grub_f2fs_read_node (data, fdiro->ino, &fdiro->inode);
+      if (grub_errno)
+        goto fail;
+    }
+
+  grub_memcpy (data->inode, &fdiro->inode, sizeof (*data->inode));
+  grub_free (fdiro);
+
+  inode = &(data->inode->i);
+  file->size = grub_f2fs_file_size (inode);
+  file->data = data;
+  file->offset = 0;
+
+  if (inode->i_inline & F2FS_INLINE_DATA && file->size > MAX_INLINE_DATA)
+    grub_error (GRUB_ERR_BAD_FS, "corrupted inline_data: need fsck");
+
+  return 0;
+
+ fail:
+  if (fdiro != &data->diropen)
+    grub_free (fdiro);
+  grub_free (data);
+
+  grub_dl_unref (my_mod);
+
+  return grub_errno;
+}
+
+static grub_ssize_t
+grub_f2fs_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  struct grub_f2fs_data *data = (struct grub_f2fs_data *) file->data;
+
+  return grub_f2fs_read_file (&data->diropen,
+                              file->read_hook, file->read_hook_data,
+                              file->offset, len, buf);
+}
+
+static grub_err_t
+grub_f2fs_close (grub_file_t file)
+{
+  struct grub_f2fs_data *data = (struct grub_f2fs_data *) file->data;
+
+  grub_free (data);
+
+  grub_dl_unref (my_mod);
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_uint8_t *
+grub_f2fs_utf16_to_utf8 (grub_uint16_t *in_buf_le)
+{
+  grub_uint16_t in_buf[MAX_VOLUME_NAME];
+  grub_uint8_t *out_buf;
+  int len = 0;
+
+  out_buf = grub_malloc (MAX_VOLUME_NAME * GRUB_MAX_UTF8_PER_UTF16 + 1);
+  if (!out_buf)
+    return NULL;
+
+  while (*in_buf_le != 0 && len < MAX_VOLUME_NAME) {
+    in_buf[len] = grub_le_to_cpu16 (in_buf_le[len]);
+    len++;
+  }
+
+  *grub_utf16_to_utf8 (out_buf, in_buf, len) = '\0';
+
+  return out_buf;
+}
+
+static grub_err_t
+grub_f2fs_label (grub_device_t device, char **label)
+{
+  struct grub_f2fs_data *data;
+  grub_disk_t disk = device->disk;
+
+  grub_dl_ref (my_mod);
+
+  data = grub_f2fs_mount (disk);
+  if (data)
+    *label = (char *) grub_f2fs_utf16_to_utf8 (data->sblock.volume_name);
+  else
+    *label = NULL;
+
+  grub_free (data);
+  grub_dl_unref (my_mod);
+
+  return grub_errno;
+}
+
+static grub_err_t
+grub_f2fs_uuid (grub_device_t device, char **uuid)
+{
+  struct grub_f2fs_data *data;
+  grub_disk_t disk = device->disk;
+
+  grub_dl_ref (my_mod);
+
+  data = grub_f2fs_mount (disk);
+  if (data)
+    {
+      *uuid =
+        grub_xasprintf
+        ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+         data->sblock.uuid[0], data->sblock.uuid[1],
+         data->sblock.uuid[2], data->sblock.uuid[3],
+         data->sblock.uuid[4], data->sblock.uuid[5],
+         data->sblock.uuid[6], data->sblock.uuid[7],
+         data->sblock.uuid[8], data->sblock.uuid[9],
+         data->sblock.uuid[10], data->sblock.uuid[11],
+         data->sblock.uuid[12], data->sblock.uuid[13],
+         data->sblock.uuid[14], data->sblock.uuid[15]);
+    }
+  else
+    *uuid = NULL;
+
+  grub_free (data);
+  grub_dl_unref (my_mod);
+
+  return grub_errno;
+}
+
+static struct grub_fs grub_f2fs_fs = {
+  .name                  = "f2fs",
+  .dir                   = grub_f2fs_dir,
+  .open                  = grub_f2fs_open,
+  .read                  = grub_f2fs_read,
+  .close                 = grub_f2fs_close,
+  .label                 = grub_f2fs_label,
+  .uuid                  = grub_f2fs_uuid,
+#ifdef GRUB_UTIL
+  .reserved_first_sector = 1,
+  .blocklist_install     = 0,
+#endif
+  .next                  = 0
+};
+
+GRUB_MOD_INIT (f2fs)
+{
+  grub_fs_register (&grub_f2fs_fs);
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI (f2fs)
+{
+  grub_fs_unregister (&grub_f2fs_fs);
+}
diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
index 839bff88963baba7730d788869e1f50481a66a30..00a16098b47aff52a352fa9433e279beae261329 100644
--- a/grub-core/fs/udf.c
+++ b/grub-core/fs/udf.c
@@ -321,6 +321,32 @@ struct grub_udf_partmap
   };
 } GRUB_PACKED;
 
+struct grub_udf_pvd
+{
+  struct grub_udf_tag tag;
+  grub_uint32_t seq_num;
+  grub_uint32_t pvd_num;
+  grub_uint8_t ident[32];
+  grub_uint16_t vol_seq_num;
+  grub_uint16_t max_vol_seq_num;
+  grub_uint16_t interchange_level;
+  grub_uint16_t max_interchange_level;
+  grub_uint32_t charset_list;
+  grub_uint32_t max_charset_list;
+  grub_uint8_t volset_ident[128];
+  struct grub_udf_charspec desc_charset;
+  struct grub_udf_charspec expl_charset;
+  struct grub_udf_extent_ad vol_abstract;
+  struct grub_udf_extent_ad vol_copyright;
+  struct grub_udf_regid app_ident;
+  struct grub_udf_timestamp recording_time;
+  struct grub_udf_regid imp_ident;
+  grub_uint8_t imp_use[64];
+  grub_uint32_t pred_vds_loc;
+  grub_uint16_t flags;
+  grub_uint8_t reserved[22];
+} GRUB_PACKED;
+
 struct grub_udf_lvd
 {
   struct grub_udf_tag tag;
@@ -348,6 +374,7 @@ struct grub_udf_aed
 struct grub_udf_data
 {
   grub_disk_t disk;
+  struct grub_udf_pvd pvd;
   struct grub_udf_lvd lvd;
   struct grub_udf_pd pds[GRUB_UDF_MAX_PDS];
   struct grub_udf_partmap *pms[GRUB_UDF_MAX_PMS];
@@ -692,7 +719,17 @@ grub_udf_mount (grub_disk_t disk)
 	}
 
       tag.tag_ident = U16 (tag.tag_ident);
-      if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PD)
+      if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PVD)
+	{
+	  if (grub_disk_read (disk, block << lbshift, 0,
+			      sizeof (struct grub_udf_pvd),
+			      &data->pvd))
+	    {
+	      grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem");
+	      goto fail;
+	    }
+	}
+      else if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PD)
 	{
 	  if (data->npd >= GRUB_UDF_MAX_PDS)
 	    {
@@ -860,6 +897,25 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf)
   return outbuf;
 }
 
+static char *
+read_dstring (const grub_uint8_t *raw, grub_size_t sz)
+{
+  grub_size_t len;
+
+  if (raw[0] == 0) {
+      char *outbuf = grub_malloc (1);
+      if (!outbuf)
+	return NULL;
+      outbuf[0] = 0;
+      return outbuf;
+    }
+
+  len = raw[sz - 1];
+  if (len > sz - 1)
+    len = sz - 1;
+  return read_string (raw, len, NULL);
+}
+
 static int
 grub_udf_iterate_dir (grub_fshelp_node_t dir,
 		      grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
@@ -1197,7 +1253,7 @@ grub_udf_label (grub_device_t device, char **label)
 
   if (data)
     {
-      *label = read_string (data->lvd.ident, sizeof (data->lvd.ident), 0);
+      *label = read_dstring (data->lvd.ident, sizeof (data->lvd.ident));
       grub_free (data);
     }
   else
@@ -1206,6 +1262,87 @@ grub_udf_label (grub_device_t device, char **label)
   return grub_errno;
 }
 
+static char *
+gen_uuid_from_volset (char *volset_ident)
+{
+  grub_size_t i;
+  grub_size_t len;
+  grub_size_t nonhexpos;
+  grub_uint8_t buf[17];
+  char *uuid;
+
+  len = grub_strlen (volset_ident);
+  if (len < 8)
+    return NULL;
+
+  uuid = grub_malloc (17);
+  if (!uuid)
+    return NULL;
+
+  if (len > 16)
+    len = 16;
+
+  grub_memset (buf, 0, sizeof (buf));
+  grub_memcpy (buf, volset_ident, len);
+
+  nonhexpos = 16;
+  for (i = 0; i < 16; ++i)
+    {
+      if (!grub_isxdigit (buf[i]))
+        {
+          nonhexpos = i;
+          break;
+        }
+    }
+
+  if (nonhexpos < 8)
+    {
+      grub_snprintf (uuid, 17, "%02x%02x%02x%02x%02x%02x%02x%02x",
+                    buf[0], buf[1], buf[2], buf[3],
+                    buf[4], buf[5], buf[6], buf[7]);
+    }
+  else if (nonhexpos < 16)
+    {
+      for (i = 0; i < 8; ++i)
+        uuid[i] = grub_tolower (buf[i]);
+      grub_snprintf (uuid+8, 9, "%02x%02x%02x%02x",
+                    buf[8], buf[9], buf[10], buf[11]);
+    }
+  else
+    {
+      for (i = 0; i < 16; ++i)
+        uuid[i] = grub_tolower (buf[i]);
+      uuid[16] = 0;
+    }
+
+  return uuid;
+}
+
+static grub_err_t
+grub_udf_uuid (grub_device_t device, char **uuid)
+{
+  char *volset_ident;
+  struct grub_udf_data *data;
+  data = grub_udf_mount (device->disk);
+
+  if (data)
+    {
+      volset_ident = read_dstring (data->pvd.volset_ident, sizeof (data->pvd.volset_ident));
+      if (volset_ident)
+        {
+          *uuid = gen_uuid_from_volset (volset_ident);
+          grub_free (volset_ident);
+        }
+      else
+        *uuid = 0;
+      grub_free (data);
+    }
+  else
+    *uuid = 0;
+
+  return grub_errno;
+}
+
 static struct grub_fs grub_udf_fs = {
   .name = "udf",
   .dir = grub_udf_dir,
@@ -1213,6 +1350,7 @@ static struct grub_fs grub_udf_fs = {
   .read = grub_udf_read,
   .close = grub_udf_close,
   .label = grub_udf_label,
+  .uuid = grub_udf_uuid,
 #ifdef GRUB_UTIL
   .reserved_first_sector = 1,
   .blocklist_install = 1,
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
index 9f66dd6e4c6491e6b2cbfc7866335b432c824502..3b00c744e23c34243df781baa96e5b1b0d88417d 100644
--- a/grub-core/fs/xfs.c
+++ b/grub-core/fs/xfs.c
@@ -79,9 +79,18 @@ GRUB_MOD_LICENSE ("GPLv3+");
 #define XFS_SB_FEAT_INCOMPAT_SPINODES   (1 << 1)        /* sparse inode chunks */
 #define XFS_SB_FEAT_INCOMPAT_META_UUID  (1 << 2)        /* metadata UUID */
 
-/* We do not currently verify metadata UUID so it is safe to read such filesystem */
+/*
+ * Directory entries with ftype are explicitly handled by GRUB code.
+ *
+ * We do not currently read the inode btrees, so it is safe to read filesystems
+ * with the XFS_SB_FEAT_INCOMPAT_SPINODES feature.
+ *
+ * We do not currently verify metadata UUID, so it is safe to read filesystems
+ * with the XFS_SB_FEAT_INCOMPAT_META_UUID feature.
+ */
 #define XFS_SB_FEAT_INCOMPAT_SUPPORTED \
 	(XFS_SB_FEAT_INCOMPAT_FTYPE | \
+	 XFS_SB_FEAT_INCOMPAT_SPINODES | \
 	 XFS_SB_FEAT_INCOMPAT_META_UUID)
 
 struct grub_xfs_sblock
@@ -828,6 +837,9 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
 	    entries = (grub_be_to_cpu32 (tail->leaf_count)
 		       - grub_be_to_cpu32 (tail->leaf_stale));
 
+	    if (!entries)
+	      continue;
+
 	    /* Iterate over all entries within this block.  */
 	    while ((char *)direntry < (char *)tail)
 	      {
diff --git a/grub-core/fs/zfs/zfs_lz4.c b/grub-core/fs/zfs/zfs_lz4.c
index 2f73449f0d4c63cadc7b5b4388250a4d474594b6..5453822d0258527ba751e551cbb54753f0331043 100644
--- a/grub-core/fs/zfs/zfs_lz4.c
+++ b/grub-core/fs/zfs/zfs_lz4.c
@@ -73,7 +73,6 @@ static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest,
 #define	U32	grub_uint32_t
 #define	S32	grub_int32_t
 #define	U64	grub_uint64_t
-typedef grub_size_t size_t;
 
 typedef struct _U16_S {
 	U16 v;
@@ -133,10 +132,10 @@ typedef struct _U64_S {
 
 /* Decompression functions */
 grub_err_t
-lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len);
+lz4_decompress(void *s_start, void *d_start, grub_size_t s_len, grub_size_t d_len);
 
 grub_err_t
-lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len)
+lz4_decompress(void *s_start, void *d_start, grub_size_t s_len, grub_size_t d_len)
 {
 	const BYTE *src = s_start;
 	U32 bufsiz = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) |
@@ -167,7 +166,7 @@ LZ4_uncompress_unknownOutputSize(const char *source,
 	BYTE *const oend = op + maxOutputSize;
 	BYTE *cpy;
 
-	size_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 };
+	grub_size_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 };
 
 	/* Main Loop */
 	while (ip < iend) {
@@ -237,8 +236,8 @@ LZ4_uncompress_unknownOutputSize(const char *source,
 		/* copy repeated sequence */
 		if unlikely(op - ref < STEPSIZE) {
 #if LZ4_ARCH64
-			size_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
-			size_t dec2 = dec2table[op - ref];
+			grub_size_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
+			grub_size_t dec2 = dec2table[op - ref];
 #else
 			const int dec2 = 0;
 #endif
diff --git a/grub-core/io/bufio.c b/grub-core/io/bufio.c
index 22438277d7456358dfc6bcbb51317fd704987738..dbed64744317c2f849fb2bda8fd5a6b142affe91 100644
--- a/grub-core/io/bufio.c
+++ b/grub-core/io/bufio.c
@@ -61,6 +61,13 @@ grub_bufio_open (grub_file_t io, int size)
     size = ((io->size > GRUB_BUFIO_MAX_SIZE) ? GRUB_BUFIO_MAX_SIZE :
             io->size);
 
+  /*
+   * Round up size to power of 2 which the binary math to
+   * calculate next_buf in grub_bufio_read() requires.
+   */
+  while (size & (size - 1))
+    size = (size | (size - 1)) + 1;
+
   bufio = grub_zalloc (sizeof (struct grub_bufio) + size);
   if (! bufio)
     {
diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c
index 0f2ea6bd845227265eef205c212e7c52ee03ebcf..86ea8cfdea2e0abd1f73c6df4dca58806c8f2d9b 100644
--- a/grub-core/io/gzio.c
+++ b/grub-core/io/gzio.c
@@ -43,6 +43,7 @@
 #include <grub/dl.h>
 #include <grub/deflate.h>
 #include <grub/i18n.h>
+#include <grub/crypto.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -94,6 +95,14 @@ struct grub_gzio
   struct huft *tl;
   /* The distance code table.  */
   struct huft *td;
+  /* The checksum algorithm */
+  const gcry_md_spec_t *hdesc;
+  /* The wanted checksum */
+  grub_uint32_t orig_checksum;
+  /* The uncompressed length */
+  grub_size_t orig_len;
+  /* Context for checksum calculation */
+  grub_uint8_t *hcontext;
   /* The lookup bits for the literal/length code table. */
   int bl;
   /* The lookup bits for the distance code table.  */
@@ -140,24 +149,24 @@ eat_field (grub_file_t file, int len)
 #define OLD_GZIP_MAGIC	grub_le_to_cpu16 (0x9E1F)
 
 /* Compression methods (see algorithm.doc) */
-#define STORED      0
-#define COMPRESSED  1
-#define PACKED      2
-#define LZHED       3
+#define GRUB_GZ_STORED      0
+#define GRUB_GZ_COMPRESSED  1
+#define GRUB_GZ_PACKED      2
+#define GRUB_GZ_LZHED       3
 /* methods 4 to 7 reserved */
-#define DEFLATED    8
-#define MAX_METHODS 9
+#define GRUB_GZ_DEFLATED    8
+#define GRUB_GZ_MAX_METHODS 9
 
 /* gzip flag byte */
-#define ASCII_FLAG   0x01	/* bit 0 set: file probably ascii text */
-#define CONTINUATION 0x02	/* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD  0x04	/* bit 2 set: extra field present */
-#define ORIG_NAME    0x08	/* bit 3 set: original file name present */
-#define COMMENT      0x10	/* bit 4 set: file comment present */
-#define ENCRYPTED    0x20	/* bit 5 set: file is encrypted */
-#define RESERVED     0xC0	/* bit 6,7:   reserved */
+#define GRUB_GZ_ASCII_FLAG   0x01	/* bit 0 set: file probably ascii text */
+#define GRUB_GZ_CONTINUATION 0x02	/* bit 1 set: continuation of multi-part gzip file */
+#define GRUB_GZ_EXTRA_FIELD  0x04	/* bit 2 set: extra field present */
+#define GRUB_GZ_ORIG_NAME    0x08	/* bit 3 set: original file name present */
+#define GRUB_GZ_COMMENT      0x10	/* bit 4 set: file comment present */
+#define GRUB_GZ_ENCRYPTED    0x20	/* bit 5 set: file is encrypted */
+#define GRUB_GZ_RESERVED     0xC0	/* bit 6,7:   reserved */
 
-#define UNSUPPORTED_FLAGS	(CONTINUATION | ENCRYPTED | RESERVED)
+#define GRUB_GZ_UNSUPPORTED_FLAGS	(GRUB_GZ_CONTINUATION | GRUB_GZ_ENCRYPTED | GRUB_GZ_RESERVED)
 
 /* inflate block codes */
 #define INFLATE_STORED	0
@@ -180,7 +189,7 @@ test_gzip_header (grub_file_t file)
     grub_uint8_t os_type;
   } hdr;
   grub_uint16_t extra_len;
-  grub_uint32_t orig_len;
+  grub_uint32_t crc32;
   grub_gzio_t gzio = file->data;
 
   if (grub_file_tell (gzio->file) != 0)
@@ -201,26 +210,29 @@ test_gzip_header (grub_file_t file)
    *  problem occurs from here on, then we have corrupt or otherwise
    *  bad data, and the error should be reported to the user.
    */
-  if (hdr.method != DEFLATED
-      || (hdr.flags & UNSUPPORTED_FLAGS)
-      || ((hdr.flags & EXTRA_FIELD)
+  if (hdr.method != GRUB_GZ_DEFLATED
+      || (hdr.flags & GRUB_GZ_UNSUPPORTED_FLAGS)
+      || ((hdr.flags & GRUB_GZ_EXTRA_FIELD)
 	  && (grub_file_read (gzio->file, &extra_len, 2) != 2
 	      || eat_field (gzio->file,
 			    grub_le_to_cpu16 (extra_len))))
-      || ((hdr.flags & ORIG_NAME) && eat_field (gzio->file, -1))
-      || ((hdr.flags & COMMENT) && eat_field (gzio->file, -1)))
+      || ((hdr.flags & GRUB_GZ_ORIG_NAME) && eat_field (gzio->file, -1))
+      || ((hdr.flags & GRUB_GZ_COMMENT) && eat_field (gzio->file, -1)))
     return 0;
 
   gzio->data_offset = grub_file_tell (gzio->file);
 
   /* FIXME: don't do this on not easily seekable files.  */
   {
-    grub_file_seek (gzio->file, grub_file_size (gzio->file) - 4);
-    if (grub_file_read (gzio->file, &orig_len, 4) != 4)
+    grub_file_seek (gzio->file, grub_file_size (gzio->file) - 8);
+    if (grub_file_read (gzio->file, &crc32, 4) != 4)
+      return 0;
+    gzio->orig_checksum = grub_le_to_cpu32 (crc32);
+    if (grub_file_read (gzio->file, &gzio->orig_len, 4) != 4)
       return 0;
     /* FIXME: this does not handle files whose original size is over 4GB.
        But how can we know the real original size?  */
-    file->size = grub_le_to_cpu32 (orig_len);
+    file->size = grub_le_to_cpu32 (gzio->orig_len);
   }
 
   initialize_tables (gzio);
@@ -1095,7 +1107,23 @@ inflate_window (grub_gzio_t gzio)
 
   gzio->saved_offset += gzio->wp;
 
-  /* XXX do CRC calculation here! */
+  if (gzio->hcontext)
+    {
+      gzio->hdesc->write (gzio->hcontext, gzio->slide, gzio->wp);
+
+      if (gzio->saved_offset == gzio->orig_len)
+	{
+	  grub_uint32_t csum;
+
+	  gzio->hdesc->final (gzio->hcontext);
+	  csum = grub_get_unaligned32 (gzio->hdesc->read (gzio->hcontext));
+	  csum = grub_be_to_cpu32 (csum);
+	  if (csum != gzio->orig_checksum)
+	    grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
+			"checksum mismatch %08x/%08x",
+			gzio->orig_checksum, csum);
+	}
+    }
 }
 
 
@@ -1118,6 +1146,9 @@ initialize_tables (grub_gzio_t gzio)
   huft_free (gzio->td);
   gzio->tl = NULL;
   gzio->td = NULL;
+
+  if (gzio->hcontext)
+    gzio->hdesc->init(gzio->hcontext);
 }
 
 
@@ -1143,6 +1174,9 @@ grub_gzio_open (grub_file_t io, const char *name __attribute__ ((unused)))
 
   gzio->file = io;
 
+  gzio->hdesc = GRUB_MD_CRC32;
+  gzio->hcontext = grub_malloc(gzio->hdesc->contextsize);
+
   file->device = io->device;
   file->data = gzio;
   file->fs = &grub_gzio_fs;
@@ -1151,6 +1185,7 @@ grub_gzio_open (grub_file_t io, const char *name __attribute__ ((unused)))
   if (! test_gzip_header (file))
     {
       grub_errno = GRUB_ERR_NONE;
+      grub_free (gzio->hcontext);
       grub_free (gzio);
       grub_free (file);
       grub_file_seek (io, 0);
@@ -1183,7 +1218,7 @@ test_zlib_header (grub_gzio_t gzio)
   flg = get_byte (gzio);
 
   /* Check that compression method is DEFLATE.  */
-  if ((cmf & 0xf) != DEFLATED)
+  if ((cmf & 0xf) != GRUB_GZ_DEFLATED)
     {
       /* TRANSLATORS: It's about given file having some strange format, not
 	 complete lack of gzip support.  */
@@ -1287,6 +1322,7 @@ grub_gzio_close (grub_file_t file)
   grub_file_close (gzio->file);
   huft_free (gzio->tl);
   huft_free (gzio->td);
+  grub_free (gzio->hcontext);
   grub_free (gzio);
 
   /* No need to close the same device twice.  */
diff --git a/grub-core/kern/arm/cache.c b/grub-core/kern/arm/cache.c
index 34154ccdb0e09d7d9fd91c4164fe8577ce449260..af1c4bbf544f0ebcca5c0f58c847c8dddc1f2e91 100644
--- a/grub-core/kern/arm/cache.c
+++ b/grub-core/kern/arm/cache.c
@@ -29,6 +29,8 @@ void grub_arm_clean_dcache_range_armv6 (grub_addr_t start, grub_addr_t end,
 					grub_addr_t dlinesz);
 void grub_arm_clean_dcache_range_armv7 (grub_addr_t start, grub_addr_t end,
 					grub_addr_t dlinesz);
+void grub_arm_clean_dcache_range_poc_armv7 (grub_addr_t start, grub_addr_t end,
+					    grub_addr_t dlinesz);
 void grub_arm_invalidate_icache_range_armv6 (grub_addr_t start, grub_addr_t end,
 					     grub_addr_t dlinesz);
 void grub_arm_invalidate_icache_range_armv7 (grub_addr_t start, grub_addr_t end,
@@ -252,6 +254,38 @@ grub_arch_sync_caches (void *address, grub_size_t len)
     }
 }
 
+void
+grub_arch_sync_dma_caches (volatile void *address, grub_size_t len)
+{
+  grub_addr_t start = (grub_addr_t) address;
+  grub_addr_t end = start + len;
+
+  if (type == ARCH_UNKNOWN)
+    probe_caches ();
+  start = ALIGN_DOWN (start, grub_arch_cache_max_linesz);
+  end = ALIGN_UP (end, grub_arch_cache_max_linesz);
+  switch (type)
+    {
+    case ARCH_ARMV6:
+      grub_arm_clean_dcache_range_armv6 (start, end, grub_arch_cache_dlinesz);
+      grub_arm_invalidate_icache_range_armv6 (start, end,
+					      grub_arch_cache_ilinesz);
+      break;
+    case ARCH_ARMV5_WRITE_THROUGH:
+    case ARCH_ARMV6_UNIFIED:
+      grub_arm_clean_dcache_range_armv6 (start, end, grub_arch_cache_dlinesz);
+      break;
+    case ARCH_ARMV7:
+      grub_arm_clean_dcache_range_poc_armv7 (start, end, grub_arch_cache_dlinesz);
+      grub_arm_invalidate_icache_range_armv7 (start, end,
+					      grub_arch_cache_ilinesz);
+      break;
+      /* Pacify GCC.  */
+    case ARCH_UNKNOWN:
+      break;
+    }
+}
+
 void
 grub_arm_disable_caches_mmu (void)
 {
diff --git a/grub-core/kern/arm/coreboot/cbtable.c b/grub-core/kern/arm/coreboot/cbtable.c
new file mode 100644
index 0000000000000000000000000000000000000000..8a655bb5cc28fb013674dc792531d8a9ba1c4b85
--- /dev/null
+++ b/grub-core/kern/arm/coreboot/cbtable.c
@@ -0,0 +1,40 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007,2008,2013  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/coreboot/lbio.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/dl.h>
+#include <grub/arm/startup.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+grub_linuxbios_table_header_t
+grub_linuxbios_get_tables (void)
+{
+  grub_linuxbios_table_header_t table_header
+    = (grub_linuxbios_table_header_t) grub_arm_saved_registers.r[0];
+
+  if (!grub_linuxbios_check_signature (table_header))
+    return 0;
+
+  return table_header;
+}
diff --git a/grub-core/kern/arm/coreboot/dma.c b/grub-core/kern/arm/coreboot/dma.c
new file mode 100644
index 0000000000000000000000000000000000000000..2c2a6278904631c91bd29b3c4338c606471672fe
--- /dev/null
+++ b/grub-core/kern/arm/coreboot/dma.c
@@ -0,0 +1,59 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007,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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/dma.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/mm_private.h>
+#include <grub/cache.h>
+
+struct grub_pci_dma_chunk *
+grub_memalign_dma32 (grub_size_t align, grub_size_t size)
+{
+  void *ret;
+  if (align < 64)
+    align = 64;
+  size = ALIGN_UP (size, align);
+  ret = grub_memalign (align, size);
+  if (!ret)
+    return 0;
+  grub_arch_sync_dma_caches (ret, size);
+  return ret;
+}
+
+void
+grub_dma_free (struct grub_pci_dma_chunk *ch)
+{
+  grub_size_t size = (((struct grub_mm_header *) ch) - 1)->size * GRUB_MM_ALIGN;
+  grub_arch_sync_dma_caches (ch, size);
+  grub_free (ch);
+}
+
+volatile void *
+grub_dma_get_virt (struct grub_pci_dma_chunk *ch)
+{
+  return (void *) ch;
+}
+
+grub_uint32_t
+grub_dma_get_phys (struct grub_pci_dma_chunk *ch)
+{
+  return (grub_uint32_t) (grub_addr_t) ch;
+}
+
diff --git a/grub-core/kern/arm/coreboot/init.c b/grub-core/kern/arm/coreboot/init.c
new file mode 100644
index 0000000000000000000000000000000000000000..8d8c5b8291eff9743b0325b76f851d52509b1f4f
--- /dev/null
+++ b/grub-core/kern/arm/coreboot/init.c
@@ -0,0 +1,151 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2013  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/kernel.h>
+#include <grub/mm.h>
+#include <grub/memory.h>
+#include <grub/machine/console.h>
+#include <grub/machine/kernel.h>
+#include <grub/offsets.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/loader.h>
+#include <grub/env.h>
+#include <grub/cache.h>
+#include <grub/time.h>
+#include <grub/symbol.h>
+#include <grub/video.h>
+#include <grub/coreboot/lbio.h>
+#include <grub/fdtbus.h>
+
+extern grub_uint8_t _start[];
+extern grub_uint8_t _end[];
+extern grub_uint8_t _edata[];
+grub_addr_t start_of_ram = ~(grub_addr_t)0;
+
+void  __attribute__ ((noreturn))
+grub_exit (void)
+{
+  /* 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().  */
+  while (1)
+    grub_cpu_idle ();
+}
+
+static grub_uint64_t modend;
+static int have_memory = 0;
+
+/* Helper for grub_machine_init.  */
+static int
+heap_init (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
+	   void *data __attribute__ ((unused)))
+{
+  grub_uint64_t begin = addr, end = addr + size;
+
+#if GRUB_CPU_SIZEOF_VOID_P == 4
+  /* Restrict ourselves to 32-bit memory space.  */
+  if (begin > GRUB_ULONG_MAX)
+    return 0;
+  if (end > GRUB_ULONG_MAX)
+    end = GRUB_ULONG_MAX;
+#endif
+
+  if (start_of_ram > begin)
+    start_of_ram = begin;
+
+  if (type != GRUB_MEMORY_AVAILABLE)
+    return 0;
+
+  if (modend && begin < modend)
+    {
+      if (begin < (grub_addr_t)_start)
+	{
+	  grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) ((grub_addr_t)_start - begin));
+	  have_memory = 1;
+	}
+      begin = modend;
+    }
+
+  /* Avoid DMA problems.  */
+  if (end >= 0xfe000000)
+    end = 0xfe000000;
+
+  if (end <= begin)
+    return 0;
+
+  grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) (end - begin));
+
+  have_memory = 1;
+
+  return 0;
+}
+
+void
+grub_machine_init (void)
+{
+  struct grub_module_header *header;
+  void *dtb = 0;
+  grub_size_t dtb_size = 0;
+
+  modend = grub_modules_get_end ();
+
+  grub_video_coreboot_fb_early_init ();
+
+  grub_machine_mmap_iterate (heap_init, NULL);
+  if (!have_memory)
+    grub_fatal ("No memory found");
+
+  grub_video_coreboot_fb_late_init ();
+
+  grub_font_init ();
+  grub_gfxterm_init ();
+
+  FOR_MODULES (header)
+    if (header->type == OBJ_TYPE_DTB)
+      {
+	char *dtb_orig_addr, *dtb_copy;
+	dtb_orig_addr = (char *) header + sizeof (struct grub_module_header);
+
+	dtb_size = header->size - sizeof (struct grub_module_header);
+	dtb = dtb_copy = grub_malloc (dtb_size);
+	grub_memmove (dtb_copy, dtb_orig_addr, dtb_size);
+	break;
+      }
+  if (!dtb)
+    grub_fatal ("No DTB found");
+  grub_fdtbus_init (dtb, dtb_size);
+
+  grub_rk3288_spi_init ();
+
+  grub_machine_timer_init ();
+  grub_cros_init ();
+  grub_pl050_init ();
+}
+
+void
+grub_machine_get_bootlocation (char **device __attribute__ ((unused)),
+			       char **path __attribute__ ((unused)))
+{
+}
+
+void
+grub_machine_fini (int flags __attribute__ ((unused)))
+{
+}
diff --git a/grub-core/kern/arm/coreboot/timer.c b/grub-core/kern/arm/coreboot/timer.c
new file mode 100644
index 0000000000000000000000000000000000000000..d97b844f8487c064922a552a5ea4d5f220031dba
--- /dev/null
+++ b/grub-core/kern/arm/coreboot/timer.c
@@ -0,0 +1,101 @@
+/*
+ *  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/>.
+ */
+
+#include <grub/mm.h>
+#include <grub/machine/kernel.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/time.h>
+#include <grub/fdtbus.h>
+#include <grub/misc.h>
+
+grub_uint64_t
+grub_armv7_get_timer_value(void);
+
+grub_uint32_t
+grub_armv7_get_timer_frequency(void);
+
+grub_uint32_t
+grub_arm_pfr1(void);
+
+static int have_timer = 0;
+static volatile grub_uint32_t *sp804_regs;
+
+static grub_uint64_t
+sp804_get_time_ms (void)
+{
+  static grub_uint32_t high, last_low;
+  grub_uint32_t low = ~sp804_regs[1];
+  if (last_low > low)
+    high++;
+  last_low = low;
+  return grub_divmod64 ((((grub_uint64_t) high) << 32) | low,
+			1000, 0);
+}
+
+static grub_err_t
+sp804_attach(const struct grub_fdtbus_dev *dev)
+{
+  if (have_timer)
+    return GRUB_ERR_NONE;
+  sp804_regs = grub_fdtbus_map_reg (dev, 0, 0);
+  if (!grub_fdtbus_is_mapping_valid (sp804_regs))
+    return grub_error (GRUB_ERR_IO, "could not map sp804: %p", sp804_regs);
+  grub_install_get_time_ms (sp804_get_time_ms);
+  have_timer = 1;
+  return GRUB_ERR_NONE;
+}
+
+struct grub_fdtbus_driver sp804 =
+{
+  .compatible = "arm,sp804",
+  .attach = sp804_attach
+};
+
+static grub_uint32_t timer_frequency_in_khz;
+
+static grub_uint64_t
+generic_get_time_ms (void)
+{
+  return grub_divmod64 (grub_armv7_get_timer_value(), timer_frequency_in_khz, 0);
+}
+
+static int
+try_generic_timer (void)
+{
+  if (((grub_arm_pfr1 () >> 16) & 0xf) != 1)
+    return 0;
+  grub_printf ("freq = %x\n", grub_armv7_get_timer_frequency());
+  timer_frequency_in_khz = 0x016e3600 / 1000; //grub_armv7_get_timer_frequency() / 1000;
+  if (timer_frequency_in_khz == 0)
+    return 0;
+  grub_install_get_time_ms (generic_get_time_ms);
+  have_timer = 1;
+  return 1;
+}
+
+void
+grub_machine_timer_init (void)
+{
+  grub_fdtbus_register (&sp804);
+
+  if (!have_timer)
+    try_generic_timer ();
+  if (!have_timer)
+    grub_fatal ("No timer found");
+}
diff --git a/grub-core/kern/arm/efi/misc.c b/grub-core/kern/arm/efi/misc.c
deleted file mode 100644
index 7cd41842ae7662018c2ce5ff847aeb250572ec85..0000000000000000000000000000000000000000
--- a/grub-core/kern/arm/efi/misc.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/* misc.c - various system functions for an arm-based EFI system */
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2013 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/misc.h>
-#include <grub/mm.h>
-#include <grub/cpu/linux.h>
-#include <grub/cpu/system.h>
-#include <grub/efi/efi.h>
-#include <grub/machine/loader.h>
-
-static inline grub_size_t
-page_align (grub_size_t size)
-{
-  return (size + (1 << 12) - 1) & (~((1 << 12) - 1));
-}
-
-/* Find the optimal number of pages for the memory map. Is it better to
-   move this code to efi/mm.c?  */
-static grub_efi_uintn_t
-find_mmap_size (void)
-{
-  static grub_efi_uintn_t mmap_size = 0;
-
-  if (mmap_size != 0)
-    return mmap_size;
-  
-  mmap_size = (1 << 12);
-  while (1)
-    {
-      int ret;
-      grub_efi_memory_descriptor_t *mmap;
-      grub_efi_uintn_t desc_size;
-      
-      mmap = grub_malloc (mmap_size);
-      if (! mmap)
-	return 0;
-
-      ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0);
-      grub_free (mmap);
-      
-      if (ret < 0)
-	{
-	  grub_error (GRUB_ERR_IO, "cannot get memory map");
-	  return 0;
-	}
-      else if (ret > 0)
-	break;
-
-      mmap_size += (1 << 12);
-    }
-
-  /* Increase the size a bit for safety, because GRUB allocates more on
-     later, and EFI itself may allocate more.  */
-  mmap_size += (1 << 12);
-
-  return page_align (mmap_size);
-}
-
-#define NEXT_MEMORY_DESCRIPTOR(desc, size)      \
-  ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
-#define PAGE_SHIFT 12
-
-void *
-grub_efi_allocate_loader_memory (grub_uint32_t min_offset, grub_uint32_t size)
-{
-  grub_efi_uintn_t desc_size;
-  grub_efi_memory_descriptor_t *mmap, *mmap_end;
-  grub_efi_uintn_t mmap_size, tmp_mmap_size;
-  grub_efi_memory_descriptor_t *desc;
-  void *mem = NULL;
-  grub_addr_t min_start = 0;
-
-  mmap_size = find_mmap_size();
-  if (!mmap_size)
-    return NULL;
-
-  mmap = grub_malloc(mmap_size);
-  if (!mmap)
-    return NULL;
-
-  tmp_mmap_size = mmap_size;
-  if (grub_efi_get_memory_map (&tmp_mmap_size, mmap, 0, &desc_size, 0) <= 0)
-    {
-      grub_error (GRUB_ERR_IO, "cannot get memory map");
-      goto fail;
-    }
-
-  mmap_end = NEXT_MEMORY_DESCRIPTOR (mmap, tmp_mmap_size);
-  /* Find lowest accessible RAM location */
-  {
-    int found = 0;
-    for (desc = mmap ; !found && (desc < mmap_end) ;
-	 desc = NEXT_MEMORY_DESCRIPTOR(desc, desc_size))
-      {
-	switch (desc->type)
-	  {
-	  case GRUB_EFI_CONVENTIONAL_MEMORY:
-	  case GRUB_EFI_LOADER_CODE:
-	  case GRUB_EFI_LOADER_DATA:
-	    min_start = desc->physical_start + min_offset;
-	    found = 1;
-	    break;
-	  default:
-	    break;
-	  }
-      }
-  }
-
-  /* First, find free pages for the real mode code
-     and the memory map buffer.  */
-  for (desc = mmap ; desc < mmap_end ;
-       desc = NEXT_MEMORY_DESCRIPTOR(desc, desc_size))
-    {
-      grub_uint64_t start, end;
-
-      grub_dprintf("mm", "%s: 0x%08x bytes @ 0x%08x\n",
-		   __FUNCTION__,
-		   (grub_uint32_t) (desc->num_pages << PAGE_SHIFT),
-		   (grub_uint32_t) (desc->physical_start));
-
-      if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY)
-	continue;
-
-      start = desc->physical_start;
-      end = start + (desc->num_pages << PAGE_SHIFT);
-      grub_dprintf("mm", "%s: start=0x%016llx, end=0x%016llx\n",
-		  __FUNCTION__, start, end);
-      start = start < min_start ? min_start : start;
-      if (start + size > end)
-	continue;
-      grub_dprintf("mm", "%s: let's allocate some (0x%x) pages @ 0x%08x...\n",
-		  __FUNCTION__, (size >> PAGE_SHIFT), (grub_addr_t) start);
-      mem = grub_efi_allocate_pages (start, (size >> PAGE_SHIFT) + 1);
-      grub_dprintf("mm", "%s: retval=0x%08x\n",
-		   __FUNCTION__, (grub_addr_t) mem);
-      if (! mem)
-	{
-	  grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory");
-	  goto fail;
-	}
-      break;
-    }
-
-  if (! mem)
-    {
-      grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory");
-      goto fail;
-    }
-
-  grub_free (mmap);
-  return mem;
-
- fail:
-  grub_free (mmap);
-  return NULL;
-}
-
-grub_err_t
-grub_efi_prepare_platform (void)
-{
-  grub_efi_uintn_t mmap_size;
-  grub_efi_uintn_t map_key;
-  grub_efi_uintn_t desc_size;
-  grub_efi_uint32_t desc_version;
-  grub_efi_memory_descriptor_t *mmap_buf;
-  grub_err_t err;
-
-  /*
-   * Cloned from IA64
-   * Must be done after grub_machine_fini because map_key is used by
-   *exit_boot_services.
-   */
-  mmap_size = find_mmap_size ();
-  if (! mmap_size)
-    return GRUB_ERR_OUT_OF_MEMORY;
-  mmap_buf = grub_efi_allocate_pages (0, page_align (mmap_size) >> 12);
-  if (! mmap_buf)
-    return GRUB_ERR_OUT_OF_MEMORY;
-
-  err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, &map_key,
-				       &desc_size, &desc_version);
-  if (err != GRUB_ERR_NONE)
-    return err;
-
-  return GRUB_ERR_NONE;
-}
diff --git a/grub-core/kern/arm/uboot/init.c b/grub-core/kern/arm/uboot/init.c
new file mode 100644
index 0000000000000000000000000000000000000000..2a6aa3fdd3dd049848015f6c67dfc0f30a79a9c4
--- /dev/null
+++ b/grub-core/kern/arm/uboot/init.c
@@ -0,0 +1,70 @@
+/* init.c - generic U-Boot initialization and finalization */
+/*
+ *  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/>.
+ */
+
+#include <grub/uboot/uboot.h>
+#include <grub/arm/startup.h>
+#include <grub/uboot/api_public.h>
+
+extern int (*grub_uboot_syscall_ptr) (int, int *, ...);
+
+grub_uint32_t
+grub_uboot_get_machine_type (void)
+{
+  return grub_arm_saved_registers.r[1];
+}
+
+grub_addr_t
+grub_uboot_get_boot_data (void)
+{
+  return grub_arm_saved_registers.r[2];
+}
+
+int
+grub_uboot_api_init (void)
+{
+  struct api_signature *start, *end;
+  struct api_signature *p;
+  grub_addr_t grub_uboot_search_hint = grub_arm_saved_registers.sp;
+  if (grub_uboot_search_hint)
+    {
+      /* Extended search range to work around Trim Slice U-Boot issue */
+      start = (struct api_signature *) ((grub_uboot_search_hint & ~0x000fffff)
+					- 0x00500000);
+      end =
+	(struct api_signature *) ((grub_addr_t) start + UBOOT_API_SEARCH_LEN -
+				  API_SIG_MAGLEN + 0x00500000);
+    }
+  else
+    {
+      start = 0;
+      end = (struct api_signature *) (256 * 1024 * 1024);
+    }
+
+  /* Structure alignment is (at least) 8 bytes */
+  for (p = start; p < end; p = (void *) ((grub_addr_t) p + 8))
+    {
+      if (grub_memcmp (&(p->magic), API_SIG_MAGIC, API_SIG_MAGLEN) == 0)
+	{
+	  grub_uboot_syscall_ptr = p->syscall;
+	  return p->version;
+	}
+    }
+
+  return 0;
+}
diff --git a/grub-core/kern/coreboot/cbtable.c b/grub-core/kern/coreboot/cbtable.c
new file mode 100644
index 0000000000000000000000000000000000000000..aec63dbd1209e4c3cbbe165d54a78277ea72f361
--- /dev/null
+++ b/grub-core/kern/coreboot/cbtable.c
@@ -0,0 +1,72 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2007,2008,2013  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/i386/coreboot/memory.h>
+#include <grub/coreboot/lbio.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/dl.h>
+
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+/* Helper for grub_linuxbios_table_iterate.  */
+int
+grub_linuxbios_check_signature (grub_linuxbios_table_header_t tbl_header)
+{
+  if (! grub_memcmp (tbl_header->signature, "LBIO", 4))
+    return 1;
+
+  return 0;
+}
+
+grub_err_t
+grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t,
+					   void *),
+			      void *hook_data)
+{
+  grub_linuxbios_table_header_t table_header = grub_linuxbios_get_tables ();
+  grub_linuxbios_table_item_t table_item;
+
+  if (!table_header)
+    return 0;
+
+signature_found:
+
+  table_item =
+    (grub_linuxbios_table_item_t) ((char *) table_header +
+				   table_header->header_size);
+  for (; table_item < (grub_linuxbios_table_item_t) ((char *) table_header
+						     + table_header->header_size
+						     + table_header->table_size);
+       table_item = (grub_linuxbios_table_item_t) ((char *) table_item + table_item->size))
+    {
+      if (table_item->tag == GRUB_LINUXBIOS_MEMBER_LINK
+         && grub_linuxbios_check_signature ((grub_linuxbios_table_header_t) (grub_addr_t)
+                             *(grub_uint64_t *) (table_item + 1)))
+       {
+         table_header = (grub_linuxbios_table_header_t) (grub_addr_t)
+           *(grub_uint64_t *) (table_item + 1);
+         goto signature_found;   
+       }
+      if (hook (table_item, hook_data))
+       return 1;
+    }
+
+  return 0;
+}
diff --git a/grub-core/kern/i386/coreboot/mmap.c b/grub-core/kern/coreboot/mmap.c
similarity index 97%
rename from grub-core/kern/i386/coreboot/mmap.c
rename to grub-core/kern/coreboot/mmap.c
index 4d29f6b7d90591939cf5d837b39c5d259a55efb0..caf8f7cef1b4552c720eb3b7ca355eb6cec32955 100644
--- a/grub-core/kern/i386/coreboot/mmap.c
+++ b/grub-core/kern/coreboot/mmap.c
@@ -16,8 +16,8 @@
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <grub/machine/memory.h>
-#include <grub/machine/lbio.h>
+#include <grub/memory.h>
+#include <grub/coreboot/lbio.h>
 #include <grub/types.h>
 #include <grub/err.h>
 #include <grub/misc.h>
@@ -49,6 +49,7 @@ iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, void *data)
     {
       grub_uint64_t start = mem_region->addr;
       grub_uint64_t end = mem_region->addr + mem_region->size;
+#ifdef __i386__
       /* Mark region 0xa0000 - 0x100000 as reserved.  */
       if (start < 0x100000 && end >= 0xa0000
 	  && mem_region->type == GRUB_MACHINE_MEMORY_AVAILABLE)
@@ -75,6 +76,7 @@ iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, void *data)
 	  if (end <= start)
 	    continue;
 	}
+#endif
       if (ctx->hook (start, end - start,
 		     /* Multiboot mmaps match with the coreboot mmap
 		        definition.  Therefore, we can just pass type
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index d467785fc6ce0763ec1392a65d6b30f1747ab5c4..708581fcbde007fc0174be636771b401d5e69ea2 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -154,6 +154,15 @@ grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
 				 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
 }
 
+void
+grub_reboot (void)
+{
+  grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
+  efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
+              GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
+  for (;;) ;
+}
+
 void
 grub_exit (void)
 {
diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
index 2c31847bf6db77fab377c90e7ed36897439d6027..3dfdf2d22b02ae8847a3e19a175517d2d71544fa 100644
--- a/grub-core/kern/efi/init.c
+++ b/grub-core/kern/efi/init.c
@@ -80,4 +80,5 @@ grub_efi_fini (void)
 {
   grub_efidisk_fini ();
   grub_console_fini ();
+  grub_efi_memory_fini ();
 }
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index 20a47aaf5d0df376090510ddb8337ecc8aa18e98..42ad7c570a5532c4f6a5bef9d1ff3295f413aa11 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -49,38 +49,86 @@ static grub_efi_uintn_t finish_desc_size;
 static grub_efi_uint32_t finish_desc_version;
 int grub_efi_is_finished = 0;
 
+/*
+ * We need to roll back EFI allocations on exit. Remember allocations that
+ * we'll free on exit.
+ */
+struct efi_allocation;
+struct efi_allocation {
+	grub_efi_physical_address_t address;
+	grub_efi_uint64_t pages;
+	struct efi_allocation *next;
+};
+static struct efi_allocation *efi_allocated_memory;
+
+static void
+grub_efi_store_alloc (grub_efi_physical_address_t address,
+                         grub_efi_uintn_t pages)
+{
+  grub_efi_boot_services_t *b;
+  struct efi_allocation *alloc;
+  grub_efi_status_t status;
+
+  b = grub_efi_system_table->boot_services;
+  status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA,
+                           sizeof(*alloc), (void**)&alloc);
+
+  if (status == GRUB_EFI_SUCCESS)
+    {
+      alloc->next = efi_allocated_memory;
+      alloc->address = address;
+      alloc->pages = pages;
+      efi_allocated_memory = alloc;
+    }
+  else
+      grub_printf ("Could not malloc memory to remember EFI allocation. "
+                   "Exiting GRUB won't free all memory.\n");
+}
+
+static void
+grub_efi_drop_alloc (grub_efi_physical_address_t address,
+                           grub_efi_uintn_t pages)
+{
+  struct efi_allocation *ea, *eap;
+  grub_efi_boot_services_t *b;
+
+  b = grub_efi_system_table->boot_services;
+
+  for (eap = NULL, ea = efi_allocated_memory; ea; eap = ea, ea = ea->next)
+    {
+      if (ea->address != address || ea->pages != pages)
+         continue;
+
+      /* Remove the current entry from the list. */
+      if (eap)
+        eap->next = ea->next;
+      else
+        efi_allocated_memory = ea->next;
+
+      /* Then free the memory backing it. */
+      efi_call_1 (b->free_pool, ea);
+
+      /* And leave, we're done. */
+      break;
+    }
+}
+
 /* Allocate pages. Return the pointer to the first of allocated pages.  */
 void *
-grub_efi_allocate_pages (grub_efi_physical_address_t address,
-			 grub_efi_uintn_t pages)
+grub_efi_allocate_pages_real (grub_efi_physical_address_t address,
+			      grub_efi_uintn_t pages,
+			      grub_efi_allocate_type_t alloctype,
+			      grub_efi_memory_type_t memtype)
 {
-  grub_efi_allocate_type_t type;
   grub_efi_status_t status;
   grub_efi_boot_services_t *b;
 
-#if 1
   /* Limit the memory access to less than 4GB for 32-bit platforms.  */
   if (address > GRUB_EFI_MAX_USABLE_ADDRESS)
     return 0;
-#endif
-
-#if 1
-  if (address == 0)
-    {
-      type = GRUB_EFI_ALLOCATE_MAX_ADDRESS;
-      address = GRUB_EFI_MAX_USABLE_ADDRESS;
-    }
-  else
-    type = GRUB_EFI_ALLOCATE_ADDRESS;
-#else
-  if (address == 0)
-    type = GRUB_EFI_ALLOCATE_ANY_PAGES;
-  else
-    type = GRUB_EFI_ALLOCATE_ADDRESS;
-#endif
 
   b = grub_efi_system_table->boot_services;
-  status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address);
+  status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address);
   if (status != GRUB_EFI_SUCCESS)
     return 0;
 
@@ -89,15 +137,34 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address,
       /* Uggh, the address 0 was allocated... This is too annoying,
 	 so reallocate another one.  */
       address = GRUB_EFI_MAX_USABLE_ADDRESS;
-      status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address);
+      status = efi_call_4 (b->allocate_pages, alloctype, memtype, pages, &address);
       grub_efi_free_pages (0, pages);
       if (status != GRUB_EFI_SUCCESS)
 	return 0;
     }
 
+  grub_efi_store_alloc (address, pages);
+
   return (void *) ((grub_addr_t) address);
 }
 
+void *
+grub_efi_allocate_any_pages (grub_efi_uintn_t pages)
+{
+  return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS,
+				       pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS,
+				       GRUB_EFI_LOADER_DATA);
+}
+
+void *
+grub_efi_allocate_fixed (grub_efi_physical_address_t address,
+			 grub_efi_uintn_t pages)
+{
+  return grub_efi_allocate_pages_real (address, pages,
+				       GRUB_EFI_ALLOCATE_ADDRESS,
+				       GRUB_EFI_LOADER_DATA);
+}
+
 /* Free pages starting from ADDRESS.  */
 void
 grub_efi_free_pages (grub_efi_physical_address_t address,
@@ -107,6 +174,8 @@ grub_efi_free_pages (grub_efi_physical_address_t address,
 
   b = grub_efi_system_table->boot_services;
   efi_call_2 (b->free_pages, address, pages);
+
+  grub_efi_drop_alloc (address, pages);
 }
 
 #if defined (__i386__) || defined (__x86_64__)
@@ -217,6 +286,30 @@ grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf,
   return GRUB_ERR_NONE;
 }
 
+/*
+ * To obtain the UEFI memory map, we must pass a buffer of sufficient size
+ * to hold the entire map. This function returns a sane start value for
+ * buffer size.
+ */
+grub_efi_uintn_t
+grub_efi_find_mmap_size (void)
+{
+  grub_efi_uintn_t mmap_size = 0;
+  grub_efi_uintn_t desc_size;
+
+  if (grub_efi_get_memory_map (&mmap_size, NULL, NULL, &desc_size, 0) < 0)
+    {
+      grub_error (GRUB_ERR_IO, "cannot get EFI memory map size");
+      return 0;
+    }
+
+  /*
+   * Add an extra page, since UEFI can alter the memory map itself on
+   * callbacks or explicit calls, including console output.
+   */
+  return ALIGN_UP (mmap_size + GRUB_EFI_PAGE_SIZE, GRUB_EFI_PAGE_SIZE);
+}
+
 /* Get the memory map as defined in the EFI spec. Return 1 if successful,
    return 0 if partial, or return -1 if an error occurs.  */
 int
@@ -402,7 +495,9 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
 	  pages = required_pages;
 	}
 
-      addr = grub_efi_allocate_pages (start, pages);
+      addr = grub_efi_allocate_pages_real (start, pages,
+					   GRUB_EFI_ALLOCATE_ADDRESS,
+					   GRUB_EFI_LOADER_CODE);      
       if (! addr)
 	grub_fatal ("cannot allocate conventional memory %p with %u pages",
 		    (void *) ((grub_addr_t) start),
@@ -419,6 +514,20 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
     grub_fatal ("too little memory");
 }
 
+void
+grub_efi_memory_fini (void)
+{
+  /*
+   * Free all stale allocations. grub_efi_free_pages() will remove
+   * the found entry from the list and it will always find the first
+   * list entry (efi_allocated_memory is the list start). Hence we
+   * remove all entries from the list until none is left altogether.
+   */
+  while (efi_allocated_memory)
+      grub_efi_free_pages (efi_allocated_memory->address,
+                           efi_allocated_memory->pages);
+}
+
 #if 0
 /* Print the memory map.  */
 static void
@@ -454,8 +563,7 @@ grub_efi_mm_init (void)
   int mm_status;
 
   /* Prepare a memory region to store two memory maps.  */
-  memory_map = grub_efi_allocate_pages (0,
-					2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
+  memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
   if (! memory_map)
     grub_fatal ("cannot allocate memory");
 
@@ -473,7 +581,7 @@ grub_efi_mm_init (void)
       /* Freeing/allocating operations may increase memory map size.  */
       map_size += desc_size * 32;
 
-      memory_map = grub_efi_allocate_pages (0, 2 * BYTES_TO_PAGES (map_size));
+      memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size));
       if (! memory_map)
 	grub_fatal ("cannot allocate memory");
 
@@ -525,3 +633,34 @@ grub_efi_mm_init (void)
   grub_efi_free_pages ((grub_addr_t) memory_map,
 		       2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
 }
+
+#if defined (__aarch64__) || defined (__arm__)
+grub_err_t
+grub_efi_get_ram_base(grub_addr_t *base_addr)
+{
+  grub_efi_memory_descriptor_t *memory_map, *desc;
+  grub_efi_uintn_t memory_map_size, desc_size;
+  int ret;
+
+  memory_map_size = grub_efi_find_mmap_size();
+
+  memory_map = grub_malloc (memory_map_size);
+  if (! memory_map)
+    return GRUB_ERR_OUT_OF_MEMORY;
+  ret = grub_efi_get_memory_map (&memory_map_size, memory_map, NULL,
+				 &desc_size, NULL);
+
+  if (ret < 1)
+    return GRUB_ERR_BUG;
+
+  for (desc = memory_map, *base_addr = GRUB_UINT_MAX;
+       (grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size);
+       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+    if (desc->attribute & GRUB_EFI_MEMORY_WB)
+      *base_addr = grub_min (*base_addr, desc->physical_start);
+
+  grub_free(memory_map);
+
+  return GRUB_ERR_NONE;
+}
+#endif
diff --git a/grub-core/kern/i386/coreboot/cbtable.c b/grub-core/kern/i386/coreboot/cbtable.c
index 1669bc0ca23a2fe5dcfb8e2b6c973ddb5e27e880..34a2b59be1ffa926e9dcc931140695cc82be223c 100644
--- a/grub-core/kern/i386/coreboot/cbtable.c
+++ b/grub-core/kern/i386/coreboot/cbtable.c
@@ -17,7 +17,7 @@
  */
 
 #include <grub/i386/coreboot/memory.h>
-#include <grub/i386/coreboot/lbio.h>
+#include <grub/coreboot/lbio.h>
 #include <grub/types.h>
 #include <grub/err.h>
 #include <grub/misc.h>
@@ -25,59 +25,20 @@
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
-/* Helper for grub_linuxbios_table_iterate.  */
-static int
-check_signature (grub_linuxbios_table_header_t tbl_header)
-{
-  if (! grub_memcmp (tbl_header->signature, "LBIO", 4))
-    return 1;
-
-  return 0;
-}
-
-grub_err_t
-grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t,
-					   void *),
-			      void *hook_data)
+grub_linuxbios_table_header_t
+grub_linuxbios_get_tables (void)
 {
   grub_linuxbios_table_header_t table_header;
-  grub_linuxbios_table_item_t table_item;
-
   /* Assuming table_header is aligned to its size (8 bytes).  */
-
   for (table_header = (grub_linuxbios_table_header_t) 0x500;
        table_header < (grub_linuxbios_table_header_t) 0x1000; table_header++)
-    if (check_signature (table_header))
-      goto signature_found;
+    if (grub_linuxbios_check_signature (table_header))
+      return table_header;
 
   for (table_header = (grub_linuxbios_table_header_t) 0xf0000;
        table_header < (grub_linuxbios_table_header_t) 0x100000; table_header++)
-    if (check_signature (table_header))
-      goto signature_found;
-
-  return 0;
-
-signature_found:
-
-  table_item =
-    (grub_linuxbios_table_item_t) ((char *) table_header +
-				   table_header->header_size);
-  for (; table_item < (grub_linuxbios_table_item_t) ((char *) table_header
-						     + table_header->header_size
-						     + table_header->table_size);
-       table_item = (grub_linuxbios_table_item_t) ((char *) table_item + table_item->size))
-    {
-      if (table_item->tag == GRUB_LINUXBIOS_MEMBER_LINK
-         && check_signature ((grub_linuxbios_table_header_t) (grub_addr_t)
-                             *(grub_uint64_t *) (table_item + 1)))
-       {
-         table_header = (grub_linuxbios_table_header_t) (grub_addr_t)
-           *(grub_uint64_t *) (table_item + 1);
-         goto signature_found;   
-       }
-      if (hook (table_item, hook_data))
-       return 1;
-    }
+    if (grub_linuxbios_check_signature (table_header))
+      return table_header;
 
   return 0;
 }
diff --git a/grub-core/kern/i386/tsc.c b/grub-core/kern/i386/tsc.c
index 2e85289d848946da8260b826ed36114557299278..f266eb13185f20dd4c8f67fdffa9a4790d9e01da 100644
--- a/grub-core/kern/i386/tsc.c
+++ b/grub-core/kern/i386/tsc.c
@@ -68,7 +68,7 @@ grub_tsc_init (void)
 #ifdef GRUB_MACHINE_XEN
   (void) (grub_tsc_calibrate_from_xen () || calibrate_tsc_hardcode());
 #elif defined (GRUB_MACHINE_EFI)
-  (void) (grub_tsc_calibrate_from_pit () || grub_tsc_calibrate_from_pmtimer () || grub_tsc_calibrate_from_efi() || calibrate_tsc_hardcode());
+  (void) (grub_tsc_calibrate_from_pmtimer () || grub_tsc_calibrate_from_pit () || grub_tsc_calibrate_from_efi() || calibrate_tsc_hardcode());
 #elif defined (GRUB_MACHINE_COREBOOT)
   (void) (grub_tsc_calibrate_from_pmtimer () || grub_tsc_calibrate_from_pit () || calibrate_tsc_hardcode());
 #else
diff --git a/grub-core/kern/ieee1275/ieee1275.c b/grub-core/kern/ieee1275/ieee1275.c
index 98217029f458dcef3a5b227b300762ff14cf8c52..86f81a3c4671be293d823cd3235a66dff9774faa 100644
--- a/grub-core/kern/ieee1275/ieee1275.c
+++ b/grub-core/kern/ieee1275/ieee1275.c
@@ -19,6 +19,7 @@
 
 #include <grub/ieee1275/ieee1275.h>
 #include <grub/types.h>
+#include <grub/misc.h>
 
 #define IEEE1275_PHANDLE_INVALID  ((grub_ieee1275_cell_t) -1)
 #define IEEE1275_IHANDLE_INVALID  ((grub_ieee1275_cell_t) 0)
@@ -482,6 +483,91 @@ grub_ieee1275_close (grub_ieee1275_ihandle_t ihandle)
   return 0;
 }
 
+int
+grub_ieee1275_decode_unit4 (grub_ieee1275_ihandle_t ihandle,
+                            void *addr, grub_size_t size,
+                            grub_uint32_t *phy_lo, grub_uint32_t *phy_hi,
+                            grub_uint32_t *lun_lo, grub_uint32_t *lun_hi)
+{
+  struct decode_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t size;
+    grub_ieee1275_cell_t addr;
+    grub_ieee1275_cell_t catch_result;
+    grub_ieee1275_cell_t tgt_h;
+    grub_ieee1275_cell_t tgt_l;
+    grub_ieee1275_cell_t lun_h;
+    grub_ieee1275_cell_t lun_l;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 5);
+  args.method = (grub_ieee1275_cell_t) "decode-unit";
+  args.ihandle = ihandle;
+  args.size = size;
+  args.addr = (grub_ieee1275_cell_t) addr;
+  args.catch_result = 1;
+
+  if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result))
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "decode-unit failed\n");
+      return -1;
+    }
+
+  *phy_lo = args.tgt_l;
+  *phy_hi = args.tgt_h;
+  *lun_lo = args.lun_l;
+  *lun_hi = args.lun_h;
+  return 0;
+}
+
+char *
+grub_ieee1275_encode_uint4 (grub_ieee1275_ihandle_t ihandle,
+                            grub_uint32_t phy_lo, grub_uint32_t phy_hi,
+                            grub_uint32_t lun_lo, grub_uint32_t lun_hi,
+                            grub_size_t *size)
+{
+  char *addr;
+  struct encode_args
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t tgt_h;
+    grub_ieee1275_cell_t tgt_l;
+    grub_ieee1275_cell_t lun_h;
+    grub_ieee1275_cell_t lun_l;
+    grub_ieee1275_cell_t catch_result;
+    grub_ieee1275_cell_t size;
+    grub_ieee1275_cell_t addr;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 3);
+  args.method = (grub_ieee1275_cell_t) "encode-unit";
+  args.ihandle = ihandle;
+
+  args.tgt_l = phy_lo;
+  args.tgt_h = phy_hi;
+  args.lun_l = lun_lo;
+  args.lun_h = lun_hi;
+  args.catch_result = 1;
+
+  if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result))
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "encode-unit failed\n");
+      return 0;
+    }
+
+  addr = (void *)args.addr;
+  *size = args.size;
+  addr = grub_strdup ((char *)args.addr);
+  return addr;
+}
+
 int
 grub_ieee1275_claim (grub_addr_t addr, grub_size_t size, unsigned int align,
 		     grub_addr_t *result)
@@ -607,3 +693,117 @@ grub_ieee1275_milliseconds (grub_uint32_t *msecs)
   *msecs = args.msecs;
   return 0;
 }
+
+int
+grub_ieee1275_set_address (grub_ieee1275_ihandle_t ihandle,
+                           grub_uint32_t target, grub_uint32_t lun)
+{
+  struct set_address
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t tgt;
+    grub_ieee1275_cell_t lun;
+    grub_ieee1275_cell_t catch_result;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 1);
+
+  /*
+   * IEEE 1275-1994 Standard for Boot (Initialization Configuration)
+   * Firmware: Core Requirements and Practices
+   * E.3.2.2 Bus-specific methods for bus nodes
+   *
+   * A package implementing the scsi-2 device type shall implement the
+   * following bus-specific method:
+   *
+   * set-address ( unit# target# -- )
+   * Sets the SCSI target number (0x0..0xf) and unit number (0..7) to which
+   * subsequent commands apply.
+   */
+  args.method = (grub_ieee1275_cell_t) "set-address";
+  args.ihandle = ihandle;
+  args.tgt = target;
+  args.lun = lun;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  return args.catch_result;
+}
+
+int
+grub_ieee1275_no_data_command (grub_ieee1275_ihandle_t ihandle,
+                               const void *cmd_addr, grub_ssize_t *result)
+{
+  struct set_address
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t cmd_addr;
+    grub_ieee1275_cell_t error;
+    grub_ieee1275_cell_t catch_result;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2);
+
+  /*
+   * IEEE 1275-1994 Standard for Boot (Initialization Configuration)
+   * Firmware: Core Requirements and Practices
+   *
+   * E.3.2.2 Bus-specific methods for bus nodes
+   *
+   * A package implementing the scsi-2 device type shall implement the
+   * following bus-specific method:
+   *
+   * no-data-command ( cmd-addr -- error? )
+   * Executes a simple SCSI command, automatically retrying under
+   * certain conditions.  cmd-addr is the address of a 6-byte command buffer
+   * containing an SCSI command that does not have a data transfer phase.
+   * Executes the command, retrying indefinitely with the same retry criteria
+   * as retry-command.
+   *
+   * error? is nonzero if an error occurred, zero otherwise.
+   * NOTE no-data-command is a convenience function. It provides
+   * no capabilities that are not present in retry-command, but for
+   * those commands that meet its restrictions, it is easier to use.
+   */
+  args.method = (grub_ieee1275_cell_t) "no-data-command";
+  args.ihandle = ihandle;
+  args.cmd_addr = (grub_ieee1275_cell_t) cmd_addr;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  if (result)
+    *result = args.error;
+
+  return args.catch_result;
+}
+
+int
+grub_ieee1275_get_block_size (grub_ieee1275_ihandle_t ihandle)
+{
+  struct size_args_ieee1275
+    {
+      struct grub_ieee1275_common_hdr common;
+      grub_ieee1275_cell_t method;
+      grub_ieee1275_cell_t ihandle;
+      grub_ieee1275_cell_t result;
+      grub_ieee1275_cell_t size;
+    } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 2);
+  args.method = (grub_ieee1275_cell_t) "block-size";
+  args.ihandle = ihandle;
+  args.result = 1;
+
+  if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.result))
+    return 0;
+
+  return args.size;
+}
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index 12590225eca1483066ea5e7b7443cea3198f6d9b..0d8ebf58b95e220b233e043d2b380007b48e1235 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -94,28 +94,12 @@ void
 grub_machine_get_bootlocation (char **device, char **path)
 {
   char *bootpath;
-  grub_ssize_t bootpath_size;
   char *filename;
   char *type;
 
-  if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath",
-					 &bootpath_size)
-      || bootpath_size <= 0)
-    {
-      /* Should never happen.  */
-      grub_printf ("/chosen/bootpath property missing!\n");
-      return;
-    }
-
-  bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64);
+  bootpath = grub_ieee1275_get_boot_dev ();
   if (! bootpath)
-    {
-      grub_print_error ();
-      return;
-    }
-  grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", bootpath,
-                              (grub_size_t) bootpath_size + 1, 0);
-  bootpath[bootpath_size] = '\0';
+    return;
 
   /* Transform an OF device path to a GRUB path.  */
 
@@ -126,6 +110,8 @@ grub_machine_get_bootlocation (char **device, char **path)
       char *ptr;
       dev = grub_ieee1275_get_aliasdevname (bootpath);
       canon = grub_ieee1275_canonicalise_devname (dev);
+      if (! canon)
+        return;
       ptr = canon + grub_strlen (canon) - 1;
       while (ptr > canon && (*ptr == ',' || *ptr == ':'))
 	ptr--;
diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
index ddb778340e4ab74148898b32cd27139fd4f1465b..62929d983bfaa2c83158ee4fe6797125c6d6b844 100644
--- a/grub-core/kern/ieee1275/openfw.c
+++ b/grub-core/kern/ieee1275/openfw.c
@@ -561,3 +561,30 @@ grub_ieee1275_canonicalise_devname (const char *path)
   return NULL;
 }
 
+char *
+grub_ieee1275_get_boot_dev (void)
+{
+  char *bootpath;
+  grub_ssize_t bootpath_size;
+
+  if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath",
+					 &bootpath_size)
+      || bootpath_size <= 0)
+    {
+      /* Should never happen. */
+      grub_printf ("/chosen/bootpath property missing!\n");
+      return NULL;
+    }
+
+  bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64);
+  if (! bootpath)
+    {
+      grub_print_error ();
+      return NULL;
+    }
+  grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", bootpath,
+                              (grub_size_t) bootpath_size + 1, 0);
+  bootpath[bootpath_size] = '\0';
+
+  return bootpath;
+}
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index d1a54df6c12e3358e07aa86366c65af22ca3af5c..3b633d51f4c63e2983e8b3419dc057437224fb93 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -391,12 +391,13 @@ grub_strtoull (const char *str, char **end, int base)
       unsigned long digit;
 
       digit = grub_tolower (*str) - '0';
-      if (digit > 9)
-	{
-	  digit += '0' - 'a' + 10;
-	  if (digit >= (unsigned long) base)
-	    break;
-	}
+      if (digit >= 'a' - '0')
+	digit += '0' - 'a' + 10;
+      else if (digit > 9)
+	break;
+
+      if (digit >= (unsigned long) base)
+	break;
 
       found = 1;
 
diff --git a/grub-core/kern/sparc64/ieee1275/ieee1275.c b/grub-core/kern/sparc64/ieee1275/ieee1275.c
index 53be692c3d88940572d423ceb09e4187372fcb5b..5a59aaf06193442fa5ec7a537c9cfb10dd3081aa 100644
--- a/grub-core/kern/sparc64/ieee1275/ieee1275.c
+++ b/grub-core/kern/sparc64/ieee1275/ieee1275.c
@@ -89,3 +89,59 @@ grub_ieee1275_alloc_physmem (grub_addr_t *paddr, grub_size_t size,
 
   return args.catch_result;
 }
+
+grub_uint64_t
+grub_ieee1275_num_blocks (grub_ieee1275_ihandle_t ihandle)
+{
+  struct nblocks_args_ieee1275
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t catch_result;
+    grub_ieee1275_cell_t blocks;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 2);
+  args.method = (grub_ieee1275_cell_t) "#blocks";
+  args.ihandle = ihandle;
+  args.catch_result = 1;
+
+  if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result != 0))
+    return -1;
+
+  /*
+   * If the number of blocks exceeds the range of an unsigned number,
+   * return 0 to alert the caller to try the #blocks64 command.
+   */
+  if (args.blocks >= 0xffffffffULL)
+    return 0;
+
+  return args.blocks;
+}
+
+grub_uint64_t
+grub_ieee1275_num_blocks64 (grub_ieee1275_ihandle_t ihandle)
+{
+  struct nblocks_args_ieee1275
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t catch_result;
+    grub_ieee1275_cell_t hi_blocks;
+    grub_ieee1275_cell_t lo_blocks;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3);
+  args.method = (grub_ieee1275_cell_t) "#blocks64";
+  args.ihandle = ihandle;
+  args.catch_result = 1;
+
+  if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result != 0))
+    return -1;
+
+  return ((args.hi_blocks << 32) | (args.lo_blocks));
+}
diff --git a/grub-core/kern/uboot/init.c b/grub-core/kern/uboot/init.c
index 5dcc106ed9bcc1fa2cdbe2ba6cbb9e709420ceb3..3e338645c573aa707343235029d9fc45d515a9dc 100644
--- a/grub-core/kern/uboot/init.c
+++ b/grub-core/kern/uboot/init.c
@@ -36,30 +36,14 @@
 extern char __bss_start[];
 extern char _end[];
 extern grub_size_t grub_total_module_size;
-extern int (*grub_uboot_syscall_ptr) (int, int *, ...);
 static unsigned long timer_start;
 
-extern grub_uint32_t grub_uboot_machine_type;
-extern grub_addr_t grub_uboot_boot_data;
-
 void
 grub_exit (void)
 {
   grub_uboot_return (0);
 }
 
-grub_uint32_t
-grub_uboot_get_machine_type (void)
-{
-  return grub_uboot_machine_type;
-}
-
-grub_addr_t
-grub_uboot_get_boot_data (void)
-{
-  return grub_uboot_boot_data;
-}
-
 static grub_uint64_t
 uboot_timer_ms (void)
 {
diff --git a/grub-core/kern/uboot/uboot.c b/grub-core/kern/uboot/uboot.c
index 6800a4beb1c4e83ef9f4ac5da872d2557d8471e1..cf0168e62ddd26db50efd2351499fa7f74fce26c 100644
--- a/grub-core/kern/uboot/uboot.c
+++ b/grub-core/kern/uboot/uboot.c
@@ -39,48 +39,13 @@
  * returns:	0 if the call not found, 1 if serviced
  */
 
-extern int (*grub_uboot_syscall_ptr) (int, int *, ...);
 extern int grub_uboot_syscall (int, int *, ...);
-extern grub_addr_t grub_uboot_search_hint;
 
 static struct sys_info uboot_sys_info;
 static struct mem_region uboot_mem_info[5];
 static struct device_info * devices;
 static int num_devices;
 
-int
-grub_uboot_api_init (void)
-{
-  struct api_signature *start, *end;
-  struct api_signature *p;
-
-  if (grub_uboot_search_hint)
-    {
-      /* Extended search range to work around Trim Slice U-Boot issue */
-      start = (struct api_signature *) ((grub_uboot_search_hint & ~0x000fffff)
-					- 0x00500000);
-      end =
-	(struct api_signature *) ((grub_addr_t) start + UBOOT_API_SEARCH_LEN -
-				  API_SIG_MAGLEN + 0x00500000);
-    }
-  else
-    {
-      start = 0;
-      end = (struct api_signature *) (256 * 1024 * 1024);
-    }
-
-  /* Structure alignment is (at least) 8 bytes */
-  for (p = start; p < end; p = (void *) ((grub_addr_t) p + 8))
-    {
-      if (grub_memcmp (&(p->magic), API_SIG_MAGIC, API_SIG_MAGLEN) == 0)
-	{
-	  grub_uboot_syscall_ptr = p->syscall;
-	  return p->version;
-	}
-    }
-
-  return 0;
-}
 
 /*
  * All functions below are wrappers around the grub_uboot_syscall() function
diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c
index 44069067312a890b4e3ebb5130861ed23572bc54..3a73e6e6ce2c5aefc33313e583cb259ea9bc2645 100644
--- a/grub-core/kern/x86_64/dl.c
+++ b/grub-core/kern/x86_64/dl.c
@@ -70,6 +70,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
 	  break;
 
 	case R_X86_64_PC32:
+	case R_X86_64_PLT32:
 	  {
 	    grub_int64_t value;
 	    value = ((grub_int32_t) *addr32) + rel->r_addend + sym->st_value -
diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c
index 683a8aaa711c4eab0208d116cd7275a6ac678986..ca334d5a40e0716bdc9afbb79135c47d174532da 100644
--- a/grub-core/lib/crypto.c
+++ b/grub-core/lib/crypto.c
@@ -462,7 +462,7 @@ grub_password_get (char buf[], unsigned buf_size)
       if (key == '\n' || key == '\r')
 	break;
 
-      if (key == '\e')
+      if (key == GRUB_TERM_ESC)
 	{
 	  cur_len = 0;
 	  break;
@@ -487,7 +487,7 @@ grub_password_get (char buf[], unsigned buf_size)
   grub_xputs ("\n");
   grub_refresh ();
 
-  return (key != '\e');
+  return (key != GRUB_TERM_ESC);
 }
 #endif
 
diff --git a/grub-core/lib/uboot/datetime.c b/grub-core/lib/dummy/datetime.c
similarity index 91%
rename from grub-core/lib/uboot/datetime.c
rename to grub-core/lib/dummy/datetime.c
index 4be716928a55b789510dfdcdd1833e29e5cd11fe..cf693fc6b621376b5cae0ca0a74b4421799b5a9e 100644
--- a/grub-core/lib/uboot/datetime.c
+++ b/grub-core/lib/dummy/datetime.c
@@ -18,7 +18,6 @@
 
 #include <grub/types.h>
 #include <grub/symbol.h>
-#include <grub/uboot/uboot.h>
 #include <grub/datetime.h>
 #include <grub/dl.h>
 
@@ -30,12 +29,12 @@ grub_err_t
 grub_get_datetime (struct grub_datetime *datetime __attribute__ ((unused)))
 {
   return grub_error (GRUB_ERR_INVALID_COMMAND,
-		     "can\'t get datetime using U-Boot");
+		     "can\'t get datetime on this machine");
 }
 
 grub_err_t
 grub_set_datetime (struct grub_datetime * datetime __attribute__ ((unused)))
 {
   return grub_error (GRUB_ERR_INVALID_COMMAND,
-		     "can\'t set datetime using U-Boot");
+		     "can\'t set datetime on this machine");
 }
diff --git a/grub-core/lib/uboot/halt.c b/grub-core/lib/dummy/halt.c
similarity index 100%
rename from grub-core/lib/uboot/halt.c
rename to grub-core/lib/dummy/halt.c
diff --git a/grub-core/lib/efi/reboot.c b/grub-core/lib/dummy/reboot.c
similarity index 77%
rename from grub-core/lib/efi/reboot.c
rename to grub-core/lib/dummy/reboot.c
index 7de8bcb5d6ea128dd406001d970d18ff00ea0f3c..b8cbed8f8117ca9c53cc2087dee87ae68876d64f 100644
--- a/grub-core/lib/efi/reboot.c
+++ b/grub-core/lib/dummy/reboot.c
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2011  Free Software Foundation, Inc.
+ *  Copyright (C) 2013  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
@@ -16,10 +16,8 @@
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <grub/efi/api.h>
-#include <grub/efi/efi.h>
-#include <grub/mm.h>
 #include <grub/misc.h>
+#include <grub/mm.h>
 #include <grub/kernel.h>
 #include <grub/loader.h>
 
@@ -27,7 +25,8 @@ void
 grub_reboot (void)
 {
   grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
-  efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
-              GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
-  for (;;) ;
+
+  /* Just stop here */
+
+  while (1);
 }
diff --git a/grub-core/lib/fdt.c b/grub-core/lib/fdt.c
index b5d520f208886aa663d4aac36cec9b43a2d0da42..0d371c5633e84bbf47114bfe2c23427982e25192 100644
--- a/grub-core/lib/fdt.c
+++ b/grub-core/lib/fdt.c
@@ -41,11 +41,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
 	(2 * sizeof(grub_uint32_t)	\
 	+ ALIGN_UP (grub_strlen (name) + 1, sizeof(grub_uint32_t)))
 
-/* Size needed by a property entry: 1 token (FDT_PROPERTY), plus len and nameoff
-   fields, plus the property value, plus padding if needed. */
-#define prop_entry_size(prop_len)	\
-	(3 * sizeof(grub_uint32_t) + ALIGN_UP(prop_len, sizeof(grub_uint32_t)))
-
 #define SKIP_NODE_NAME(name, token, end)	\
   name = (char *) ((token) + 1);	\
   while (name < (char *) end)	\
@@ -86,7 +81,7 @@ static grub_uint32_t *get_next_node (const void *fdt, char *node_name)
       case FDT_PROP:
         /* Skip property token and following data (len, nameoff and property
            value). */
-        token += prop_entry_size(grub_be_to_cpu32(*(token + 1)))
+        token += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(token + 1)))
                  / sizeof(*token);
         break;
       case FDT_NOP:
@@ -102,13 +97,13 @@ static grub_uint32_t *get_next_node (const void *fdt, char *node_name)
 static int get_mem_rsvmap_size (const void *fdt)
 {
   int size = 0;
-  grub_uint64_t *ptr = (void *) ((grub_addr_t) fdt
-                                 + grub_fdt_get_off_mem_rsvmap (fdt));
+  grub_unaligned_uint64_t *ptr = (void *) ((grub_addr_t) fdt
+					   + grub_fdt_get_off_mem_rsvmap (fdt));
 
   do
   {
     size += 2 * sizeof(*ptr);
-    if (!*ptr && !*(ptr + 1))
+    if (!ptr[0].val && !ptr[1].val)
       return size;
     ptr += 2;
   } while ((grub_addr_t) ptr <= (grub_addr_t) fdt + grub_fdt_get_totalsize (fdt)
@@ -150,7 +145,7 @@ static int add_subnode (void *fdt, int parentoffset, const char *name)
     {
       case FDT_PROP:
         /* Skip len, nameoff and property value. */
-        token += prop_entry_size(grub_be_to_cpu32(*(token + 1)))
+        token += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(token + 1)))
                  / sizeof(*token);
         break;
       case FDT_BEGIN_NODE:
@@ -229,7 +224,7 @@ static int rearrange_blocks (void *fdt, unsigned int clearance)
   return 0;
 }
 
-static grub_uint32_t *find_prop (void *fdt, unsigned int nodeoffset,
+static grub_uint32_t *find_prop (const void *fdt, unsigned int nodeoffset,
 				 const char *name)
 {
   grub_uint32_t *prop = (void *) ((grub_addr_t) fdt
@@ -249,12 +244,12 @@ static grub_uint32_t *find_prop (void *fdt, unsigned int nodeoffset,
             && !grub_strcmp (name, (char *) fdt +
                              grub_fdt_get_off_dt_strings (fdt) + nameoff))
         {
-          if (prop + prop_entry_size(grub_be_to_cpu32(*(prop + 1)))
+          if (prop + grub_fdt_prop_entry_size(grub_be_to_cpu32(*(prop + 1)))
               / sizeof (*prop) >= end)
             return NULL;
           return prop;
         }
-        prop += prop_entry_size(grub_be_to_cpu32(*(prop + 1))) / sizeof (*prop);
+        prop += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(prop + 1))) / sizeof (*prop);
       }
     else if (grub_be_to_cpu32(*prop) == FDT_NOP)
       prop++;
@@ -268,9 +263,9 @@ static grub_uint32_t *find_prop (void *fdt, unsigned int nodeoffset,
    the size allocated for the FDT; if this function is called before the other
    functions in this file and returns success, the other functions are
    guaranteed not to access memory locations outside the allocated memory. */
-int grub_fdt_check_header_nosize (void *fdt)
+int grub_fdt_check_header_nosize (const void *fdt)
 {
-  if (((grub_addr_t) fdt & 0x7) || (grub_fdt_get_magic (fdt) != FDT_MAGIC)
+  if (((grub_addr_t) fdt & 0x3) || (grub_fdt_get_magic (fdt) != FDT_MAGIC)
       || (grub_fdt_get_version (fdt) < FDT_SUPPORTED_VERSION)
       || (grub_fdt_get_last_comp_version (fdt) > FDT_SUPPORTED_VERSION)
       || (grub_fdt_get_off_dt_struct (fdt) & 0x00000003)
@@ -286,7 +281,7 @@ int grub_fdt_check_header_nosize (void *fdt)
   return 0;
 }
 
-int grub_fdt_check_header (void *fdt, unsigned int size)
+int grub_fdt_check_header (const void *fdt, unsigned int size)
 {
   if (size < sizeof (grub_fdt_header_t)
       || (grub_fdt_get_totalsize (fdt) > size)
@@ -295,52 +290,105 @@ int grub_fdt_check_header (void *fdt, unsigned int size)
   return 0;
 }
 
+static const grub_uint32_t *
+advance_token (const void *fdt, const grub_uint32_t *token, const grub_uint32_t *end, int skip_current)
+{
+  for (; token < end; skip_current = 0)
+  {
+    switch (grub_be_to_cpu32 (*token))
+    {
+      case FDT_BEGIN_NODE:
+	if (skip_current)
+	  {
+	    token = get_next_node (fdt, (char *) (token + 1));
+	    continue;
+	  }
+	char *ptr;
+	for (ptr = (char *) (token + 1); *ptr && ptr < (char *) end; ptr++)
+	  ;
+        if (ptr >= (char *) end)
+          return 0;
+	return token;
+      case FDT_PROP:
+        /* Skip property token and following data (len, nameoff and property
+           value). */
+        if (token >= end - 1)
+          return 0;
+        token += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(token + 1)))
+                 / sizeof(*token);
+        break;
+      case FDT_NOP:
+        token++;
+        break;
+      default:
+        return 0;
+    }
+  }
+  return 0;
+}
+
+int grub_fdt_next_node (const void *fdt, unsigned int currentoffset)
+{
+  const grub_uint32_t *token = (const grub_uint32_t *) fdt + (currentoffset + grub_fdt_get_off_dt_struct (fdt)) / 4;
+  token = advance_token (fdt, token, (const void *) struct_end (fdt), 1);
+  if (!token)
+    return -1;
+  return (int) ((grub_addr_t) token - (grub_addr_t) fdt
+		- grub_fdt_get_off_dt_struct (fdt));
+}			 
+
+int grub_fdt_first_node (const void *fdt, unsigned int parentoffset)
+{
+  const grub_uint32_t *token, *end;
+  char *node_name;
+
+  if (parentoffset & 0x3)
+    return -1;
+  token = (const void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt)
+                    + parentoffset);
+  end = (const void *) struct_end (fdt);
+  if ((token >= end) || (grub_be_to_cpu32(*token) != FDT_BEGIN_NODE))
+    return -1;
+  SKIP_NODE_NAME(node_name, token, end);
+  token = advance_token (fdt, token, end, 0);
+  if (!token)
+    return -1;
+  return (int) ((grub_addr_t) token - (grub_addr_t) fdt
+		- grub_fdt_get_off_dt_struct (fdt));
+}			 
+
 /* Find a direct sub-node of a given parent node. */
 int grub_fdt_find_subnode (const void *fdt, unsigned int parentoffset,
 			   const char *name)
 {
-  grub_uint32_t *token, *end;
-  char *node_name;
+  const grub_uint32_t *token, *end;
+  const char *node_name;
+  int skip_current = 0;
 
   if (parentoffset & 0x3)
     return -1;
-  token = (void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt)
+  token = (const void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt)
                     + parentoffset);
-  end = (void *) struct_end (fdt);
+  end = (const void *) struct_end (fdt);
   if ((token >= end) || (grub_be_to_cpu32(*token) != FDT_BEGIN_NODE))
     return -1;
   SKIP_NODE_NAME(node_name, token, end);
-  while (token < end)
-  {
-    switch (grub_be_to_cpu32(*token))
-    {
-      case FDT_BEGIN_NODE:
-        node_name = (char *) (token + 1);
-        if (node_name + grub_strlen (name) >= (char *) end)
-          return -1;
-        if (!grub_strcmp (node_name, name))
-          return (int) ((grub_addr_t) token - (grub_addr_t) fdt
-                        - grub_fdt_get_off_dt_struct (fdt));
-        token = get_next_node (fdt, node_name);
-        if (!token)
-          return -1;
-        break;
-      case FDT_PROP:
-        /* Skip property token and following data (len, nameoff and property
-           value). */
-        if (token >= end - 1)
-          return -1;
-        token += prop_entry_size(grub_be_to_cpu32(*(token + 1)))
-                 / sizeof(*token);
-        break;
-      case FDT_NOP:
-        token++;
-        break;
-      default:
-        return -1;
-    }
+  while (1) {
+    token = advance_token (fdt, token, end, skip_current);
+    if (!token)
+      return -1;
+    skip_current = 1;
+    node_name = (const char *) token + 4;
+    if (grub_strcmp (node_name, name) == 0)
+      return (int) ((grub_addr_t) token - (grub_addr_t) fdt
+		    - grub_fdt_get_off_dt_struct (fdt));
   }
-  return -1;
+}
+
+const char *
+grub_fdt_get_nodename (const void *fdt, unsigned int nodeoffset)
+{
+  return (const char *) fdt + grub_fdt_get_off_dt_struct(fdt) + nodeoffset + 4;
 }
 
 int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset,
@@ -359,6 +407,24 @@ int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset,
   return add_subnode (fdt, parentoffset, name);
 }
 
+const void *
+grub_fdt_get_prop (const void *fdt, unsigned int nodeoffset, const char *name,
+		   grub_uint32_t *len)
+{
+  grub_uint32_t *prop;
+  if ((nodeoffset >= grub_fdt_get_size_dt_struct (fdt)) || (nodeoffset & 0x3)
+      || (grub_be_to_cpu32(*(grub_uint32_t *) ((grub_addr_t) fdt
+					       + grub_fdt_get_off_dt_struct (fdt) + nodeoffset))
+          != FDT_BEGIN_NODE))
+    return 0;
+  prop = find_prop (fdt, nodeoffset, name);
+  if (!prop)
+    return 0;
+  if (len)
+    *len = grub_be_to_cpu32 (*(prop + 1));
+  return prop + 3;
+}
+
 int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
 		       const void *val, grub_uint32_t len)
 {
@@ -396,12 +462,12 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
     unsigned int needed_space = 0;
 
     if (!prop)
-      needed_space = prop_entry_size(len);
+      needed_space = grub_fdt_prop_entry_size(len);
     if (!prop_name_present)
       needed_space += grub_strlen (name) + 1;
     if (needed_space > get_free_space (fdt))
       return -1;
-    if (rearrange_blocks (fdt, !prop ? prop_entry_size(len) : 0) < 0)
+    if (rearrange_blocks (fdt, !prop ? grub_fdt_prop_entry_size(len) : 0) < 0)
       return -1;
   }
   if (!prop_name_present) {
@@ -418,10 +484,10 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
                                 + sizeof(grub_uint32_t));
 
     prop = (void *) (node_name + ALIGN_UP(grub_strlen(node_name) + 1, 4));
-    grub_memmove (prop + prop_entry_size(len) / sizeof(*prop), prop,
+    grub_memmove (prop + grub_fdt_prop_entry_size(len) / sizeof(*prop), prop,
                   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));
+                                 + grub_fdt_prop_entry_size(len));
     *prop = grub_cpu_to_be32_compile_time (FDT_PROP);
     *(prop + 2) = grub_cpu_to_be32 (nameoff);
   }
@@ -429,7 +495,7 @@ int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
 
   /* Insert padding bytes at the end of the value; if they are not needed, they
      will be overwritten by the following memcpy. */
-  *(prop + prop_entry_size(len) / sizeof(grub_uint32_t) - 1) = 0;
+  *(prop + grub_fdt_prop_entry_size(len) / sizeof(grub_uint32_t) - 1) = 0;
 
   grub_memcpy (prop + 3, val, len);
   return 0;
diff --git a/grub-core/lib/i386/reboot.c b/grub-core/lib/i386/reboot.c
index a234244dce5b4c5afd5c68e579c4519a870cda36..dce0b563dcd39ce7acc6d5ec0cc759e67c8c8b87 100644
--- a/grub-core/lib/i386/reboot.c
+++ b/grub-core/lib/i386/reboot.c
@@ -16,6 +16,8 @@
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifndef GRUB_MACHINE_EFI
+
 #include <grub/relocator.h>
 #include <grub/cpu/relocator.h>
 #include <grub/misc.h>
@@ -58,3 +60,5 @@ grub_reboot (void)
 
   while (1);
 }
+
+#endif /* GRUB_MACHINE_EFI */
diff --git a/grub-core/lib/libgcrypt/cipher/crc.c b/grub-core/lib/libgcrypt/cipher/crc.c
index 9e406f1b19b4d1d49c1ba5140c47d630972c0d8e..28454f8ab728c657d0b440371765030deb35a407 100644
--- a/grub-core/lib/libgcrypt/cipher/crc.c
+++ b/grub-core/lib/libgcrypt/cipher/crc.c
@@ -28,116 +28,8 @@
 #include "cipher.h"
 
 #include "bithelp.h"
+#include "bufhelp.h"
 
-/* Table of CRCs of all 8-bit messages.  Generated by running code
-   from RFC 1952 modified to print out the table. */
-static u32 crc32_table[256] = {
-  0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
-  0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
-  0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
-  0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
-  0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
-  0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
-  0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
-  0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
-  0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
-  0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
-  0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
-  0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
-  0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
-  0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
-  0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
-  0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
-  0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
-  0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
-  0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
-  0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
-  0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
-  0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
-  0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
-  0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
-  0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
-  0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
-  0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
-  0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
-  0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
-  0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
-  0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
-  0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
-  0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
-  0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
-  0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
-  0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
-  0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
-  0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
-  0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
-  0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
-  0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
-  0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
-  0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-/*
- * The following function was extracted from RFC 1952 by Simon
- * Josefsson, for the Shishi project, and modified to be compatible
- * with the modified CRC-32 used by RFC 1510, and subsequently
- * modified for GNU Libgcrypt to allow it to be used for calculating
- * both unmodified CRC-32 and modified CRC-32 values.  Original
- * copyright and notice from the document follows:
- *
- *    Copyright (c) 1996 L. Peter Deutsch
- *
- *    Permission is granted to copy and distribute this document for
- *    any purpose and without charge, including translations into
- *    other languages and incorporation into compilations, provided
- *    that the copyright notice and this notice are preserved, and
- *    that any substantive changes or deletions from the original are
- *    clearly marked.
- *
- * The copyright on RFCs, and consequently the function below, are
- * supposedly also retroactively claimed by the Internet Society
- * (according to rfc-editor@rfc-editor.org), with the following
- * copyright notice:
- *
- *    Copyright (C) The Internet Society.  All Rights Reserved.
- *
- *    This document and translations of it may be copied and furnished
- *    to others, and derivative works that comment on or otherwise
- *    explain it or assist in its implementation may be prepared,
- *    copied, published and distributed, in whole or in part, without
- *    restriction of any kind, provided that the above copyright
- *    notice and this paragraph are included on all such copies and
- *    derivative works.  However, this document itself may not be
- *    modified in any way, such as by removing the copyright notice or
- *    references to the Internet Society or other Internet
- *    organizations, except as needed for the purpose of developing
- *    Internet standards in which case the procedures for copyrights
- *    defined in the Internet Standards process must be followed, or
- *    as required to translate it into languages other than English.
- *
- *    The limited permissions granted above are perpetual and will not be
- *    revoked by the Internet Society or its successors or assigns.
- *
- *    This document and the information contained herein is provided
- *    on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET
- *    ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR
- *    IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE
- *    OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY
- *    IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
- *    PARTICULAR PURPOSE.
- *
- */
-static u32
-update_crc32 (u32 crc, const void *buf_arg, size_t len)
-{
-  const char *buf = buf_arg;
-  size_t n;
-
-  for (n = 0; n < len; n++)
-    crc = crc32_table[(crc ^ buf[n]) & 0xff] ^ (crc >> 8);
-
-  return crc;
-}
 
 typedef struct
 {
@@ -146,8 +38,302 @@ typedef struct
 }
 CRC_CONTEXT;
 
+
+/*
+ * Code generated by universal_crc by Danjel McGougan
+ *
+ * CRC parameters used:
+ *   bits:       32
+ *   poly:       0x04c11db7
+ *   init:       0xffffffff
+ *   xor:        0xffffffff
+ *   reverse:    true
+ *   non-direct: false
+ *
+ * CRC of the string "123456789" is 0xcbf43926
+ */
+
+static const u32 crc32_table[1024] = {
+  0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+  0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+  0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+  0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+  0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+  0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+  0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+  0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+  0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+  0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+  0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+  0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+  0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+  0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+  0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+  0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+  0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+  0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+  0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+  0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+  0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+  0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+  0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+  0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+  0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+  0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+  0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+  0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+  0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+  0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+  0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+  0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+  0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+  0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+  0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+  0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+  0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+  0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+  0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+  0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+  0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+  0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+  0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+  0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+  0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+  0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+  0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+  0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+  0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+  0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+  0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+  0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+  0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+  0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+  0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+  0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+  0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+  0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+  0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+  0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+  0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+  0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+  0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+  0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+  0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3,
+  0x646cc504, 0x7d77f445, 0x565aa786, 0x4f4196c7,
+  0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb,
+  0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, 0x87981ccf,
+  0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+  0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496,
+  0x821b9859, 0x9b00a918, 0xb02dfadb, 0xa936cb9a,
+  0xe6775d5d, 0xff6c6c1c, 0xd4413fdf, 0xcd5a0e9e,
+  0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761,
+  0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+  0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69,
+  0x39316bae, 0x202a5aef, 0x0b07092c, 0x121c386d,
+  0xdf4636f3, 0xc65d07b2, 0xed705471, 0xf46b6530,
+  0xbb2af3f7, 0xa231c2b6, 0x891c9175, 0x9007a034,
+  0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+  0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c,
+  0xf0794f05, 0xe9627e44, 0xc24f2d87, 0xdb541cc6,
+  0x94158a01, 0x8d0ebb40, 0xa623e883, 0xbf38d9c2,
+  0x38a0c50d, 0x21bbf44c, 0x0a96a78f, 0x138d96ce,
+  0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+  0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97,
+  0xded79850, 0xc7cca911, 0xece1fad2, 0xf5facb93,
+  0x7262d75c, 0x6b79e61d, 0x4054b5de, 0x594f849f,
+  0x160e1258, 0x0f152319, 0x243870da, 0x3d23419b,
+  0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+  0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60,
+  0xad24e1af, 0xb43fd0ee, 0x9f12832d, 0x8609b26c,
+  0xc94824ab, 0xd05315ea, 0xfb7e4629, 0xe2657768,
+  0x2f3f79f6, 0x362448b7, 0x1d091b74, 0x04122a35,
+  0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+  0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d,
+  0x838a36fa, 0x9a9107bb, 0xb1bc5478, 0xa8a76539,
+  0x3b83984b, 0x2298a90a, 0x09b5fac9, 0x10aecb88,
+  0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, 0x74c20e8c,
+  0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+  0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484,
+  0x71418a1a, 0x685abb5b, 0x4377e898, 0x5a6cd9d9,
+  0x152d4f1e, 0x0c367e5f, 0x271b2d9c, 0x3e001cdd,
+  0xb9980012, 0xa0833153, 0x8bae6290, 0x92b553d1,
+  0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+  0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a,
+  0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e,
+  0x66de36e1, 0x7fc507a0, 0x54e85463, 0x4df36522,
+  0x02b2f3e5, 0x1ba9c2a4, 0x30849167, 0x299fa026,
+  0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+  0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f,
+  0x2c1c24b0, 0x350715f1, 0x1e2a4632, 0x07317773,
+  0x4870e1b4, 0x516bd0f5, 0x7a468336, 0x635db277,
+  0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d,
+  0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+  0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85,
+  0x674f9842, 0x7e54a903, 0x5579fac0, 0x4c62cb81,
+  0x8138c51f, 0x9823f45e, 0xb30ea79d, 0xaa1596dc,
+  0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8,
+  0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+  0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0,
+  0x5e7ef3ec, 0x4765c2ad, 0x6c48916e, 0x7553a02f,
+  0x3a1236e8, 0x230907a9, 0x0824546a, 0x113f652b,
+  0x96a779e4, 0x8fbc48a5, 0xa4911b66, 0xbd8a2a27,
+  0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+  0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e,
+  0x70d024b9, 0x69cb15f8, 0x42e6463b, 0x5bfd777a,
+  0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876,
+  0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, 0x9324fd72,
+  0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59,
+  0x0709a8dc, 0x06cbc2eb, 0x048d7cb2, 0x054f1685,
+  0x0e1351b8, 0x0fd13b8f, 0x0d9785d6, 0x0c55efe1,
+  0x091af964, 0x08d89353, 0x0a9e2d0a, 0x0b5c473d,
+  0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+  0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5,
+  0x1235f2c8, 0x13f798ff, 0x11b126a6, 0x10734c91,
+  0x153c5a14, 0x14fe3023, 0x16b88e7a, 0x177ae44d,
+  0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9,
+  0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+  0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901,
+  0x3157bf84, 0x3095d5b3, 0x32d36bea, 0x331101dd,
+  0x246be590, 0x25a98fa7, 0x27ef31fe, 0x262d5bc9,
+  0x23624d4c, 0x22a0277b, 0x20e69922, 0x2124f315,
+  0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+  0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad,
+  0x709a8dc0, 0x7158e7f7, 0x731e59ae, 0x72dc3399,
+  0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45,
+  0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, 0x7ccf6221,
+  0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+  0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9,
+  0x6bb5866c, 0x6a77ec5b, 0x68315202, 0x69f33835,
+  0x62af7f08, 0x636d153f, 0x612bab66, 0x60e9c151,
+  0x65a6d7d4, 0x6464bde3, 0x662203ba, 0x67e0698d,
+  0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+  0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5,
+  0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1,
+  0x41cd3244, 0x400f5873, 0x4249e62a, 0x438b8c1d,
+  0x54f16850, 0x55330267, 0x5775bc3e, 0x56b7d609,
+  0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+  0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1,
+  0x5deb9134, 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d,
+  0xe1351b80, 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9,
+  0xe63cb35c, 0xe7fed96b, 0xe5b86732, 0xe47a0d05,
+  0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+  0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd,
+  0xfd13b8f0, 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9,
+  0xfa1a102c, 0xfbd87a1b, 0xf99ec442, 0xf85cae75,
+  0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711,
+  0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+  0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339,
+  0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5,
+  0xd76b0cd8, 0xd6a966ef, 0xd4efd8b6, 0xd52db281,
+  0xd062a404, 0xd1a0ce33, 0xd3e6706a, 0xd2241a5d,
+  0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+  0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895,
+  0xcb4dafa8, 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1,
+  0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d,
+  0x91af9640, 0x906dfc77, 0x922b422e, 0x93e92819,
+  0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+  0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1,
+  0x98b56f24, 0x99770513, 0x9b31bb4a, 0x9af3d17d,
+  0x8d893530, 0x8c4b5f07, 0x8e0de15e, 0x8fcf8b69,
+  0x8a809dec, 0x8b42f7db, 0x89044982, 0x88c623b5,
+  0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+  0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d,
+  0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, 0xaba46ef9,
+  0xaeeb787c, 0xaf29124b, 0xad6fac12, 0xacadc625,
+  0xa7f18118, 0xa633eb2f, 0xa4755576, 0xa5b73f41,
+  0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+  0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89,
+  0xb2cddb0c, 0xb30fb13b, 0xb1490f62, 0xb08b6555,
+  0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31,
+  0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, 0xbe9834ed,
+  0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee,
+  0x8f629757, 0x37def032, 0x256b5fdc, 0x9dd738b9,
+  0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701,
+  0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, 0x58631056,
+  0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+  0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26,
+  0x95ad7f70, 0x2d111815, 0x3fa4b7fb, 0x8718d09e,
+  0x1acfe827, 0xa2738f42, 0xb0c620ac, 0x087a47c9,
+  0xa032af3e, 0x188ec85b, 0x0a3b67b5, 0xb28700d0,
+  0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+  0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f,
+  0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68,
+  0xf02bf8a1, 0x48979fc4, 0x5a22302a, 0xe29e574f,
+  0x7f496ff6, 0xc7f50893, 0xd540a77d, 0x6dfcc018,
+  0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+  0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7,
+  0x9b14583d, 0x23a83f58, 0x311d90b6, 0x89a1f7d3,
+  0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, 0x06c36084,
+  0x5ea070d2, 0xe61c17b7, 0xf4a9b859, 0x4c15df3c,
+  0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+  0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c,
+  0x446f98f5, 0xfcd3ff90, 0xee66507e, 0x56da371b,
+  0x0eb9274d, 0xb6054028, 0xa4b0efc6, 0x1c0c88a3,
+  0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4,
+  0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+  0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba,
+  0xfe92dfec, 0x462eb889, 0x549b1767, 0xec277002,
+  0x71f048bb, 0xc94c2fde, 0xdbf98030, 0x6345e755,
+  0x6b3fa09c, 0xd383c7f9, 0xc1366817, 0x798a0f72,
+  0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+  0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d,
+  0x21e91f24, 0x99557841, 0x8be0d7af, 0x335cb0ca,
+  0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5,
+  0x623b216c, 0xda874609, 0xc832e9e7, 0x708e8e82,
+  0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+  0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d,
+  0xbd40e1a4, 0x05fc86c1, 0x1749292f, 0xaff54e4a,
+  0x322276f3, 0x8a9e1196, 0x982bbe78, 0x2097d91d,
+  0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, 0x6a4166a5,
+  0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+  0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb,
+  0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc,
+  0x88df31ea, 0x3063568f, 0x22d6f961, 0x9a6a9e04,
+  0x07bda6bd, 0xbf01c1d8, 0xadb46e36, 0x15080953,
+  0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+  0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623,
+  0xd8c66675, 0x607a0110, 0x72cfaefe, 0xca73c99b,
+  0x57a4f122, 0xef189647, 0xfdad39a9, 0x45115ecc,
+  0x764dee06, 0xcef18963, 0xdc44268d, 0x64f841e8,
+  0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+  0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907,
+  0x3c9b51be, 0x842736db, 0x96929935, 0x2e2efe50,
+  0x2654b999, 0x9ee8defc, 0x8c5d7112, 0x34e11677,
+  0xa9362ece, 0x118a49ab, 0x033fe645, 0xbb838120,
+  0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+  0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf,
+  0xd67f4138, 0x6ec3265d, 0x7c7689b3, 0xc4caeed6,
+  0x591dd66f, 0xe1a1b10a, 0xf3141ee4, 0x4ba87981,
+  0x13cb69d7, 0xab770eb2, 0xb9c2a15c, 0x017ec639,
+  0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+  0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949,
+  0x090481f0, 0xb1b8e695, 0xa30d497b, 0x1bb12e1e,
+  0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6,
+  0xccb0a91f, 0x740cce7a, 0x66b96194, 0xde0506f1
+};
+
 /* CRC32 */
 
+static inline u32
+crc32_next (u32 crc, byte data)
+{
+  return (crc >> 8) ^ crc32_table[(crc & 0xff) ^ data];
+}
+
+/*
+ * Process 4 bytes in one go
+ */
+static inline u32
+crc32_next4 (u32 crc, u32 data)
+{
+  crc ^= data;
+  crc = crc32_table[(crc & 0xff) + 0x300] ^
+        crc32_table[((crc >> 8) & 0xff) + 0x200] ^
+        crc32_table[((crc >> 16) & 0xff) + 0x100] ^
+        crc32_table[(crc >> 24) & 0xff];
+  return crc;
+}
+
 static void
 crc32_init (void *context)
 {
@@ -156,12 +342,40 @@ crc32_init (void *context)
 }
 
 static void
-crc32_write (void *context, const void *inbuf, size_t inlen)
+crc32_write (void *context, const void *inbuf_arg, size_t inlen)
 {
   CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
-  if (!inbuf)
+  const byte *inbuf = inbuf_arg;
+  u32 crc;
+
+  if (!inbuf || !inlen)
     return;
-  ctx->CRC = update_crc32 (ctx->CRC, inbuf, inlen);
+
+  crc = ctx->CRC;
+
+  while (inlen >= 16)
+    {
+      inlen -= 16;
+      crc = crc32_next4(crc, buf_get_le32(&inbuf[0]));
+      crc = crc32_next4(crc, buf_get_le32(&inbuf[4]));
+      crc = crc32_next4(crc, buf_get_le32(&inbuf[8]));
+      crc = crc32_next4(crc, buf_get_le32(&inbuf[12]));
+      inbuf += 16;
+    }
+
+  while (inlen >= 4)
+    {
+      inlen -= 4;
+      crc = crc32_next4(crc, buf_get_le32(inbuf));
+      inbuf += 4;
+    }
+
+  while (inlen--)
+    {
+      crc = crc32_next(crc, *inbuf++);
+    }
+
+  ctx->CRC = crc;
 }
 
 static byte *
@@ -176,13 +390,12 @@ crc32_final (void *context)
 {
   CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
   ctx->CRC ^= 0xffffffffL;
-  ctx->buf[0] = (ctx->CRC >> 24) & 0xFF;
-  ctx->buf[1] = (ctx->CRC >> 16) & 0xFF;
-  ctx->buf[2] = (ctx->CRC >>  8) & 0xFF;
-  ctx->buf[3] = (ctx->CRC      ) & 0xFF;
+  buf_put_be32 (ctx->buf, ctx->CRC);
 }
 
 /* CRC32 a'la RFC 1510 */
+/* CRC of the string "123456789" is 0x2dfd2d88 */
+
 static void
 crc32rfc1510_init (void *context)
 {
@@ -194,82 +407,366 @@ static void
 crc32rfc1510_final (void *context)
 {
   CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
-  ctx->buf[0] = (ctx->CRC >> 24) & 0xFF;
-  ctx->buf[1] = (ctx->CRC >> 16) & 0xFF;
-  ctx->buf[2] = (ctx->CRC >>  8) & 0xFF;
-  ctx->buf[3] = (ctx->CRC      ) & 0xFF;
+  buf_put_be32(ctx->buf, ctx->CRC);
 }
 
 /* CRC24 a'la RFC 2440 */
 /*
- * The following CRC 24 routines are adapted from RFC 2440, which has
- * the following copyright notice:
+ * Code generated by universal_crc by Danjel McGougan
  *
- *   Copyright (C) The Internet Society (1998).  All Rights Reserved.
+ * CRC parameters used:
+ *   bits:       24
+ *   poly:       0x864cfb
+ *   init:       0xb704ce
+ *   xor:        0x000000
+ *   reverse:    false
+ *   non-direct: false
  *
- *   This document and translations of it may be copied and furnished
- *   to others, and derivative works that comment on or otherwise
- *   explain it or assist in its implementation may be prepared,
- *   copied, published and distributed, in whole or in part, without
- *   restriction of any kind, provided that the above copyright notice
- *   and this paragraph are included on all such copies and derivative
- *   works.  However, this document itself may not be modified in any
- *   way, such as by removing the copyright notice or references to
- *   the Internet Society or other Internet organizations, except as
- *   needed for the purpose of developing Internet standards in which
- *   case the procedures for copyrights defined in the Internet
- *   Standards process must be followed, or as required to translate
- *   it into languages other than English.
- *
- *   The limited permissions granted above are perpetual and will not be
- *   revoked by the Internet Society or its successors or assigns.
- *
- *   This document and the information contained herein is provided on
- *   an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET
- *   ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR
- *   IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE
- *   OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY
- *   IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
- *   PURPOSE.
+ * CRC of the string "123456789" is 0x21cf02
+ */
+
+static const u32 crc24_table[1024] =
+{
+  0x00000000, 0x00fb4c86, 0x000dd58a, 0x00f6990c,
+  0x00e1e693, 0x001aaa15, 0x00ec3319, 0x00177f9f,
+  0x003981a1, 0x00c2cd27, 0x0034542b, 0x00cf18ad,
+  0x00d86732, 0x00232bb4, 0x00d5b2b8, 0x002efe3e,
+  0x00894ec5, 0x00720243, 0x00849b4f, 0x007fd7c9,
+  0x0068a856, 0x0093e4d0, 0x00657ddc, 0x009e315a,
+  0x00b0cf64, 0x004b83e2, 0x00bd1aee, 0x00465668,
+  0x005129f7, 0x00aa6571, 0x005cfc7d, 0x00a7b0fb,
+  0x00e9d10c, 0x00129d8a, 0x00e40486, 0x001f4800,
+  0x0008379f, 0x00f37b19, 0x0005e215, 0x00feae93,
+  0x00d050ad, 0x002b1c2b, 0x00dd8527, 0x0026c9a1,
+  0x0031b63e, 0x00cafab8, 0x003c63b4, 0x00c72f32,
+  0x00609fc9, 0x009bd34f, 0x006d4a43, 0x009606c5,
+  0x0081795a, 0x007a35dc, 0x008cacd0, 0x0077e056,
+  0x00591e68, 0x00a252ee, 0x0054cbe2, 0x00af8764,
+  0x00b8f8fb, 0x0043b47d, 0x00b52d71, 0x004e61f7,
+  0x00d2a319, 0x0029ef9f, 0x00df7693, 0x00243a15,
+  0x0033458a, 0x00c8090c, 0x003e9000, 0x00c5dc86,
+  0x00eb22b8, 0x00106e3e, 0x00e6f732, 0x001dbbb4,
+  0x000ac42b, 0x00f188ad, 0x000711a1, 0x00fc5d27,
+  0x005beddc, 0x00a0a15a, 0x00563856, 0x00ad74d0,
+  0x00ba0b4f, 0x004147c9, 0x00b7dec5, 0x004c9243,
+  0x00626c7d, 0x009920fb, 0x006fb9f7, 0x0094f571,
+  0x00838aee, 0x0078c668, 0x008e5f64, 0x007513e2,
+  0x003b7215, 0x00c03e93, 0x0036a79f, 0x00cdeb19,
+  0x00da9486, 0x0021d800, 0x00d7410c, 0x002c0d8a,
+  0x0002f3b4, 0x00f9bf32, 0x000f263e, 0x00f46ab8,
+  0x00e31527, 0x001859a1, 0x00eec0ad, 0x00158c2b,
+  0x00b23cd0, 0x00497056, 0x00bfe95a, 0x0044a5dc,
+  0x0053da43, 0x00a896c5, 0x005e0fc9, 0x00a5434f,
+  0x008bbd71, 0x0070f1f7, 0x008668fb, 0x007d247d,
+  0x006a5be2, 0x00911764, 0x00678e68, 0x009cc2ee,
+  0x00a44733, 0x005f0bb5, 0x00a992b9, 0x0052de3f,
+  0x0045a1a0, 0x00beed26, 0x0048742a, 0x00b338ac,
+  0x009dc692, 0x00668a14, 0x00901318, 0x006b5f9e,
+  0x007c2001, 0x00876c87, 0x0071f58b, 0x008ab90d,
+  0x002d09f6, 0x00d64570, 0x0020dc7c, 0x00db90fa,
+  0x00ccef65, 0x0037a3e3, 0x00c13aef, 0x003a7669,
+  0x00148857, 0x00efc4d1, 0x00195ddd, 0x00e2115b,
+  0x00f56ec4, 0x000e2242, 0x00f8bb4e, 0x0003f7c8,
+  0x004d963f, 0x00b6dab9, 0x004043b5, 0x00bb0f33,
+  0x00ac70ac, 0x00573c2a, 0x00a1a526, 0x005ae9a0,
+  0x0074179e, 0x008f5b18, 0x0079c214, 0x00828e92,
+  0x0095f10d, 0x006ebd8b, 0x00982487, 0x00636801,
+  0x00c4d8fa, 0x003f947c, 0x00c90d70, 0x003241f6,
+  0x00253e69, 0x00de72ef, 0x0028ebe3, 0x00d3a765,
+  0x00fd595b, 0x000615dd, 0x00f08cd1, 0x000bc057,
+  0x001cbfc8, 0x00e7f34e, 0x00116a42, 0x00ea26c4,
+  0x0076e42a, 0x008da8ac, 0x007b31a0, 0x00807d26,
+  0x009702b9, 0x006c4e3f, 0x009ad733, 0x00619bb5,
+  0x004f658b, 0x00b4290d, 0x0042b001, 0x00b9fc87,
+  0x00ae8318, 0x0055cf9e, 0x00a35692, 0x00581a14,
+  0x00ffaaef, 0x0004e669, 0x00f27f65, 0x000933e3,
+  0x001e4c7c, 0x00e500fa, 0x001399f6, 0x00e8d570,
+  0x00c62b4e, 0x003d67c8, 0x00cbfec4, 0x0030b242,
+  0x0027cddd, 0x00dc815b, 0x002a1857, 0x00d154d1,
+  0x009f3526, 0x006479a0, 0x0092e0ac, 0x0069ac2a,
+  0x007ed3b5, 0x00859f33, 0x0073063f, 0x00884ab9,
+  0x00a6b487, 0x005df801, 0x00ab610d, 0x00502d8b,
+  0x00475214, 0x00bc1e92, 0x004a879e, 0x00b1cb18,
+  0x00167be3, 0x00ed3765, 0x001bae69, 0x00e0e2ef,
+  0x00f79d70, 0x000cd1f6, 0x00fa48fa, 0x0001047c,
+  0x002ffa42, 0x00d4b6c4, 0x00222fc8, 0x00d9634e,
+  0x00ce1cd1, 0x00355057, 0x00c3c95b, 0x003885dd,
+  0x00000000, 0x00488f66, 0x00901ecd, 0x00d891ab,
+  0x00db711c, 0x0093fe7a, 0x004b6fd1, 0x0003e0b7,
+  0x00b6e338, 0x00fe6c5e, 0x0026fdf5, 0x006e7293,
+  0x006d9224, 0x00251d42, 0x00fd8ce9, 0x00b5038f,
+  0x006cc771, 0x00244817, 0x00fcd9bc, 0x00b456da,
+  0x00b7b66d, 0x00ff390b, 0x0027a8a0, 0x006f27c6,
+  0x00da2449, 0x0092ab2f, 0x004a3a84, 0x0002b5e2,
+  0x00015555, 0x0049da33, 0x00914b98, 0x00d9c4fe,
+  0x00d88ee3, 0x00900185, 0x0048902e, 0x00001f48,
+  0x0003ffff, 0x004b7099, 0x0093e132, 0x00db6e54,
+  0x006e6ddb, 0x0026e2bd, 0x00fe7316, 0x00b6fc70,
+  0x00b51cc7, 0x00fd93a1, 0x0025020a, 0x006d8d6c,
+  0x00b44992, 0x00fcc6f4, 0x0024575f, 0x006cd839,
+  0x006f388e, 0x0027b7e8, 0x00ff2643, 0x00b7a925,
+  0x0002aaaa, 0x004a25cc, 0x0092b467, 0x00da3b01,
+  0x00d9dbb6, 0x009154d0, 0x0049c57b, 0x00014a1d,
+  0x004b5141, 0x0003de27, 0x00db4f8c, 0x0093c0ea,
+  0x0090205d, 0x00d8af3b, 0x00003e90, 0x0048b1f6,
+  0x00fdb279, 0x00b53d1f, 0x006dacb4, 0x002523d2,
+  0x0026c365, 0x006e4c03, 0x00b6dda8, 0x00fe52ce,
+  0x00279630, 0x006f1956, 0x00b788fd, 0x00ff079b,
+  0x00fce72c, 0x00b4684a, 0x006cf9e1, 0x00247687,
+  0x00917508, 0x00d9fa6e, 0x00016bc5, 0x0049e4a3,
+  0x004a0414, 0x00028b72, 0x00da1ad9, 0x009295bf,
+  0x0093dfa2, 0x00db50c4, 0x0003c16f, 0x004b4e09,
+  0x0048aebe, 0x000021d8, 0x00d8b073, 0x00903f15,
+  0x00253c9a, 0x006db3fc, 0x00b52257, 0x00fdad31,
+  0x00fe4d86, 0x00b6c2e0, 0x006e534b, 0x0026dc2d,
+  0x00ff18d3, 0x00b797b5, 0x006f061e, 0x00278978,
+  0x002469cf, 0x006ce6a9, 0x00b47702, 0x00fcf864,
+  0x0049fbeb, 0x0001748d, 0x00d9e526, 0x00916a40,
+  0x00928af7, 0x00da0591, 0x0002943a, 0x004a1b5c,
+  0x0096a282, 0x00de2de4, 0x0006bc4f, 0x004e3329,
+  0x004dd39e, 0x00055cf8, 0x00ddcd53, 0x00954235,
+  0x002041ba, 0x0068cedc, 0x00b05f77, 0x00f8d011,
+  0x00fb30a6, 0x00b3bfc0, 0x006b2e6b, 0x0023a10d,
+  0x00fa65f3, 0x00b2ea95, 0x006a7b3e, 0x0022f458,
+  0x002114ef, 0x00699b89, 0x00b10a22, 0x00f98544,
+  0x004c86cb, 0x000409ad, 0x00dc9806, 0x00941760,
+  0x0097f7d7, 0x00df78b1, 0x0007e91a, 0x004f667c,
+  0x004e2c61, 0x0006a307, 0x00de32ac, 0x0096bdca,
+  0x00955d7d, 0x00ddd21b, 0x000543b0, 0x004dccd6,
+  0x00f8cf59, 0x00b0403f, 0x0068d194, 0x00205ef2,
+  0x0023be45, 0x006b3123, 0x00b3a088, 0x00fb2fee,
+  0x0022eb10, 0x006a6476, 0x00b2f5dd, 0x00fa7abb,
+  0x00f99a0c, 0x00b1156a, 0x006984c1, 0x00210ba7,
+  0x00940828, 0x00dc874e, 0x000416e5, 0x004c9983,
+  0x004f7934, 0x0007f652, 0x00df67f9, 0x0097e89f,
+  0x00ddf3c3, 0x00957ca5, 0x004ded0e, 0x00056268,
+  0x000682df, 0x004e0db9, 0x00969c12, 0x00de1374,
+  0x006b10fb, 0x00239f9d, 0x00fb0e36, 0x00b38150,
+  0x00b061e7, 0x00f8ee81, 0x00207f2a, 0x0068f04c,
+  0x00b134b2, 0x00f9bbd4, 0x00212a7f, 0x0069a519,
+  0x006a45ae, 0x0022cac8, 0x00fa5b63, 0x00b2d405,
+  0x0007d78a, 0x004f58ec, 0x0097c947, 0x00df4621,
+  0x00dca696, 0x009429f0, 0x004cb85b, 0x0004373d,
+  0x00057d20, 0x004df246, 0x009563ed, 0x00ddec8b,
+  0x00de0c3c, 0x0096835a, 0x004e12f1, 0x00069d97,
+  0x00b39e18, 0x00fb117e, 0x002380d5, 0x006b0fb3,
+  0x0068ef04, 0x00206062, 0x00f8f1c9, 0x00b07eaf,
+  0x0069ba51, 0x00213537, 0x00f9a49c, 0x00b12bfa,
+  0x00b2cb4d, 0x00fa442b, 0x0022d580, 0x006a5ae6,
+  0x00df5969, 0x0097d60f, 0x004f47a4, 0x0007c8c2,
+  0x00042875, 0x004ca713, 0x009436b8, 0x00dcb9de,
+  0x00000000, 0x00d70983, 0x00555f80, 0x00825603,
+  0x0051f286, 0x0086fb05, 0x0004ad06, 0x00d3a485,
+  0x0059a88b, 0x008ea108, 0x000cf70b, 0x00dbfe88,
+  0x00085a0d, 0x00df538e, 0x005d058d, 0x008a0c0e,
+  0x00491c91, 0x009e1512, 0x001c4311, 0x00cb4a92,
+  0x0018ee17, 0x00cfe794, 0x004db197, 0x009ab814,
+  0x0010b41a, 0x00c7bd99, 0x0045eb9a, 0x0092e219,
+  0x0041469c, 0x00964f1f, 0x0014191c, 0x00c3109f,
+  0x006974a4, 0x00be7d27, 0x003c2b24, 0x00eb22a7,
+  0x00388622, 0x00ef8fa1, 0x006dd9a2, 0x00bad021,
+  0x0030dc2f, 0x00e7d5ac, 0x006583af, 0x00b28a2c,
+  0x00612ea9, 0x00b6272a, 0x00347129, 0x00e378aa,
+  0x00206835, 0x00f761b6, 0x007537b5, 0x00a23e36,
+  0x00719ab3, 0x00a69330, 0x0024c533, 0x00f3ccb0,
+  0x0079c0be, 0x00aec93d, 0x002c9f3e, 0x00fb96bd,
+  0x00283238, 0x00ff3bbb, 0x007d6db8, 0x00aa643b,
+  0x0029a4ce, 0x00fead4d, 0x007cfb4e, 0x00abf2cd,
+  0x00785648, 0x00af5fcb, 0x002d09c8, 0x00fa004b,
+  0x00700c45, 0x00a705c6, 0x002553c5, 0x00f25a46,
+  0x0021fec3, 0x00f6f740, 0x0074a143, 0x00a3a8c0,
+  0x0060b85f, 0x00b7b1dc, 0x0035e7df, 0x00e2ee5c,
+  0x00314ad9, 0x00e6435a, 0x00641559, 0x00b31cda,
+  0x003910d4, 0x00ee1957, 0x006c4f54, 0x00bb46d7,
+  0x0068e252, 0x00bfebd1, 0x003dbdd2, 0x00eab451,
+  0x0040d06a, 0x0097d9e9, 0x00158fea, 0x00c28669,
+  0x001122ec, 0x00c62b6f, 0x00447d6c, 0x009374ef,
+  0x001978e1, 0x00ce7162, 0x004c2761, 0x009b2ee2,
+  0x00488a67, 0x009f83e4, 0x001dd5e7, 0x00cadc64,
+  0x0009ccfb, 0x00dec578, 0x005c937b, 0x008b9af8,
+  0x00583e7d, 0x008f37fe, 0x000d61fd, 0x00da687e,
+  0x00506470, 0x00876df3, 0x00053bf0, 0x00d23273,
+  0x000196f6, 0x00d69f75, 0x0054c976, 0x0083c0f5,
+  0x00a9041b, 0x007e0d98, 0x00fc5b9b, 0x002b5218,
+  0x00f8f69d, 0x002fff1e, 0x00ada91d, 0x007aa09e,
+  0x00f0ac90, 0x0027a513, 0x00a5f310, 0x0072fa93,
+  0x00a15e16, 0x00765795, 0x00f40196, 0x00230815,
+  0x00e0188a, 0x00371109, 0x00b5470a, 0x00624e89,
+  0x00b1ea0c, 0x0066e38f, 0x00e4b58c, 0x0033bc0f,
+  0x00b9b001, 0x006eb982, 0x00ecef81, 0x003be602,
+  0x00e84287, 0x003f4b04, 0x00bd1d07, 0x006a1484,
+  0x00c070bf, 0x0017793c, 0x00952f3f, 0x004226bc,
+  0x00918239, 0x00468bba, 0x00c4ddb9, 0x0013d43a,
+  0x0099d834, 0x004ed1b7, 0x00cc87b4, 0x001b8e37,
+  0x00c82ab2, 0x001f2331, 0x009d7532, 0x004a7cb1,
+  0x00896c2e, 0x005e65ad, 0x00dc33ae, 0x000b3a2d,
+  0x00d89ea8, 0x000f972b, 0x008dc128, 0x005ac8ab,
+  0x00d0c4a5, 0x0007cd26, 0x00859b25, 0x005292a6,
+  0x00813623, 0x00563fa0, 0x00d469a3, 0x00036020,
+  0x0080a0d5, 0x0057a956, 0x00d5ff55, 0x0002f6d6,
+  0x00d15253, 0x00065bd0, 0x00840dd3, 0x00530450,
+  0x00d9085e, 0x000e01dd, 0x008c57de, 0x005b5e5d,
+  0x0088fad8, 0x005ff35b, 0x00dda558, 0x000aacdb,
+  0x00c9bc44, 0x001eb5c7, 0x009ce3c4, 0x004bea47,
+  0x00984ec2, 0x004f4741, 0x00cd1142, 0x001a18c1,
+  0x009014cf, 0x00471d4c, 0x00c54b4f, 0x001242cc,
+  0x00c1e649, 0x0016efca, 0x0094b9c9, 0x0043b04a,
+  0x00e9d471, 0x003eddf2, 0x00bc8bf1, 0x006b8272,
+  0x00b826f7, 0x006f2f74, 0x00ed7977, 0x003a70f4,
+  0x00b07cfa, 0x00677579, 0x00e5237a, 0x00322af9,
+  0x00e18e7c, 0x003687ff, 0x00b4d1fc, 0x0063d87f,
+  0x00a0c8e0, 0x0077c163, 0x00f59760, 0x00229ee3,
+  0x00f13a66, 0x002633e5, 0x00a465e6, 0x00736c65,
+  0x00f9606b, 0x002e69e8, 0x00ac3feb, 0x007b3668,
+  0x00a892ed, 0x007f9b6e, 0x00fdcd6d, 0x002ac4ee,
+  0x00000000, 0x00520936, 0x00a4126c, 0x00f61b5a,
+  0x004825d8, 0x001a2cee, 0x00ec37b4, 0x00be3e82,
+  0x006b0636, 0x00390f00, 0x00cf145a, 0x009d1d6c,
+  0x002323ee, 0x00712ad8, 0x00873182, 0x00d538b4,
+  0x00d60c6c, 0x0084055a, 0x00721e00, 0x00201736,
+  0x009e29b4, 0x00cc2082, 0x003a3bd8, 0x006832ee,
+  0x00bd0a5a, 0x00ef036c, 0x00191836, 0x004b1100,
+  0x00f52f82, 0x00a726b4, 0x00513dee, 0x000334d8,
+  0x00ac19d8, 0x00fe10ee, 0x00080bb4, 0x005a0282,
+  0x00e43c00, 0x00b63536, 0x00402e6c, 0x0012275a,
+  0x00c71fee, 0x009516d8, 0x00630d82, 0x003104b4,
+  0x008f3a36, 0x00dd3300, 0x002b285a, 0x0079216c,
+  0x007a15b4, 0x00281c82, 0x00de07d8, 0x008c0eee,
+  0x0032306c, 0x0060395a, 0x00962200, 0x00c42b36,
+  0x00111382, 0x00431ab4, 0x00b501ee, 0x00e708d8,
+  0x0059365a, 0x000b3f6c, 0x00fd2436, 0x00af2d00,
+  0x00a37f36, 0x00f17600, 0x00076d5a, 0x0055646c,
+  0x00eb5aee, 0x00b953d8, 0x004f4882, 0x001d41b4,
+  0x00c87900, 0x009a7036, 0x006c6b6c, 0x003e625a,
+  0x00805cd8, 0x00d255ee, 0x00244eb4, 0x00764782,
+  0x0075735a, 0x00277a6c, 0x00d16136, 0x00836800,
+  0x003d5682, 0x006f5fb4, 0x009944ee, 0x00cb4dd8,
+  0x001e756c, 0x004c7c5a, 0x00ba6700, 0x00e86e36,
+  0x005650b4, 0x00045982, 0x00f242d8, 0x00a04bee,
+  0x000f66ee, 0x005d6fd8, 0x00ab7482, 0x00f97db4,
+  0x00474336, 0x00154a00, 0x00e3515a, 0x00b1586c,
+  0x006460d8, 0x003669ee, 0x00c072b4, 0x00927b82,
+  0x002c4500, 0x007e4c36, 0x0088576c, 0x00da5e5a,
+  0x00d96a82, 0x008b63b4, 0x007d78ee, 0x002f71d8,
+  0x00914f5a, 0x00c3466c, 0x00355d36, 0x00675400,
+  0x00b26cb4, 0x00e06582, 0x00167ed8, 0x004477ee,
+  0x00fa496c, 0x00a8405a, 0x005e5b00, 0x000c5236,
+  0x0046ff6c, 0x0014f65a, 0x00e2ed00, 0x00b0e436,
+  0x000edab4, 0x005cd382, 0x00aac8d8, 0x00f8c1ee,
+  0x002df95a, 0x007ff06c, 0x0089eb36, 0x00dbe200,
+  0x0065dc82, 0x0037d5b4, 0x00c1ceee, 0x0093c7d8,
+  0x0090f300, 0x00c2fa36, 0x0034e16c, 0x0066e85a,
+  0x00d8d6d8, 0x008adfee, 0x007cc4b4, 0x002ecd82,
+  0x00fbf536, 0x00a9fc00, 0x005fe75a, 0x000dee6c,
+  0x00b3d0ee, 0x00e1d9d8, 0x0017c282, 0x0045cbb4,
+  0x00eae6b4, 0x00b8ef82, 0x004ef4d8, 0x001cfdee,
+  0x00a2c36c, 0x00f0ca5a, 0x0006d100, 0x0054d836,
+  0x0081e082, 0x00d3e9b4, 0x0025f2ee, 0x0077fbd8,
+  0x00c9c55a, 0x009bcc6c, 0x006dd736, 0x003fde00,
+  0x003cead8, 0x006ee3ee, 0x0098f8b4, 0x00caf182,
+  0x0074cf00, 0x0026c636, 0x00d0dd6c, 0x0082d45a,
+  0x0057ecee, 0x0005e5d8, 0x00f3fe82, 0x00a1f7b4,
+  0x001fc936, 0x004dc000, 0x00bbdb5a, 0x00e9d26c,
+  0x00e5805a, 0x00b7896c, 0x00419236, 0x00139b00,
+  0x00ada582, 0x00ffacb4, 0x0009b7ee, 0x005bbed8,
+  0x008e866c, 0x00dc8f5a, 0x002a9400, 0x00789d36,
+  0x00c6a3b4, 0x0094aa82, 0x0062b1d8, 0x0030b8ee,
+  0x00338c36, 0x00618500, 0x00979e5a, 0x00c5976c,
+  0x007ba9ee, 0x0029a0d8, 0x00dfbb82, 0x008db2b4,
+  0x00588a00, 0x000a8336, 0x00fc986c, 0x00ae915a,
+  0x0010afd8, 0x0042a6ee, 0x00b4bdb4, 0x00e6b482,
+  0x00499982, 0x001b90b4, 0x00ed8bee, 0x00bf82d8,
+  0x0001bc5a, 0x0053b56c, 0x00a5ae36, 0x00f7a700,
+  0x00229fb4, 0x00709682, 0x00868dd8, 0x00d484ee,
+  0x006aba6c, 0x0038b35a, 0x00cea800, 0x009ca136,
+  0x009f95ee, 0x00cd9cd8, 0x003b8782, 0x00698eb4,
+  0x00d7b036, 0x0085b900, 0x0073a25a, 0x0021ab6c,
+  0x00f493d8, 0x00a69aee, 0x005081b4, 0x00028882,
+  0x00bcb600, 0x00eebf36, 0x0018a46c, 0x004aad5a
+};
+
+static inline
+u32 crc24_init (void)
+{
+  return 0xce04b7;
+}
+
+static inline
+u32 crc24_next (u32 crc, byte data)
+{
+  return (crc >> 8) ^ crc24_table[(crc & 0xff) ^ data];
+}
+
+/*
+ * Process 4 bytes in one go
  */
+static inline
+u32 crc24_next4 (u32 crc, u32 data)
+{
+  crc ^= data;
+  crc = crc24_table[(crc & 0xff) + 0x300] ^
+        crc24_table[((crc >> 8) & 0xff) + 0x200] ^
+        crc24_table[((crc >> 16) & 0xff) + 0x100] ^
+        crc24_table[(crc >> 24) & 0xff];
+  return crc;
+}
 
-#define CRC24_INIT 0xb704ceL
-#define CRC24_POLY 0x1864cfbL
+static inline
+u32 crc24_final (u32 crc)
+{
+  return crc & 0xffffff;
+}
 
 static void
 crc24rfc2440_init (void *context)
 {
   CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
-  ctx->CRC = CRC24_INIT;
+  ctx->CRC = crc24_init();
 }
 
 static void
 crc24rfc2440_write (void *context, const void *inbuf_arg, size_t inlen)
 {
   const unsigned char *inbuf = inbuf_arg;
-  int i;
   CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
+  u32 crc;
 
-  if (!inbuf)
+  if (!inbuf || !inlen)
     return;
 
-  while (inlen--) {
-    ctx->CRC ^= (*inbuf++) << 16;
-    for (i = 0; i < 8; i++) {
-      ctx->CRC <<= 1;
-      if (ctx->CRC & 0x1000000)
-	ctx->CRC ^= CRC24_POLY;
+  crc = ctx->CRC;
+
+  while (inlen >= 16)
+    {
+      inlen -= 16;
+      crc = crc24_next4(crc, buf_get_le32(&inbuf[0]));
+      crc = crc24_next4(crc, buf_get_le32(&inbuf[4]));
+      crc = crc24_next4(crc, buf_get_le32(&inbuf[8]));
+      crc = crc24_next4(crc, buf_get_le32(&inbuf[12]));
+      inbuf += 16;
     }
-  }
+
+  while (inlen >= 4)
+    {
+      inlen -= 4;
+      crc = crc24_next4(crc, buf_get_le32(inbuf));
+      inbuf += 4;
+    }
+
+  while (inlen--)
+    {
+      crc = crc24_next(crc, *inbuf++);
+    }
+
+  ctx->CRC = crc;
 }
 
 static void
 crc24rfc2440_final (void *context)
 {
   CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
-  ctx->buf[0] = (ctx->CRC >> 16) & 0xFF;
-  ctx->buf[1] = (ctx->CRC >>  8) & 0xFF;
-  ctx->buf[2] = (ctx->CRC      ) & 0xFF;
+  ctx->CRC = crc24_final(ctx->CRC);
+  buf_put_le32 (ctx->buf, ctx->CRC);
 }
 
 gcry_md_spec_t _gcry_digest_spec_crc32 =
diff --git a/grub-core/loader/arm/linux.c b/grub-core/loader/arm/linux.c
index 5b39f02bb2e592d85639891db6eb68a97ce12dfa..b4f609d2d01184b8d0a3e5aff448725f80a36a93 100644
--- a/grub-core/loader/arm/linux.c
+++ b/grub-core/loader/arm/linux.c
@@ -42,21 +42,18 @@ static grub_size_t linux_size;
 static char *linux_args;
 
 static grub_uint32_t machine_type;
-static void *fdt_addr;
+static const void *current_fdt;
 
 typedef void (*kernel_entry_t) (int, unsigned long, void *);
 
-#define LINUX_ZIMAGE_OFFSET	0x24
-#define LINUX_ZIMAGE_MAGIC	0x016f2818
-
 #define LINUX_PHYS_OFFSET        (0x00008000)
 #define LINUX_INITRD_PHYS_OFFSET (LINUX_PHYS_OFFSET + 0x02000000)
 #define LINUX_FDT_PHYS_OFFSET    (LINUX_INITRD_PHYS_OFFSET - 0x10000)
 
 static grub_size_t
-get_atag_size (grub_uint32_t *atag)
+get_atag_size (const grub_uint32_t *atag)
 {
-  grub_uint32_t *atag0 = atag;
+  const grub_uint32_t *atag0 = atag;
   while (atag[0] && atag[1])
     atag += atag[0];
   return atag - atag0;
@@ -68,10 +65,11 @@ get_atag_size (grub_uint32_t *atag)
  *   Merges in command line parameters and sets up initrd addresses.
  */
 static grub_err_t
-linux_prepare_atag (void)
+linux_prepare_atag (void *target_atag)
 {
-  grub_uint32_t *atag_orig = (grub_uint32_t *) fdt_addr;
-  grub_uint32_t *tmp_atag, *from, *to;
+  const grub_uint32_t *atag_orig = (const grub_uint32_t *) current_fdt;
+  grub_uint32_t *tmp_atag, *to;
+  const grub_uint32_t *from;
   grub_size_t tmp_size;
   grub_size_t arg_size = grub_strlen (linux_args);
   char *cmdline_orig = NULL;
@@ -142,7 +140,7 @@ linux_prepare_atag (void)
   to += 2;
 
   /* Copy updated FDT to its launch location */
-  grub_memcpy (atag_orig, tmp_atag, sizeof (grub_uint32_t) * (to - tmp_atag));
+  grub_memcpy (target_atag, tmp_atag, sizeof (grub_uint32_t) * (to - tmp_atag));
   grub_free (tmp_atag);
 
   grub_dprintf ("loader", "ATAG updated for Linux boot\n");
@@ -156,19 +154,19 @@ linux_prepare_atag (void)
  *   Merges in command line parameters and sets up initrd addresses.
  */
 static grub_err_t
-linux_prepare_fdt (void)
+linux_prepare_fdt (void *target_fdt)
 {
   int node;
   int retval;
   int tmp_size;
   void *tmp_fdt;
 
-  tmp_size = grub_fdt_get_totalsize (fdt_addr) + 0x100 + grub_strlen (linux_args);
+  tmp_size = grub_fdt_get_totalsize (current_fdt) + 0x100 + grub_strlen (linux_args);
   tmp_fdt = grub_malloc (tmp_size);
   if (!tmp_fdt)
     return grub_errno;
 
-  grub_memcpy (tmp_fdt, fdt_addr, grub_fdt_get_totalsize (fdt_addr));
+  grub_memcpy (tmp_fdt, current_fdt, grub_fdt_get_totalsize (current_fdt));
   grub_fdt_set_totalsize (tmp_fdt, tmp_size);
 
   /* Find or create '/chosen' node */
@@ -209,7 +207,7 @@ linux_prepare_fdt (void)
     }
 
   /* Copy updated FDT to its launch location */
-  grub_memcpy (fdt_addr, tmp_fdt, tmp_size);
+  grub_memcpy (target_fdt, tmp_fdt, tmp_size);
   grub_free (tmp_fdt);
 
   grub_dprintf ("loader", "FDT updated for Linux boot\n");
@@ -226,16 +224,17 @@ linux_boot (void)
 {
   kernel_entry_t linuxmain;
   int fdt_valid, atag_valid;
+  void *target_fdt = 0;
 
-  fdt_valid = (fdt_addr && grub_fdt_check_header_nosize (fdt_addr) == 0);
-  atag_valid = ((((grub_uint16_t *) fdt_addr)[3] & ~3) == 0x5440
-		&& *((grub_uint32_t *) fdt_addr));
+  fdt_valid = (current_fdt && grub_fdt_check_header_nosize (current_fdt) == 0);
+  atag_valid = ((((const grub_uint16_t *) current_fdt)[3] & ~3) == 0x5440
+		&& *((const grub_uint32_t *) current_fdt));
   grub_dprintf ("loader", "atag: %p, %x, %x, %s, %s\n",
-		fdt_addr,
-		((grub_uint16_t *) fdt_addr)[3],
-		*((grub_uint32_t *) fdt_addr),
-		(char *) fdt_addr,
-		(char *) fdt_addr + 1);
+		current_fdt,
+		((const grub_uint16_t *) current_fdt)[3],
+		*((const grub_uint32_t *) current_fdt),
+		(const char *) current_fdt,
+		(const char *) current_fdt + 1);
 
   if (!fdt_valid && machine_type == GRUB_ARM_MACHINE_TYPE_FDT)
     return grub_error (GRUB_ERR_FILE_NOT_FOUND,
@@ -245,23 +244,40 @@ linux_boot (void)
 
   grub_dprintf ("loader", "Kernel at: 0x%x\n", linux_addr);
 
+  if (fdt_valid || atag_valid)
+    {
+#ifdef GRUB_MACHINE_EFI
+      grub_size_t size;
+      if (fdt_valid)
+	size = grub_fdt_get_totalsize (current_fdt);
+      else
+	size = 4 * get_atag_size (current_fdt);
+      size += grub_strlen (linux_args) + 256;
+      target_fdt = grub_efi_allocate_loader_memory (LINUX_FDT_PHYS_OFFSET, size);
+      if (!target_fdt)
+	return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+#else
+      target_fdt = (void *) LINUX_FDT_ADDRESS;
+#endif
+    }
+
   if (fdt_valid)
     {
       grub_err_t err;
 
-      err = linux_prepare_fdt ();
+      err = linux_prepare_fdt (target_fdt);
       if (err)
 	return err;
-      grub_dprintf ("loader", "FDT @ 0x%p\n", fdt_addr);
+      grub_dprintf ("loader", "FDT @ %p\n", target_fdt);
     }
   else if (atag_valid)
     {
       grub_err_t err;
 
-      err = linux_prepare_atag ();
+      err = linux_prepare_atag (target_fdt);
       if (err)
 	return err;
-      grub_dprintf ("loader", "ATAG @ 0x%p\n", fdt_addr);
+      grub_dprintf ("loader", "ATAG @ %p\n", target_fdt);
     }
 
   grub_dprintf ("loader", "Jumping to Linux...\n");
@@ -274,18 +290,9 @@ linux_boot (void)
    */
   linuxmain = (kernel_entry_t) linux_addr;
 
-#ifdef GRUB_MACHINE_EFI
-  {
-    grub_err_t err;
-    err = grub_efi_prepare_platform();
-    if (err != GRUB_ERR_NONE)
-      return err;
-  }
-#endif
-
   grub_arm_disable_caches_mmu ();
 
-  linuxmain (0, machine_type, fdt_addr);
+  linuxmain (0, machine_type, target_fdt);
 
   return grub_error (GRUB_ERR_BAD_OS, "Linux call returned");
 }
@@ -296,17 +303,12 @@ linux_boot (void)
 static grub_err_t
 linux_load (const char *filename, grub_file_t file)
 {
+  struct linux_arm_kernel_header *lh;
   int size;
 
   size = grub_file_size (file);
 
-#ifdef GRUB_MACHINE_EFI
-  linux_addr = (grub_addr_t) grub_efi_allocate_loader_memory (LINUX_PHYS_OFFSET, size);
-  if (!linux_addr)
-    return grub_errno;
-#else
   linux_addr = LINUX_ADDRESS;
-#endif
   grub_dprintf ("loader", "Loading Linux to 0x%08x\n",
 		(grub_addr_t) linux_addr);
 
@@ -318,9 +320,10 @@ linux_load (const char *filename, grub_file_t file)
       return grub_errno;
     }
 
-  if (size > LINUX_ZIMAGE_OFFSET + 4
-      && *(grub_uint32_t *) (linux_addr + LINUX_ZIMAGE_OFFSET)
-      == LINUX_ZIMAGE_MAGIC)
+  lh = (void *) linux_addr;
+
+  if ((grub_size_t) size > sizeof (*lh) &&
+      lh->magic == GRUB_LINUX_ARM_MAGIC_SIGNATURE)
     ;
   else if (size > 0x8000 && *(grub_uint32_t *) (linux_addr) == 0xea000006
 	   && machine_type == GRUB_ARM_MACHINE_TYPE_RASPBERRY_PI)
@@ -410,20 +413,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 
   size = grub_get_initrd_size (&initrd_ctx);
 
-#ifdef GRUB_MACHINE_EFI
-  if (initrd_start)
-    grub_efi_free_pages (initrd_start,
-			 (initrd_end - initrd_start + 0xfff) >> 12);
-  initrd_start = (grub_addr_t) grub_efi_allocate_loader_memory (LINUX_INITRD_PHYS_OFFSET, size);
-
-  if (!initrd_start)
-    {
-      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
-      goto fail;
-    }
-#else
   initrd_start = LINUX_INITRD_ADDRESS;
-#endif
 
   grub_dprintf ("loader", "Loading initrd to 0x%08x\n",
 		(grub_addr_t) initrd_start);
@@ -444,11 +434,26 @@ fail:
 static grub_err_t
 load_dtb (grub_file_t dtb, int size)
 {
-  if ((grub_file_read (dtb, fdt_addr, size) != size)
-      || (grub_fdt_check_header (fdt_addr, size) != 0))
-    return grub_error (GRUB_ERR_BAD_OS, N_("invalid device tree"));
+  void *new_fdt = grub_zalloc (size);
+  if (!new_fdt)
+    return grub_errno;
+  grub_dprintf ("loader", "Loading device tree to %p\n",
+		new_fdt);
+  if ((grub_file_read (dtb, new_fdt, size) != size)
+      || (grub_fdt_check_header (new_fdt, size) != 0))
+    {
+      grub_free (new_fdt);
+      return grub_error (GRUB_ERR_BAD_OS, N_("invalid device tree"));
+    }
+
+  grub_fdt_set_totalsize (new_fdt, size);
+  current_fdt = new_fdt;
+  /* 
+   * We've successfully loaded an FDT, so any machine type passed
+   * from firmware is now obsolete.
+   */
+  machine_type = GRUB_ARM_MACHINE_TYPE_FDT;
 
-  grub_fdt_set_totalsize (fdt_addr, size);
   return GRUB_ERR_NONE;
 }
 
@@ -464,42 +469,13 @@ grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
 
   dtb = grub_file_open (argv[0]);
   if (!dtb)
-    goto out;
+    return grub_errno;
 
   size = grub_file_size (dtb);
   if (size == 0)
-    {
-      grub_error (GRUB_ERR_BAD_OS, "empty file");
-      goto out;
-    }
-
-#ifdef GRUB_MACHINE_EFI
-  fdt_addr = grub_efi_allocate_loader_memory (LINUX_FDT_PHYS_OFFSET, size);
-  if (!fdt_addr)
-    {
-      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
-      goto out;
-    }
-#else
-  fdt_addr = (void *) LINUX_FDT_ADDRESS;
-#endif
-
-  grub_dprintf ("loader", "Loading device tree to 0x%08x\n",
-		(grub_addr_t) fdt_addr);
-  load_dtb (dtb, size);
-  if (grub_errno != GRUB_ERR_NONE)
-    {
-      fdt_addr = NULL;
-      goto out;
-    }
-
-  /* 
-   * We've successfully loaded an FDT, so any machine type passed
-   * from firmware is now obsolete.
-   */
-  machine_type = GRUB_ARM_MACHINE_TYPE_FDT;
-
- out:
+    grub_error (GRUB_ERR_BAD_OS, "empty file");
+  else
+    load_dtb (dtb, size);
   grub_file_close (dtb);
 
   return grub_errno;
@@ -517,7 +493,7 @@ GRUB_MOD_INIT (linux)
 					  /* TRANSLATORS: DTB stands for device tree blob.  */
 					  0, N_("Load DTB file."));
   my_mod = mod;
-  fdt_addr = (void *) grub_arm_firmware_get_boot_data ();
+  current_fdt = (const void *) grub_arm_firmware_get_boot_data ();
   machine_type = grub_arm_firmware_get_machine_type ();
 }
 
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
index 9519d2e4d3ec1229a76eb4bce773c78c7af24a6e..1f86229f86b01e4700bb13c9f936490ea9ac859f 100644
--- a/grub-core/loader/arm64/linux.c
+++ b/grub-core/loader/arm64/linux.c
@@ -26,8 +26,9 @@
 #include <grub/mm.h>
 #include <grub/types.h>
 #include <grub/cpu/linux.h>
-#include <grub/cpu/fdtload.h>
 #include <grub/efi/efi.h>
+#include <grub/efi/fdtload.h>
+#include <grub/efi/memory.h>
 #include <grub/efi/pe32.h>
 #include <grub/i18n.h>
 #include <grub/lib/cmdline.h>
@@ -47,18 +48,16 @@ static grub_addr_t initrd_start;
 static grub_addr_t initrd_end;
 
 grub_err_t
-grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header * lh)
+grub_armxx_efi_linux_check_image (struct linux_armxx_kernel_header * lh)
 {
-  if (lh->magic != GRUB_ARM64_LINUX_MAGIC)
+  if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE)
     return grub_error(GRUB_ERR_BAD_OS, "invalid magic number");
 
-  if ((lh->code0 & 0xffff) != GRUB_EFI_PE_MAGIC)
+  if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC)
     return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
 		       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",
-		(long long unsigned) lh->text_offset);
   grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset);
 
   return GRUB_ERR_NONE;
@@ -86,8 +85,8 @@ finalize_params_linux (void)
   /* Set initrd info */
   if (initrd_start && initrd_end > initrd_start)
     {
-      grub_dprintf ("linux", "Initrd @ 0x%012lx-0x%012lx\n",
-		    initrd_start, initrd_end);
+      grub_dprintf ("linux", "Initrd @ %p-%p\n",
+		    (void *) initrd_start, (void *) initrd_end);
 
       retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start",
 				    initrd_start);
@@ -110,7 +109,7 @@ failure:
 }
 
 grub_err_t
-grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
+grub_armxx_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
 {
   grub_efi_memory_mapped_device_path_t *mempath;
   grub_efi_handle_t image_handle;
@@ -148,8 +147,7 @@ grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
   loaded_image->load_options_size = len =
     (grub_strlen (args) + 1) * sizeof (grub_efi_char16_t);
   loaded_image->load_options =
-    grub_efi_allocate_pages (0,
-			     GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+    grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
   if (!loaded_image->load_options)
     return grub_errno;
 
@@ -162,7 +160,7 @@ grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
 
   /* When successful, not reached */
   b->unload_image (image_handle);
-  grub_efi_free_pages ((grub_efi_physical_address_t) loaded_image->load_options,
+  grub_efi_free_pages ((grub_addr_t) loaded_image->load_options,
 		       GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
 
   return grub_errno;
@@ -174,8 +172,8 @@ grub_linux_boot (void)
   if (finalize_params_linux () != GRUB_ERR_NONE)
     return grub_errno;
 
-  return (grub_arm64_uefi_boot_image((grub_addr_t)kernel_addr,
-                                     kernel_size, linux_args));
+  return (grub_armxx_efi_linux_boot_image((grub_addr_t)kernel_addr,
+                                          kernel_size, linux_args));
 }
 
 static grub_err_t
@@ -189,12 +187,48 @@ grub_linux_unload (void)
   initrd_start = initrd_end = 0;
   grub_free (linux_args);
   if (kernel_addr)
-    grub_efi_free_pages ((grub_efi_physical_address_t) kernel_addr,
+    grub_efi_free_pages ((grub_addr_t) kernel_addr,
 			 GRUB_EFI_BYTES_TO_PAGES (kernel_size));
   grub_fdt_unload ();
   return GRUB_ERR_NONE;
 }
 
+/*
+ * As per linux/Documentation/arm/Booting
+ * ARM initrd needs to be covered by kernel linear mapping,
+ * so place it in the first 512MB of DRAM.
+ *
+ * As per linux/Documentation/arm64/booting.txt
+ * ARM64 initrd needs to be contained entirely within a 1GB aligned window
+ * of up to 32GB of size that covers the kernel image as well.
+ * Since the EFI stub loader will attempt to load the kernel near start of
+ * RAM, place the buffer in the first 32GB of RAM.
+ */
+#ifdef __arm__
+#define INITRD_MAX_ADDRESS_OFFSET (512U * 1024 * 1024)
+#else /* __aarch64__ */
+#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024)
+#endif
+
+/*
+ * This function returns a pointer to a legally allocated initrd buffer,
+ * or NULL if unsuccessful
+ */
+static void *
+allocate_initrd_mem (int initrd_pages)
+{
+  grub_addr_t max_addr;
+
+  if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE)
+    return NULL;
+
+  max_addr += INITRD_MAX_ADDRESS_OFFSET - 1;
+
+  return grub_efi_allocate_pages_real (max_addr, initrd_pages,
+				       GRUB_EFI_ALLOCATE_MAX_ADDRESS,
+				       GRUB_EFI_LOADER_DATA);
+}
+
 static grub_err_t
 grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 		 int argc, char *argv[])
@@ -223,7 +257,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
   grub_dprintf ("linux", "Loading initrd\n");
 
   initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size));
-  initrd_mem = grub_efi_allocate_pages (0, initrd_pages);
+  initrd_mem = allocate_initrd_mem (initrd_pages);
+
   if (!initrd_mem)
     {
       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
@@ -241,8 +276,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
  fail:
   grub_initrd_close (&initrd_ctx);
   if (initrd_mem && !initrd_start)
-    grub_efi_free_pages ((grub_efi_physical_address_t) initrd_mem,
-			 initrd_pages);
+    grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages);
 
   return grub_errno;
 }
@@ -252,7 +286,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 		int argc, char *argv[])
 {
   grub_file_t file = 0;
-  struct grub_arm64_linux_kernel_header lh;
+  struct linux_armxx_kernel_header lh;
 
   grub_dl_ref (my_mod);
 
@@ -271,13 +305,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
   if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh))
     return grub_errno;
 
-  if (grub_arm64_uefi_check_image (&lh) != GRUB_ERR_NONE)
+  if (grub_armxx_efi_linux_check_image (&lh) != GRUB_ERR_NONE)
     goto fail;
 
   grub_loader_unset();
 
   grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size);
-  kernel_addr = grub_efi_allocate_pages (0, GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+  kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (kernel_size));
   grub_dprintf ("linux", "kernel numpages: %lld\n",
 		(long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size));
   if (!kernel_addr)
@@ -329,7 +363,7 @@ fail:
     grub_free (linux_args);
 
   if (kernel_addr && !loaded)
-    grub_efi_free_pages ((grub_efi_physical_address_t) kernel_addr,
+    grub_efi_free_pages ((grub_addr_t) kernel_addr,
 			 GRUB_EFI_BYTES_TO_PAGES (kernel_size));
 
   return grub_errno;
diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
index a914eb8e2df24ebaab41a2eb0ed205bcebafcf5d..1003a0b9997a46ea7e5106da02ef77e9be3a21fc 100644
--- a/grub-core/loader/arm64/xen_boot.c
+++ b/grub-core/loader/arm64/xen_boot.c
@@ -27,9 +27,10 @@
 #include <grub/misc.h>
 #include <grub/mm.h>
 #include <grub/types.h>
-#include <grub/cpu/fdtload.h>
 #include <grub/cpu/linux.h>
 #include <grub/efi/efi.h>
+#include <grub/efi/fdtload.h>
+#include <grub/efi/memory.h>
 #include <grub/efi/pe32.h>	/* required by struct xen_hypervisor_header */
 #include <grub/i18n.h>
 #include <grub/lib/cmdline.h>
@@ -66,7 +67,7 @@ typedef enum module_type module_type_t;
 
 struct xen_hypervisor_header
 {
-  struct grub_arm64_linux_kernel_header efi_head;
+  struct linux_arm64_kernel_header efi_head;
 
   /* This is always PE\0\0.  */
   grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
@@ -115,6 +116,17 @@ prepare_xen_hypervisor_params (void *xen_boot_fdt)
   if (chosen_node < 1)
     return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
 
+  /*
+   * The address and size are always written using 64-bits value. Set
+   * #address-cells and #size-cells accordingly.
+   */
+  retval = grub_fdt_set_prop32 (xen_boot_fdt, chosen_node, "#address-cells", 2);
+  if (retval)
+    return grub_error (GRUB_ERR_IO, "failed to set #address-cells");
+  retval = grub_fdt_set_prop32 (xen_boot_fdt, chosen_node, "#size-cells", 2);
+  if (retval)
+    return grub_error (GRUB_ERR_IO, "failed to set #size-cells");
+
   grub_dprintf ("xen_loader",
 		"Xen Hypervisor cmdline : %s @ %p size:%d\n",
 		xen_hypervisor->cmdline, xen_hypervisor->cmdline,
@@ -156,7 +168,7 @@ prepare_xen_module_params (struct xen_boot_binary *module, void *xen_boot_fdt)
       grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
 
   retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
-			      MODULE_CUSTOM_COMPATIBLE, sizeof(MODULE_CUSTOM_COMPATIBLE) - 1);
+			      MODULE_CUSTOM_COMPATIBLE, sizeof(MODULE_CUSTOM_COMPATIBLE));
   if (retval)
     return grub_error (GRUB_ERR_IO, "failed to update FDT");
 
@@ -253,9 +265,9 @@ xen_boot (void)
   if (err)
     return err;
 
-  return grub_arm64_uefi_boot_image (xen_hypervisor->start,
-				     xen_hypervisor->size,
-				     xen_hypervisor->cmdline);
+  return grub_armxx_efi_linux_boot_image (xen_hypervisor->start,
+					  xen_hypervisor->size,
+					  xen_hypervisor->cmdline);
 }
 
 static void
@@ -324,10 +336,9 @@ xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
   grub_dprintf ("xen_loader", "Xen_boot file size: 0x%lx\n", binary->size);
 
   binary->start
-    = (grub_addr_t) grub_efi_allocate_pages (0,
-					     GRUB_EFI_BYTES_TO_PAGES
-					     (binary->size +
-					      binary->align));
+    = (grub_addr_t) grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES
+						 (binary->size +
+						  binary->align));
   if (!binary->start)
     {
       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
@@ -379,6 +390,20 @@ grub_cmd_xen_module (grub_command_t cmd __attribute__((unused)),
 
   struct xen_boot_binary *module = NULL;
   grub_file_t file = 0;
+  int nounzip = 0;
+
+  if (!argc)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+      goto fail;
+    }
+
+  if (grub_strcmp (argv[0], "--nounzip") == 0)
+    {
+      argv++;
+      argc--;
+      nounzip = 1;
+    }
 
   if (!argc)
     {
@@ -403,6 +428,8 @@ grub_cmd_xen_module (grub_command_t cmd __attribute__((unused)),
 
   grub_dprintf ("xen_loader", "Init module and node info\n");
 
+  if (nounzip)
+    grub_file_filter_disable_compression ();
   file = grub_file_open (argv[0]);
   if (!file)
     goto fail;
@@ -441,8 +468,8 @@ grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
 
   if (grub_file_read (file, &sh, sizeof (sh)) != (long) sizeof (sh))
     goto fail;
-  if (grub_arm64_uefi_check_image
-      ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
+  if (grub_armxx_efi_linux_check_image
+      ((struct linux_armxx_kernel_header *) &sh) != GRUB_ERR_NONE)
     goto fail;
   grub_file_seek (file, 0);
 
diff --git a/grub-core/loader/arm64/fdt.c b/grub-core/loader/efi/fdt.c
similarity index 79%
rename from grub-core/loader/arm64/fdt.c
rename to grub-core/loader/efi/fdt.c
index db49cf64991764686c3f643e5289abbd4874a559..a4c6e8036454c1a53deefad791133488281462ea 100644
--- a/grub-core/loader/arm64/fdt.c
+++ b/grub-core/loader/efi/fdt.c
@@ -18,26 +18,33 @@
 
 #include <grub/fdt.h>
 #include <grub/mm.h>
-#include <grub/cpu/fdtload.h>
 #include <grub/err.h>
 #include <grub/dl.h>
 #include <grub/command.h>
 #include <grub/file.h>
 #include <grub/efi/efi.h>
+#include <grub/efi/fdtload.h>
+#include <grub/efi/memory.h>
 
 static void *loaded_fdt;
 static void *fdt;
 
+#define FDT_ADDR_CELLS_STRING "#address-cells"
+#define FDT_SIZE_CELLS_STRING "#size-cells"
+#define FDT_ADDR_SIZE_EXTRA ((2 * grub_fdt_prop_entry_size (sizeof(grub_uint32_t))) + \
+                             sizeof (FDT_ADDR_CELLS_STRING) + \
+                             sizeof (FDT_SIZE_CELLS_STRING))
+
 void *
 grub_fdt_load (grub_size_t additional_size)
 {
   void *raw_fdt;
-  grub_size_t size;
+  unsigned int size;
 
   if (fdt)
     {
       size = GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt));
-      grub_efi_free_pages ((grub_efi_physical_address_t) fdt, size);
+      grub_efi_free_pages ((grub_addr_t) fdt, size);
     }
 
   if (loaded_fdt)
@@ -45,12 +52,15 @@ grub_fdt_load (grub_size_t additional_size)
   else
     raw_fdt = grub_efi_get_firmware_fdt();
 
-  size =
-    raw_fdt ? grub_fdt_get_totalsize (raw_fdt) : GRUB_FDT_EMPTY_TREE_SZ;
+  if (raw_fdt)
+      size = grub_fdt_get_totalsize (raw_fdt);
+  else
+      size = GRUB_FDT_EMPTY_TREE_SZ + FDT_ADDR_SIZE_EXTRA;
+
   size += additional_size;
 
-  grub_dprintf ("linux", "allocating %ld bytes for fdt\n", size);
-  fdt = grub_efi_allocate_pages (0, GRUB_EFI_BYTES_TO_PAGES (size));
+  grub_dprintf ("linux", "allocating %d bytes for fdt\n", size);
+  fdt = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (size));
   if (!fdt)
     return NULL;
 
@@ -62,6 +72,8 @@ grub_fdt_load (grub_size_t additional_size)
   else
     {
       grub_fdt_create_empty_tree (fdt, size);
+      grub_fdt_set_prop32 (fdt, 0, FDT_ADDR_CELLS_STRING, 2);
+      grub_fdt_set_prop32 (fdt, 0, FDT_SIZE_CELLS_STRING, 2);
     }
   return fdt;
 }
@@ -88,7 +100,7 @@ grub_fdt_unload (void) {
   if (!fdt) {
     return;
   }
-  grub_efi_free_pages ((grub_efi_physical_address_t) fdt,
+  grub_efi_free_pages ((grub_addr_t) fdt,
 		       GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt)));
   fdt = NULL;
 }
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
index 083f9417cb65e509e673dba09a71616c5661ab05..9b53d3168f9bb78eab7a124518e83915183912b9 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -306,6 +306,12 @@ grub_linux_setup_video (struct linux_kernel_params *params)
   params->lfb_line_len = mode_info.pitch;
 
   params->lfb_base = (grub_size_t) framebuffer;
+
+#if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
+  params->ext_lfb_base = (grub_size_t) (((grub_uint64_t)(grub_size_t) framebuffer) >> 32);
+  params->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
+#endif
+
   params->lfb_size = ALIGN_UP (params->lfb_line_len * params->lfb_height, 65536);
 
   params->red_mask_size = mode_info.red_mask_size;
@@ -678,7 +684,7 @@ 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_i386_kernel_header lh;
   grub_uint8_t setup_sects;
   grub_size_t real_size, prot_size, prot_file_size;
   grub_ssize_t len;
@@ -721,7 +727,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_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+  if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_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/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c
index fd7b41b0cad4f26d1170d70692ac1ac27fd6bd73..dc98dbcae258b340e155c64f1f73213ac724806a 100644
--- a/grub-core/loader/i386/multiboot_mbi.c
+++ b/grub-core/loader/i386/multiboot_mbi.c
@@ -239,7 +239,7 @@ grub_multiboot_get_mbi_size (void)
   ret = sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
     + modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
     + ALIGN_UP (sizeof(PACKAGE_STRING), 4) 
-    + grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)
+    + grub_multiboot_get_mmap_count () * sizeof (struct multiboot_mmap_entry)
     + elf_sec_entsize * elf_sec_num
     + 256 * sizeof (struct multiboot_color)
 #if GRUB_MACHINE_HAS_VBE || GRUB_MACHINE_HAS_VGA_TEXT
@@ -542,7 +542,7 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
       mbi->mods_count = 0;
     }
 
-  mmap_size = grub_get_multiboot_mmap_count () 
+  mmap_size = grub_multiboot_get_mmap_count () 
     * sizeof (struct multiboot_mmap_entry);
   grub_fill_multiboot_mmap ((struct multiboot_mmap_entry *) ptrorig);
   mbi->mmap_length = mmap_size;
diff --git a/grub-core/loader/i386/pc/chainloader.c b/grub-core/loader/i386/pc/chainloader.c
index c79c4fe0fc99a876b3e92f0a24f16cd636e00a0d..ef3a322b78cf10a406c0420780f821e2e1d1b284 100644
--- a/grub-core/loader/i386/pc/chainloader.c
+++ b/grub-core/loader/i386/pc/chainloader.c
@@ -19,6 +19,7 @@
 
 #include <grub/loader.h>
 #include <grub/machine/chainloader.h>
+#include <grub/machine/biosdisk.h>
 #include <grub/machine/memory.h>
 #include <grub/file.h>
 #include <grub/err.h>
@@ -86,9 +87,16 @@ grub_chainloader_unload (void)
 void
 grub_chainloader_patch_bpb (void *bs, grub_device_t dev, grub_uint8_t dl)
 {
-  grub_uint32_t part_start = 0;
+  grub_uint32_t part_start = 0, heads = 0, sectors = 0;
   if (dev && dev->disk)
-    part_start = grub_partition_get_start (dev->disk->partition);
+    {
+      part_start = grub_partition_get_start (dev->disk->partition);
+      if (dev->disk->data)
+        {
+          heads = ((struct grub_biosdisk_data *)(dev->disk->data))->heads;
+          sectors = ((struct grub_biosdisk_data *)(dev->disk->data))->sectors;
+        }
+    }
   if (grub_memcmp ((char *) &((struct grub_ntfs_bpb *) bs)->oem_name,
 		   "NTFS", 4) == 0)
     {
@@ -117,7 +125,7 @@ grub_chainloader_patch_bpb (void *bs, grub_device_t dev, grub_uint8_t dl)
 
       if (bpb->num_reserved_sectors == 0)
 	break;
-      if (bpb->num_total_sectors_16 == 0 || bpb->num_total_sectors_32 == 0)
+      if (bpb->num_total_sectors_16 == 0 && bpb->num_total_sectors_32 == 0)
 	break;
 
       if (bpb->num_fats == 0)
@@ -127,12 +135,20 @@ grub_chainloader_patch_bpb (void *bs, grub_device_t dev, grub_uint8_t dl)
 	{
 	  bpb->num_hidden_sectors = grub_cpu_to_le32 (part_start);
 	  bpb->version_specific.fat12_or_fat16.num_ph_drive = dl;
+          if (sectors)
+            bpb->sectors_per_track = grub_cpu_to_le16 (sectors);
+          if (heads)
+            bpb->num_heads = grub_cpu_to_le16 (heads);
 	  return;
 	}
       if (bpb->version_specific.fat32.sectors_per_fat_32)
 	{
 	  bpb->num_hidden_sectors = grub_cpu_to_le32 (part_start);
 	  bpb->version_specific.fat32.num_ph_drive = dl;
+          if (sectors)
+            bpb->sectors_per_track = grub_cpu_to_le16 (sectors);
+          if (heads)
+            bpb->num_heads = grub_cpu_to_le16 (heads);
 	  return;
 	}
       break;
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
index a293b17aa101b308635bbed4086ae1547b91b884..b69cb7a3a7f8a9ca96a91a78c47fa1515e628699 100644
--- a/grub-core/loader/i386/pc/linux.c
+++ b/grub-core/loader/i386/pc/linux.c
@@ -121,7 +121,7 @@ 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_i386_kernel_header lh;
   grub_uint8_t setup_sects;
   grub_size_t real_size;
   grub_ssize_t len;
@@ -169,7 +169,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 
   maximal_cmdline_size = 256;
 
-  if (lh.header == grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+  if (lh.header == grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
       && grub_le_to_cpu16 (lh.version) >= 0x0200)
     {
       grub_linux_is_bzimage = (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL);
@@ -322,7 +322,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
       goto fail;
     }
 
-  if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+  if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
       || grub_le_to_cpu16 (lh.version) < 0x0200)
     /* Clear the heap space.  */
     grub_memset (grub_linux_real_chunk
@@ -387,7 +387,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 {
   grub_size_t size = 0;
   grub_addr_t addr_max, addr_min;
-  struct linux_kernel_header *lh;
+  struct linux_i386_kernel_header *lh;
   grub_uint8_t *initrd_chunk;
   grub_addr_t initrd_addr;
   grub_err_t err;
@@ -405,9 +405,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
       goto fail;
     }
 
-  lh = (struct linux_kernel_header *) grub_linux_real_chunk;
+  lh = (struct linux_i386_kernel_header *) grub_linux_real_chunk;
 
-  if (!(lh->header == grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+  if (!(lh->header == grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_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/grub-core/loader/i386/xen_file.c b/grub-core/loader/i386/xen_file.c
index 99fad4cadae42ab09497babca15cd9606557fcd2..77a93e7b228316e1df731e01e51e67f9225b4482 100644
--- a/grub-core/loader/i386/xen_file.c
+++ b/grub-core/loader/i386/xen_file.c
@@ -26,7 +26,7 @@ grub_elf_t
 grub_xen_file (grub_file_t file)
 {
   grub_elf_t elf;
-  struct linux_kernel_header lh;
+  struct linux_i386_kernel_header lh;
   grub_file_t off_file;
   grub_uint32_t payload_offset, payload_length;
   grub_uint8_t magic[6];
@@ -43,7 +43,7 @@ grub_xen_file (grub_file_t file)
     goto fail;
 
   if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55)
-      || lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
+      || lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_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/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c
index efaa42ccdd2bf74321de20cf5033a80676cc7dc3..750330d4572d0dcd09d02b4b75c1f03045fa897b 100644
--- a/grub-core/loader/ia64/efi/linux.c
+++ b/grub-core/loader/ia64/efi/linux.c
@@ -252,7 +252,7 @@ allocate_pages (grub_uint64_t align, grub_uint64_t size_pages,
 	aligned_start += align;
       if (aligned_start + size > end)
 	continue;
-      mem = grub_efi_allocate_pages (aligned_start, size_pages);
+      mem = grub_efi_allocate_fixed (aligned_start, size_pages);
       if (! mem)
 	{
 	  grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory");
@@ -326,7 +326,7 @@ grub_linux_boot (void)
   mmap_size = find_mmap_size ();
   if (! mmap_size)
     return grub_errno;
-  mmap_buf = grub_efi_allocate_pages (0, page_align (mmap_size) >> 12);
+  mmap_buf = grub_efi_allocate_any_pages (page_align (mmap_size) >> 12);
   if (! mmap_buf)
     return grub_error (GRUB_ERR_IO, "cannot allocate memory map");
   err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, &map_key,
@@ -422,7 +422,7 @@ grub_load_elf64 (grub_file_t file, void *buffer, const char *filename)
   relocate = grub_env_get ("linux_relocate");
   if (!relocate || grub_strcmp (relocate, "force") != 0)
     {
-      kernel_mem = grub_efi_allocate_pages (low_addr, kernel_pages);
+      kernel_mem = grub_efi_allocate_fixed (low_addr, kernel_pages);
       reloc_offset = 0;
     }
   /* Try to relocate.  */
@@ -524,7 +524,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
     len += grub_strlen (argv[i]) + 1;
   len += sizeof (struct ia64_boot_param) + 512; /* Room for extensions.  */
   boot_param_pages = page_align (len) >> 12;
-  boot_param = grub_efi_allocate_pages (0, boot_param_pages);
+  boot_param = grub_efi_allocate_any_pages (boot_param_pages);
   if (boot_param == 0)
     {
       grub_error (GRUB_ERR_OUT_OF_MEMORY,
@@ -589,7 +589,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
   grub_dprintf ("linux", "Loading initrd\n");
 
   initrd_pages = (page_align (initrd_size) >> 12);
-  initrd_mem = grub_efi_allocate_pages (0, initrd_pages);
+  initrd_mem = grub_efi_allocate_any_pages (initrd_pages);
   if (! initrd_mem)
     {
       grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate pages");
diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
index bd9d5b3e698588db594a2c334d715e0e883bab92..40c67e82489ec3ecf891ae564cde810bf280b242 100644
--- a/grub-core/loader/multiboot.c
+++ b/grub-core/loader/multiboot.c
@@ -28,7 +28,15 @@
 
 #include <grub/loader.h>
 #include <grub/command.h>
+#ifdef GRUB_USE_MULTIBOOT2
+#include <grub/multiboot2.h>
+#define GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER GRUB_MULTIBOOT2_CONSOLE_FRAMEBUFFER
+#define GRUB_MULTIBOOT_CONSOLE_EGA_TEXT GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT
+#define GRUB_MULTIBOOT(x) grub_multiboot2_ ## x
+#else
 #include <grub/multiboot.h>
+#define GRUB_MULTIBOOT(x) grub_multiboot_ ## x
+#endif
 #include <grub/cpu/multiboot.h>
 #include <grub/elf.h>
 #include <grub/aout.h>
@@ -49,8 +57,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
 #include <grub/efi/efi.h>
 #endif
 
-struct grub_relocator *grub_multiboot_relocator = NULL;
-grub_uint32_t grub_multiboot_payload_eip;
+struct grub_relocator *GRUB_MULTIBOOT (relocator) = NULL;
+grub_uint32_t GRUB_MULTIBOOT (payload_eip);
 #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
 #define DEFAULT_VIDEO_MODE "text"
 #else
@@ -78,7 +86,7 @@ count_hook (grub_uint64_t addr __attribute__ ((unused)),
 /* Return the length of the Multiboot mmap that will be needed to allocate
    our platform's map.  */
 grub_uint32_t
-grub_get_multiboot_mmap_count (void)
+GRUB_MULTIBOOT (get_mmap_count) (void)
 {
   grub_size_t count = 0;
 
@@ -88,7 +96,7 @@ grub_get_multiboot_mmap_count (void)
 }
 
 grub_err_t
-grub_multiboot_set_video_mode (void)
+GRUB_MULTIBOOT (set_video_mode) (void)
 {
   grub_err_t err;
   const char *modevar;
@@ -130,9 +138,12 @@ static void
 efi_boot (struct grub_relocator *rel,
 	  grub_uint32_t target)
 {
+#ifdef GRUB_USE_MULTIBOOT2
+  struct grub_relocator_efi_state state_efi = MULTIBOOT2_EFI_INITIAL_STATE;
+#else
   struct grub_relocator_efi_state state_efi = MULTIBOOT_EFI_INITIAL_STATE;
-
-  state_efi.MULTIBOOT_EFI_ENTRY_REGISTER = grub_multiboot_payload_eip;
+#endif
+  state_efi.MULTIBOOT_EFI_ENTRY_REGISTER = GRUB_MULTIBOOT (payload_eip);
   state_efi.MULTIBOOT_EFI_MBI_REGISTER = target;
 
   grub_relocator_efi_boot (rel, state_efi);
@@ -164,19 +175,23 @@ static grub_err_t
 grub_multiboot_boot (void)
 {
   grub_err_t err;
+
+#ifdef GRUB_USE_MULTIBOOT2
+  struct grub_relocator32_state state = MULTIBOOT2_INITIAL_STATE;
+#else
   struct grub_relocator32_state state = MULTIBOOT_INITIAL_STATE;
+#endif
+  state.MULTIBOOT_ENTRY_REGISTER = GRUB_MULTIBOOT (payload_eip);
 
-  state.MULTIBOOT_ENTRY_REGISTER = grub_multiboot_payload_eip;
-
-  err = grub_multiboot_make_mbi (&state.MULTIBOOT_MBI_REGISTER);
+  err = GRUB_MULTIBOOT (make_mbi) (&state.MULTIBOOT_MBI_REGISTER);
 
   if (err)
     return err;
 
   if (grub_efi_is_finished)
-    normal_boot (grub_multiboot_relocator, state);
+    normal_boot (GRUB_MULTIBOOT (relocator), state);
   else
-    efi_boot (grub_multiboot_relocator, state.MULTIBOOT_MBI_REGISTER);
+    efi_boot (GRUB_MULTIBOOT (relocator), state.MULTIBOOT_MBI_REGISTER);
 
   /* Not reached.  */
   return GRUB_ERR_NONE;
@@ -185,10 +200,10 @@ grub_multiboot_boot (void)
 static grub_err_t
 grub_multiboot_unload (void)
 {
-  grub_multiboot_free_mbi ();
+  GRUB_MULTIBOOT (free_mbi) ();
 
-  grub_relocator_unload (grub_multiboot_relocator);
-  grub_multiboot_relocator = NULL;
+  grub_relocator_unload (GRUB_MULTIBOOT (relocator));
+  GRUB_MULTIBOOT (relocator) = NULL;
 
   grub_dl_unref (my_mod);
 
@@ -207,7 +222,7 @@ static grub_uint64_t highest_load;
 
 /* Load ELF32 or ELF64.  */
 grub_err_t
-grub_multiboot_load_elf (mbi_load_data_t *mld)
+GRUB_MULTIBOOT (load_elf) (mbi_load_data_t *mld)
 {
   if (grub_multiboot_is_elf32 (mld->buffer))
     return grub_multiboot_load_elf32 (mld);
@@ -218,9 +233,9 @@ grub_multiboot_load_elf (mbi_load_data_t *mld)
 }
 
 grub_err_t
-grub_multiboot_set_console (int console_type, int accepted_consoles,
-			    int width, int height, int depth,
-			    int console_req)
+GRUB_MULTIBOOT (set_console) (int console_type, int accepted_consoles,
+			      int width, int height, int depth,
+			      int console_req)
 {
   console_required = console_req;
   if (!(accepted_consoles 
@@ -313,19 +328,19 @@ grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
   grub_dl_ref (my_mod);
 
   /* Skip filename.  */
-  grub_multiboot_init_mbi (argc - 1, argv + 1);
+  GRUB_MULTIBOOT (init_mbi) (argc - 1, argv + 1);
 
-  grub_relocator_unload (grub_multiboot_relocator);
-  grub_multiboot_relocator = grub_relocator_new ();
+  grub_relocator_unload (GRUB_MULTIBOOT (relocator));
+  GRUB_MULTIBOOT (relocator) = grub_relocator_new ();
 
-  if (!grub_multiboot_relocator)
+  if (!GRUB_MULTIBOOT (relocator))
     goto fail;
 
-  err = grub_multiboot_load (file, argv[0]);
+  err = GRUB_MULTIBOOT (load) (file, argv[0]);
   if (err)
     goto fail;
 
-  grub_multiboot_set_bootdev ();
+  GRUB_MULTIBOOT (set_bootdev) ();
 
   grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
 
@@ -335,8 +350,8 @@ grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
 
   if (grub_errno != GRUB_ERR_NONE)
     {
-      grub_relocator_unload (grub_multiboot_relocator);
-      grub_multiboot_relocator = NULL;
+      grub_relocator_unload (GRUB_MULTIBOOT (relocator));
+      GRUB_MULTIBOOT (relocator) = NULL;
       grub_dl_unref (my_mod);
     }
 
@@ -368,7 +383,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
   if (argc == 0)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
 
-  if (!grub_multiboot_relocator)
+  if (!GRUB_MULTIBOOT (relocator))
     return grub_error (GRUB_ERR_BAD_ARGUMENT,
 		       N_("you need to load the kernel first"));
 
@@ -389,7 +404,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
   if (size)
   {
     grub_relocator_chunk_t ch;
-    err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
+    err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch,
 					    lowest_addr, (0xffffffff - size) + 1,
 					    size, MULTIBOOT_MOD_ALIGN,
 					    GRUB_RELOCATOR_PREFERENCE_NONE, 1);
@@ -407,7 +422,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
       target = 0;
     }
 
-  err = grub_multiboot_add_module (target, size, argc - 1, argv + 1);
+  err = GRUB_MULTIBOOT (add_module) (target, size, argc - 1, argv + 1);
   if (err)
     {
       grub_file_close (file);
diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c
index 5e649ed2545bee3fbe9602c9d97079160dc6420a..70cd1db513e679f0e02e06dc2de24747a62b88ba 100644
--- a/grub-core/loader/multiboot_elfxx.c
+++ b/grub-core/loader/multiboot_elfxx.c
@@ -57,9 +57,9 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
   char *phdr_base;
   grub_err_t err;
   grub_relocator_chunk_t ch;
-  grub_uint32_t load_offset, load_size;
+  grub_uint32_t load_offset = 0, load_size;
   int i;
-  void *source;
+  void *source = NULL;
 
   if (ehdr->e_ident[EI_MAG0] != ELFMAG0
       || ehdr->e_ident[EI_MAG1] != ELFMAG1
@@ -97,38 +97,38 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
     return grub_error (GRUB_ERR_BAD_OS, "segment crosses 4 GiB border");
 #endif
 
-  load_size = highest_load - mld->link_base_addr;
-
   if (mld->relocatable)
     {
+      load_size = highest_load - mld->link_base_addr;
+
+      grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, "
+		    "load_size=0x%x, avoid_efi_boot_services=%d\n",
+		    (long) mld->align, mld->preference, load_size,
+		    mld->avoid_efi_boot_services);
+
       if (load_size > mld->max_addr || mld->min_addr > mld->max_addr - load_size)
 	return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
 
-      err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
+      err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch,
 					      mld->min_addr, mld->max_addr - load_size,
 					      load_size, mld->align ? mld->align : 1,
 					      mld->preference, mld->avoid_efi_boot_services);
+
+      if (err)
+        {
+          grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n");
+          return err;
+        }
+
+      mld->load_base_addr = get_physical_target_address (ch);
+      source = get_virtual_current_address (ch);
     }
   else
-    err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, &ch,
-					   mld->link_base_addr, load_size);
+    mld->load_base_addr = mld->link_base_addr;
 
-  if (err)
-    {
-      grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n");
-      return err;
-    }
-
-  mld->load_base_addr = get_physical_target_address (ch);
-  source = get_virtual_current_address (ch);
-
-  grub_dprintf ("multiboot_loader", "link_base_addr=0x%x, load_base_addr=0x%x, "
-		"load_size=0x%x, relocatable=%d\n", mld->link_base_addr,
-		mld->load_base_addr, load_size, mld->relocatable);
-
-  if (mld->relocatable)
-    grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, avoid_efi_boot_services=%d\n",
-		  (long) mld->align, mld->preference, mld->avoid_efi_boot_services);
+  grub_dprintf ("multiboot_loader", "relocatable=%d, link_base_addr=0x%x, "
+		"load_base_addr=0x%x\n", mld->relocatable,
+		mld->link_base_addr, mld->load_base_addr);
 
   /* Load every loadable segment in memory.  */
   for (i = 0; i < ehdr->e_phnum; i++)
@@ -139,7 +139,24 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
 	  grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, memsz=0x%lx, vaddr=0x%lx\n",
 			i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long) phdr(i)->p_vaddr);
 
-	  load_offset = phdr(i)->p_paddr - mld->link_base_addr;
+	  if (mld->relocatable)
+	    {
+	      load_offset = phdr(i)->p_paddr - mld->link_base_addr;
+	      grub_dprintf ("multiboot_loader", "segment %d: load_offset=0x%x\n", i, load_offset);
+	    }
+	  else
+	    {
+	      err = grub_relocator_alloc_chunk_addr (GRUB_MULTIBOOT (relocator), &ch,
+	                                             phdr(i)->p_paddr, phdr(i)->p_memsz);
+
+	      if (err)
+		{
+		  grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n");
+		  return err;
+		}
+
+	      source = get_virtual_current_address (ch);
+	    }
 
 	  if (phdr(i)->p_filesz != 0)
 	    {
@@ -167,7 +184,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
     if (phdr(i)->p_vaddr <= ehdr->e_entry
 	&& phdr(i)->p_vaddr + phdr(i)->p_memsz > ehdr->e_entry)
       {
-	grub_multiboot_payload_eip = (ehdr->e_entry - phdr(i)->p_vaddr)
+	GRUB_MULTIBOOT (payload_eip) = (ehdr->e_entry - phdr(i)->p_vaddr)
 	  + phdr(i)->p_paddr;
 #ifdef MULTIBOOT_LOAD_ELF64
 # ifdef __mips
@@ -191,7 +208,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
 #if defined (__i386__) || defined (__x86_64__)
   
 #elif defined (__mips)
-  grub_multiboot_payload_eip |= 0x80000000;
+  GRUB_MULTIBOOT (payload_eip) |= 0x80000000;
 #else
 #error Please complete this
 #endif
@@ -238,7 +255,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
 	  if (sh->sh_size == 0)
 	    continue;
 
-	  err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, 0,
+	  err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch, 0,
 						  (0xffffffff - sh->sh_size) + 1,
 						  sh->sh_size, sh->sh_addralign,
 						  GRUB_RELOCATOR_PREFERENCE_NONE,
@@ -264,8 +281,8 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
 	    }
 	  sh->sh_addr = target;
 	}
-      grub_multiboot_add_elfsyms (ehdr->e_shnum, ehdr->e_shentsize,
-				  ehdr->e_shstrndx, shdr);
+      GRUB_MULTIBOOT (add_elfsyms) (ehdr->e_shnum, ehdr->e_shentsize,
+				    ehdr->e_shstrndx, shdr);
     }
 
 #undef phdr
diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
index b0679a9f6c9848d81cb74cf799ad3a7b235d937c..4df6595954d889028e4525bb66b42cf391f4c9ce 100644
--- a/grub-core/loader/multiboot_mbi2.c
+++ b/grub-core/loader/multiboot_mbi2.c
@@ -22,7 +22,7 @@
 #include <grub/machine/apm.h>
 #include <grub/machine/memory.h>
 #endif
-#include <grub/multiboot.h>
+#include <grub/multiboot2.h>
 #include <grub/cpu/multiboot.h>
 #include <grub/cpu/relocator.h>
 #include <grub/disk.h>
@@ -71,7 +71,7 @@ static int keep_bs = 0;
 static grub_uint32_t load_base_addr;
 
 void
-grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize,
+grub_multiboot2_add_elfsyms (grub_size_t num, grub_size_t entsize,
 			    unsigned shndx, void *data)
 {
   elf_sec_num = num;
@@ -90,17 +90,17 @@ find_header (grub_properly_aligned_t *buffer, grub_ssize_t len)
        ((char *) header <= (char *) buffer + len - 12);
        header = (struct multiboot_header *) ((grub_uint32_t *) header + MULTIBOOT_HEADER_ALIGN / 4))
     {
-      if (header->magic == MULTIBOOT_HEADER_MAGIC
+      if (header->magic == MULTIBOOT2_HEADER_MAGIC
 	  && !(header->magic + header->architecture
 	       + header->header_length + header->checksum)
-	  && header->architecture == MULTIBOOT_ARCHITECTURE_CURRENT)
+	  && header->architecture == MULTIBOOT2_ARCHITECTURE_CURRENT)
 	return header;
     }
   return NULL;
 }
 
 grub_err_t
-grub_multiboot_load (grub_file_t file, const char *filename)
+grub_multiboot2_load (grub_file_t file, const char *filename)
 {
   grub_ssize_t len;
   struct multiboot_header *header;
@@ -112,7 +112,7 @@ grub_multiboot_load (grub_file_t file, const char *filename)
   grub_addr_t entry = 0, efi_entry = 0;
   grub_uint32_t console_required = 0;
   struct multiboot_header_tag_framebuffer *fbtag = NULL;
-  int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
+  int accepted_consoles = GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT;
   mbi_load_data_t mld;
 
   mld.mbi_ver = 2;
@@ -210,7 +210,7 @@ grub_multiboot_load (grub_file_t file, const char *filename)
       case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
 	if (!(((struct multiboot_header_tag_console_flags *) tag)->console_flags
 	    & MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED))
-	  accepted_consoles &= ~GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
+	  accepted_consoles &= ~GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT;
 	if (((struct multiboot_header_tag_console_flags *) tag)->console_flags
 	    & MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED)
 	  console_required = 1;
@@ -218,7 +218,7 @@ grub_multiboot_load (grub_file_t file, const char *filename)
 
       case MULTIBOOT_HEADER_TAG_FRAMEBUFFER:
 	fbtag = (struct multiboot_header_tag_framebuffer *) tag;
-	accepted_consoles |= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER;
+	accepted_consoles |= GRUB_MULTIBOOT2_CONSOLE_FRAMEBUFFER;
 	break;
 
       case MULTIBOOT_HEADER_TAG_RELOCATABLE:
@@ -295,13 +295,13 @@ grub_multiboot_load (grub_file_t file, const char *filename)
 	      return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
 	    }
 
-	  err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
+	  err = grub_relocator_alloc_chunk_align (grub_multiboot2_relocator, &ch,
 						  mld.min_addr, mld.max_addr - code_size,
 						  code_size, mld.align ? mld.align : 1,
 						  mld.preference, keep_bs);
 	}
       else
-	err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator,
+	err = grub_relocator_alloc_chunk_addr (grub_multiboot2_relocator,
 					       &ch, load_addr, code_size);
       if (err)
 	{
@@ -343,7 +343,7 @@ grub_multiboot_load (grub_file_t file, const char *filename)
       mld.file = file;
       mld.filename = filename;
       mld.avoid_efi_boot_services = keep_bs;
-      err = grub_multiboot_load_elf (&mld);
+      err = grub_multiboot2_load_elf (&mld);
       if (err)
 	{
 	  grub_free (mld.buffer);
@@ -354,9 +354,9 @@ grub_multiboot_load (grub_file_t file, const char *filename)
   load_base_addr = mld.load_base_addr;
 
   if (keep_bs && efi_entry_specified)
-    grub_multiboot_payload_eip = efi_entry;
+    grub_multiboot2_payload_eip = efi_entry;
   else if (entry_specified)
-    grub_multiboot_payload_eip = entry;
+    grub_multiboot2_payload_eip = entry;
 
   if (mld.relocatable)
     {
@@ -370,20 +370,20 @@ grub_multiboot_load (grub_file_t file, const char *filename)
        * 64-bit int here.
        */
       if (mld.load_base_addr >= mld.link_base_addr)
-	grub_multiboot_payload_eip += mld.load_base_addr - mld.link_base_addr;
+	grub_multiboot2_payload_eip += mld.load_base_addr - mld.link_base_addr;
       else
-	grub_multiboot_payload_eip -= mld.link_base_addr - mld.load_base_addr;
+	grub_multiboot2_payload_eip -= mld.link_base_addr - mld.load_base_addr;
     }
 
   if (fbtag)
-    err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
-				      accepted_consoles,
-				      fbtag->width, fbtag->height,
-				      fbtag->depth, console_required);
+    err = grub_multiboot2_set_console (GRUB_MULTIBOOT2_CONSOLE_FRAMEBUFFER,
+				       accepted_consoles,
+				       fbtag->width, fbtag->height,
+				       fbtag->depth, console_required);
   else
-    err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
-				      accepted_consoles,
-				      0, 0, 0, console_required);
+    err = grub_multiboot2_set_console (GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT,
+				       accepted_consoles,
+				       0, 0, 0, console_required);
   return err;
 }
 
@@ -459,7 +459,7 @@ net_size (void)
 }
 
 static grub_size_t
-grub_multiboot_get_mbi_size (void)
+grub_multiboot2_get_mbi_size (void)
 {
 #ifdef GRUB_MACHINE_EFI
   if (!keep_bs && !efi_mmap_size)
@@ -478,7 +478,7 @@ grub_multiboot_get_mbi_size (void)
     + ALIGN_UP (sizeof (struct multiboot_tag_elf_sections), MULTIBOOT_TAG_ALIGN)
     + ALIGN_UP (elf_sec_entsize * elf_sec_num, MULTIBOOT_TAG_ALIGN)
     + ALIGN_UP ((sizeof (struct multiboot_tag_mmap)
-		 + grub_get_multiboot_mmap_count ()
+		 + grub_multiboot2_get_mmap_count ()
 		 * sizeof (struct multiboot_mmap_entry)), MULTIBOOT_TAG_ALIGN)
     + ALIGN_UP (sizeof (struct multiboot_tag_framebuffer), MULTIBOOT_TAG_ALIGN)
     + ALIGN_UP (sizeof (struct multiboot_tag_old_acpi)
@@ -522,7 +522,7 @@ grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag)
 
   tag->type = MULTIBOOT_TAG_TYPE_MMAP;
   tag->size = sizeof (struct multiboot_tag_mmap)
-    + sizeof (struct multiboot_mmap_entry) * grub_get_multiboot_mmap_count (); 
+    + sizeof (struct multiboot_mmap_entry) * grub_multiboot2_get_mmap_count (); 
   tag->entry_size = sizeof (struct multiboot_mmap_entry);
   tag->entry_version = 0;
 
@@ -588,7 +588,7 @@ retrieve_video_parameters (grub_properly_aligned_t **ptrorig)
   struct multiboot_tag_framebuffer *tag
     = (struct multiboot_tag_framebuffer *) *ptrorig;
 
-  err = grub_multiboot_set_video_mode ();
+  err = grub_multiboot2_set_video_mode ();
   if (err)
     {
       grub_print_error ();
@@ -731,7 +731,7 @@ retrieve_video_parameters (grub_properly_aligned_t **ptrorig)
 }
 
 grub_err_t
-grub_multiboot_make_mbi (grub_uint32_t *target)
+grub_multiboot2_make_mbi (grub_uint32_t *target)
 {
   grub_properly_aligned_t *ptrorig;
   grub_properly_aligned_t *mbistart;
@@ -739,11 +739,11 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
   grub_size_t bufsize;
   grub_relocator_chunk_t ch;
 
-  bufsize = grub_multiboot_get_mbi_size ();
+  bufsize = grub_multiboot2_get_mbi_size ();
 
   COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % sizeof (grub_properly_aligned_t) == 0);
 
-  err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
+  err = grub_relocator_alloc_chunk_align (grub_multiboot2_relocator, &ch,
 					  0, 0xffffffff - bufsize,
 					  bufsize, MULTIBOOT_TAG_ALIGN,
 					  GRUB_RELOCATOR_PREFERENCE_NONE, 1);
@@ -1039,7 +1039,7 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
 }
 
 void
-grub_multiboot_free_mbi (void)
+grub_multiboot2_free_mbi (void)
 {
   struct module *cur, *next;
 
@@ -1061,11 +1061,11 @@ grub_multiboot_free_mbi (void)
 }
 
 grub_err_t
-grub_multiboot_init_mbi (int argc, char *argv[])
+grub_multiboot2_init_mbi (int argc, char *argv[])
 {
   grub_ssize_t len = 0;
 
-  grub_multiboot_free_mbi ();
+  grub_multiboot2_free_mbi ();
 
   len = grub_loader_cmdline_size (argc, argv);
 
@@ -1081,7 +1081,7 @@ grub_multiboot_init_mbi (int argc, char *argv[])
 }
 
 grub_err_t
-grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
+grub_multiboot2_add_module (grub_addr_t start, grub_size_t size,
 			   int argc, char *argv[])
 {
   struct module *newmod;
@@ -1119,7 +1119,7 @@ grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
 }
 
 void
-grub_multiboot_set_bootdev (void)
+grub_multiboot2_set_bootdev (void)
 {
   grub_device_t dev;
 
diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c
index 4b68c4151a11db214602f74e111e7552801d8450..54306e3b16d25fe5d3bdf9502683822237be488d 100644
--- a/grub-core/net/arp.c
+++ b/grub-core/net/arp.c
@@ -111,8 +111,8 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
 }
 
 grub_err_t
-grub_net_arp_receive (struct grub_net_buff *nb,
-		      struct grub_net_card *card)
+grub_net_arp_receive (struct grub_net_buff *nb, struct grub_net_card *card,
+                      grub_uint16_t *vlantag)
 {
   struct arppkt *arp_packet = (struct arppkt *) nb->data;
   grub_net_network_level_address_t sender_addr, target_addr;
@@ -138,6 +138,14 @@ grub_net_arp_receive (struct grub_net_buff *nb,
 
   FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
   {
+    /* Verify vlantag id */
+    if (inf->card == card && inf->vlantag != *vlantag)
+      {
+        grub_dprintf ("net", "invalid vlantag! %x != %x\n",
+                      inf->vlantag, *vlantag);
+        break;
+      }
+
     /* 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))
diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c
index a78d164db1a0abbaf0417f70dc7180b9b2c4df76..002446be1c385934762824a965806ffb75f422a0 100644
--- a/grub-core/net/drivers/ieee1275/ofnet.c
+++ b/grub-core/net/drivers/ieee1275/ofnet.c
@@ -153,11 +153,11 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
   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 = NULL;
+  grub_uint16_t vlantag = 0;
 
   hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
 
@@ -175,6 +175,11 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
           *equal_char = 0;
           grub_env_set_net_property ((*card)->name, args, equal_char + 1,
                                      grub_strlen(equal_char + 1));
+
+          if ((grub_strcmp (args, "vtag") == 0) &&
+              (grub_strlen (equal_char + 1) == 8))
+            vlantag = grub_strtoul (equal_char + 1 + 4, 0, 16);
+
           *equal_char = '=';
         }
       else
@@ -213,8 +218,10 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
                                   hw_addr.mac, sizeof(hw_addr.mac), 0);
       inter = grub_net_add_addr ((*card)->name, *card, &client_addr, &hw_addr,
                                  flags);
+      inter->vlantag = vlantag;
       grub_net_add_ipv4_local (inter,
                           __builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4)));
+
     }
 
   if (gateway_addr.ipv4 != 0)
diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c
index c397b1b348ce559070cabe1e0b6e28e4dbf254d8..4d7ceed6f93c7e87019546b544a4365a504f5f9f 100644
--- a/grub-core/net/ethernet.c
+++ b/grub-core/net/ethernet.c
@@ -18,6 +18,7 @@
 
 #include <grub/misc.h>
 #include <grub/mm.h>
+#include <grub/env.h>
 #include <grub/net/ethernet.h>
 #include <grub/net/ip.h>
 #include <grub/net/arp.h>
@@ -56,10 +57,17 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
 {
   struct etherhdr *eth;
   grub_err_t err;
+  grub_uint8_t etherhdr_size;
+  grub_uint16_t vlantag_id = VLANTAG_IDENTIFIER;
 
-  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));
+  /* Increase ethernet header in case of vlantag */
+  if (inf->vlantag != 0)
+    etherhdr_size += 4;
+
+  err = grub_netbuff_push (nb, etherhdr_size);
   if (err)
     return err;
   eth = (struct etherhdr *) nb->data;
@@ -76,6 +84,19 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
 	return err;
       inf->card->opened = 1;
     }
+
+  /* Check and add a vlan-tag if needed. */
+  if (inf->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_id, 2);
+      grub_memcpy ((char *) nb->data + etherhdr_size - 4, (char *) &(inf->vlantag), 2);
+    }
+
   return inf->card->driver->send (inf->card, nb);
 }
 
@@ -90,10 +111,25 @@ 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 = 0;
+
+
+  /* Check if a vlan-tag is present. If so, the ethernet header is 4 bytes */
+  /* longer than the original one. The vlantag id is extracted and the header */
+  /* is reseted to the original size. */
+  if (grub_get_unaligned16 (nb->data + etherhdr_size - 2) == VLANTAG_IDENTIFIER)
+    {
+      vlantag = grub_get_unaligned16 (nb->data + etherhdr_size);
+      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;
 
@@ -121,13 +157,14 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
     {
       /* ARP packet. */
     case GRUB_NET_ETHERTYPE_ARP:
-      grub_net_arp_receive (nb, card);
+      grub_net_arp_receive (nb, card, &vlantag);
       grub_netbuff_free (nb);
       return GRUB_ERR_NONE;
       /* IP packet.  */
     case GRUB_NET_ETHERTYPE_IP:
     case GRUB_NET_ETHERTYPE_IP6:
-      return grub_net_recv_ip_packets (nb, card, &hwaddress, &src_hwaddress);
+      return grub_net_recv_ip_packets (nb, card, &hwaddress, &src_hwaddress,
+                                       &vlantag);
     }
   grub_netbuff_free (nb);
   return GRUB_ERR_NONE;
diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
index aba4f89087bc14b1fe28a77794dd6792beb0bf36..7c95cc7464a09af4b223c94d6653a03f0dbee062 100644
--- a/grub-core/net/ip.c
+++ b/grub-core/net/ip.c
@@ -228,12 +228,13 @@ handle_dgram (struct grub_net_buff *nb,
 	      grub_net_ip_protocol_t proto,
 	      const grub_net_network_level_address_t *source,
 	      const grub_net_network_level_address_t *dest,
+              grub_uint16_t *vlantag,
 	      grub_uint8_t ttl)
 {
   struct grub_net_network_level_interface *inf = NULL;
   grub_err_t err;
   int multicast = 0;
-  
+
   /* DHCP needs special treatment since we don't know IP yet.  */
   {
     struct udphdr *udph;
@@ -293,6 +294,15 @@ handle_dgram (struct grub_net_buff *nb,
 	&& grub_net_addr_cmp (&inf->address, dest) == 0
 	&& grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0)
       break;
+
+    /* Verify vlantag id */
+    if (inf->card == card && inf->vlantag != *vlantag)
+      {
+        grub_dprintf ("net", "invalid vlantag! %x != %x\n",
+                      inf->vlantag, *vlantag);
+        break;
+      }
+
     /* Solicited node multicast.  */
     if (inf->card == card
 	&& inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
@@ -383,7 +393,8 @@ static grub_err_t
 grub_net_recv_ip4_packets (struct grub_net_buff *nb,
 			   struct grub_net_card *card,
 			   const grub_net_link_level_address_t *hwaddress,
-			   const grub_net_link_level_address_t *src_hwaddress)
+			   const grub_net_link_level_address_t *src_hwaddress,
+                           grub_uint16_t *vlantag)
 {
   struct iphdr *iph = (struct iphdr *) nb->data;
   grub_err_t err;
@@ -458,7 +469,7 @@ grub_net_recv_ip4_packets (struct grub_net_buff *nb,
       dest.ipv4 = iph->dest;
 
       return handle_dgram (nb, card, src_hwaddress, hwaddress, iph->protocol,
-			   &source, &dest, iph->ttl);
+			   &source, &dest, vlantag, iph->ttl);
     }
 
   for (prev = &reassembles, rsm = *prev; rsm; prev = &rsm->next, rsm = *prev)
@@ -594,7 +605,7 @@ grub_net_recv_ip4_packets (struct grub_net_buff *nb,
       dest.ipv4 = dst;
 
       return handle_dgram (ret, card, src_hwaddress,
-			   hwaddress, proto, &source, &dest,
+			   hwaddress, proto, &source, &dest, vlantag,
 			   ttl);
     }
 }
@@ -652,7 +663,8 @@ static grub_err_t
 grub_net_recv_ip6_packets (struct grub_net_buff *nb,
 			   struct grub_net_card *card,
 			   const grub_net_link_level_address_t *hwaddress,
-			   const grub_net_link_level_address_t *src_hwaddress)
+			   const grub_net_link_level_address_t *src_hwaddress,
+                           grub_uint16_t *vlantag)
 {
   struct ip6hdr *iph = (struct ip6hdr *) nb->data;
   grub_err_t err;
@@ -703,21 +715,24 @@ grub_net_recv_ip6_packets (struct grub_net_buff *nb,
   grub_memcpy (dest.ipv6, &iph->dest, sizeof (dest.ipv6));
 
   return handle_dgram (nb, card, src_hwaddress, hwaddress, iph->protocol,
-		       &source, &dest, iph->ttl);
+		       &source, &dest, vlantag, iph->ttl);
 }
 
 grub_err_t
 grub_net_recv_ip_packets (struct grub_net_buff *nb,
 			  struct grub_net_card *card,
 			  const grub_net_link_level_address_t *hwaddress,
-			  const grub_net_link_level_address_t *src_hwaddress)
+			  const grub_net_link_level_address_t *src_hwaddress,
+                          grub_uint16_t *vlantag)
 {
   struct iphdr *iph = (struct iphdr *) nb->data;
 
   if ((iph->verhdrlen >> 4) == 4)
-    return grub_net_recv_ip4_packets (nb, card, hwaddress, src_hwaddress);
+    return grub_net_recv_ip4_packets (nb, card, hwaddress, src_hwaddress,
+                                      vlantag);
   if ((iph->verhdrlen >> 4) == 6)
-    return grub_net_recv_ip6_packets (nb, card, hwaddress, src_hwaddress);
+    return grub_net_recv_ip6_packets (nb, card, hwaddress, src_hwaddress,
+                                      vlantag);
   grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4));
   grub_netbuff_free (nb);
   return GRUB_ERR_NONE;
diff --git a/grub-core/normal/auth.c b/grub-core/normal/auth.c
index 7338f8245e3a9bbe47e821fb43c2b699b9527ffb..6be678c0de1ac236b60f765e767ae43d113b1117 100644
--- a/grub-core/normal/auth.c
+++ b/grub-core/normal/auth.c
@@ -166,13 +166,13 @@ grub_username_get (char buf[], unsigned buf_size)
       if (key == '\n' || key == '\r')
 	break;
 
-      if (key == '\e')
+      if (key == GRUB_TERM_ESC)
 	{
 	  cur_len = 0;
 	  break;
 	}
 
-      if (key == '\b')
+      if (key == GRUB_TERM_BACKSPACE)
 	{
 	  if (cur_len)
 	    {
@@ -197,7 +197,7 @@ grub_username_get (char buf[], unsigned buf_size)
   grub_xputs ("\n");
   grub_refresh ();
 
-  return (key != '\e');
+  return (key != GRUB_TERM_ESC);
 }
 
 grub_err_t
diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c
index a36180d75305f421e96903a46acb9dd99af06572..c037d5050ed2b34fa3b2ac0c7564e4208ca143c4 100644
--- a/grub-core/normal/cmdline.c
+++ b/grub-core/normal/cmdline.c
@@ -626,12 +626,12 @@ grub_cmdline_get (const char *prompt_translated)
 	    cl_insert (cl_terms, nterms, &lpos, &llen, &max_len, &buf, kill_buf);
 	  break;
 
-	case '\e':
+	case GRUB_TERM_ESC:
 	  grub_free (cl_terms);
 	  grub_free (buf);
 	  return 0;
 
-	case '\b':
+	case GRUB_TERM_BACKSPACE:
 	  if (lpos > 0)
 	    {
 	      lpos--;
diff --git a/grub-core/normal/crypto.c b/grub-core/normal/crypto.c
index 2bfd67c8ef388097701a7415df3cd7321c6a1e57..e6d345f33458a167e703235d611afdd8c2a245b0 100644
--- a/grub-core/normal/crypto.c
+++ b/grub-core/normal/crypto.c
@@ -147,8 +147,8 @@ read_crypto_list (const char *prefix)
       if (! cur->modname)
 	{
 	  grub_errno = GRUB_ERR_NONE;
-	  grub_free (cur);
 	  grub_free (cur->name);
+	  grub_free (cur);
 	  continue;
 	}
       cur->next = crypto_specs;
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
index 719e2fb1c260b16d96cea2b787d7f7e592b428b7..e7a83c2d6e2aaa8248ed739b28f2c6be76622eb4 100644
--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -763,7 +763,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
               *auto_boot = 0;
 	      return current_entry;
 
-	    case '\e':
+	    case GRUB_TERM_ESC:
 	      if (nested)
 		{
 		  menu_fini ();
diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c
index eeeee5580abea9798278ef85cf417366cf4f0e0a..cdf3590a3646ce4be0caf99cafedcbc38cbe51e4 100644
--- a/grub-core/normal/menu_entry.c
+++ b/grub-core/normal/menu_entry.c
@@ -1403,7 +1403,7 @@ grub_menu_entry_run (grub_menu_entry_t entry)
 	    goto fail;
 	  break;
 
-	case '\e':
+	case GRUB_TERM_ESC:
 	  destroy_screen (screen);
 	  return;
 
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index a79682a5e31e1b4e77d9b99f55cc5a1fca9e159b..a6153d359546d237933cba0f300e7d59fdb1007b 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -38,6 +38,46 @@
 #include <errno.h>
 #include <ctype.h>
 
+#ifdef __sparc__
+typedef enum
+  {
+    GRUB_OFPATH_SPARC_WWN_ADDR = 1,
+    GRUB_OFPATH_SPARC_TGT_LUN,
+  } ofpath_sparc_addressing;
+
+struct ofpath_sparc_hba
+{
+  grub_uint32_t device_id;
+  ofpath_sparc_addressing addressing;
+};
+
+static struct ofpath_sparc_hba sparc_lsi_hba[] = {
+  /* Rhea, Jasper 320, LSI53C1020/1030. */
+  {0x30, GRUB_OFPATH_SPARC_TGT_LUN},
+  /* SAS-1068E. */
+  {0x50, GRUB_OFPATH_SPARC_TGT_LUN},
+  /* SAS-1064E. */
+  {0x56, GRUB_OFPATH_SPARC_TGT_LUN},
+  /* Pandora SAS-1068E. */
+  {0x58, GRUB_OFPATH_SPARC_TGT_LUN},
+  /* Aspen, Invader, LSI SAS-3108. */
+  {0x5d, GRUB_OFPATH_SPARC_TGT_LUN},
+  /* Niwot, SAS 2108. */
+  {0x79, GRUB_OFPATH_SPARC_TGT_LUN},
+  /* Erie, Falcon, LSI SAS 2008. */
+  {0x72, GRUB_OFPATH_SPARC_WWN_ADDR},
+  /* LSI WarpDrive 6203. */
+  {0x7e, GRUB_OFPATH_SPARC_WWN_ADDR},
+  /* LSI SAS 2308. */
+  {0x87, GRUB_OFPATH_SPARC_WWN_ADDR},
+  /* LSI SAS 3008. */
+  {0x97, GRUB_OFPATH_SPARC_WWN_ADDR},
+  {0, 0}
+};
+
+static const int LSI_VENDOR_ID = 0x1000;
+#endif
+
 #ifdef OFPATH_STANDALONE
 #define xmalloc malloc
 void
@@ -120,6 +160,8 @@ find_obppath (const char *sysfs_path_orig)
 #endif
 
       fd = open(path, O_RDONLY);
+
+#ifndef __sparc__
       if (fd < 0 || fstat (fd, &st) < 0)
 	{
 	  if (fd >= 0)
@@ -127,6 +169,7 @@ find_obppath (const char *sysfs_path_orig)
 	  snprintf(path, path_size, "%s/devspec", sysfs_path);
 	  fd = open(path, O_RDONLY);
 	}
+#endif
 
       if (fd < 0 || fstat (fd, &st) < 0)
 	{
@@ -307,6 +350,55 @@ of_path_of_ide(const char *sys_devname __attribute__((unused)), const char *devi
   return ret;
 }
 
+#ifdef __sparc__
+static char *
+of_path_of_nvme(const char *sys_devname __attribute__((unused)),
+	        const char *device,
+	        const char *devnode __attribute__((unused)),
+	        const char *devicenode)
+{
+  char *sysfs_path, *of_path, disk[MAX_DISK_CAT];
+  const char *digit_string, *part_end;
+
+  digit_string = trailing_digits (device);
+  part_end = devicenode + strlen (devicenode) - 1;
+
+  if ((*digit_string != '\0') && (*part_end == 'p'))
+    {
+      /* We have a partition number, strip it off. */
+      int part;
+      char *nvmedev, *end;
+
+      nvmedev = strdup (devicenode);
+
+      if (!nvmedev)
+        return NULL;
+
+      end = nvmedev + strlen (nvmedev) - 1;
+      /* Remove the p. */
+      *end = '\0';
+      sscanf (digit_string, "%d", &part);
+      snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
+      sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
+      free (nvmedev);
+    }
+  else
+    {
+      /* We do not have the parition. */
+      snprintf (disk, sizeof (disk), "/disk@1");
+      sysfs_path = block_device_get_sysfs_path_and_link (device);
+    }
+
+  of_path = find_obppath (sysfs_path);
+
+  if (of_path)
+    strcat (of_path, disk);
+
+  free (sysfs_path);
+  return of_path;
+}
+#endif
+
 static int
 vendor_is_ATA(const char *path)
 {
@@ -335,6 +427,64 @@ vendor_is_ATA(const char *path)
   return (memcmp(bufcont, "ATA", 3) == 0);
 }
 
+#ifdef __sparc__
+static void
+check_hba_identifiers (const char *sysfs_path, int *vendor, int *device_id)
+{
+  char *ed = strstr (sysfs_path, "host");
+  size_t path_size;
+  char *p, *path;
+  char buf[8];
+  int fd;
+
+  if (!ed)
+    return;
+
+  p = xstrdup (sysfs_path);
+  ed = strstr (p, "host");
+
+  *ed = '\0';
+
+  path_size = (strlen (p) + sizeof ("vendor"));
+  path = xmalloc (path_size);
+
+  if (!path)
+    goto out;
+
+  snprintf (path, path_size, "%svendor", p);
+  fd = open (path, O_RDONLY);
+
+  if (fd < 0)
+    goto out;
+
+  memset (buf, 0, sizeof (buf));
+
+  if (read (fd, buf, sizeof (buf) - 1) < 0)
+    goto out;
+
+  close (fd);
+  sscanf (buf, "%x", vendor);
+
+  snprintf (path, path_size, "%sdevice", p);
+  fd = open (path, O_RDONLY);
+
+  if (fd < 0)
+    goto out;
+
+  memset (buf, 0, sizeof (buf));
+
+  if (read (fd, buf, sizeof (buf) - 1) < 0)
+    goto out;
+
+  close (fd);
+  sscanf (buf, "%x", device_id);
+
+ out:
+  free (path);
+  free (p);
+}
+#endif
+
 static void
 check_sas (const char *sysfs_path, int *tgt, unsigned long int *sas_address)
 {
@@ -396,7 +546,7 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
 {
   const char *p, *digit_string, *disk_name;
   int host, bus, tgt, lun;
-  unsigned long int sas_address;
+  unsigned long int sas_address = 0;
   char *sysfs_path, disk[MAX_DISK_CAT - sizeof ("/fp@0,0")];
   char *of_path;
 
@@ -413,9 +563,8 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
     }
 
   of_path = find_obppath(sysfs_path);
-  free (sysfs_path);
   if (!of_path)
-    return NULL;
+    goto out;
 
   if (strstr (of_path, "qlc"))
     strcat (of_path, "/fp@0,0");
@@ -444,6 +593,46 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
     }
   else
     {
+#ifdef __sparc__
+      ofpath_sparc_addressing addressing = GRUB_OFPATH_SPARC_TGT_LUN;
+      int vendor = 0, device_id = 0;
+      char *optr = disk;
+
+      check_hba_identifiers (sysfs_path, &vendor, &device_id);
+
+      if (vendor == LSI_VENDOR_ID)
+        {
+          struct ofpath_sparc_hba *lsi_hba;
+
+	  /*
+	   * Over time different OF addressing schemes have been supported.
+	   * There is no generic addressing scheme that works across
+	   * every HBA.
+	   */
+          for (lsi_hba = sparc_lsi_hba; lsi_hba->device_id; lsi_hba++)
+            if (lsi_hba->device_id == device_id)
+              {
+                addressing = lsi_hba->addressing;
+                break;
+              }
+        }
+
+      if (addressing == GRUB_OFPATH_SPARC_WWN_ADDR)
+        optr += snprintf (disk, sizeof (disk), "/%s@w%lx,%x", disk_name,
+                          sas_address, lun);
+      else
+        optr += snprintf (disk, sizeof (disk), "/%s@%x,%x", disk_name, tgt,
+                          lun);
+
+      if (*digit_string != '\0')
+        {
+          int part;
+
+          sscanf (digit_string, "%d", &part);
+          snprintf (optr, sizeof (disk) - (optr - disk - 1), ":%c", 'a'
+                    + (part - 1));
+        }
+#else
       if (lun == 0)
         {
           int sas_id = 0;
@@ -491,8 +680,12 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
             }
 	  free (lunstr);
         }
+#endif
     }
   strcat(of_path, disk);
+
+ out:
+  free (sysfs_path);
   return of_path;
 }
 
@@ -537,6 +730,11 @@ grub_util_devname_to_ofpath (const char *sys_devname)
     /* All the models I've seen have a devalias "floppy".
        New models have no floppy at all. */
     ofpath = xstrdup ("floppy");
+#ifdef __sparc__
+  else if (device[0] == 'n' && device[1] == 'v' && device[2] == 'm'
+           && device[3] == 'e')
+    ofpath = of_path_of_nvme (name_buf, device, devnode, devicenode);
+#endif
   else
     {
       grub_util_warn (_("unknown device type %s"), device);
diff --git a/grub-core/osdep/unix/exec.c b/grub-core/osdep/unix/exec.c
index 935ff120ebe117f7492715813789db364ef1b12f..db3259f6504d5d5958cfa330bfd4a8b12b64f970 100644
--- a/grub-core/osdep/unix/exec.c
+++ b/grub-core/osdep/unix/exec.c
@@ -99,7 +99,7 @@ grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file,
 	{
 	  fd = open (stdin_file, O_RDONLY);
 	  if (fd < 0)
-	    exit (127);
+	    _exit (127);
 	  dup2 (fd, STDIN_FILENO);
 	  close (fd);
 	}
@@ -108,7 +108,7 @@ grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file,
 	{
 	  fd = open (stdout_file, O_WRONLY | O_CREAT, 0700);
 	  if (fd < 0)
-	    exit (127);
+	    _exit (127);
 	  dup2 (fd, STDOUT_FILENO);
 	  close (fd);
 	}
@@ -117,7 +117,7 @@ grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file,
 	{
 	  fd = open (stderr_file, O_WRONLY | O_CREAT, 0700);
 	  if (fd < 0)
-	    exit (127);
+	    _exit (127);
 	  dup2 (fd, STDERR_FILENO);
 	  close (fd);
 	}
@@ -126,7 +126,7 @@ grub_util_exec_redirect_all (const char *const *argv, const char *stdin_file,
       setenv ("LC_ALL", "C", 1);
 
       execvp ((char *) argv[0], (char **) argv);
-      exit (127);
+      _exit (127);
     }
   waitpid (pid, &status, 0);
   if (!WIFEXITED (status))
diff --git a/grub-core/osdep/unix/getroot.c b/grub-core/osdep/unix/getroot.c
index 4bf37b027be660a14994fb316f08dd478490c4e2..3046e22cc012d1012add87931a018043e3ecc714 100644
--- a/grub-core/osdep/unix/getroot.c
+++ b/grub-core/osdep/unix/getroot.c
@@ -428,8 +428,11 @@ grub_find_device (const char *dir, dev_t dev)
 	{
 #ifdef __linux__
 	  /* Skip device names like /dev/dm-0, which are short-hand aliases
-	     to more descriptive device names, e.g. those under /dev/mapper */
-	  if (ent->d_name[0] == 'd' &&
+	     to more descriptive device names, e.g. those under /dev/mapper.
+	     Also, don't skip devices which names start with dm-[0-9] in
+	     directories below /dev, e.g. /dev/mapper/dm-0-luks. */
+	  if (strcmp (dir, "/dev") == 0 &&
+	      ent->d_name[0] == 'd' &&
 	      ent->d_name[1] == 'm' &&
 	      ent->d_name[2] == '-' &&
 	      ent->d_name[3] >= '0' &&
diff --git a/grub-core/osdep/unix/hostdisk.c b/grub-core/osdep/unix/hostdisk.c
index 2a8c5882e3d10b98bc305a116f8cca06acfe89f5..5450cf4166e04c2cfab806e93dfa63c6abdb9698 100644
--- a/grub-core/osdep/unix/hostdisk.c
+++ b/grub-core/osdep/unix/hostdisk.c
@@ -77,11 +77,19 @@ grub_util_get_fd_size (grub_util_fd_t fd, const char *name, unsigned *log_secsiz
 int
 grub_util_fd_seek (grub_util_fd_t fd, grub_uint64_t off)
 {
+#if SIZEOF_OFF_T == 8
   off_t offset = (off_t) off;
 
   if (lseek (fd, offset, SEEK_SET) != offset)
     return -1;
+#elif SIZEOF_OFF64_T == 8
+  off64_t offset = (off64_t) off;
 
+  if (lseek64 (fd, offset, SEEK_SET) != offset)
+    return -1;
+#else
+#error "No large file support"
+#endif
   return 0;
 }
 
diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
index a3fcfcacaa814d3ab62104f0dd406ef0c2163613..ca448bc11a05b9e0c6203a799ff62ab1dd75274f 100644
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -78,19 +78,20 @@ get_ofpathname (const char *dev)
 		   dev);
 }
 
-static void
+static int
 grub_install_remove_efi_entries_by_distributor (const char *efi_distributor)
 {
   int fd;
   pid_t pid = grub_util_exec_pipe ((const char * []){ "efibootmgr", NULL }, &fd);
   char *line = NULL;
   size_t len = 0;
+  int rc;
 
   if (!pid)
     {
       grub_util_warn (_("Unable to open stream from %s: %s"),
 		      "efibootmgr", strerror (errno));
-      return;
+      return errno;
     }
 
   FILE *fp = fdopen (fd, "r");
@@ -98,7 +99,7 @@ grub_install_remove_efi_entries_by_distributor (const char *efi_distributor)
     {
       grub_util_warn (_("Unable to open stream from %s: %s"),
 		      "efibootmgr", strerror (errno));
-      return;
+      return errno;
     }
 
   line = xmalloc (80);
@@ -119,23 +120,25 @@ grub_install_remove_efi_entries_by_distributor (const char *efi_distributor)
       bootnum = line + sizeof ("Boot") - 1;
       bootnum[4] = '\0';
       if (!verbosity)
-	grub_util_exec ((const char * []){ "efibootmgr", "-q",
+	rc = grub_util_exec ((const char * []){ "efibootmgr", "-q",
 	      "-b", bootnum,  "-B", NULL });
       else
-	grub_util_exec ((const char * []){ "efibootmgr",
+	rc = grub_util_exec ((const char * []){ "efibootmgr",
 	      "-b", bootnum, "-B", NULL });
     }
 
   free (line);
+  return rc;
 }
 
-void
+int
 grub_install_register_efi (grub_device_t efidir_grub_dev,
 			   const char *efifile_path,
 			   const char *efi_distributor)
 {
   const char * efidir_disk;
   int efidir_part;
+  int ret;
   efidir_disk = grub_util_biosdisk_get_osdev (efidir_grub_dev->disk);
   efidir_part = efidir_grub_dev->disk->partition ? efidir_grub_dev->disk->partition->number + 1 : 1;
 
@@ -151,23 +154,26 @@ grub_install_register_efi (grub_device_t efidir_grub_dev,
   grub_util_exec ((const char * []){ "modprobe", "-q", "efivars", NULL });
 #endif
   /* Delete old entries from the same distributor.  */
-  grub_install_remove_efi_entries_by_distributor (efi_distributor);
+  ret = grub_install_remove_efi_entries_by_distributor (efi_distributor);
+  if (ret)
+    return ret;
 
   char *efidir_part_str = xasprintf ("%d", efidir_part);
 
   if (!verbosity)
-    grub_util_exec ((const char * []){ "efibootmgr", "-q",
+    ret = grub_util_exec ((const char * []){ "efibootmgr", "-q",
 	  "-c", "-d", efidir_disk,
 	  "-p", efidir_part_str, "-w",
 	  "-L", efi_distributor, "-l", 
 	  efifile_path, NULL });
   else
-    grub_util_exec ((const char * []){ "efibootmgr",
+    ret = grub_util_exec ((const char * []){ "efibootmgr",
 	  "-c", "-d", efidir_disk,
 	  "-p", efidir_part_str, "-w",
 	  "-L", efi_distributor, "-l", 
 	  efifile_path, NULL });
   free (efidir_part_str);
+  return ret;
 }
 
 void
diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c
index 83bcba7791421825da6922a7ee346f4fd5fcd7a4..103f6796f39f38209b0f554842aa6697faa5df2f 100644
--- a/grub-core/partmap/gpt.c
+++ b/grub-core/partmap/gpt.c
@@ -33,10 +33,10 @@ static grub_uint8_t grub_gpt_magic[8] =
     0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54
   };
 
-static const grub_gpt_part_type_t grub_gpt_partition_type_empty = GRUB_GPT_PARTITION_TYPE_EMPTY;
+static const grub_gpt_part_guid_t grub_gpt_partition_type_empty = GRUB_GPT_PARTITION_TYPE_EMPTY;
 
 #ifdef GRUB_UTIL
-static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT;
+static const grub_gpt_part_guid_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT;
 #endif
 
 /* 512 << 7 = 65536 byte sectors.  */
diff --git a/grub-core/term/arm/cros.c b/grub-core/term/arm/cros.c
new file mode 100644
index 0000000000000000000000000000000000000000..1ff9f8ccfb8270884ba962a05ca99df4c6ed1f41
--- /dev/null
+++ b/grub-core/term/arm/cros.c
@@ -0,0 +1,125 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *
+ *  Copyright (C) 2012  Google Inc.
+ *  Copyright (C) 2016  Free Software Foundation, Inc.
+ *
+ *  This is based on depthcharge code.
+ *
+ *  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/ps2.h>
+#include <grub/fdtbus.h>
+#include <grub/err.h>
+#include <grub/machine/kernel.h>
+#include <grub/misc.h>
+#include <grub/term.h>
+#include <grub/time.h>
+#include <grub/fdtbus.h>
+#include <grub/arm/cros_ec.h>
+
+struct grub_ps2_state ps2_state;
+
+struct grub_cros_ec_keyscan old_scan;
+
+static const struct grub_fdtbus_dev *cros_ec;
+
+static grub_uint8_t map_code[GRUB_CROS_EC_KEYSCAN_COLS][GRUB_CROS_EC_KEYSCAN_ROWS];
+
+static grub_uint8_t e0_translate[16] =
+  {
+    0x1c, 0x1d, 0x35, 0x00,
+    0x38, 0x00, 0x47, 0x48,
+    0x49, 0x4b, 0x4d, 0x4f,
+    0x50, 0x51, 0x52, 0x53,
+  };
+
+/* If there is a character pending, return it;
+   otherwise return GRUB_TERM_NO_KEY.  */
+static int
+grub_cros_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
+{
+  struct grub_cros_ec_keyscan scan;
+  int i, j;
+  if (grub_cros_ec_scan_keyboard (cros_ec, &scan) < 0)
+    return GRUB_TERM_NO_KEY;
+  for (i = 0; i < GRUB_CROS_EC_KEYSCAN_COLS; i++)
+    if (scan.data[i] ^ old_scan.data[i])
+      for (j = 0; j < GRUB_CROS_EC_KEYSCAN_ROWS; j++)
+	if ((scan.data[i] ^ old_scan.data[i]) & (1 << j))
+	  {
+	    grub_uint8_t code = map_code[i][j];
+	    int ret;
+	    grub_uint8_t brk = 0;
+	    if (!(scan.data[i] & (1 << j)))
+	      brk = 0x80;
+	    grub_dprintf ("cros_keyboard", "key <%d, %d> code %x\n", i, j, code);
+	    if (code < 0x60)
+	      ret = grub_ps2_process_incoming_byte (&ps2_state, code | brk);
+	    else if (code >= 0x60 && code < 0x70 && e0_translate[code - 0x60])
+	      {
+		grub_ps2_process_incoming_byte (&ps2_state, 0xe0);
+		ret = grub_ps2_process_incoming_byte (&ps2_state, e0_translate[code - 0x60] | brk);
+	      }
+	    else
+	      ret = GRUB_TERM_NO_KEY;
+	    old_scan.data[i] ^= (1 << j);
+	    if (ret != GRUB_TERM_NO_KEY)
+	      return ret;
+	  }
+  return GRUB_TERM_NO_KEY;
+}
+
+static struct grub_term_input grub_cros_keyboard_term =
+  {
+    .name = "cros_keyboard",
+    .getkey = grub_cros_keyboard_getkey
+  };
+
+static grub_err_t
+cros_attach (const struct grub_fdtbus_dev *dev)
+{
+  grub_size_t keymap_size, i;
+  const grub_uint8_t *keymap = grub_fdtbus_get_prop (dev, "linux,keymap", &keymap_size);
+
+  if (!dev->parent || !grub_cros_ec_validate (dev->parent))
+    return GRUB_ERR_IO;
+
+  if (keymap)
+    {
+      for (i = 0; i + 3 < keymap_size; i += 4)
+	if (keymap[i+1] < GRUB_CROS_EC_KEYSCAN_COLS && keymap[i] < GRUB_CROS_EC_KEYSCAN_ROWS
+	    && keymap[i+2] == 0 && keymap[i+3] < 0x80)
+	  map_code[keymap[i+1]][keymap[i]] = keymap[i+3];
+    }
+
+  cros_ec = dev->parent;
+  ps2_state.current_set = 1;
+  ps2_state.at_keyboard_status = 0;
+  grub_term_register_input ("cros_keyboard", &grub_cros_keyboard_term);
+  return GRUB_ERR_NONE;
+}
+
+static struct grub_fdtbus_driver cros =
+{
+  .compatible = "google,cros-ec-keyb",
+  .attach = cros_attach
+};
+
+void
+grub_cros_init (void)
+{
+  grub_fdtbus_register (&cros);
+}
diff --git a/grub-core/term/arm/cros_ec.c b/grub-core/term/arm/cros_ec.c
new file mode 100644
index 0000000000000000000000000000000000000000..f4144818b5bfdb9a512316ccc321586d539653ac
--- /dev/null
+++ b/grub-core/term/arm/cros_ec.c
@@ -0,0 +1,238 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *
+ *  Copyright (C) 2012  Google Inc.
+ *  Copyright (C) 2016  Free Software Foundation, Inc.
+ *
+ *  This is based on depthcharge code.
+ *
+ *  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/mm.h>
+#include <grub/time.h>
+#include <grub/misc.h>
+#include <grub/arm/cros_ec.h>
+#include <grub/fdtbus.h>
+
+static const grub_uint64_t FRAMING_TIMEOUT_MS = 300;
+
+static const grub_uint8_t EC_FRAMING_BYTE = 0xec;
+
+#define EC_CMD_MKBP_STATE 0x60
+#define EC_CMD_VERSION0 0xdc
+
+static grub_uint64_t last_transfer;
+
+static void
+stop_bus (const struct grub_fdtbus_dev *spi)
+{
+  spi->driver->stop (spi);
+  last_transfer = grub_get_time_ms ();
+}
+
+static int
+wait_for_frame (const struct grub_fdtbus_dev *spi)
+{
+  grub_uint64_t start = grub_get_time_ms ();
+  grub_uint8_t byte;
+  do
+    {
+      if (spi->driver->receive (spi, &byte, 1))
+	return -1;
+      if (byte != EC_FRAMING_BYTE &&
+	  grub_get_time_ms () - start > FRAMING_TIMEOUT_MS)
+	{
+	  grub_dprintf ("cros", "Timeout waiting for framing byte.\n");
+	  return -1;
+	}
+    }
+  while (byte != EC_FRAMING_BYTE);
+  return 0;
+}
+
+/*
+ * Calculate a simple 8-bit checksum of a data block
+ *
+ * @param data	Data block to checksum
+ * @param size	Size of data block in bytes
+ * @return checksum value (0 to 255)
+ */
+static grub_uint8_t
+cros_ec_calc_checksum (const void *data, int size)
+{
+  grub_uint8_t csum;
+  const grub_uint8_t *bytes = data;
+  int i;
+
+  for (i = csum = 0; i < size; i++)
+    csum += bytes[i];
+  return csum & 0xff;
+}
+
+enum
+{
+  /* response, arglen */
+  CROS_EC_SPI_IN_HDR_SIZE = 2,
+  /* version, cmd, arglen */
+  CROS_EC_SPI_OUT_HDR_SIZE = 3
+};
+
+static grub_uint8_t busbuf[256];
+#define MSG_BYTES ((int)sizeof (busbuf))
+
+static int
+ec_command (const struct grub_fdtbus_dev *dev, int cmd, int cmd_version,
+	    const void *dout, int dout_len, void *din, int din_len)
+{
+  const struct grub_fdtbus_dev *spi = dev->parent;
+  grub_uint8_t *bytes;
+
+  /* Header + data + checksum. */
+  grub_uint32_t out_bytes = CROS_EC_SPI_OUT_HDR_SIZE + dout_len + 1;
+  grub_uint32_t in_bytes = CROS_EC_SPI_IN_HDR_SIZE + din_len + 1;
+
+  /*
+   * Sanity-check I/O sizes given transaction overhead in internal
+   * buffers.
+   */
+  if (out_bytes > MSG_BYTES)
+    {
+      grub_dprintf ("cros", "Cannot send %d bytes\n", dout_len);
+      return -1;
+    }
+  if (in_bytes > MSG_BYTES)
+    {
+      grub_dprintf ("cros", "Cannot receive %d bytes\n", din_len);
+      return -1;
+    }
+
+  /* Prepare the output. */
+  bytes = busbuf;
+  *bytes++ = EC_CMD_VERSION0 + cmd_version;
+  *bytes++ = cmd;
+  *bytes++ = dout_len;
+  grub_memcpy (bytes, dout, dout_len);
+  bytes += dout_len;
+
+  *bytes++ = cros_ec_calc_checksum (busbuf,
+				    CROS_EC_SPI_OUT_HDR_SIZE + dout_len);
+
+  /* Depthcharge uses 200 us here but GRUB timer resolution is only 1ms,
+     decrease this when we increase timer resolution.  */
+  while (grub_get_time_ms () - last_transfer < 1)
+    ;
+
+  if (spi->driver->start (spi))
+    return -1;
+
+  /* Allow EC to ramp up clock after being awoken. */
+  /* Depthcharge only waits 100 us here but GRUB timer resolution is only 1ms,
+     decrease this when we increase timer resolution.  */
+  grub_millisleep (1);
+
+  if (spi->driver->send (spi, busbuf, out_bytes))
+    {
+      stop_bus (spi);
+      return -1;
+    }
+
+  /* Wait until the EC is ready. */
+  if (wait_for_frame (spi))
+    {
+      stop_bus (spi);
+      return -1;
+    }
+
+  /* Read the response code and the data length. */
+  bytes = busbuf;
+  if (spi->driver->receive (spi, bytes, 2))
+    {
+      stop_bus (spi);
+      return -1;
+    }
+  grub_uint8_t result = *bytes++;
+  grub_uint8_t length = *bytes++;
+
+  /* Make sure there's enough room for the data. */
+  if (CROS_EC_SPI_IN_HDR_SIZE + length + 1 > MSG_BYTES)
+    {
+      grub_dprintf ("cros", "Received length %#02x too large\n", length);
+      stop_bus (spi);
+      return -1;
+    }
+
+  /* Read the data and the checksum, and finish up. */
+  if (spi->driver->receive (spi, bytes, length + 1))
+    {
+      stop_bus (spi);
+      return -1;
+    }
+  bytes += length;
+  int expected = *bytes++;
+  stop_bus (spi);
+
+  /* Check the integrity of the response. */
+  if (result != 0)
+    {
+      grub_dprintf ("cros", "Received bad result code %d\n", result);
+      return -result;
+    }
+
+  int csum = cros_ec_calc_checksum (busbuf,
+				    CROS_EC_SPI_IN_HDR_SIZE + length);
+
+  if (csum != expected)
+    {
+      grub_dprintf ("cros", "Invalid checksum rx %#02x, calced %#02x\n",
+		    expected, csum);
+      return -1;
+    }
+
+  /* If the caller wants the response, copy it out for them. */
+  if (length < din_len)
+    din_len = length;
+  if (din)
+    {
+      grub_memcpy (din, (grub_uint8_t *) busbuf + CROS_EC_SPI_IN_HDR_SIZE, din_len);
+    }
+
+  return din_len;
+}
+
+int
+grub_cros_ec_scan_keyboard (const struct grub_fdtbus_dev *dev, struct grub_cros_ec_keyscan *scan)
+{
+  if (ec_command (dev, EC_CMD_MKBP_STATE, 0, NULL, 0, scan,
+		  sizeof (*scan)) < (int) sizeof (*scan))
+    return -1;
+
+  return 0;
+}
+
+int
+grub_cros_ec_validate (const struct grub_fdtbus_dev *dev)
+{
+  if (!grub_fdtbus_is_compatible("google,cros-ec-spi", dev))
+    return 0;
+  if (!dev->parent)
+    return 0;
+  if (!dev->parent->driver)
+    return 0;
+  if (!dev->parent->driver->send
+      || !dev->parent->driver->receive)
+    return 0;
+  return 1;
+}
+
diff --git a/grub-core/term/arm/pl050.c b/grub-core/term/arm/pl050.c
new file mode 100644
index 0000000000000000000000000000000000000000..e4cda305666df20eba26e10d74b879361e83d6ea
--- /dev/null
+++ b/grub-core/term/arm/pl050.c
@@ -0,0 +1,189 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/ps2.h>
+#include <grub/fdtbus.h>
+#include <grub/err.h>
+#include <grub/machine/kernel.h>
+#include <grub/at_keyboard.h>
+#include <grub/misc.h>
+#include <grub/term.h>
+#include <grub/time.h>
+#include <grub/ps2.h>
+#include <grub/fdtbus.h>
+
+static volatile grub_uint32_t *pl050_regs;
+
+struct grub_ps2_state ps2_state;
+
+static void
+keyboard_controller_wait_until_ready (void)
+{
+  while (! (pl050_regs[1] & 0x40));
+}
+
+static grub_uint8_t
+wait_ack (void)
+{
+  grub_uint64_t endtime;
+  grub_uint8_t ack;
+
+  endtime = grub_get_time_ms () + 20;
+  do
+    ack = pl050_regs[2];
+  while (ack != GRUB_AT_ACK && ack != GRUB_AT_NACK
+	 && grub_get_time_ms () < endtime);
+  return ack;
+}
+
+
+static int
+write_mode (int mode)
+{
+  unsigned i;
+  for (i = 0; i < GRUB_AT_TRIES; i++)
+    {
+      grub_uint8_t ack;
+      keyboard_controller_wait_until_ready ();
+      pl050_regs[2] = 0xf0;
+      keyboard_controller_wait_until_ready ();
+      pl050_regs[2] = mode;
+      keyboard_controller_wait_until_ready ();
+      ack = wait_ack ();
+      if (ack == GRUB_AT_NACK)
+	continue;
+      if (ack == GRUB_AT_ACK)
+	break;
+      return 0;
+    }
+
+  return (i != GRUB_AT_TRIES);
+}
+
+static int
+query_mode (void)
+{
+  grub_uint8_t ret;
+  int e;
+
+  e = write_mode (0);
+  if (!e)
+    return 0;
+
+  keyboard_controller_wait_until_ready ();
+
+  do
+    ret = pl050_regs[2];
+  while (ret == GRUB_AT_ACK);
+
+  /* QEMU translates the set even in no-translate mode.  */
+  if (ret == 0x43 || ret == 1)
+    return 1;
+  if (ret == 0x41 || ret == 2)
+    return 2;
+  if (ret == 0x3f || ret == 3)
+    return 3;
+  return 0;
+}
+
+static void
+set_scancodes (void)
+{
+  write_mode (2);
+  ps2_state.current_set = query_mode ();
+  grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
+  if (ps2_state.current_set == 2)
+    return;
+
+  write_mode (1);
+  ps2_state.current_set = query_mode ();
+  grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
+  if (ps2_state.current_set == 1)
+    return;
+  grub_dprintf ("atkeyb", "no supported scancode set found\n");
+}
+
+static void
+keyboard_controller_led (grub_uint8_t leds)
+{
+  keyboard_controller_wait_until_ready ();
+  pl050_regs[2] = 0xed;
+  keyboard_controller_wait_until_ready ();
+  pl050_regs[2] = leds & 0x7;
+}
+
+/* If there is a character pending, return it;
+   otherwise return GRUB_TERM_NO_KEY.  */
+static int
+grub_pl050_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
+{
+  grub_uint8_t at_key;
+  int ret;
+  grub_uint8_t old_led;
+
+  if (!(pl050_regs[1] & 0x10))
+    return -1;
+  at_key = pl050_regs[2];
+  old_led = ps2_state.led_status;
+
+  ret = grub_ps2_process_incoming_byte (&ps2_state, at_key);
+  if (old_led != ps2_state.led_status)
+    keyboard_controller_led (ps2_state.led_status);
+  return ret;
+}
+
+static struct grub_term_input grub_pl050_keyboard_term =
+  {
+    .name = "pl050_keyboard",
+    .getkey = grub_pl050_keyboard_getkey
+  };
+
+static grub_err_t
+pl050_attach(const struct grub_fdtbus_dev *dev)
+{
+  const grub_uint32_t *reg;
+  reg = grub_fdtbus_get_prop (dev, "reg", 0);
+
+  /* Mouse.  Nothing to do.  */
+  if (grub_be_to_cpu32 (*reg) == 0x7000)
+    return 0;
+
+  pl050_regs = grub_fdtbus_map_reg (dev, 0, 0);
+
+  if (!grub_fdtbus_is_mapping_valid (pl050_regs))
+    return grub_error (GRUB_ERR_IO, "could not map pl050");
+
+  ps2_state.at_keyboard_status = 0;
+  set_scancodes ();
+  keyboard_controller_led (ps2_state.led_status);
+
+  grub_term_register_input ("pl050_keyboard", &grub_pl050_keyboard_term);
+  return GRUB_ERR_NONE;
+}
+
+struct grub_fdtbus_driver pl050 =
+{
+  .compatible = "arm,pl050",
+  .attach = pl050_attach
+};
+
+void
+grub_pl050_init (void)
+{
+  grub_fdtbus_register (&pl050);
+}
diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c
index b4ea9ff7e637f59c653b86cea79d4d664c78af84..f0a986eb176aef6c4fe3f5a65c646756e5bbde56 100644
--- a/grub-core/term/at_keyboard.c
+++ b/grub-core/term/at_keyboard.c
@@ -22,215 +22,26 @@
 #include <grub/cpu/io.h>
 #include <grub/misc.h>
 #include <grub/term.h>
-#include <grub/keyboard_layouts.h>
 #include <grub/time.h>
 #include <grub/loader.h>
+#include <grub/ps2.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
-static short at_keyboard_status = 0;
-static int e0_received = 0;
-static int f0_received = 0;
-
-static grub_uint8_t led_status;
-
-#define KEYBOARD_LED_SCROLL		(1 << 0)
-#define KEYBOARD_LED_NUM		(1 << 1)
-#define KEYBOARD_LED_CAPS		(1 << 2)
-
 static grub_uint8_t grub_keyboard_controller_orig;
 static grub_uint8_t grub_keyboard_orig_set;
-static grub_uint8_t current_set; 
-
-static void
-grub_keyboard_controller_init (void);
-
-static const grub_uint8_t set1_mapping[128] =
-  {
-    /* 0x00 */ 0 /* Unused  */,               GRUB_KEYBOARD_KEY_ESCAPE, 
-    /* 0x02 */ GRUB_KEYBOARD_KEY_1,           GRUB_KEYBOARD_KEY_2, 
-    /* 0x04 */ GRUB_KEYBOARD_KEY_3,           GRUB_KEYBOARD_KEY_4, 
-    /* 0x06 */ GRUB_KEYBOARD_KEY_5,           GRUB_KEYBOARD_KEY_6, 
-    /* 0x08 */ GRUB_KEYBOARD_KEY_7,           GRUB_KEYBOARD_KEY_8, 
-    /* 0x0a */ GRUB_KEYBOARD_KEY_9,           GRUB_KEYBOARD_KEY_0, 
-    /* 0x0c */ GRUB_KEYBOARD_KEY_DASH,        GRUB_KEYBOARD_KEY_EQUAL, 
-    /* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE,   GRUB_KEYBOARD_KEY_TAB, 
-    /* 0x10 */ GRUB_KEYBOARD_KEY_Q,           GRUB_KEYBOARD_KEY_W, 
-    /* 0x12 */ GRUB_KEYBOARD_KEY_E,           GRUB_KEYBOARD_KEY_R, 
-    /* 0x14 */ GRUB_KEYBOARD_KEY_T,           GRUB_KEYBOARD_KEY_Y, 
-    /* 0x16 */ GRUB_KEYBOARD_KEY_U,           GRUB_KEYBOARD_KEY_I, 
-    /* 0x18 */ GRUB_KEYBOARD_KEY_O,           GRUB_KEYBOARD_KEY_P, 
-    /* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET,    GRUB_KEYBOARD_KEY_RBRACKET, 
-    /* 0x1c */ GRUB_KEYBOARD_KEY_ENTER,       GRUB_KEYBOARD_KEY_LEFT_CTRL, 
-    /* 0x1e */ GRUB_KEYBOARD_KEY_A,           GRUB_KEYBOARD_KEY_S, 
-    /* 0x20 */ GRUB_KEYBOARD_KEY_D,           GRUB_KEYBOARD_KEY_F, 
-    /* 0x22 */ GRUB_KEYBOARD_KEY_G,           GRUB_KEYBOARD_KEY_H, 
-    /* 0x24 */ GRUB_KEYBOARD_KEY_J,           GRUB_KEYBOARD_KEY_K, 
-    /* 0x26 */ GRUB_KEYBOARD_KEY_L,           GRUB_KEYBOARD_KEY_SEMICOLON, 
-    /* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE,      GRUB_KEYBOARD_KEY_RQUOTE, 
-    /* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT,  GRUB_KEYBOARD_KEY_BACKSLASH, 
-    /* 0x2c */ GRUB_KEYBOARD_KEY_Z,           GRUB_KEYBOARD_KEY_X, 
-    /* 0x2e */ GRUB_KEYBOARD_KEY_C,           GRUB_KEYBOARD_KEY_V, 
-    /* 0x30 */ GRUB_KEYBOARD_KEY_B,           GRUB_KEYBOARD_KEY_N, 
-    /* 0x32 */ GRUB_KEYBOARD_KEY_M,           GRUB_KEYBOARD_KEY_COMMA, 
-    /* 0x34 */ GRUB_KEYBOARD_KEY_DOT,         GRUB_KEYBOARD_KEY_SLASH, 
-    /* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL, 
-    /* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT,    GRUB_KEYBOARD_KEY_SPACE, 
-    /* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK,   GRUB_KEYBOARD_KEY_F1, 
-    /* 0x3c */ GRUB_KEYBOARD_KEY_F2,          GRUB_KEYBOARD_KEY_F3, 
-    /* 0x3e */ GRUB_KEYBOARD_KEY_F4,          GRUB_KEYBOARD_KEY_F5, 
-    /* 0x40 */ GRUB_KEYBOARD_KEY_F6,          GRUB_KEYBOARD_KEY_F7, 
-    /* 0x42 */ GRUB_KEYBOARD_KEY_F8,          GRUB_KEYBOARD_KEY_F9, 
-    /* 0x44 */ GRUB_KEYBOARD_KEY_F10,         GRUB_KEYBOARD_KEY_NUM_LOCK, 
-    /* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7, 
-    /* 0x48 */ GRUB_KEYBOARD_KEY_NUM8,        GRUB_KEYBOARD_KEY_NUM9, 
-    /* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS,    GRUB_KEYBOARD_KEY_NUM4, 
-    /* 0x4c */ GRUB_KEYBOARD_KEY_NUM5,        GRUB_KEYBOARD_KEY_NUM6, 
-    /* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS,     GRUB_KEYBOARD_KEY_NUM1, 
-    /* 0x50 */ GRUB_KEYBOARD_KEY_NUM2,        GRUB_KEYBOARD_KEY_NUM3, 
-    /* 0x52 */ GRUB_KEYBOARD_KEY_NUM0,        GRUB_KEYBOARD_KEY_NUMDOT, 
-    /* 0x54 */ 0,                             0, 
-    /* 0x56 */ GRUB_KEYBOARD_KEY_102ND,       GRUB_KEYBOARD_KEY_F11, 
-    /* 0x58 */ GRUB_KEYBOARD_KEY_F12,         0,
-    /* 0x5a */ 0,                             0,
-    /* 0x5c */ 0,                             0,
-    /* 0x5e */ 0,                             0,
-    /* 0x60 */ 0,                             0,
-    /* 0x62 */ 0,                             0,
-    /* OLPC keys. Just mapped to normal keys.  */
-    /* 0x64 */ 0,                             GRUB_KEYBOARD_KEY_UP,
-    /* 0x66 */ GRUB_KEYBOARD_KEY_DOWN,        GRUB_KEYBOARD_KEY_LEFT,
-    /* 0x68 */ GRUB_KEYBOARD_KEY_RIGHT,       0,
-    /* 0x6a */ 0,                             0,
-    /* 0x6c */ 0,                             0,
-    /* 0x6e */ 0,                             0,
-    /* 0x70 */ 0,                             0,
-    /* 0x72 */ 0,                             GRUB_KEYBOARD_KEY_JP_RO,
-    /* 0x74 */ 0,                             0,
-    /* 0x76 */ 0,                             0,
-    /* 0x78 */ 0,                             0,
-    /* 0x7a */ 0,                             0,
-    /* 0x7c */ 0,                             GRUB_KEYBOARD_KEY_JP_YEN,
-    /* 0x7e */ GRUB_KEYBOARD_KEY_KPCOMMA
-  };
-
-static const struct
-{
-  grub_uint8_t from, to;
-} set1_e0_mapping[] = 
-  {
-    {0x1c, GRUB_KEYBOARD_KEY_NUMENTER},
-    {0x1d, GRUB_KEYBOARD_KEY_RIGHT_CTRL},
-    {0x35, GRUB_KEYBOARD_KEY_NUMSLASH }, 
-    {0x38, GRUB_KEYBOARD_KEY_RIGHT_ALT},
-    {0x47, GRUB_KEYBOARD_KEY_HOME}, 
-    {0x48, GRUB_KEYBOARD_KEY_UP},
-    {0x49, GRUB_KEYBOARD_KEY_PPAGE}, 
-    {0x4b, GRUB_KEYBOARD_KEY_LEFT},
-    {0x4d, GRUB_KEYBOARD_KEY_RIGHT},
-    {0x4f, GRUB_KEYBOARD_KEY_END}, 
-    {0x50, GRUB_KEYBOARD_KEY_DOWN},
-    {0x51, GRUB_KEYBOARD_KEY_NPAGE},
-    {0x52, GRUB_KEYBOARD_KEY_INSERT},
-    {0x53, GRUB_KEYBOARD_KEY_DELETE}, 
-  };
-
-static const grub_uint8_t set2_mapping[256] =
-  {
-    /* 0x00 */ 0,                             GRUB_KEYBOARD_KEY_F9,
-    /* 0x02 */ 0,                             GRUB_KEYBOARD_KEY_F5,
-    /* 0x04 */ GRUB_KEYBOARD_KEY_F3,          GRUB_KEYBOARD_KEY_F1,
-    /* 0x06 */ GRUB_KEYBOARD_KEY_F2,          GRUB_KEYBOARD_KEY_F12,
-    /* 0x08 */ 0,                             GRUB_KEYBOARD_KEY_F10,
-    /* 0x0a */ GRUB_KEYBOARD_KEY_F8,          GRUB_KEYBOARD_KEY_F6,
-    /* 0x0c */ GRUB_KEYBOARD_KEY_F4,          GRUB_KEYBOARD_KEY_TAB,
-    /* 0x0e */ GRUB_KEYBOARD_KEY_RQUOTE,      0,
-    /* 0x10 */ 0,                             GRUB_KEYBOARD_KEY_LEFT_ALT,
-    /* 0x12 */ GRUB_KEYBOARD_KEY_LEFT_SHIFT,  0,
-    /* 0x14 */ GRUB_KEYBOARD_KEY_LEFT_CTRL,   GRUB_KEYBOARD_KEY_Q,
-    /* 0x16 */ GRUB_KEYBOARD_KEY_1,           0,
-    /* 0x18 */ 0,                             0,
-    /* 0x1a */ GRUB_KEYBOARD_KEY_Z,           GRUB_KEYBOARD_KEY_S,
-    /* 0x1c */ GRUB_KEYBOARD_KEY_A,           GRUB_KEYBOARD_KEY_W,
-    /* 0x1e */ GRUB_KEYBOARD_KEY_2,           0,
-    /* 0x20 */ 0,                             GRUB_KEYBOARD_KEY_C,
-    /* 0x22 */ GRUB_KEYBOARD_KEY_X,           GRUB_KEYBOARD_KEY_D,
-    /* 0x24 */ GRUB_KEYBOARD_KEY_E,           GRUB_KEYBOARD_KEY_4,
-    /* 0x26 */ GRUB_KEYBOARD_KEY_3,           0,
-    /* 0x28 */ 0,                             GRUB_KEYBOARD_KEY_SPACE,
-    /* 0x2a */ GRUB_KEYBOARD_KEY_V,           GRUB_KEYBOARD_KEY_F,
-    /* 0x2c */ GRUB_KEYBOARD_KEY_T,           GRUB_KEYBOARD_KEY_R,
-    /* 0x2e */ GRUB_KEYBOARD_KEY_5,           0,
-    /* 0x30 */ 0,                             GRUB_KEYBOARD_KEY_N,
-    /* 0x32 */ GRUB_KEYBOARD_KEY_B,           GRUB_KEYBOARD_KEY_H,
-    /* 0x34 */ GRUB_KEYBOARD_KEY_G,           GRUB_KEYBOARD_KEY_Y,
-    /* 0x36 */ GRUB_KEYBOARD_KEY_6,           0,
-    /* 0x38 */ 0,                             0,
-    /* 0x3a */ GRUB_KEYBOARD_KEY_M,           GRUB_KEYBOARD_KEY_J,
-    /* 0x3c */ GRUB_KEYBOARD_KEY_U,           GRUB_KEYBOARD_KEY_7,
-    /* 0x3e */ GRUB_KEYBOARD_KEY_8,           0,
-    /* 0x40 */ 0,                             GRUB_KEYBOARD_KEY_COMMA,
-    /* 0x42 */ GRUB_KEYBOARD_KEY_K,           GRUB_KEYBOARD_KEY_I,
-    /* 0x44 */ GRUB_KEYBOARD_KEY_O,           GRUB_KEYBOARD_KEY_0,
-    /* 0x46 */ GRUB_KEYBOARD_KEY_9,           0,
-    /* 0x48 */ 0,                             GRUB_KEYBOARD_KEY_DOT,
-    /* 0x4a */ GRUB_KEYBOARD_KEY_SLASH,       GRUB_KEYBOARD_KEY_L,
-    /* 0x4c */ GRUB_KEYBOARD_KEY_SEMICOLON,   GRUB_KEYBOARD_KEY_P,
-    /* 0x4e */ GRUB_KEYBOARD_KEY_DASH,        0,
-    /* 0x50 */ 0,                             GRUB_KEYBOARD_KEY_JP_RO,
-    /* 0x52 */ GRUB_KEYBOARD_KEY_DQUOTE,      0,
-    /* 0x54 */ GRUB_KEYBOARD_KEY_LBRACKET,    GRUB_KEYBOARD_KEY_EQUAL,
-    /* 0x56 */ 0,                             0,
-    /* 0x58 */ GRUB_KEYBOARD_KEY_CAPS_LOCK,   GRUB_KEYBOARD_KEY_RIGHT_SHIFT,
-    /* 0x5a */ GRUB_KEYBOARD_KEY_ENTER,       GRUB_KEYBOARD_KEY_RBRACKET,
-    /* 0x5c */ 0,                             GRUB_KEYBOARD_KEY_BACKSLASH,
-    /* 0x5e */ 0,                             0,
-    /* 0x60 */ 0,                             GRUB_KEYBOARD_KEY_102ND,
-    /* 0x62 */ 0,                             0,
-    /* 0x64 */ 0,                             0,
-    /* 0x66 */ GRUB_KEYBOARD_KEY_BACKSPACE,   0,
-    /* 0x68 */ 0,                             GRUB_KEYBOARD_KEY_NUM1,
-    /* 0x6a */ GRUB_KEYBOARD_KEY_JP_YEN,      GRUB_KEYBOARD_KEY_NUM4,
-    /* 0x6c */ GRUB_KEYBOARD_KEY_NUM7,        GRUB_KEYBOARD_KEY_KPCOMMA,
-    /* 0x6e */ 0,                             0,
-    /* 0x70 */ GRUB_KEYBOARD_KEY_NUM0,        GRUB_KEYBOARD_KEY_NUMDOT,
-    /* 0x72 */ GRUB_KEYBOARD_KEY_NUM2,        GRUB_KEYBOARD_KEY_NUM5,
-    /* 0x74 */ GRUB_KEYBOARD_KEY_NUM6,        GRUB_KEYBOARD_KEY_NUM8,
-    /* 0x76 */ GRUB_KEYBOARD_KEY_ESCAPE,      GRUB_KEYBOARD_KEY_NUM_LOCK,
-    /* 0x78 */ GRUB_KEYBOARD_KEY_F11,         GRUB_KEYBOARD_KEY_NUMPLUS,
-    /* 0x7a */ GRUB_KEYBOARD_KEY_NUM3,        GRUB_KEYBOARD_KEY_NUMMINUS,
-    /* 0x7c */ GRUB_KEYBOARD_KEY_NUMMUL,      GRUB_KEYBOARD_KEY_NUM9,
-    /* 0x7e */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, 0,
-    /* 0x80 */ 0,                             0, 
-    /* 0x82 */ 0,                             GRUB_KEYBOARD_KEY_F7,
-  };
-
-static const struct
-{
-  grub_uint8_t from, to;
-} set2_e0_mapping[] = 
-  {
-    {0x11, GRUB_KEYBOARD_KEY_RIGHT_ALT},
-    {0x14, GRUB_KEYBOARD_KEY_RIGHT_CTRL},
-    {0x4a, GRUB_KEYBOARD_KEY_NUMSLASH},
-    {0x5a, GRUB_KEYBOARD_KEY_NUMENTER},
-    {0x69, GRUB_KEYBOARD_KEY_END},
-    {0x6b, GRUB_KEYBOARD_KEY_LEFT},
-    {0x6c, GRUB_KEYBOARD_KEY_HOME},
-    {0x70, GRUB_KEYBOARD_KEY_INSERT},
-    {0x71, GRUB_KEYBOARD_KEY_DELETE},
-    {0x72, GRUB_KEYBOARD_KEY_DOWN},
-    {0x74, GRUB_KEYBOARD_KEY_RIGHT},
-    {0x75, GRUB_KEYBOARD_KEY_UP},
-    {0x7a, GRUB_KEYBOARD_KEY_NPAGE},
-    {0x7d, GRUB_KEYBOARD_KEY_PPAGE},
-  };
+struct grub_ps2_state ps2_state;
 
 static int ping_sent;
 
+static void
+grub_keyboard_controller_init (void);
+
 static void
 keyboard_controller_wait_until_ready (void)
 {
+  /* 50 us would be enough but our current time resolution is 1ms.  */
+  grub_millisleep (1);
   while (! KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS)));
 }
 
@@ -241,10 +52,11 @@ wait_ack (void)
   grub_uint8_t ack;
 
   endtime = grub_get_time_ms () + 20;
-  do
+  do {
+    keyboard_controller_wait_until_ready ();
     ack = grub_inb (KEYBOARD_REG_DATA);
-  while (ack != GRUB_AT_ACK && ack != GRUB_AT_NACK
-	 && grub_get_time_ms () < endtime);
+  } while (ack != GRUB_AT_ACK && ack != GRUB_AT_NACK
+	   && grub_get_time_ms () < endtime);
   return ack;
 }
 
@@ -326,12 +138,10 @@ query_mode (void)
   if (!e)
     return 0;
 
-  keyboard_controller_wait_until_ready ();
-
-  do
+  do {
+    keyboard_controller_wait_until_ready ();
     ret = grub_inb (KEYBOARD_REG_DATA);
-  while (ret == GRUB_AT_ACK);
-
+  } while (ret == GRUB_AT_ACK);
   /* QEMU translates the set even in no-translate mode.  */
   if (ret == 0x43 || ret == 1)
     return 1;
@@ -350,28 +160,32 @@ set_scancodes (void)
   if (!grub_keyboard_orig_set)
     {
       grub_dprintf ("atkeyb", "No sets support assumed\n");
-      current_set = 1;
+      ps2_state.current_set = 1;
       return;
     }
 
 #if !USE_SCANCODE_SET
-  current_set = 1;
+  ps2_state.current_set = 1;
   return;
 #else
 
   grub_keyboard_controller_write (grub_keyboard_controller_orig
-				  & ~KEYBOARD_AT_TRANSLATE);
+				  & ~KEYBOARD_AT_TRANSLATE
+				  & ~KEYBOARD_AT_DISABLE);
+
+  keyboard_controller_wait_until_ready ();
+  grub_outb (KEYBOARD_COMMAND_ENABLE, KEYBOARD_REG_DATA);
 
   write_mode (2);
-  current_set = query_mode ();
-  grub_dprintf ("atkeyb", "returned set %d\n", current_set);
-  if (current_set == 2)
+  ps2_state.current_set = query_mode ();
+  grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
+  if (ps2_state.current_set == 2)
     return;
 
   write_mode (1);
-  current_set = query_mode ();
-  grub_dprintf ("atkeyb", "returned set %d\n", current_set);
-  if (current_set == 1)
+  ps2_state.current_set = query_mode ();
+  grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
+  if (ps2_state.current_set == 1)
     return;
   grub_dprintf ("atkeyb", "no supported scancode set found\n");
 #endif
@@ -386,164 +200,10 @@ keyboard_controller_led (grub_uint8_t leds)
   grub_outb (leds & 0x7, KEYBOARD_REG_DATA);
 }
 
-static int
-fetch_key (int *is_break)
-{
-  int was_ext = 0;
-  grub_uint8_t at_key;
-  int ret = 0;
-
-  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;
-      return -1;
-    }
-
-  if ((current_set == 2 || current_set == 3) && at_key == 0xf0)
-    {
-      f0_received = 1;
-      return -1;
-    }
-
-  /* Setting LEDs may generate ACKs.  */
-  if (at_key == GRUB_AT_ACK)
-    return -1;
-
-  was_ext = e0_received;
-  e0_received = 0;
-
-  switch (current_set)
-    {
-    case 1:
-      *is_break = !!(at_key & 0x80);
-      if (!was_ext)
-	ret = set1_mapping[at_key & 0x7f];
-      else
-	{
-	  unsigned i;
-	  for (i = 0; i < ARRAY_SIZE (set1_e0_mapping); i++)
-	    if (set1_e0_mapping[i].from == (at_key & 0x7f))
-	      {
-		ret = set1_e0_mapping[i].to;
-		break;
-	      }
-	}
-      break;
-    case 2:
-      *is_break = f0_received;
-      f0_received = 0;
-      if (!was_ext)
-	ret = set2_mapping[at_key];
-      else
-	{
-	  unsigned i;
-	  for (i = 0; i < ARRAY_SIZE (set2_e0_mapping); i++)
-	    if (set2_e0_mapping[i].from == at_key)
-	      {
-		ret = set2_e0_mapping[i].to;
-		break;
-	      }
-	}	
-      break;
-    default:
-      return -1;
-    }
-  if (!ret)
-    {
-      if (was_ext)
-	grub_dprintf ("atkeyb", "Unknown key 0xe0+0x%02x from set %d\n",
-		      at_key, current_set);
-      else
-	grub_dprintf ("atkeyb", "Unknown key 0x%02x from set %d\n",
-		      at_key, current_set);
-      return -1;
-    }
-  return ret;
-}
-
-/* FIXME: This should become an interrupt service routine.  For now
-   it's just used to catch events from control keys.  */
-static int
-grub_keyboard_isr (grub_keyboard_key_t key, int is_break)
-{
-  if (!is_break)
-    switch (key)
-      {
-      case GRUB_KEYBOARD_KEY_LEFT_SHIFT:
-	at_keyboard_status |= GRUB_TERM_STATUS_LSHIFT;
-	return 1;
-      case GRUB_KEYBOARD_KEY_RIGHT_SHIFT:
-	at_keyboard_status |= GRUB_TERM_STATUS_RSHIFT;
-	return 1;
-      case GRUB_KEYBOARD_KEY_LEFT_CTRL:
-	at_keyboard_status |= GRUB_TERM_STATUS_LCTRL;
-	return 1;
-      case GRUB_KEYBOARD_KEY_RIGHT_CTRL:
-	at_keyboard_status |= GRUB_TERM_STATUS_RCTRL;
-	return 1;
-      case GRUB_KEYBOARD_KEY_RIGHT_ALT:
-	at_keyboard_status |= GRUB_TERM_STATUS_RALT;
-	return 1;
-      case GRUB_KEYBOARD_KEY_LEFT_ALT:
-	at_keyboard_status |= GRUB_TERM_STATUS_LALT;
-	return 1;
-      default:
-	return 0;
-      }
-  else
-    switch (key)
-      {
-      case GRUB_KEYBOARD_KEY_LEFT_SHIFT:
-	at_keyboard_status &= ~GRUB_TERM_STATUS_LSHIFT;
-	return 1;
-      case GRUB_KEYBOARD_KEY_RIGHT_SHIFT:
-	at_keyboard_status &= ~GRUB_TERM_STATUS_RSHIFT;
-	return 1;
-      case GRUB_KEYBOARD_KEY_LEFT_CTRL:
-	at_keyboard_status &= ~GRUB_TERM_STATUS_LCTRL;
-	return 1;
-      case GRUB_KEYBOARD_KEY_RIGHT_CTRL:
-	at_keyboard_status &= ~GRUB_TERM_STATUS_RCTRL;
-	return 1;
-      case GRUB_KEYBOARD_KEY_RIGHT_ALT:
-	at_keyboard_status &= ~GRUB_TERM_STATUS_RALT;
-	return 1;
-      case GRUB_KEYBOARD_KEY_LEFT_ALT:
-	at_keyboard_status &= ~GRUB_TERM_STATUS_LALT;
-	return 1;
-      default:
-	return 0;
-      }
-}
-
-/* If there is a raw key pending, return it; otherwise return -1.  */
-static int
-grub_keyboard_getkey (void)
-{
-  int key;
-  int is_break = 0;
-
-  key = fetch_key (&is_break);
-  if (key == -1)
-    return -1;
-
-  if (grub_keyboard_isr (key, is_break))
-    return -1;
-  if (is_break)
-    return -1;
-  return key;
-}
-
 int
 grub_at_keyboard_is_alive (void)
 {
-  if (current_set != 0)
+  if (ps2_state.current_set != 0)
     return 1;
   if (ping_sent
       && KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS))
@@ -566,51 +226,28 @@ grub_at_keyboard_is_alive (void)
 static int
 grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
 {
-  int code;
+  grub_uint8_t at_key;
+  int ret;
+  grub_uint8_t old_led;
 
   if (!grub_at_keyboard_is_alive ())
     return GRUB_TERM_NO_KEY;
 
-  code = grub_keyboard_getkey ();
-  if (code == -1)
-    return GRUB_TERM_NO_KEY;
-#ifdef DEBUG_AT_KEYBOARD
-  grub_dprintf ("atkeyb", "Detected key 0x%x\n", code);
-#endif
-  switch (code)
-    {
-      case GRUB_KEYBOARD_KEY_CAPS_LOCK:
-	at_keyboard_status ^= GRUB_TERM_STATUS_CAPS;
-	led_status ^= KEYBOARD_LED_CAPS;
-	keyboard_controller_led (led_status);
+  if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
+    return -1;
+  at_key = grub_inb (KEYBOARD_REG_DATA);
+  old_led = ps2_state.led_status;
 
-#ifdef DEBUG_AT_KEYBOARD
-	grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & GRUB_KEYBOARD_STATUS_CAPS_LOCK));
-#endif
-	return GRUB_TERM_NO_KEY;
-      case GRUB_KEYBOARD_KEY_NUM_LOCK:
-	at_keyboard_status ^= GRUB_TERM_STATUS_NUM;
-	led_status ^= KEYBOARD_LED_NUM;
-	keyboard_controller_led (led_status);
-
-#ifdef DEBUG_AT_KEYBOARD
-	grub_dprintf ("atkeyb", "num_lock = %d\n", !!(at_keyboard_status & GRUB_KEYBOARD_STATUS_NUM_LOCK));
-#endif
-	return GRUB_TERM_NO_KEY;
-      case GRUB_KEYBOARD_KEY_SCROLL_LOCK:
-	at_keyboard_status ^= GRUB_TERM_STATUS_SCROLL;
-	led_status ^= KEYBOARD_LED_SCROLL;
-	keyboard_controller_led (led_status);
-	return GRUB_TERM_NO_KEY;
-      default:
-	return grub_term_map_key (code, at_keyboard_status);
-    }
+  ret = grub_ps2_process_incoming_byte (&ps2_state, at_key);
+  if (old_led != ps2_state.led_status)
+    keyboard_controller_led (ps2_state.led_status);
+  return ret;
 }
 
 static void
 grub_keyboard_controller_init (void)
 {
-  at_keyboard_status = 0;
+  ps2_state.at_keyboard_status = 0;
   /* Drain input buffer. */
   while (1)
     {
@@ -632,13 +269,13 @@ grub_keyboard_controller_init (void)
   grub_keyboard_orig_set = query_mode ();
 #endif
   set_scancodes ();
-  keyboard_controller_led (led_status);
+  keyboard_controller_led (ps2_state.led_status);
 }
 
 static grub_err_t
 grub_keyboard_controller_fini (struct grub_term_input *term __attribute__ ((unused)))
 {
-  if (current_set == 0)
+  if (ps2_state.current_set == 0)
     return GRUB_ERR_NONE;
   if (grub_keyboard_orig_set)
     write_mode (grub_keyboard_orig_set);
@@ -655,7 +292,7 @@ grub_at_fini_hw (int noreturn __attribute__ ((unused)))
 static grub_err_t
 grub_at_restore_hw (void)
 {
-  if (current_set == 0)
+  if (ps2_state.current_set == 0)
     return GRUB_ERR_NONE;
 
   /* Drain input buffer. */
@@ -668,7 +305,7 @@ grub_at_restore_hw (void)
       grub_inb (KEYBOARD_REG_DATA);
     }
   set_scancodes ();
-  keyboard_controller_led (led_status);
+  keyboard_controller_led (ps2_state.led_status);
 
   return GRUB_ERR_NONE;
 }
diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c
index 7d31095b1ef8d01886a0516343f2e5c5601265dd..4840cc59d3f68944fb2ca6b40cc6488e74b5da02 100644
--- a/grub-core/term/efi/console.c
+++ b/grub-core/term/efi/console.c
@@ -104,7 +104,7 @@ 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, GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12, '\e'
+    GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12, GRUB_TERM_ESC
   };
 
 static int
@@ -122,6 +122,9 @@ grub_efi_translate_key (grub_efi_input_key_t key)
       else
 	return key.unicode_char;
     }
+  /* Some devices send enter with scan_code 0x0d (F3) and unicode_char 0x0d. */
+  else if (key.scan_code == '\r' && key.unicode_char == '\r')
+    return key.unicode_char;
   else if (key.scan_code < ARRAY_SIZE (efi_codes))
     return efi_codes[key.scan_code];
 
diff --git a/grub-core/term/i386/coreboot/cbmemc.c b/grub-core/term/i386/coreboot/cbmemc.c
index 25e64a05c03286f644b39398e9e68cbdde333510..cea9b84315bdaf3b1238acc915f35ba6148ffbcf 100644
--- a/grub-core/term/i386/coreboot/cbmemc.c
+++ b/grub-core/term/i386/coreboot/cbmemc.c
@@ -23,17 +23,20 @@
 #include <grub/time.h>
 #include <grub/terminfo.h>
 #include <grub/dl.h>
-#include <grub/i386/coreboot/lbio.h>
+#include <grub/coreboot/lbio.h>
 #include <grub/command.h>
 #include <grub/normal.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
+#define CURSOR_MASK ((1 << 28) - 1)
+#define OVERFLOW (1 << 31)
+
 struct grub_linuxbios_cbmemc
 {
   grub_uint32_t size;
-  grub_uint32_t pointer;
-  char data[0];
+  grub_uint32_t cursor;
+  char body[0];
 };
 
 static struct grub_linuxbios_cbmemc *cbmemc;
@@ -41,11 +44,20 @@ static struct grub_linuxbios_cbmemc *cbmemc;
 static void
 put (struct grub_term_output *term __attribute__ ((unused)), const int c)
 {
+  grub_uint32_t flags, cursor;
   if (!cbmemc)
     return;
-  if (cbmemc->pointer < cbmemc->size)
-    cbmemc->data[cbmemc->pointer] = c;
-  cbmemc->pointer++;
+  flags = cbmemc->cursor & ~CURSOR_MASK;
+  cursor = cbmemc->cursor & CURSOR_MASK;
+  if (cursor >= cbmemc->size)
+    return;
+  cbmemc->body[cursor++] = c;
+  if (cursor >= cbmemc->size)
+    {
+      cursor = 0;
+      flags |= OVERFLOW;
+    }
+  cbmemc->cursor = flags | cursor;
 }
 
 struct grub_terminfo_output_state grub_cbmemc_terminfo_output =
@@ -87,21 +99,29 @@ grub_cmd_cbmemc (struct grub_command *cmd __attribute__ ((unused)),
 		 int argc __attribute__ ((unused)),
 		 char *argv[] __attribute__ ((unused)))
 {
-  grub_size_t len;
-  char *str;
-  struct grub_linuxbios_cbmemc *cbmemc_saved;
+  grub_size_t size, cursor;
+  struct grub_linuxbios_cbmemc *real_cbmemc;
 
   if (!cbmemc)
     return grub_error (GRUB_ERR_IO, "no CBMEM console found");
 
-  len = cbmemc->pointer;
-  if (len > cbmemc->size)
-    len = cbmemc->size;
-  str = cbmemc->data;
-  cbmemc_saved = cbmemc;
+  real_cbmemc = cbmemc;
   cbmemc = 0;
-  grub_xnputs (str, len);
-  cbmemc = cbmemc_saved;
+  cursor = real_cbmemc->cursor & CURSOR_MASK;
+  if (!(real_cbmemc->cursor & OVERFLOW) && cursor < real_cbmemc->size)
+    size = cursor;
+  else
+    size = real_cbmemc->size;
+  if (real_cbmemc->cursor & OVERFLOW)
+    {
+      if (cursor > size)
+        cursor = 0;
+      grub_xnputs(real_cbmemc->body + cursor, size - cursor);
+      grub_xnputs(real_cbmemc->body, cursor);
+    }
+  else
+    grub_xnputs(real_cbmemc->body, size);
+  cbmemc = real_cbmemc;
   return 0;
 }
 
diff --git a/grub-core/term/i386/pc/console.c b/grub-core/term/i386/pc/console.c
index 28de46b576a667fd40c5852b16a4bcc3ea681849..f6142a2dea8036f5301c81a9e2fbd5ddbff5fd90 100644
--- a/grub-core/term/i386/pc/console.c
+++ b/grub-core/term/i386/pc/console.c
@@ -204,7 +204,7 @@ static int
 grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
 {
   const grub_uint16_t bypass_table[] = {
-    0x0100 | '\e', 0x0f00 | '\t', 0x0e00 | '\b', 0x1c00 | '\r', 0x1c00 | '\n'
+    0x0100 | GRUB_TERM_ESC, 0x0f00 | GRUB_TERM_TAB, 0x0e00 | GRUB_TERM_BACKSPACE, 0x1c00 | '\r', 0x1c00 | '\n'
   };
   struct grub_bios_int_registers regs;
   unsigned i;
diff --git a/grub-core/term/ps2.c b/grub-core/term/ps2.c
new file mode 100644
index 0000000000000000000000000000000000000000..7ae4e9f2f8cd4a0ba4405c21581f906f7b458379
--- /dev/null
+++ b/grub-core/term/ps2.c
@@ -0,0 +1,387 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/term.h>
+#include <grub/keyboard_layouts.h>
+#include <grub/ps2.h>
+
+#define KEYBOARD_LED_SCROLL		(1 << 0)
+#define KEYBOARD_LED_NUM		(1 << 1)
+#define KEYBOARD_LED_CAPS		(1 << 2)
+
+static const grub_uint8_t set1_mapping[128] =
+  {
+    /* 0x00 */ 0 /* Unused  */,               GRUB_KEYBOARD_KEY_ESCAPE, 
+    /* 0x02 */ GRUB_KEYBOARD_KEY_1,           GRUB_KEYBOARD_KEY_2, 
+    /* 0x04 */ GRUB_KEYBOARD_KEY_3,           GRUB_KEYBOARD_KEY_4, 
+    /* 0x06 */ GRUB_KEYBOARD_KEY_5,           GRUB_KEYBOARD_KEY_6, 
+    /* 0x08 */ GRUB_KEYBOARD_KEY_7,           GRUB_KEYBOARD_KEY_8, 
+    /* 0x0a */ GRUB_KEYBOARD_KEY_9,           GRUB_KEYBOARD_KEY_0, 
+    /* 0x0c */ GRUB_KEYBOARD_KEY_DASH,        GRUB_KEYBOARD_KEY_EQUAL, 
+    /* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE,   GRUB_KEYBOARD_KEY_TAB, 
+    /* 0x10 */ GRUB_KEYBOARD_KEY_Q,           GRUB_KEYBOARD_KEY_W, 
+    /* 0x12 */ GRUB_KEYBOARD_KEY_E,           GRUB_KEYBOARD_KEY_R, 
+    /* 0x14 */ GRUB_KEYBOARD_KEY_T,           GRUB_KEYBOARD_KEY_Y, 
+    /* 0x16 */ GRUB_KEYBOARD_KEY_U,           GRUB_KEYBOARD_KEY_I, 
+    /* 0x18 */ GRUB_KEYBOARD_KEY_O,           GRUB_KEYBOARD_KEY_P, 
+    /* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET,    GRUB_KEYBOARD_KEY_RBRACKET, 
+    /* 0x1c */ GRUB_KEYBOARD_KEY_ENTER,       GRUB_KEYBOARD_KEY_LEFT_CTRL, 
+    /* 0x1e */ GRUB_KEYBOARD_KEY_A,           GRUB_KEYBOARD_KEY_S, 
+    /* 0x20 */ GRUB_KEYBOARD_KEY_D,           GRUB_KEYBOARD_KEY_F, 
+    /* 0x22 */ GRUB_KEYBOARD_KEY_G,           GRUB_KEYBOARD_KEY_H, 
+    /* 0x24 */ GRUB_KEYBOARD_KEY_J,           GRUB_KEYBOARD_KEY_K, 
+    /* 0x26 */ GRUB_KEYBOARD_KEY_L,           GRUB_KEYBOARD_KEY_SEMICOLON, 
+    /* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE,      GRUB_KEYBOARD_KEY_RQUOTE, 
+    /* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT,  GRUB_KEYBOARD_KEY_BACKSLASH, 
+    /* 0x2c */ GRUB_KEYBOARD_KEY_Z,           GRUB_KEYBOARD_KEY_X, 
+    /* 0x2e */ GRUB_KEYBOARD_KEY_C,           GRUB_KEYBOARD_KEY_V, 
+    /* 0x30 */ GRUB_KEYBOARD_KEY_B,           GRUB_KEYBOARD_KEY_N, 
+    /* 0x32 */ GRUB_KEYBOARD_KEY_M,           GRUB_KEYBOARD_KEY_COMMA, 
+    /* 0x34 */ GRUB_KEYBOARD_KEY_DOT,         GRUB_KEYBOARD_KEY_SLASH, 
+    /* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL, 
+    /* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT,    GRUB_KEYBOARD_KEY_SPACE, 
+    /* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK,   GRUB_KEYBOARD_KEY_F1, 
+    /* 0x3c */ GRUB_KEYBOARD_KEY_F2,          GRUB_KEYBOARD_KEY_F3, 
+    /* 0x3e */ GRUB_KEYBOARD_KEY_F4,          GRUB_KEYBOARD_KEY_F5, 
+    /* 0x40 */ GRUB_KEYBOARD_KEY_F6,          GRUB_KEYBOARD_KEY_F7, 
+    /* 0x42 */ GRUB_KEYBOARD_KEY_F8,          GRUB_KEYBOARD_KEY_F9, 
+    /* 0x44 */ GRUB_KEYBOARD_KEY_F10,         GRUB_KEYBOARD_KEY_NUM_LOCK, 
+    /* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7, 
+    /* 0x48 */ GRUB_KEYBOARD_KEY_NUM8,        GRUB_KEYBOARD_KEY_NUM9, 
+    /* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS,    GRUB_KEYBOARD_KEY_NUM4, 
+    /* 0x4c */ GRUB_KEYBOARD_KEY_NUM5,        GRUB_KEYBOARD_KEY_NUM6, 
+    /* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS,     GRUB_KEYBOARD_KEY_NUM1, 
+    /* 0x50 */ GRUB_KEYBOARD_KEY_NUM2,        GRUB_KEYBOARD_KEY_NUM3, 
+    /* 0x52 */ GRUB_KEYBOARD_KEY_NUM0,        GRUB_KEYBOARD_KEY_NUMDOT, 
+    /* 0x54 */ 0,                             0, 
+    /* 0x56 */ GRUB_KEYBOARD_KEY_102ND,       GRUB_KEYBOARD_KEY_F11, 
+    /* 0x58 */ GRUB_KEYBOARD_KEY_F12,         0,
+    /* 0x5a */ 0,                             0,
+    /* 0x5c */ 0,                             0,
+    /* 0x5e */ 0,                             0,
+    /* 0x60 */ 0,                             0,
+    /* 0x62 */ 0,                             0,
+    /* OLPC keys. Just mapped to normal keys.  */
+    /* 0x64 */ 0,                             GRUB_KEYBOARD_KEY_UP,
+    /* 0x66 */ GRUB_KEYBOARD_KEY_DOWN,        GRUB_KEYBOARD_KEY_LEFT,
+    /* 0x68 */ GRUB_KEYBOARD_KEY_RIGHT,       0,
+    /* 0x6a */ 0,                             0,
+    /* 0x6c */ 0,                             0,
+    /* 0x6e */ 0,                             0,
+    /* 0x70 */ 0,                             0,
+    /* 0x72 */ 0,                             GRUB_KEYBOARD_KEY_JP_RO,
+    /* 0x74 */ 0,                             0,
+    /* 0x76 */ 0,                             0,
+    /* 0x78 */ 0,                             0,
+    /* 0x7a */ 0,                             0,
+    /* 0x7c */ 0,                             GRUB_KEYBOARD_KEY_JP_YEN,
+    /* 0x7e */ GRUB_KEYBOARD_KEY_KPCOMMA
+  };
+
+static const struct
+{
+  grub_uint8_t from, to;
+} set1_e0_mapping[] = 
+  {
+    {0x1c, GRUB_KEYBOARD_KEY_NUMENTER},
+    {0x1d, GRUB_KEYBOARD_KEY_RIGHT_CTRL},
+    {0x35, GRUB_KEYBOARD_KEY_NUMSLASH }, 
+    {0x38, GRUB_KEYBOARD_KEY_RIGHT_ALT},
+    {0x47, GRUB_KEYBOARD_KEY_HOME}, 
+    {0x48, GRUB_KEYBOARD_KEY_UP},
+    {0x49, GRUB_KEYBOARD_KEY_PPAGE}, 
+    {0x4b, GRUB_KEYBOARD_KEY_LEFT},
+    {0x4d, GRUB_KEYBOARD_KEY_RIGHT},
+    {0x4f, GRUB_KEYBOARD_KEY_END}, 
+    {0x50, GRUB_KEYBOARD_KEY_DOWN},
+    {0x51, GRUB_KEYBOARD_KEY_NPAGE},
+    {0x52, GRUB_KEYBOARD_KEY_INSERT},
+    {0x53, GRUB_KEYBOARD_KEY_DELETE}, 
+  };
+
+static const grub_uint8_t set2_mapping[256] =
+  {
+    /* 0x00 */ 0,                             GRUB_KEYBOARD_KEY_F9,
+    /* 0x02 */ 0,                             GRUB_KEYBOARD_KEY_F5,
+    /* 0x04 */ GRUB_KEYBOARD_KEY_F3,          GRUB_KEYBOARD_KEY_F1,
+    /* 0x06 */ GRUB_KEYBOARD_KEY_F2,          GRUB_KEYBOARD_KEY_F12,
+    /* 0x08 */ 0,                             GRUB_KEYBOARD_KEY_F10,
+    /* 0x0a */ GRUB_KEYBOARD_KEY_F8,          GRUB_KEYBOARD_KEY_F6,
+    /* 0x0c */ GRUB_KEYBOARD_KEY_F4,          GRUB_KEYBOARD_KEY_TAB,
+    /* 0x0e */ GRUB_KEYBOARD_KEY_RQUOTE,      0,
+    /* 0x10 */ 0,                             GRUB_KEYBOARD_KEY_LEFT_ALT,
+    /* 0x12 */ GRUB_KEYBOARD_KEY_LEFT_SHIFT,  0,
+    /* 0x14 */ GRUB_KEYBOARD_KEY_LEFT_CTRL,   GRUB_KEYBOARD_KEY_Q,
+    /* 0x16 */ GRUB_KEYBOARD_KEY_1,           0,
+    /* 0x18 */ 0,                             0,
+    /* 0x1a */ GRUB_KEYBOARD_KEY_Z,           GRUB_KEYBOARD_KEY_S,
+    /* 0x1c */ GRUB_KEYBOARD_KEY_A,           GRUB_KEYBOARD_KEY_W,
+    /* 0x1e */ GRUB_KEYBOARD_KEY_2,           0,
+    /* 0x20 */ 0,                             GRUB_KEYBOARD_KEY_C,
+    /* 0x22 */ GRUB_KEYBOARD_KEY_X,           GRUB_KEYBOARD_KEY_D,
+    /* 0x24 */ GRUB_KEYBOARD_KEY_E,           GRUB_KEYBOARD_KEY_4,
+    /* 0x26 */ GRUB_KEYBOARD_KEY_3,           0,
+    /* 0x28 */ 0,                             GRUB_KEYBOARD_KEY_SPACE,
+    /* 0x2a */ GRUB_KEYBOARD_KEY_V,           GRUB_KEYBOARD_KEY_F,
+    /* 0x2c */ GRUB_KEYBOARD_KEY_T,           GRUB_KEYBOARD_KEY_R,
+    /* 0x2e */ GRUB_KEYBOARD_KEY_5,           0,
+    /* 0x30 */ 0,                             GRUB_KEYBOARD_KEY_N,
+    /* 0x32 */ GRUB_KEYBOARD_KEY_B,           GRUB_KEYBOARD_KEY_H,
+    /* 0x34 */ GRUB_KEYBOARD_KEY_G,           GRUB_KEYBOARD_KEY_Y,
+    /* 0x36 */ GRUB_KEYBOARD_KEY_6,           0,
+    /* 0x38 */ 0,                             0,
+    /* 0x3a */ GRUB_KEYBOARD_KEY_M,           GRUB_KEYBOARD_KEY_J,
+    /* 0x3c */ GRUB_KEYBOARD_KEY_U,           GRUB_KEYBOARD_KEY_7,
+    /* 0x3e */ GRUB_KEYBOARD_KEY_8,           0,
+    /* 0x40 */ 0,                             GRUB_KEYBOARD_KEY_COMMA,
+    /* 0x42 */ GRUB_KEYBOARD_KEY_K,           GRUB_KEYBOARD_KEY_I,
+    /* 0x44 */ GRUB_KEYBOARD_KEY_O,           GRUB_KEYBOARD_KEY_0,
+    /* 0x46 */ GRUB_KEYBOARD_KEY_9,           0,
+    /* 0x48 */ 0,                             GRUB_KEYBOARD_KEY_DOT,
+    /* 0x4a */ GRUB_KEYBOARD_KEY_SLASH,       GRUB_KEYBOARD_KEY_L,
+    /* 0x4c */ GRUB_KEYBOARD_KEY_SEMICOLON,   GRUB_KEYBOARD_KEY_P,
+    /* 0x4e */ GRUB_KEYBOARD_KEY_DASH,        0,
+    /* 0x50 */ 0,                             GRUB_KEYBOARD_KEY_JP_RO,
+    /* 0x52 */ GRUB_KEYBOARD_KEY_DQUOTE,      0,
+    /* 0x54 */ GRUB_KEYBOARD_KEY_LBRACKET,    GRUB_KEYBOARD_KEY_EQUAL,
+    /* 0x56 */ 0,                             0,
+    /* 0x58 */ GRUB_KEYBOARD_KEY_CAPS_LOCK,   GRUB_KEYBOARD_KEY_RIGHT_SHIFT,
+    /* 0x5a */ GRUB_KEYBOARD_KEY_ENTER,       GRUB_KEYBOARD_KEY_RBRACKET,
+    /* 0x5c */ 0,                             GRUB_KEYBOARD_KEY_BACKSLASH,
+    /* 0x5e */ 0,                             0,
+    /* 0x60 */ 0,                             GRUB_KEYBOARD_KEY_102ND,
+    /* 0x62 */ 0,                             0,
+    /* 0x64 */ 0,                             0,
+    /* 0x66 */ GRUB_KEYBOARD_KEY_BACKSPACE,   0,
+    /* 0x68 */ 0,                             GRUB_KEYBOARD_KEY_NUM1,
+    /* 0x6a */ GRUB_KEYBOARD_KEY_JP_YEN,      GRUB_KEYBOARD_KEY_NUM4,
+    /* 0x6c */ GRUB_KEYBOARD_KEY_NUM7,        GRUB_KEYBOARD_KEY_KPCOMMA,
+    /* 0x6e */ 0,                             0,
+    /* 0x70 */ GRUB_KEYBOARD_KEY_NUM0,        GRUB_KEYBOARD_KEY_NUMDOT,
+    /* 0x72 */ GRUB_KEYBOARD_KEY_NUM2,        GRUB_KEYBOARD_KEY_NUM5,
+    /* 0x74 */ GRUB_KEYBOARD_KEY_NUM6,        GRUB_KEYBOARD_KEY_NUM8,
+    /* 0x76 */ GRUB_KEYBOARD_KEY_ESCAPE,      GRUB_KEYBOARD_KEY_NUM_LOCK,
+    /* 0x78 */ GRUB_KEYBOARD_KEY_F11,         GRUB_KEYBOARD_KEY_NUMPLUS,
+    /* 0x7a */ GRUB_KEYBOARD_KEY_NUM3,        GRUB_KEYBOARD_KEY_NUMMINUS,
+    /* 0x7c */ GRUB_KEYBOARD_KEY_NUMMUL,      GRUB_KEYBOARD_KEY_NUM9,
+    /* 0x7e */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, 0,
+    /* 0x80 */ 0,                             0, 
+    /* 0x82 */ 0,                             GRUB_KEYBOARD_KEY_F7,
+  };
+
+static const struct
+{
+  grub_uint8_t from, to;
+} set2_e0_mapping[] = 
+  {
+    {0x11, GRUB_KEYBOARD_KEY_RIGHT_ALT},
+    {0x14, GRUB_KEYBOARD_KEY_RIGHT_CTRL},
+    {0x4a, GRUB_KEYBOARD_KEY_NUMSLASH},
+    {0x5a, GRUB_KEYBOARD_KEY_NUMENTER},
+    {0x69, GRUB_KEYBOARD_KEY_END},
+    {0x6b, GRUB_KEYBOARD_KEY_LEFT},
+    {0x6c, GRUB_KEYBOARD_KEY_HOME},
+    {0x70, GRUB_KEYBOARD_KEY_INSERT},
+    {0x71, GRUB_KEYBOARD_KEY_DELETE},
+    {0x72, GRUB_KEYBOARD_KEY_DOWN},
+    {0x74, GRUB_KEYBOARD_KEY_RIGHT},
+    {0x75, GRUB_KEYBOARD_KEY_UP},
+    {0x7a, GRUB_KEYBOARD_KEY_NPAGE},
+    {0x7d, GRUB_KEYBOARD_KEY_PPAGE},
+  };
+
+static int
+fetch_key (struct grub_ps2_state *ps2_state, grub_uint8_t at_key, int *is_break)
+{
+  int was_ext = 0;
+  int ret = 0;
+
+  /* May happen if no keyboard is connected. Just ignore this.  */
+  if (at_key == 0xff)
+    return -1;
+  if (at_key == 0xe0)
+    {
+      ps2_state->e0_received = 1;
+      return -1;
+    }
+
+  if ((ps2_state->current_set == 2 || ps2_state->current_set == 3) && at_key == 0xf0)
+    {
+      ps2_state->f0_received = 1;
+      return -1;
+    }
+
+  /* Setting LEDs may generate ACKs.  */
+  if (at_key == GRUB_AT_ACK)
+    return -1;
+
+  was_ext = ps2_state->e0_received;
+  ps2_state->e0_received = 0;
+
+  switch (ps2_state->current_set)
+    {
+    case 1:
+      *is_break = !!(at_key & 0x80);
+      if (!was_ext)
+	ret = set1_mapping[at_key & 0x7f];
+      else
+	{
+	  unsigned i;
+	  for (i = 0; i < ARRAY_SIZE (set1_e0_mapping); i++)
+	    if (set1_e0_mapping[i].from == (at_key & 0x7f))
+	      {
+		ret = set1_e0_mapping[i].to;
+		break;
+	      }
+	}
+      break;
+    case 2:
+      *is_break = ps2_state->f0_received;
+      ps2_state->f0_received = 0;
+      if (!was_ext)
+	ret = set2_mapping[at_key];
+      else
+	{
+	  unsigned i;
+	  for (i = 0; i < ARRAY_SIZE (set2_e0_mapping); i++)
+	    if (set2_e0_mapping[i].from == at_key)
+	      {
+		ret = set2_e0_mapping[i].to;
+		break;
+	      }
+	}	
+      break;
+    default:
+      return -1;
+    }
+  if (!ret)
+    {
+      if (was_ext)
+	grub_dprintf ("atkeyb", "Unknown key 0xe0+0x%02x from set %d\n",
+		      at_key, ps2_state->current_set);
+      else
+	grub_dprintf ("atkeyb", "Unknown key 0x%02x from set %d\n",
+		      at_key, ps2_state->current_set);
+      return -1;
+    }
+  return ret;
+}
+
+/* FIXME: This should become an interrupt service routine.  For now
+   it's just used to catch events from control keys.  */
+static int
+grub_keyboard_isr (struct grub_ps2_state *ps2_state,
+		   grub_keyboard_key_t key, int is_break)
+{
+  if (!is_break)
+    switch (key)
+      {
+      case GRUB_KEYBOARD_KEY_LEFT_SHIFT:
+	ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_LSHIFT;
+	return 1;
+      case GRUB_KEYBOARD_KEY_RIGHT_SHIFT:
+	ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_RSHIFT;
+	return 1;
+      case GRUB_KEYBOARD_KEY_LEFT_CTRL:
+	ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_LCTRL;
+	return 1;
+      case GRUB_KEYBOARD_KEY_RIGHT_CTRL:
+	ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_RCTRL;
+	return 1;
+      case GRUB_KEYBOARD_KEY_RIGHT_ALT:
+	ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_RALT;
+	return 1;
+      case GRUB_KEYBOARD_KEY_LEFT_ALT:
+	ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_LALT;
+	return 1;
+      default:
+	return 0;
+      }
+  else
+    switch (key)
+      {
+      case GRUB_KEYBOARD_KEY_LEFT_SHIFT:
+	ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_LSHIFT;
+	return 1;
+      case GRUB_KEYBOARD_KEY_RIGHT_SHIFT:
+	ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_RSHIFT;
+	return 1;
+      case GRUB_KEYBOARD_KEY_LEFT_CTRL:
+	ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_LCTRL;
+	return 1;
+      case GRUB_KEYBOARD_KEY_RIGHT_CTRL:
+	ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_RCTRL;
+	return 1;
+      case GRUB_KEYBOARD_KEY_RIGHT_ALT:
+	ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_RALT;
+	return 1;
+      case GRUB_KEYBOARD_KEY_LEFT_ALT:
+	ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_LALT;
+	return 1;
+      default:
+	return 0;
+      }
+}
+
+/* If there is a key pending, return it; otherwise return GRUB_TERM_NO_KEY.  */
+int
+grub_ps2_process_incoming_byte (struct grub_ps2_state *ps2_state,
+				grub_uint8_t at_key)
+{
+  int code;
+  int is_break = 0;
+
+  code = fetch_key (ps2_state, at_key, &is_break);
+  if (code == -1)
+    return GRUB_TERM_NO_KEY;
+
+  if (grub_keyboard_isr (ps2_state, code, is_break))
+    return GRUB_TERM_NO_KEY;
+  if (is_break)
+    return GRUB_TERM_NO_KEY;
+#ifdef DEBUG_AT_KEYBOARD
+  grub_dprintf ("atkeyb", "Detected key 0x%x\n", code);
+#endif
+  switch (code)
+    {
+      case GRUB_KEYBOARD_KEY_CAPS_LOCK:
+	ps2_state->at_keyboard_status ^= GRUB_TERM_STATUS_CAPS;
+	ps2_state->led_status ^= KEYBOARD_LED_CAPS;
+
+#ifdef DEBUG_AT_KEYBOARD
+	grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(ps2_state->at_keyboard_status & GRUB_KEYBOARD_STATUS_CAPS_LOCK));
+#endif
+	return GRUB_TERM_NO_KEY;
+      case GRUB_KEYBOARD_KEY_NUM_LOCK:
+	ps2_state->at_keyboard_status ^= GRUB_TERM_STATUS_NUM;
+	ps2_state->led_status ^= KEYBOARD_LED_NUM;
+
+#ifdef DEBUG_AT_KEYBOARD
+	grub_dprintf ("atkeyb", "num_lock = %d\n", !!(ps2_state->at_keyboard_status & GRUB_KEYBOARD_STATUS_NUM_LOCK));
+#endif
+	return GRUB_TERM_NO_KEY;
+      case GRUB_KEYBOARD_KEY_SCROLL_LOCK:
+	ps2_state->at_keyboard_status ^= GRUB_TERM_STATUS_SCROLL;
+	ps2_state->led_status ^= KEYBOARD_LED_SCROLL;
+	return GRUB_TERM_NO_KEY;
+      default:
+	return grub_term_map_key (code, ps2_state->at_keyboard_status);
+    }
+}
diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c
index f0d3e3debc60aa8dd04a5643a8a0537ffb88ec26..d317efa368d846963743a243fd672026a2221933 100644
--- a/grub-core/term/terminfo.c
+++ b/grub-core/term/terminfo.c
@@ -426,12 +426,12 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
     }
   *len = 1;
   keys[0] = c;
-  if (c != ANSI_CSI && c != '\e')
+  if (c != ANSI_CSI && c != GRUB_TERM_ESC)
     {
       /* Backspace: Ctrl-h.  */
       if (c == 0x7f)
-	c = '\b'; 
-      if (c < 0x20 && c != '\t' && c!= '\b' && c != '\n' && c != '\r')
+	c = GRUB_TERM_BACKSPACE;
+      if (c < 0x20 && c != GRUB_TERM_TAB && c!= GRUB_TERM_BACKSPACE && c != '\n' && c != '\r')
 	c = GRUB_TERM_CTRL | (c - 1 + 'a');
       *len = 1;
       keys[0] = c;
@@ -487,7 +487,7 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
 	  GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_END };
     unsigned i;
 
-    if (c == '\e')
+    if (c == GRUB_TERM_ESC)
       {
 	CONTINUE_READ;
 
@@ -606,7 +606,7 @@ grub_terminfo_getkey (struct grub_term_input *termi)
 			 &data->npending, data->readkey);
 
 #if defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275)
-  if (data->npending == 1 && data->input_buf[0] == '\e'
+  if (data->npending == 1 && data->input_buf[0] == GRUB_TERM_ESC
       && grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_REPEAT)
       && grub_get_time_ms () - data->last_key_time < 1000
       && (data->last_key & GRUB_TERM_EXTENDED))
diff --git a/grub-core/tests/cmdline_cat_test.c b/grub-core/tests/cmdline_cat_test.c
index f1e21439e2be229d386cb310d62164fc9a5f4f92..baea7688a1d3c49d37a2c03e585109ccd04328f8 100644
--- a/grub-core/tests/cmdline_cat_test.c
+++ b/grub-core/tests/cmdline_cat_test.c
@@ -103,7 +103,7 @@ cmdline_cat_test (void)
 					     '/', 't', 'e', 's', 't', '.',
 					     't', 'x', 't', '\n',
 					     GRUB_TERM_NO_KEY,
-					     GRUB_TERM_NO_KEY, '\e'},
+					     GRUB_TERM_NO_KEY, GRUB_TERM_ESC},
 					 23);
 
       grub_video_checksum ("cmdline_cat");
diff --git a/grub-core/tests/gfxterm_menu.c b/grub-core/tests/gfxterm_menu.c
index 8f63dc27a35bd769ecb5d94599de3ba9e97cf5dc..12836fb96598d98b5cbf371a953e6ec702eb50de 100644
--- a/grub-core/tests/gfxterm_menu.c
+++ b/grub-core/tests/gfxterm_menu.c
@@ -146,7 +146,7 @@ gfxterm_menu (void)
 	    return;
 	  }
 	grub_terminal_input_fake_sequence ((int []) { -1, -1, -1, GRUB_TERM_KEY_DOWN, -1, 'e',
-	      -1, GRUB_TERM_KEY_RIGHT, -1, 'x', -1,  '\e', -1, '\e' }, 14);
+	      -1, GRUB_TERM_KEY_RIGHT, -1, 'x', -1,  GRUB_TERM_ESC, -1, GRUB_TERM_ESC }, 14);
 
 	grub_video_checksum (tests[j].name);
 
diff --git a/grub-core/tests/lib/functional_test.c b/grub-core/tests/lib/functional_test.c
index d4822a12456525e4abc5f587bc897364db4e52b7..96781fb39b5f37b201345f60fe4297629bb672cf 100644
--- a/grub-core/tests/lib/functional_test.c
+++ b/grub-core/tests/lib/functional_test.c
@@ -26,14 +26,23 @@ GRUB_MOD_LICENSE ("GPLv3+");
 
 static grub_err_t
 grub_functional_test (grub_extcmd_context_t ctxt __attribute__ ((unused)),
-		      int argc __attribute__ ((unused)),
-		      char **args __attribute__ ((unused)))
+		      int argc,
+		      char **args)
 {
   grub_test_t test;
   int ok = 1;
+  int i;
 
   FOR_LIST_ELEMENTS (test, grub_test_list)
     {
+      if (argc != 0)
+	{
+	  for (i = 0; i < argc; i++)
+	    if (grub_strcmp(args[i], test->name) == 0)
+	      break;
+	  if (i == argc)
+	    continue;
+	}
       grub_errno = 0;
       ok = ok && !grub_test_run (test);
       grub_errno = 0;
diff --git a/grub-core/video/i386/coreboot/cbfb.c b/grub-core/video/coreboot/cbfb.c
similarity index 99%
rename from grub-core/video/i386/coreboot/cbfb.c
rename to grub-core/video/coreboot/cbfb.c
index dede0c37ea3e8a8948cd6535d26d008e117206bc..9af81fa5b01b63677d97ba9a242e60080df84e5a 100644
--- a/grub-core/video/i386/coreboot/cbfb.c
+++ b/grub-core/video/coreboot/cbfb.c
@@ -25,7 +25,7 @@
 #include <grub/mm.h>
 #include <grub/video.h>
 #include <grub/video_fb.h>
-#include <grub/machine/lbio.h>
+#include <grub/coreboot/lbio.h>
 #include <grub/machine/console.h>
 
 struct grub_linuxbios_table_framebuffer *grub_video_coreboot_fbtable;
diff --git a/grub-core/video/efi_uga.c b/grub-core/video/efi_uga.c
index 464ede874daff480fb4199927cb30d48f0558e8b..044af1d20d38f08e3b5c5dcec4281c0b452cf8ea 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;
 
diff --git a/tests/printf_unit_test.c b/tests/printf_unit_test.c
index d7b12c6dbee6e84ace9d9f81d476622194810b26..098c29fd9ce2d28a5b83b74afc0f9e40b7c401ec 100644
--- a/tests/printf_unit_test.c
+++ b/tests/printf_unit_test.c
@@ -23,6 +23,10 @@
 
 #define MSG "printf test failed: %s, %s", real, expected
 
+#if defined(__GNUC__) && __GNUC__ >= 7
+#pragma GCC diagnostic ignored "-Wformat-truncation="
+#endif
+
 static void
 printf_test (void)
 {
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index 452b230daedc3db0296cab014e89ddacf1c21347..0a2e24a79f11916527650d124e38c6184c4ceb93 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -73,6 +73,7 @@ grub_install_help_filter (int key, const char *text,
 
 static int (*compress_func) (const char *src, const char *dest) = NULL;
 char *grub_install_copy_buffer;
+static char *dtb;
 
 int
 grub_install_copy_file (const char *src,
@@ -364,6 +365,11 @@ grub_install_parse (int key, char *arg)
     case GRUB_INSTALL_OPTIONS_INSTALL_FONTS:
       handle_install_list (&install_fonts, arg, 0);
       return 1;
+    case GRUB_INSTALL_OPTIONS_DTB:
+      if (dtb)
+	free (dtb);
+      dtb = xstrdup (arg);
+      return 1;
     case GRUB_INSTALL_OPTIONS_INSTALL_COMPRESS:
       if (strcmp (arg, "no") == 0
 	  || strcmp (arg, "none") == 0)
@@ -486,9 +492,10 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
 
   grub_util_info ("grub-mkimage --directory '%s' --prefix '%s'"
 		  " --output '%s' "
+		  " --dtb '%s' "
 		  "--format '%s' --compression '%s' %s %s\n",
 		  dir, prefix,
-		  outname, mkimage_target,
+		  outname, dtb ? : "", mkimage_target,
 		  compnames[compression], note ? "--note" : "", s);
   free (s);
 
@@ -499,7 +506,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
   grub_install_generate_image (dir, prefix, fp, outname,
 			       modules.entries, memdisk_path,
 			       pubkeys, npubkeys, config_path, tgt,
-			       note, compression);
+			       note, compression, dtb);
   while (dc--)
     grub_install_pop_module ();
 }
@@ -585,6 +592,7 @@ copy_all (const char *srcd,
   grub_util_fd_closedir (d);
 }
 
+#if !(defined (GRUB_UTIL) && defined(ENABLE_NLS) && ENABLE_NLS)
 static const char *
 get_localedir (void)
 {
@@ -639,6 +647,59 @@ copy_locales (const char *dstd)
     }
   grub_util_fd_closedir (d);
 }
+#endif
+
+static void
+grub_install_copy_nls(const char *src __attribute__ ((unused)),
+                      const char *dst __attribute__ ((unused)))
+{
+#if !(defined (GRUB_UTIL) && defined(ENABLE_NLS) && ENABLE_NLS)
+  char *dst_locale;
+
+  dst_locale = grub_util_path_concat (2, dst, "locale");
+  grub_install_mkdir_p (dst_locale);
+  clean_grub_dir (dst_locale);
+
+  if (install_locales.is_default)
+    {
+      char *srcd = grub_util_path_concat (2, src, "po");
+      copy_by_ext (srcd, dst_locale, ".mo", 0);
+      copy_locales (dst_locale);
+      free (srcd);
+    }
+  else
+    {
+      size_t i;
+      const char *locale_dir = get_localedir ();
+
+      for (i = 0; i < install_locales.n_entries; i++)
+      {
+        char *srcf = grub_util_path_concat_ext (3, src, "po",
+                                                install_locales.entries[i],
+                                                ".mo");
+        char *dstf = grub_util_path_concat_ext (2, dst_locale,
+                                                install_locales.entries[i],
+                                                ".mo");
+        if (grub_install_compress_file (srcf, dstf, 0))
+          {
+            free (srcf);
+            free (dstf);
+            continue;
+          }
+        free (srcf);
+        srcf = grub_util_path_concat_ext (4, locale_dir,
+                                          install_locales.entries[i],
+                                          "LC_MESSAGES", PACKAGE, ".mo");
+        if (grub_install_compress_file (srcf, dstf, 0) == 0)
+          grub_util_error (_("cannot find locale `%s'"),
+                           install_locales.entries[i]);
+        free (srcf);
+        free (dstf);
+      }
+    }
+  free (dst_locale);
+#endif
+}
 
 static struct
 {
@@ -666,6 +727,7 @@ static struct
     [GRUB_INSTALL_PLATFORM_ARM_EFI] =          { "arm",     "efi"       },
     [GRUB_INSTALL_PLATFORM_ARM64_EFI] =        { "arm64",   "efi"       },
     [GRUB_INSTALL_PLATFORM_ARM_UBOOT] =        { "arm",     "uboot"     },
+    [GRUB_INSTALL_PLATFORM_ARM_COREBOOT] =     { "arm",     "coreboot"  },
   }; 
 
 char *
@@ -723,7 +785,7 @@ grub_install_copy_files (const char *src,
 			 const char *dst,
 			 enum grub_install_plat platid)
 {
-  char *dst_platform, *dst_locale, *dst_fonts;
+  char *dst_platform, *dst_fonts;
   const char *pkgdatadir = grub_util_get_pkgdatadir ();
   char *themes_dir;
 
@@ -734,13 +796,12 @@ grub_install_copy_files (const char *src,
     dst_platform = grub_util_path_concat (2, dst, platform);
     free (platform);
   }
-  dst_locale = grub_util_path_concat (2, dst, "locale");
   dst_fonts = grub_util_path_concat (2, dst, "fonts");
   grub_install_mkdir_p (dst_platform);
-  grub_install_mkdir_p (dst_locale);
   clean_grub_dir (dst);
   clean_grub_dir (dst_platform);
-  clean_grub_dir (dst_locale);
+
+  grub_install_copy_nls(src, dst);
 
   if (install_modules.is_default)
     copy_by_ext (src, dst_platform, ".mod", 1);
@@ -789,50 +850,6 @@ grub_install_copy_files (const char *src,
       free (dstf);
     }
 
-  if (install_locales.is_default)
-    {
-      char *srcd = grub_util_path_concat (2, src, "po");
-      copy_by_ext (srcd, dst_locale, ".mo", 0);
-      copy_locales (dst_locale);
-      free (srcd);
-    }
-  else
-    {
-      const char *locale_dir = get_localedir ();
-
-      for (i = 0; i < install_locales.n_entries; i++)
-	{
-	  char *srcf = grub_util_path_concat_ext (3, src,
-						"po",
-						install_locales.entries[i],
-						".mo");
-	  char *dstf = grub_util_path_concat_ext (2, dst_locale,
-						install_locales.entries[i],
-						".mo");
-	  if (grub_install_compress_file (srcf, dstf, 0))
-	    {
-	      free (srcf);
-	      free (dstf);
-	      continue;
-	    }
-	  free (srcf);
-	  srcf = grub_util_path_concat_ext (4,
-						 locale_dir,
-						 install_locales.entries[i],
-						 "LC_MESSAGES",
-						 PACKAGE,
-						 ".mo");
-	  if (grub_install_compress_file (srcf, dstf, 0))
-	    {
-	      free (srcf);
-	      free (dstf);
-	      continue;
-	    }
-	  grub_util_error (_("cannot find locale `%s'"),
-			   install_locales.entries[i]);
-	}
-    }
-
   if (install_themes.is_default)
     {
       install_themes.is_default = 0;
@@ -895,7 +912,6 @@ grub_install_copy_files (const char *src,
     }
 
   free (dst_platform);
-  free (dst_locale);
   free (dst_fonts);
 }
 
diff --git a/util/grub-install.c b/util/grub-install.c
index 9074d3e9e52d2a2e215a10b2f8b3cf627ca80db3..78d0138cb0a8c891f8140f1804d68d275eb690f6 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -486,6 +486,7 @@ have_bootdev (enum grub_install_plat pl)
 
     case GRUB_INSTALL_PLATFORM_I386_QEMU:
     case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
+    case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
     case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
     case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
     case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
@@ -713,7 +714,7 @@ is_prep_partition (grub_device_t dev)
       if (grub_disk_read (dev->disk, p->offset, p->index,
 			  sizeof (gptdata), &gptdata) == 0)
 	{
-	  const grub_gpt_part_type_t template = {
+	  const grub_gpt_part_guid_t template = {
 	    grub_cpu_to_le32_compile_time (0x9e1a2d38),
 	    grub_cpu_to_le16_compile_time (0xc612),
 	    grub_cpu_to_le16_compile_time (0x4316),
@@ -911,6 +912,7 @@ main (int argc, char *argv[])
 
     case GRUB_INSTALL_PLATFORM_I386_QEMU:
     case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
+    case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
     case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
     case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
     case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
@@ -946,6 +948,7 @@ main (int argc, char *argv[])
     case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
     case GRUB_INSTALL_PLATFORM_I386_QEMU:
     case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
+    case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
     case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
     case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
     case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
@@ -1448,6 +1451,7 @@ main (int argc, char *argv[])
 		  case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
 		  case GRUB_INSTALL_PLATFORM_I386_QEMU:
 		  case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
+		  case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
 		  case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
 		  case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
 		  case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
@@ -1468,6 +1472,7 @@ main (int argc, char *argv[])
 		{
 		  grub_util_fprint_full_disk_name (load_cfg_f, g, dev);
 		  fprintf (load_cfg_f, " ");
+		  free (g);
 		}
 	      if (dev != grub_dev)
 		grub_device_close (dev);
@@ -1542,6 +1547,7 @@ main (int argc, char *argv[])
       break;
 
     case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
+    case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
     case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
     case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
     case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
@@ -1629,6 +1635,7 @@ main (int argc, char *argv[])
     case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
     case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
     case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
+    case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
     case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
     case GRUB_INSTALL_PLATFORM_I386_PC:
     case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
@@ -1841,9 +1848,13 @@ main (int argc, char *argv[])
 	  if (!removable && update_nvram)
 	    {
 	      /* Try to make this image bootable using the EFI Boot Manager, if available.  */
-	      grub_install_register_efi (efidir_grub_dev,
-					 "\\System\\Library\\CoreServices",
-					 efi_distributor);
+	      int ret;
+	      ret = grub_install_register_efi (efidir_grub_dev,
+					       "\\System\\Library\\CoreServices",
+					       efi_distributor);
+	      if (ret)
+	        grub_util_error (_("efibootmgr failed to register the boot entry: %s"),
+				 strerror (ret));
 	    }
 
 	  grub_device_close (ins_dev);
@@ -1864,6 +1875,7 @@ main (int argc, char *argv[])
 	{
 	  char * efifile_path;
 	  char * part;
+	  int ret;
 
 	  /* Try to make this image bootable using the EFI Boot Manager, if available.  */
 	  if (!efi_distributor || efi_distributor[0] == '\0')
@@ -1880,8 +1892,11 @@ main (int argc, char *argv[])
 			  efidir_grub_dev->disk->name,
 			  (part ? ",": ""), (part ? : ""));
 	  grub_free (part);
-	  grub_install_register_efi (efidir_grub_dev,
-				     efifile_path, efi_distributor);
+	  ret = grub_install_register_efi (efidir_grub_dev,
+					   efifile_path, efi_distributor);
+	  if (ret)
+	    grub_util_error (_("efibootmgr failed to register the boot entry: %s"),
+			     strerror (ret));
 	}
       break;
 
@@ -1889,6 +1904,7 @@ main (int argc, char *argv[])
     case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
     case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
     case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
+    case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
     case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
     case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
     case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
index aba19d21b9a774e63ad49f166554d90f8c667e36..98d24cc06ea57b88a4f02f38f177f44ec4f38f3f 100644
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -71,6 +71,7 @@ static struct argp_option options[] = {
    N_("embed FILE as a memdisk image\n"
       "Implies `-p (memdisk)/boot/grub' and overrides any prefix supplied previously,"
       " but the prefix itself can be overridden by later options"), 0},
+  {"dtb",  'D', N_("FILE"), 0, N_("embed FILE as a device tree (DTB)\n"), 0},
    /* TRANSLATORS: "embed" is a verb (command description).  "*/
   {"config",   'c', N_("FILE"), 0, N_("embed FILE as an early config"), 0},
    /* TRANSLATORS: "embed" is a verb (command description).  "*/
@@ -117,6 +118,7 @@ struct arguments
   char *dir;
   char *prefix;
   char *memdisk;
+  char *dtb;
   char **pubkeys;
   size_t npubkeys;
   char *font;
@@ -176,6 +178,13 @@ argp_parser (int key, char *arg, struct argp_state *state)
       arguments->prefix = xstrdup ("(memdisk)/boot/grub");
       break;
 
+    case 'D':
+      if (arguments->dtb)
+	free (arguments->dtb);
+
+      arguments->dtb = xstrdup (arg);
+      break;
+
     case 'k':
       arguments->pubkeys = xrealloc (arguments->pubkeys,
 				     sizeof (arguments->pubkeys[0])
@@ -300,7 +309,7 @@ main (int argc, char *argv[])
 			       arguments.memdisk, arguments.pubkeys,
 			       arguments.npubkeys, arguments.config,
 			       arguments.image_target, arguments.note,
-			       arguments.comp);
+			       arguments.comp, arguments.dtb);
 
   grub_util_file_sync  (fp);
   fclose (fp);
diff --git a/util/grub-mkimage32.c b/util/grub-mkimage32.c
index 9b31397bc40b95b69a1edc4f2d4c4b5d6eaa63cd..1f2ccccd225bbbb32e7e38801ddafeb90d9a69bb 100644
--- a/util/grub-mkimage32.c
+++ b/util/grub-mkimage32.c
@@ -19,4 +19,6 @@
 # define ELF_ST_TYPE(val)		ELF32_ST_TYPE(val)
 #define XEN_NOTE_SIZE 132
 
+#ifndef GRUB_MKIMAGEXX
 #include "grub-mkimagexx.c"
+#endif
diff --git a/util/grub-mkimage64.c b/util/grub-mkimage64.c
index d83345924705353b3c20a1e4dd087371ec5383ec..4ff72a625e0030d05cee0675a481b0803cda081e 100644
--- a/util/grub-mkimage64.c
+++ b/util/grub-mkimage64.c
@@ -19,4 +19,6 @@
 # define ELF_ST_TYPE(val)		ELF64_ST_TYPE(val)
 #define XEN_NOTE_SIZE 120
 
+#ifndef GRUB_MKIMAGEXX
 #include "grub-mkimagexx.c"
+#endif
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index e63f148e48cf6f66852b15063405f81371d95ae9..a483c674c4908bca02ecda73de78d04456667a37 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -50,6 +50,15 @@
 
 #pragma GCC diagnostic ignored "-Wcast-align"
 
+#define GRUB_MKIMAGEXX
+#if !defined(MKIMAGE_ELF32) && !defined(MKIMAGE_ELF64)
+#if __SIZEOF_POINTER__ == 8
+#include "grub-mkimage64.c"
+#else
+#include "grub-mkimage32.c"
+#endif
+#endif
+
 /* These structures are defined according to the CHRP binding to IEEE1275,
    "Client Program Format" section.  */
 
@@ -84,10 +93,22 @@ struct fixup_block_list
 
 #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
 
+struct section_metadata
+{
+  Elf_Half num_sections;
+  Elf_Shdr *sections;
+  Elf_Addr *addrs;
+  Elf_Addr *vaddrs;
+  Elf_Half section_entsize;
+  Elf_Shdr *symtab;
+  const char *strtab;
+};
+
 static int
 is_relocatable (const struct grub_install_image_target_desc *image_target)
 {
-  return image_target->id == IMAGE_EFI || image_target->id == IMAGE_UBOOT;
+  return image_target->id == IMAGE_EFI || image_target->id == IMAGE_UBOOT
+    || (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM);
 }
 
 #ifdef MKIMAGE_ELF32
@@ -185,8 +206,8 @@ grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
 void
 SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
 				    int note, char **core_img, size_t *core_size,
-				    Elf_Addr target_addr, grub_size_t align,
-				    size_t kernel_size, size_t bss_size)
+				    Elf_Addr target_addr,
+				    struct grub_mkimage_layout *layout)
 {
   char *elf_img;
   size_t program_size;
@@ -214,7 +235,7 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
       footer_size += XEN_NOTE_SIZE;
     }
   header_size = ALIGN_UP (sizeof (*ehdr) + phnum * sizeof (*phdr)
-			  + shnum * sizeof (*shdr) + string_size, align);
+			  + shnum * sizeof (*shdr) + string_size, layout->align);
 
   program_size = ALIGN_ADDR (*core_size);
 
@@ -258,7 +279,8 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
   ehdr->e_entry = grub_host_to_target32 (target_addr);
   phdr->p_vaddr = grub_host_to_target32 (target_addr);
   phdr->p_paddr = grub_host_to_target32 (target_addr);
-  phdr->p_align = grub_host_to_target32 (align > image_target->link_align ? align : image_target->link_align);
+  phdr->p_align = grub_host_to_target32 (layout->align > image_target->link_align ?
+					 layout->align : image_target->link_align);
   if (image_target->id == IMAGE_LOONGSON_ELF)
     ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER 
 					   | EF_MIPS_PIC | EF_MIPS_CPIC);
@@ -272,27 +294,34 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
   else
     {
       grub_uint32_t target_addr_mods;
-      phdr->p_filesz = grub_host_to_target32 (kernel_size);
-      phdr->p_memsz = grub_host_to_target32 (kernel_size + bss_size);
+      phdr->p_filesz = grub_host_to_target32 (layout->kernel_size);
+      if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
+	phdr->p_memsz = grub_host_to_target32 (layout->kernel_size);
+      else
+	phdr->p_memsz = grub_host_to_target32 (layout->kernel_size + layout->bss_size);
 
       phdr++;
       phdr->p_type = grub_host_to_target32 (PT_GNU_STACK);
-      phdr->p_offset = grub_host_to_target32 (header_size + kernel_size);
+      phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
       phdr->p_paddr = phdr->p_vaddr = phdr->p_filesz = phdr->p_memsz = 0;
       phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
       phdr->p_align = grub_host_to_target32 (image_target->link_align);
 
       phdr++;
       phdr->p_type = grub_host_to_target32 (PT_LOAD);
-      phdr->p_offset = grub_host_to_target32 (header_size + kernel_size);
+      phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
       phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
       phdr->p_filesz = phdr->p_memsz
-	= grub_host_to_target32 (*core_size - kernel_size);
+	= grub_host_to_target32 (*core_size - layout->kernel_size);
 
-      if (image_target->id == IMAGE_COREBOOT)
+      if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_386)
 	target_addr_mods = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR;
+      else if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
+	target_addr_mods = ALIGN_UP (target_addr + layout->end
+				     + image_target->mod_gap,
+				     image_target->mod_align);
       else
-	target_addr_mods = ALIGN_UP (target_addr + kernel_size + bss_size
+	target_addr_mods = ALIGN_UP (target_addr + layout->kernel_size + layout->bss_size
 				     + image_target->mod_gap,
 				     image_target->mod_align);
       phdr->p_vaddr = grub_host_to_target_addr (target_addr_mods);
@@ -434,7 +463,7 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
     shdr->sh_size = grub_host_to_target32 (string_size);
     shdr->sh_link = grub_host_to_target32 (0);
     shdr->sh_info = grub_host_to_target32 (0);
-    shdr->sh_addralign = grub_host_to_target32 (align);
+    shdr->sh_addralign = grub_host_to_target32 (layout->align);
     shdr->sh_entsize = grub_host_to_target32 (0);
     shdr++;
 
@@ -445,10 +474,10 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
     shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
     shdr->sh_addr = grub_host_to_target_addr (target_addr);
     shdr->sh_offset = grub_host_to_target_addr (header_size);
-    shdr->sh_size = grub_host_to_target32 (kernel_size);
+    shdr->sh_size = grub_host_to_target32 (layout->kernel_size);
     shdr->sh_link = grub_host_to_target32 (0);
     shdr->sh_info = grub_host_to_target32 (0);
-    shdr->sh_addralign = grub_host_to_target32 (align);
+    shdr->sh_addralign = grub_host_to_target32 (layout->align);
     shdr->sh_entsize = grub_host_to_target32 (0);
     shdr++;
 
@@ -456,9 +485,9 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
     shdr->sh_name = grub_host_to_target32 (ptr - str_start);
     ptr += sizeof ("mods");
     shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
-    shdr->sh_addr = grub_host_to_target_addr (target_addr + kernel_size);
-    shdr->sh_offset = grub_host_to_target_addr (header_size + kernel_size);
-    shdr->sh_size = grub_host_to_target32 (*core_size - kernel_size);
+    shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
+    shdr->sh_offset = grub_host_to_target_addr (header_size + layout->kernel_size);
+    shdr->sh_size = grub_host_to_target32 (*core_size - layout->kernel_size);
     shdr->sh_link = grub_host_to_target32 (0);
     shdr->sh_info = grub_host_to_target32 (0);
     shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
@@ -471,7 +500,7 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
 	shdr->sh_name = grub_host_to_target32 (ptr - str_start);
 	ptr += sizeof (".xen");
 	shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
-	shdr->sh_addr = grub_host_to_target_addr (target_addr + kernel_size);
+	shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
 	shdr->sh_offset = grub_host_to_target_addr (program_size + header_size);
 	shdr->sh_size = grub_host_to_target32 (XEN_NOTE_SIZE);
 	shdr->sh_link = grub_host_to_target32 (0);
@@ -490,9 +519,7 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
 /* Relocate symbols; note that this function overwrites the symbol table.
    Return the address of a start symbol.  */
 static Elf_Addr
-SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
-			   Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
-			   Elf_Half section_entsize, Elf_Half num_sections,
+SUFFIX (relocate_symbols) (Elf_Ehdr *e, struct section_metadata *smd,
 			   void *jumpers, Elf_Addr jumpers_addr,
 			   Elf_Addr bss_start, Elf_Addr end,
 			   const struct grub_install_image_target_desc *image_target)
@@ -502,19 +529,18 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
   Elf_Addr start_address = (Elf_Addr) -1;
   Elf_Sym *sym;
   Elf_Word i;
-  Elf_Shdr *strtab_section;
-  const char *strtab;
+  Elf_Shdr *symtab_section;
+  const char *symtab;
   grub_uint64_t *jptr = jumpers;
 
-  strtab_section
-    = (Elf_Shdr *) ((char *) sections
-		      + (grub_target_to_host32 (symtab_section->sh_link)
-			 * section_entsize));
-  strtab = (char *) e + grub_target_to_host (strtab_section->sh_offset);
+  symtab_section = (Elf_Shdr *) ((char *) smd->sections
+				 + grub_target_to_host32 (smd->symtab->sh_link)
+				   * smd->section_entsize);
+  symtab = (char *) e + grub_target_to_host (symtab_section->sh_offset);
 
-  symtab_size = grub_target_to_host (symtab_section->sh_size);
-  sym_size = grub_target_to_host (symtab_section->sh_entsize);
-  symtab_offset = grub_target_to_host (symtab_section->sh_offset);
+  symtab_size = grub_target_to_host (smd->symtab->sh_size);
+  sym_size = grub_target_to_host (smd->symtab->sh_entsize);
+  symtab_offset = grub_target_to_host (smd->symtab->sh_offset);
   num_syms = symtab_size / sym_size;
 
   for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
@@ -524,7 +550,7 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
       Elf_Section cur_index;
       const char *name;
 
-      name = strtab + grub_target_to_host32 (sym->st_name);
+      name = symtab + grub_target_to_host32 (sym->st_name);
 
       cur_index = grub_target_to_host16 (sym->st_shndx);
       if (cur_index == STN_ABS)
@@ -542,12 +568,12 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
 	  else
 	    continue;
 	}
-      else if (cur_index >= num_sections)
+      else if (cur_index >= smd->num_sections)
 	grub_util_error ("section %d does not exist", cur_index);
       else
 	{
 	  sym->st_value = (grub_target_to_host (sym->st_value)
-			   + section_addresses[cur_index]);
+			   + smd->vaddrs[cur_index]);
 	}
 
       if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
@@ -562,7 +588,7 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
       grub_util_info ("locating %s at 0x%"  GRUB_HOST_PRIxLONG_LONG
 		      " (0x%"  GRUB_HOST_PRIxLONG_LONG ")", name,
 		      (unsigned long long) sym->st_value,
-		      (unsigned long long) section_addresses[cur_index]);
+		      (unsigned long long) smd->vaddrs[cur_index]);
 
       if (start_address == (Elf_Addr)-1)
 	if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
@@ -699,17 +725,19 @@ arm_get_trampoline_size (Elf_Ehdr *e,
 }
 #endif
 
+static int
+SUFFIX (is_kept_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target);
+static int
+SUFFIX (is_kept_reloc_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target,
+				struct section_metadata *smd);
+
 /* Deal with relocation information. This function relocates addresses
    within the virtual address space starting from 0. So only relative
    addresses can be fully resolved. Absolute addresses must be relocated
    again by a PE32 relocator when loaded.  */
 static void
-SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
-			     Elf_Addr *section_addresses,
-			     Elf_Half section_entsize, Elf_Half num_sections,
-			     const char *strtab,
-			     char *pe_target, Elf_Addr tramp_off,
-			     Elf_Addr got_off,
+SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd,
+			     char *pe_target, Elf_Addr tramp_off, Elf_Addr got_off,
 			     const struct grub_install_image_target_desc *image_target)
 {
   Elf_Half i;
@@ -723,33 +751,37 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
   grub_uint32_t *tr = (void *) (pe_target + tramp_off);
 #endif
 
-  for (i = 0, s = sections;
-       i < num_sections;
-       i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+  for (i = 0, s = smd->sections;
+       i < smd->num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
     if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
         (s->sh_type == grub_host_to_target32 (SHT_RELA)))
       {
 	Elf_Rela *r;
 	Elf_Word rtab_size, r_size, num_rs;
 	Elf_Off rtab_offset;
-	Elf_Shdr *symtab_section;
 	Elf_Word target_section_index;
 	Elf_Addr target_section_addr;
 	Elf_Shdr *target_section;
 	Elf_Word j;
 
-	symtab_section = (Elf_Shdr *) ((char *) sections
-					 + (grub_target_to_host32 (s->sh_link)
-					    * section_entsize));
+	if (!SUFFIX (is_kept_section) (s, image_target) &&
+	    !SUFFIX (is_kept_reloc_section) (s, image_target, smd))
+	  {
+	    grub_util_info ("not translating relocations for omitted section %s",
+			smd->strtab + grub_le_to_cpu32 (s->sh_name));
+	    continue;
+	  }
+
 	target_section_index = grub_target_to_host32 (s->sh_info);
-	target_section_addr = section_addresses[target_section_index];
-	target_section = (Elf_Shdr *) ((char *) sections
+	target_section_addr = smd->addrs[target_section_index];
+	target_section = (Elf_Shdr *) ((char *) smd->sections
 					 + (target_section_index
-					    * section_entsize));
+					    * smd->section_entsize));
 
 	grub_util_info ("dealing with the relocation section %s for %s",
-			strtab + grub_target_to_host32 (s->sh_name),
-			strtab + grub_target_to_host32 (target_section->sh_name));
+			smd->strtab + grub_target_to_host32 (s->sh_name),
+			smd->strtab + grub_target_to_host32 (target_section->sh_name));
 
 	rtab_size = grub_target_to_host (s->sh_size);
 	r_size = grub_target_to_host (s->sh_entsize);
@@ -770,7 +802,7 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
 	    target = SUFFIX (get_target_address) (e, target_section,
 						  offset, image_target);
 	    info = grub_target_to_host (r->r_info);
-	    sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
+	    sym_addr = SUFFIX (get_symbol_address) (e, smd->symtab,
 						    ELF_R_SYM (info), image_target);
 
             addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
@@ -832,6 +864,7 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
 		  break;
 
 		case R_X86_64_PC32:
+		case R_X86_64_PLT32:
 		  {
 		    grub_uint32_t *t32 = (grub_uint32_t *) target;
 		    *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
@@ -900,8 +933,8 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
 		    Elf_Sym *sym;
 
 		    sym = (Elf_Sym *) ((char *) e
-				       + grub_target_to_host (symtab_section->sh_offset)
-				       + ELF_R_SYM (info) * grub_target_to_host (symtab_section->sh_entsize));
+				       + grub_target_to_host (smd->symtab->sh_offset)
+				       + ELF_R_SYM (info) * grub_target_to_host (smd->symtab->sh_entsize));
 		    if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
 		      sym_addr = grub_target_to_host64 (*(grub_uint64_t *) (pe_target
 									    + sym->st_value
@@ -1086,8 +1119,8 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
 							- (char *) e),
 				       sym_addr);
 		       sym = (Elf_Sym *) ((char *) e
-					  + grub_target_to_host (symtab_section->sh_offset)
-					  + ELF_R_SYM (info) * grub_target_to_host (symtab_section->sh_entsize));
+					  + grub_target_to_host (smd->symtab->sh_offset)
+					  + ELF_R_SYM (info) * grub_target_to_host (smd->symtab->sh_entsize));
 		       if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
 			 sym_addr |= 1;
 		       if (!(sym_addr & 1))
@@ -1625,9 +1658,7 @@ create_u64_fixups (struct translate_context *ctx,
 /* Make a .reloc section.  */
 static void
 make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
-		    Elf_Addr *section_addresses, Elf_Shdr *sections,
-		    Elf_Half section_entsize, Elf_Half num_sections,
-		    const char *strtab,
+		    struct section_metadata *smd,
 		    const struct grub_install_image_target_desc *image_target)
 {
   unsigned i;
@@ -1636,8 +1667,8 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
 
   translate_reloc_start (&ctx, image_target);
 
-  for (i = 0, s = sections; i < num_sections;
-       i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+  for (i = 0, s = smd->sections; i < smd->num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
     if ((grub_target_to_host32 (s->sh_type) == SHT_REL) ||
         (grub_target_to_host32 (s->sh_type) == SHT_RELA))
       {
@@ -1647,15 +1678,22 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
 	Elf_Addr section_address;
 	Elf_Word j;
 
+	if (!SUFFIX (is_kept_reloc_section) (s, image_target, smd))
+	  {
+	    grub_util_info ("not translating the skipped relocation section %s",
+			    smd->strtab + grub_le_to_cpu32 (s->sh_name));
+	    continue;
+	  }
+
 	grub_util_info ("translating the relocation section %s",
-			strtab + grub_le_to_cpu32 (s->sh_name));
+			smd->strtab + grub_le_to_cpu32 (s->sh_name));
 
 	rtab_size = grub_target_to_host (s->sh_size);
 	r_size = grub_target_to_host (s->sh_entsize);
 	rtab_offset = grub_target_to_host (s->sh_offset);
 	num_rs = rtab_size / r_size;
 
-	section_address = section_addresses[grub_le_to_cpu32 (s->sh_info)];
+	section_address = smd->vaddrs[grub_le_to_cpu32 (s->sh_info)];
 
 	for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
 	     j < num_rs;
@@ -1722,6 +1760,56 @@ SUFFIX (is_bss_section) (Elf_Shdr *s, const struct grub_install_image_target_des
 	  == SHF_ALLOC) && (grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
 }
 
+/* Determine if a section is going to be in the final output */
+static int
+SUFFIX (is_kept_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
+{
+  /* We keep .text and .data */
+  if (SUFFIX (is_text_section) (s, image_target)
+      || SUFFIX (is_data_section) (s, image_target))
+    return 1;
+
+  /*
+   * And we keep .bss if we're producing PE binaries or the target doesn't
+   * have a relocating loader.  Platforms other than EFI and U-boot shouldn't
+   * have .bss in their binaries as we build with -Wl,-Ttext.
+   */
+  if (SUFFIX (is_bss_section) (s, image_target)
+      && (image_target->id == IMAGE_EFI || !is_relocatable (image_target)))
+    return 1;
+
+  /* Otherwise this is not a section we're keeping in the final output. */
+  return 0;
+}
+
+static int
+SUFFIX (is_kept_reloc_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target,
+				struct section_metadata *smd)
+{
+  int i;
+  int r = 0;
+  const char *name = smd->strtab + grub_host_to_target32 (s->sh_name);
+
+  if (!strncmp (name, ".rela.", 6))
+    name += 5;
+  else if (!strncmp (name, ".rel.", 5))
+    name += 4;
+  else
+    return 1;
+
+  for (i = 0, s = smd->sections; i < smd->num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
+    {
+      const char *sname = smd->strtab + grub_host_to_target32 (s->sh_name);
+      if (strcmp (sname, name))
+	continue;
+
+      return SUFFIX (is_kept_section) (s, image_target);
+    }
+
+  return r;
+}
+
 /* Return if the ELF header is valid.  */
 static int
 SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_image_target_desc *image_target)
@@ -1742,12 +1830,11 @@ SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_i
 static Elf_Addr
 SUFFIX (put_section) (Elf_Shdr *s, int i,
 		      Elf_Addr current_address,
-		      Elf_Addr *section_addresses,
-		      const char *strtab,
+		      struct section_metadata *smd,
 		      const struct grub_install_image_target_desc *image_target)
 {
 	Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
-	const char *name = strtab + grub_host_to_target32 (s->sh_name);
+	const char *name = smd->strtab + grub_host_to_target32 (s->sh_name);
 
 	if (align)
 	  current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
@@ -1759,24 +1846,23 @@ SUFFIX (put_section) (Elf_Shdr *s, int i,
 			name, (unsigned long long) current_address);
 	if (!is_relocatable (image_target))
 	  current_address = grub_host_to_target_addr (s->sh_addr)
-	    - image_target->link_addr;
-	section_addresses[i] = current_address;
+			    - image_target->link_addr;
+	smd->addrs[i] = current_address;
 	current_address += grub_host_to_target_addr (s->sh_size);
 	return current_address;
 }
 
-/* Locate section addresses by merging code sections and data sections
-   into .text and .data, respectively. Return the array of section
-   addresses.  */
-static Elf_Addr *
+/*
+ * Locate section addresses by merging code sections and data sections
+ * into .text and .data, respectively.
+ */
+static void
 SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
-			  Elf_Shdr *sections, Elf_Half section_entsize,
-			  Elf_Half num_sections, const char *strtab,
+			  struct section_metadata *smd,
 			  struct grub_mkimage_layout *layout,
 			  const struct grub_install_image_target_desc *image_target)
 {
   int i;
-  Elf_Addr *section_addresses;
   Elf_Shdr *s;
 
   layout->align = 1;
@@ -1784,30 +1870,23 @@ SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
   if (image_target->elf_target == EM_AARCH64)
     layout->align = 4096;
 
-  section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
-  memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
-
   layout->kernel_size = 0;
 
-  for (i = 0, s = sections;
-       i < num_sections;
-       i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
-    if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC) 
+  for (i = 0, s = smd->sections;
+       i < smd->num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
+    if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)
 	&& grub_host_to_target32 (s->sh_addralign) > layout->align)
       layout->align = grub_host_to_target32 (s->sh_addralign);
 
-
   /* .text */
-  for (i = 0, s = sections;
-       i < num_sections;
-       i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+  for (i = 0, s = smd->sections;
+       i < smd->num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
     if (SUFFIX (is_text_section) (s, image_target))
       {
-	layout->kernel_size = SUFFIX (put_section) (s, i,
-						layout->kernel_size,
-						section_addresses,
-						strtab,
-						image_target);
+	layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size,
+						smd, image_target);
 	if (!is_relocatable (image_target) &&
 	    grub_host_to_target_addr (s->sh_addr) != image_target->link_addr)
 	  {
@@ -1827,15 +1906,12 @@ SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
   layout->exec_size = layout->kernel_size;
 
   /* .data */
-  for (i = 0, s = sections;
-       i < num_sections;
-       i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+  for (i = 0, s = smd->sections;
+       i < smd->num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
     if (SUFFIX (is_data_section) (s, image_target))
-      layout->kernel_size = SUFFIX (put_section) (s, i,
-					      layout->kernel_size,
-					      section_addresses,
-					      strtab,
-					      image_target);
+      layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size, smd,
+						  image_target);
 
 #ifdef MKIMAGE_ELF32
   if (image_target->elf_target == EM_ARM)
@@ -1846,8 +1922,8 @@ SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
 
       layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
 
-      tramp = arm_get_trampoline_size (e, sections, section_entsize,
-				       num_sections, image_target);
+      tramp = arm_get_trampoline_size (e, smd->sections, smd->section_entsize,
+				       smd->num_sections, image_target);
 
       layout->tramp_off = layout->kernel_size;
       layout->kernel_size += ALIGN_UP (tramp, 16);
@@ -1858,15 +1934,18 @@ SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
   layout->end = layout->kernel_size;
   
   /* .bss */
-  for (i = 0, s = sections;
-       i < num_sections;
-       i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
-    if (SUFFIX (is_bss_section) (s, image_target))
-      layout->end = SUFFIX (put_section) (s, i,
-					  layout->end,
-					  section_addresses,
-					  strtab,
-					  image_target);
+  for (i = 0, s = smd->sections;
+       i < smd->num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
+    {
+      if (SUFFIX (is_bss_section) (s, image_target))
+	layout->end = SUFFIX (put_section) (s, i, layout->end, smd, image_target);
+
+      /*
+       * This must to be in the last time this function passes through the loop.
+       */
+      smd->vaddrs[i] = smd->addrs[i] + image_target->vaddr_offset;
+    }
 
   layout->end = ALIGN_UP (layout->end + image_target->vaddr_offset,
 			      image_target->section_align) - image_target->vaddr_offset;
@@ -1875,10 +1954,8 @@ SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
      Platforms other than EFI and U-boot shouldn't have .bss in
      their binaries as we build with -Wl,-Ttext.
   */
-  if (image_target->id != IMAGE_UBOOT)
+  if (image_target->id == IMAGE_EFI || !is_relocatable (image_target))
     layout->kernel_size = layout->end;
-
-  return section_addresses;
 }
 
 char *
@@ -1888,18 +1965,12 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
 				  const struct grub_install_image_target_desc *image_target)
 {
   char *kernel_img, *out_img;
-  const char *strtab;
+  struct section_metadata smd = { 0, 0, 0, 0, 0, 0, 0 };
   Elf_Ehdr *e;
-  Elf_Shdr *sections;
-  Elf_Addr *section_addresses;
-  Elf_Addr *section_vaddresses;
   int i;
   Elf_Shdr *s;
-  Elf_Half num_sections;
   Elf_Off section_offset;
-  Elf_Half section_entsize;
   grub_size_t kernel_size;
-  Elf_Shdr *symtab_section = 0;
 
   grub_memset (layout, 0, sizeof (*layout));
 
@@ -1914,48 +1985,45 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
     grub_util_error ("invalid ELF header");
 
   section_offset = grub_target_to_host (e->e_shoff);
-  section_entsize = grub_target_to_host16 (e->e_shentsize);
-  num_sections = grub_target_to_host16 (e->e_shnum);
+  smd.section_entsize = grub_target_to_host16 (e->e_shentsize);
+  smd.num_sections = grub_target_to_host16 (e->e_shnum);
 
-  if (kernel_size < section_offset + (grub_uint32_t) section_entsize * num_sections)
+  if (kernel_size < section_offset
+		    + (grub_uint32_t) smd.section_entsize * smd.num_sections)
     grub_util_error (_("premature end of file %s"), kernel_path);
 
-  sections = (Elf_Shdr *) (kernel_img + section_offset);
+  smd.sections = (Elf_Shdr *) (kernel_img + section_offset);
 
   /* Relocate sections then symbols in the virtual address space.  */
-  s = (Elf_Shdr *) ((char *) sections
-		      + grub_host_to_target16 (e->e_shstrndx) * section_entsize);
-  strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
+  s = (Elf_Shdr *) ((char *) smd.sections
+		      + grub_host_to_target16 (e->e_shstrndx) * smd.section_entsize);
+  smd.strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
 
-  section_addresses = SUFFIX (locate_sections) (e, kernel_path,
-						sections, section_entsize,
-						num_sections, strtab,
-						layout,
-						image_target);
+  smd.addrs = xmalloc (sizeof (*smd.addrs) * smd.num_sections);
+  memset (smd.addrs, 0, sizeof (*smd.addrs) * smd.num_sections);
+  smd.vaddrs = xmalloc (sizeof (*smd.vaddrs) * smd.num_sections);
+  memset (smd.vaddrs, 0, sizeof (*smd.vaddrs) * smd.num_sections);
 
-  section_vaddresses = xmalloc (sizeof (*section_addresses) * num_sections);
-
-  for (i = 0; i < num_sections; i++)
-    section_vaddresses[i] = section_addresses[i] + image_target->vaddr_offset;
+  SUFFIX (locate_sections) (e, kernel_path, &smd, layout, image_target);
 
   if (!is_relocatable (image_target))
     {
       Elf_Addr current_address = layout->kernel_size;
 
-      for (i = 0, s = sections;
-	   i < num_sections;
-	   i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+      for (i = 0, s = smd.sections;
+	   i < smd.num_sections;
+	   i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
 	if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
 	  {
 	    Elf_Word sec_align = grub_host_to_target_addr (s->sh_addralign);
-	    const char *name = strtab + grub_host_to_target32 (s->sh_name);
+	    const char *name = smd.strtab + grub_host_to_target32 (s->sh_name);
 
 	    if (sec_align)
 	      current_address = ALIGN_UP (current_address
 					  + image_target->vaddr_offset,
 					  sec_align)
 		- image_target->vaddr_offset;
-	
+
 	    grub_util_info ("locating the section %s at 0x%"
 			    GRUB_HOST_PRIxLONG_LONG,
 			    name, (unsigned long long) current_address);
@@ -1963,7 +2031,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
 	      current_address = grub_host_to_target_addr (s->sh_addr)
 		- image_target->link_addr;
 
-	    section_vaddresses[i] = current_address
+	    smd.vaddrs[i] = current_address
 	      + image_target->vaddr_offset;
 	    current_address += grub_host_to_target_addr (s->sh_size);
 	  }
@@ -1978,21 +2046,22 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
   if (image_target->id == IMAGE_SPARC64_AOUT
       || image_target->id == IMAGE_SPARC64_RAW
       || image_target->id == IMAGE_UBOOT
+      || image_target->id == IMAGE_COREBOOT
       || image_target->id == IMAGE_SPARC64_CDCORE)
     layout->kernel_size = ALIGN_UP (layout->kernel_size, image_target->mod_align);
 
   if (is_relocatable (image_target))
     {
-      symtab_section = NULL;
-      for (i = 0, s = sections;
-	   i < num_sections;
-	   i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+      smd.symtab = NULL;
+      for (i = 0, s = smd.sections;
+	   i < smd.num_sections;
+	   i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
 	if (s->sh_type == grub_host_to_target32 (SHT_SYMTAB))
 	  {
-	    symtab_section = s;
+	    smd.symtab = s;
 	    break;
 	  }
-      if (! symtab_section)
+      if (! smd.symtab)
 	grub_util_error ("%s", _("no symbol table"));
 #ifdef MKIMAGE_ELF64
       if (image_target->elf_target == EM_IA_64)
@@ -2007,7 +2076,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
 	  layout->kernel_size += ALIGN_UP (tramp, 16);
 
 	  layout->ia64jmp_off = layout->kernel_size;
-	  layout->ia64jmpnum = SUFFIX (count_funcs) (e, symtab_section,
+	  layout->ia64jmpnum = SUFFIX (count_funcs) (e, smd.symtab,
 						     image_target);
 	  layout->kernel_size += 16 * layout->ia64jmpnum;
 
@@ -2038,31 +2107,19 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
 
   if (is_relocatable (image_target))
     {
-      layout->start_address = SUFFIX (relocate_symbols) (e, sections, symtab_section,
-					  section_vaddresses, section_entsize,
-					  num_sections, 
-					  (char *) out_img + layout->ia64jmp_off, 
-					  layout->ia64jmp_off 
-					  + image_target->vaddr_offset,
-							 layout->bss_start,
-							 layout->end,
-					  image_target);
+      layout->start_address = SUFFIX (relocate_symbols) (e, &smd,
+				  (char *) out_img + layout->ia64jmp_off,
+				  layout->ia64jmp_off + image_target->vaddr_offset,
+				  layout->bss_start, layout->end, image_target);
+
       if (layout->start_address == (Elf_Addr) -1)
 	grub_util_error ("start symbol is not defined");
 
-      /* Resolve addresses in the virtual address space.  */
-      SUFFIX (relocate_addresses) (e, sections, section_addresses, 
-				   section_entsize,
-				   num_sections, strtab,
-				   out_img, layout->tramp_off,
-				   layout->got_off,
-				   image_target);
+      /* Resolve addrs in the virtual address space.  */
+      SUFFIX (relocate_addrs) (e, &smd, out_img, layout->tramp_off,
+				   layout->got_off, image_target);
 
-      make_reloc_section (e, layout,
-			  section_vaddresses, sections,
-			  section_entsize, num_sections,
-			  strtab,
-			  image_target);
+      make_reloc_section (e, layout, &smd, image_target);
       if (image_target->id != IMAGE_EFI)
 	{
 	  out_img = xrealloc (out_img, layout->kernel_size + total_module_size
@@ -2074,30 +2131,25 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
 	}
     }
 
-  for (i = 0, s = sections;
-       i < num_sections;
-       i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
-    if (SUFFIX (is_data_section) (s, image_target)
-	/* Explicitly initialize BSS
-	   when producing PE32 to avoid a bug in EFI implementations.
-	   Platforms other than EFI and U-boot shouldn't have .bss in
-	   their binaries as we build with -Wl,-Ttext.
-	*/
-	|| (SUFFIX (is_bss_section) (s, image_target) && (image_target->id != IMAGE_UBOOT))
-	|| SUFFIX (is_text_section) (s, image_target))
+  for (i = 0, s = smd.sections;
+       i < smd.num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
+    if (SUFFIX (is_kept_section) (s, image_target))
       {
 	if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
-	  memset (out_img + section_addresses[i], 0,
+	  memset (out_img + smd.addrs[i], 0,
 		  grub_host_to_target_addr (s->sh_size));
 	else
-	  memcpy (out_img + section_addresses[i],
+	  memcpy (out_img + smd.addrs[i],
 		  kernel_img + grub_host_to_target_addr (s->sh_offset),
 		  grub_host_to_target_addr (s->sh_size));
       }
   free (kernel_img);
 
-  free (section_vaddresses);
-  free (section_addresses);
+  free (smd.vaddrs);
+  smd.vaddrs = NULL;
+  free (smd.addrs);
+  smd.addrs = NULL;
 
   return out_img;
 }
diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c
index 238d4840e2f9613c6392e16cb88e7f413cae41c4..9545945d8f3b1a85dea8404fe1a0c9b3a3b84ba1 100644
--- a/util/grub-mkrescue.c
+++ b/util/grub-mkrescue.c
@@ -323,6 +323,7 @@ check_xorriso (const char *val)
   char *buf = NULL;
   size_t len = 0;
   int ret = 0;
+  int wstatus = 0;
 
   argv[0] = xorriso;
   argv[1] = "-as";
@@ -347,8 +348,10 @@ check_xorriso (const char *val)
     }
 
   close (fd);
-  waitpid (pid, NULL, 0);
+  waitpid (pid, &wstatus, 0);
   free (buf);
+  if (!WIFEXITED (wstatus) || WEXITSTATUS(wstatus) != 0)
+    return 0;
   return ret;
 }
 
@@ -426,6 +429,7 @@ main (int argc, char *argv[])
   char **argp_argv;
   int xorriso_tail_argc;
   char **xorriso_tail_argv;
+  int rv;
 
   grub_util_host_init (&argc, &argv);
   grub_util_disable_fd_syncs ();
@@ -478,6 +482,10 @@ main (int argc, char *argv[])
   if (!output_image)
     grub_util_error ("%s", _("output file must be specified"));
 
+  if (!check_xorriso ("graft-points")) {
+    grub_util_error ("%s", _("xorriso not found"));
+  }
+
   grub_init_all ();
   grub_hostfs_init ();
   grub_host_init ();
@@ -787,7 +795,6 @@ main (int argc, char *argv[])
       free (efidir_efi_boot);
 
       efiimgfat = grub_util_path_concat (2, iso9660_dir, "efi.img");
-      int rv;
       rv = grub_util_exec ((const char * []) { "mformat", "-C", "-f", "2880", "-L", "16", "-i",
 	    efiimgfat, "::", NULL });
       if (rv != 0)
@@ -960,7 +967,9 @@ main (int argc, char *argv[])
 
   xorriso_argv[xorriso_argc] = NULL;
 
-  grub_util_exec ((const char *const *)xorriso_argv);
+  rv = grub_util_exec ((const char *const *)xorriso_argv);
+  if (rv != 0)
+    grub_util_error ("`%s` invocation failed\n", "xorriso");
 
   grub_util_unlink_recursive (iso9660_dir);
 
diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c
index 9179285a5ffe5d641a4c2726ce8367dba623d29e..a79271f663166f4d302e1f73d1bcd400c9e8604e 100644
--- a/util/grub-module-verifier.c
+++ b/util/grub-module-verifier.c
@@ -19,6 +19,7 @@ struct grub_module_verifier_arch archs[] = {
       -1
     }, (int[]){
       R_X86_64_PC32,
+      R_X86_64_PLT32,
       -1
     }
   },
diff --git a/util/grub-probe.c b/util/grub-probe.c
index 8ac527d2f2a17142c5cf873d27c5818477d2c1a4..e45dbf9e049bd41f3122793330b2d0f7bcc844f8 100644
--- a/util/grub-probe.c
+++ b/util/grub-probe.c
@@ -28,6 +28,7 @@
 #include <grub/partition.h>
 #include <grub/msdos_partition.h>
 #include <grub/gpt_partition.h>
+#include <grub/i386/pc/boot.h>
 #include <grub/emu/hostdisk.h>
 #include <grub/emu/getroot.h>
 #include <grub/term.h>
@@ -62,6 +63,7 @@ enum {
   PRINT_DRIVE,
   PRINT_DEVICE,
   PRINT_PARTMAP,
+  PRINT_PARTUUID,
   PRINT_ABSTRACTION,
   PRINT_CRYPTODISK_UUID,
   PRINT_HINT_STR,
@@ -85,6 +87,7 @@ static const char *targets[] =
     [PRINT_DRIVE]              = "drive",
     [PRINT_DEVICE]             = "device",
     [PRINT_PARTMAP]            = "partmap",
+    [PRINT_PARTUUID]           = "partuuid",
     [PRINT_ABSTRACTION]        = "abstraction",
     [PRINT_CRYPTODISK_UUID]    = "cryptodisk_uuid",
     [PRINT_HINT_STR]           = "hints_string",
@@ -129,6 +132,20 @@ get_targets_string (void)
   return str;
 }
 
+static int
+print_gpt_guid (grub_gpt_part_guid_t guid)
+{
+  guid.data1 = grub_le_to_cpu32 (guid.data1);
+  guid.data2 = grub_le_to_cpu16 (guid.data2);
+  guid.data3 = grub_le_to_cpu16 (guid.data3);
+
+  return grub_printf ("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+		      guid.data1, guid.data2, guid.data3, guid.data4[0],
+		      guid.data4[1], guid.data4[2], guid.data4[3],
+		      guid.data4[4], guid.data4[5], guid.data4[6],
+		      guid.data4[7]);
+}
+
 static void
 do_print (const char *x, void *data)
 {
@@ -167,6 +184,45 @@ probe_partmap (grub_disk_t disk, char delim)
     }
 }
 
+static void
+probe_partuuid (grub_disk_t disk, char delim)
+{
+  grub_partition_t p = disk->partition;
+
+  /*
+   * Nested partitions not supported for now.
+   * Non-nested partitions must have disk->partition->parent == NULL
+   */
+  if (p && p->parent == NULL)
+    {
+      disk->partition = p->parent;
+
+      if (strcmp(p->partmap->name, "msdos") == 0)
+	{
+	    /*
+	     * The partition GUID for MSDOS is the partition number (starting
+	     * with 1) prepended with the NT disk signature.
+	     */
+	    grub_uint32_t nt_disk_sig;
+
+	    if (grub_disk_read (disk, 0, GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC,
+				sizeof(nt_disk_sig), &nt_disk_sig) == 0)
+	      grub_printf ("%08x-%02x",
+			   grub_le_to_cpu32(nt_disk_sig), 1 + p->number);
+	}
+      else if (strcmp(p->partmap->name, "gpt") == 0)
+	{
+	  struct grub_gpt_partentry gptdata;
+
+	  if (grub_disk_read (disk, p->offset, p->index,
+			      sizeof(gptdata), &gptdata) == 0)
+	    print_gpt_guid(gptdata.guid);
+	}
+
+      disk->partition = p;
+    }
+}
+
 static void
 probe_cryptodisk_uuid (grub_disk_t disk, char delim)
 {
@@ -621,6 +677,12 @@ probe (const char *path, char **device_names, char delim)
 	/* Check if dev->disk itself is contained in a partmap.  */
 	probe_partmap (dev->disk, delim);
 
+      else if (print == PRINT_PARTUUID)
+	{
+	  probe_partuuid (dev->disk, delim);
+	  putchar (delim);
+	}
+
       else if (print == PRINT_MSDOS_PARTTYPE)
 	{
 	  if (dev->disk->partition
@@ -641,21 +703,7 @@ probe (const char *path, char **device_names, char delim)
 
               if (grub_disk_read (dev->disk, p->offset, p->index,
                                   sizeof (gptdata), &gptdata) == 0)
-                {
-                  grub_gpt_part_type_t gpttype;
-                  gpttype.data1 = grub_le_to_cpu32 (gptdata.type.data1);
-                  gpttype.data2 = grub_le_to_cpu16 (gptdata.type.data2);
-                  gpttype.data3 = grub_le_to_cpu16 (gptdata.type.data3);
-                  grub_memcpy (gpttype.data4, gptdata.type.data4, 8);
-
-                  grub_printf ("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-                               gpttype.data1, gpttype.data2,
-                               gpttype.data3, gpttype.data4[0], 
-                               gpttype.data4[1], gpttype.data4[2],
-                               gpttype.data4[3], gpttype.data4[4],
-                               gpttype.data4[5], gpttype.data4[6],
-                               gpttype.data4[7]);
-                }
+		print_gpt_guid(gptdata.type);
               dev->disk->partition = p;
             }
           putchar (delim);
diff --git a/util/ieee1275/grub-ofpathname.c b/util/ieee1275/grub-ofpathname.c
index 8e5d766cb63871c1479a42626c8cfa7fddd6f771..300fbddad7c54e2b52d90a7de5eb868a9a1ae705 100644
--- a/util/ieee1275/grub-ofpathname.c
+++ b/util/ieee1275/grub-ofpathname.c
@@ -46,7 +46,9 @@ int main(int argc, char **argv)
     }
 
   of_path = grub_util_devname_to_ofpath (argv[1]);
-  printf("%s\n", of_path);
+
+  if (of_path)
+    printf ("%s\n", of_path);
 
   free (of_path);
 
diff --git a/util/mkimage.c b/util/mkimage.c
index 9ad4cfe4223b661c11ab9d3783cb13c88100631c..e22d82afa61a6aa4209c7ab6d2aa5b58f95e1bfe 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -533,6 +533,45 @@ static const struct grub_install_image_target_desc image_targets[] =
       .mod_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
       .link_align = 4
     },
+    /* For coreboot versions that don't support self-relocating images. */
+    {
+      .dirname = "arm-coreboot-vexpress",
+      .names = { "arm-coreboot-vexpress", NULL },
+      .voidp_sizeof = 4,
+      .bigendian = 0,
+      .id = IMAGE_COREBOOT,
+      .flags = PLATFORM_FLAGS_NONE,
+      .total_module_size = GRUB_KERNEL_ARM_COREBOOT_TOTAL_MODULE_SIZE,
+      .decompressor_compressed_size = TARGET_NO_FIELD,
+      .decompressor_uncompressed_size = TARGET_NO_FIELD,
+      .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+      .section_align = GRUB_KERNEL_ARM_COREBOOT_MOD_ALIGN,
+      .vaddr_offset = 0,
+      .elf_target = EM_ARM,
+      .mod_gap = GRUB_KERNEL_ARM_COREBOOT_MOD_GAP,
+      .mod_align = GRUB_KERNEL_ARM_COREBOOT_MOD_ALIGN,
+      .link_align = 4,
+      .link_addr = 0x62000000,
+    },
+    {
+      .dirname = "arm-coreboot-veyron",
+      .names = { "arm-coreboot-veyron", NULL },
+      .voidp_sizeof = 4,
+      .bigendian = 0,
+      .id = IMAGE_COREBOOT,
+      .flags = PLATFORM_FLAGS_NONE,
+      .total_module_size = GRUB_KERNEL_ARM_COREBOOT_TOTAL_MODULE_SIZE,
+      .decompressor_compressed_size = TARGET_NO_FIELD,
+      .decompressor_uncompressed_size = TARGET_NO_FIELD,
+      .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+      .section_align = GRUB_KERNEL_ARM_COREBOOT_MOD_ALIGN,
+      .vaddr_offset = 0,
+      .elf_target = EM_ARM,
+      .mod_gap = GRUB_KERNEL_ARM_COREBOOT_MOD_GAP,
+      .mod_align = GRUB_KERNEL_ARM_COREBOOT_MOD_ALIGN,
+      .link_align = 4,
+      .link_addr = 0x43000000,
+    },
     {
       .dirname = "arm-efi",
       .names = { "arm-efi", NULL },
@@ -738,13 +777,12 @@ grub_install_generate_image (const char *dir, const char *prefix,
 			     char *memdisk_path, char **pubkey_paths,
 			     size_t npubkeys, char *config_path,
 			     const struct grub_install_image_target_desc *image_target,
-			     int note,
-			     grub_compression_t comp)
+			     int note, grub_compression_t comp, const char *dtb_path)
 {
   char *kernel_img, *core_img;
   size_t total_module_size, core_size;
   size_t memdisk_size = 0, config_size = 0;
-  size_t prefix_size = 0;
+  size_t prefix_size = 0, dtb_size = 0;
   char *kernel_path;
   size_t offset;
   struct grub_util_path_list *path_list, *p;
@@ -789,6 +827,12 @@ grub_install_generate_image (const char *dir, const char *prefix,
       total_module_size += memdisk_size + sizeof (struct grub_module_header);
     }
 
+  if (dtb_path)
+    {
+      dtb_size = ALIGN_UP(grub_util_get_image_size (dtb_path), 4);
+      total_module_size += dtb_size + sizeof (struct grub_module_header);
+    }
+
   if (config_path)
     {
       config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1);
@@ -911,6 +955,19 @@ grub_install_generate_image (const char *dir, const char *prefix,
       offset += memdisk_size;
     }
 
+  if (dtb_path)
+    {
+      struct grub_module_header *header;
+
+      header = (struct grub_module_header *) (kernel_img + offset);
+      header->type = grub_host_to_target32 (OBJ_TYPE_DTB);
+      header->size = grub_host_to_target32 (dtb_size + sizeof (*header));
+      offset += sizeof (*header);
+
+      grub_util_load_image (dtb_path, kernel_img + offset);
+      offset += dtb_size;
+    }
+
   if (config_path)
     {
       struct grub_module_header *header;
@@ -1033,7 +1090,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	/* fallthrough */
     case IMAGE_COREBOOT:
     case IMAGE_QEMU:
-	if (layout.kernel_size + layout.bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000)
+	if (image_target->elf_target != EM_ARM && layout.kernel_size + layout.bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000)
 	  grub_util_error (_("kernel image is too big (0x%x > 0x%x)"),
 			   (unsigned) layout.kernel_size + (unsigned) layout.bss_size
 			   + GRUB_KERNEL_I386_PC_LINK_ADDR,
@@ -1638,10 +1695,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	  target_addr = image_target->link_addr;
 	if (image_target->voidp_sizeof == 4)
 	  grub_mkimage_generate_elf32 (image_target, note, &core_img, &core_size,
-				       target_addr, layout.align, layout.kernel_size, layout.bss_size);
+				       target_addr, &layout);
 	else
 	  grub_mkimage_generate_elf64 (image_target, note, &core_img, &core_size,
-				       target_addr, layout.align, layout.kernel_size, layout.bss_size);
+				       target_addr, &layout);
       }
       break;
     }
diff --git a/util/setup.c b/util/setup.c
index 8aa5a39a79465c33b0ff6a5a6b1bc82128df2e18..9c1e1b7da6a85ea7aece6433f2eaf81a6ccde451 100644
--- a/util/setup.c
+++ b/util/setup.c
@@ -137,6 +137,9 @@ struct blocklists
   struct grub_boot_blocklist *first_block, *block;
 #ifdef GRUB_SETUP_BIOS
   grub_uint16_t current_segment;
+#endif
+#ifdef GRUB_SETUP_SPARC64
+  grub_uint64_t gpt_offset;
 #endif
   grub_uint16_t last_length;
   grub_disk_addr_t first_sector;
@@ -151,6 +154,10 @@ save_blocklists (grub_disk_addr_t sector, unsigned offset, unsigned length,
   struct grub_boot_blocklist *prev = bl->block + 1;
   grub_uint64_t seclen;
 
+#ifdef GRUB_SETUP_SPARC64
+  sector -= bl->gpt_offset;
+#endif
+
   grub_util_info ("saving <%"  GRUB_HOST_PRIuLONG_LONG ",%u,%u>",
 		  (unsigned long long) sector, offset, length);
 
@@ -298,9 +305,8 @@ SETUP (const char *dir,
   bl.first_block = (struct grub_boot_blocklist *) (core_img
 						   + GRUB_DISK_SECTOR_SIZE
 						   - sizeof (*bl.block));
-  grub_util_info ("root is `%s', dest is `%s'", root, dest);
 
-  grub_util_info ("Opening dest");
+  grub_util_info ("Opening dest `%s'", dest);
   dest_dev = grub_device_open (dest);
   if (! dest_dev)
     grub_util_error ("%s", grub_errmsg);
@@ -662,6 +668,16 @@ unable_to_embed:
 
   bl.block = bl.first_block;
 
+#ifdef GRUB_SETUP_SPARC64
+  {
+    grub_partition_t container = root_dev->disk->partition;
+    bl.gpt_offset = 0;
+
+    if (grub_strstr (container->partmap->name, "gpt"))
+      bl.gpt_offset = grub_partition_get_start (container);
+  }
+#endif
+
   grub_install_get_blocklist (root_dev, core_path, core_img, core_size,
 			      save_blocklists, &bl);
 
@@ -721,15 +737,18 @@ unable_to_embed:
   {
     char *buf, *ptr = core_img;
     size_t len = core_size;
-    grub_uint64_t blk;
+    grub_uint64_t blk, offset = 0;
     grub_partition_t container = core_dev->disk->partition;
     grub_err_t err;
 
     core_dev->disk->partition = 0;
+#ifdef GRUB_SETUP_SPARC64
+    offset = bl.gpt_offset;
+#endif
 
     buf = xmalloc (core_size);
     blk = bl.first_sector;
-    err = grub_disk_read (core_dev->disk, blk, 0, GRUB_DISK_SECTOR_SIZE, buf);
+    err = grub_disk_read (core_dev->disk, blk + offset, 0, GRUB_DISK_SECTOR_SIZE, buf);
     if (err)
       grub_util_error (_("cannot read `%s': %s"), core_dev->disk->name,
 		       grub_errmsg);
@@ -748,7 +767,7 @@ unable_to_embed:
 	if (cur > len)
 	  cur = len;
 
-	err = grub_disk_read (core_dev->disk, blk, 0, cur, buf);
+	err = grub_disk_read (core_dev->disk, blk + offset, 0, cur, buf);
 	if (err)
 	  grub_util_error (_("cannot read `%s': %s"), core_dev->disk->name,
 			   grub_errmsg);
diff --git a/grub-core/lib/libgcrypt/cipher/bufhelp.h b/grub-core/lib/libgcrypt/cipher/bufhelp.h
new file mode 100644
index 0000000000000000000000000000000000000000..df3559472312d8c6c0c038e27571c546ce489283
--- /dev/null
+++ b/grub-core/lib/libgcrypt/cipher/bufhelp.h
@@ -0,0 +1,432 @@
+/* bufhelp.h  -  Some buffer manipulation helpers
+ * Copyright (C) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GCRYPT_BUFHELP_H
+#define GCRYPT_BUFHELP_H
+
+
+#include "bithelp.h"
+
+
+#undef BUFHELP_FAST_UNALIGNED_ACCESS
+#if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \
+    defined(HAVE_GCC_ATTRIBUTE_ALIGNED) && \
+    (defined(__i386__) || defined(__x86_64__) || \
+     (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) || \
+     defined(__aarch64__))
+/* These architectures are able of unaligned memory accesses and can
+   handle those fast.
+ */
+# define BUFHELP_FAST_UNALIGNED_ACCESS 1
+#endif
+
+
+#ifdef BUFHELP_FAST_UNALIGNED_ACCESS
+/* Define type with one-byte alignment on architectures with fast unaligned
+   memory accesses.
+ */
+typedef struct bufhelp_int_s
+{
+  uintptr_t a;
+} __attribute__((packed, aligned(1))) bufhelp_int_t;
+#else
+/* Define type with default alignment for other architectures (unaligned
+   accessed handled in per byte loops).
+ */
+typedef struct bufhelp_int_s
+{
+  uintptr_t a;
+} bufhelp_int_t;
+#endif
+
+
+/* Optimized function for small buffer copying */
+static inline void
+buf_cpy(void *_dst, const void *_src, size_t len)
+{
+#if __GNUC__ >= 4 && (defined(__x86_64__) || defined(__i386__))
+  /* For AMD64 and i386, memcpy is faster.  */
+  memcpy(_dst, _src, len);
+#else
+  byte *dst = _dst;
+  const byte *src = _src;
+  bufhelp_int_t *ldst;
+  const bufhelp_int_t *lsrc;
+#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
+  const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
+
+  /* Skip fast processing if buffers are unaligned.  */
+  if (((uintptr_t)dst | (uintptr_t)src) & longmask)
+    goto do_bytes;
+#endif
+
+  ldst = (bufhelp_int_t *)(void *)dst;
+  lsrc = (const bufhelp_int_t *)(const void *)src;
+
+  for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
+    (ldst++)->a = (lsrc++)->a;
+
+  dst = (byte *)ldst;
+  src = (const byte *)lsrc;
+
+#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
+do_bytes:
+#endif
+  /* Handle tail.  */
+  for (; len; len--)
+    *dst++ = *src++;
+#endif /*__GNUC__ >= 4 && (__x86_64__ || __i386__)*/
+}
+
+
+/* Optimized function for buffer xoring */
+static inline void
+buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len)
+{
+  byte *dst = _dst;
+  const byte *src1 = _src1;
+  const byte *src2 = _src2;
+  bufhelp_int_t *ldst;
+  const bufhelp_int_t *lsrc1, *lsrc2;
+#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
+  const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
+
+  /* Skip fast processing if buffers are unaligned.  */
+  if (((uintptr_t)dst | (uintptr_t)src1 | (uintptr_t)src2) & longmask)
+    goto do_bytes;
+#endif
+
+  ldst = (bufhelp_int_t *)(void *)dst;
+  lsrc1 = (const bufhelp_int_t *)(const void *)src1;
+  lsrc2 = (const bufhelp_int_t *)(const void *)src2;
+
+  for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
+    (ldst++)->a = (lsrc1++)->a ^ (lsrc2++)->a;
+
+  dst = (byte *)ldst;
+  src1 = (const byte *)lsrc1;
+  src2 = (const byte *)lsrc2;
+
+#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
+do_bytes:
+#endif
+  /* Handle tail.  */
+  for (; len; len--)
+    *dst++ = *src1++ ^ *src2++;
+}
+
+
+/* Optimized function for in-place buffer xoring. */
+static inline void
+buf_xor_1(void *_dst, const void *_src, size_t len)
+{
+  byte *dst = _dst;
+  const byte *src = _src;
+  bufhelp_int_t *ldst;
+  const bufhelp_int_t *lsrc;
+#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
+  const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
+
+  /* Skip fast processing if buffers are unaligned.  */
+  if (((uintptr_t)dst | (uintptr_t)src) & longmask)
+    goto do_bytes;
+#endif
+
+  ldst = (bufhelp_int_t *)(void *)dst;
+  lsrc = (const bufhelp_int_t *)(const void *)src;
+
+  for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
+    (ldst++)->a ^= (lsrc++)->a;
+
+  dst = (byte *)ldst;
+  src = (const byte *)lsrc;
+
+#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
+do_bytes:
+#endif
+  /* Handle tail.  */
+  for (; len; len--)
+    *dst++ ^= *src++;
+}
+
+
+/* Optimized function for buffer xoring with two destination buffers.  Used
+   mainly by CFB mode encryption.  */
+static inline void
+buf_xor_2dst(void *_dst1, void *_dst2, const void *_src, size_t len)
+{
+  byte *dst1 = _dst1;
+  byte *dst2 = _dst2;
+  const byte *src = _src;
+  bufhelp_int_t *ldst1, *ldst2;
+  const bufhelp_int_t *lsrc;
+#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
+  const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
+
+  /* Skip fast processing if buffers are unaligned.  */
+  if (((uintptr_t)src | (uintptr_t)dst1 | (uintptr_t)dst2) & longmask)
+    goto do_bytes;
+#endif
+
+  ldst1 = (bufhelp_int_t *)(void *)dst1;
+  ldst2 = (bufhelp_int_t *)(void *)dst2;
+  lsrc = (const bufhelp_int_t *)(const void *)src;
+
+  for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
+    (ldst1++)->a = ((ldst2++)->a ^= (lsrc++)->a);
+
+  dst1 = (byte *)ldst1;
+  dst2 = (byte *)ldst2;
+  src = (const byte *)lsrc;
+
+#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
+do_bytes:
+#endif
+  /* Handle tail.  */
+  for (; len; len--)
+    *dst1++ = (*dst2++ ^= *src++);
+}
+
+
+/* Optimized function for combined buffer xoring and copying.  Used by mainly
+   CBC mode decryption.  */
+static inline void
+buf_xor_n_copy_2(void *_dst_xor, const void *_src_xor, void *_srcdst_cpy,
+		 const void *_src_cpy, size_t len)
+{
+  byte *dst_xor = _dst_xor;
+  byte *srcdst_cpy = _srcdst_cpy;
+  const byte *src_xor = _src_xor;
+  const byte *src_cpy = _src_cpy;
+  byte temp;
+  bufhelp_int_t *ldst_xor, *lsrcdst_cpy;
+  const bufhelp_int_t *lsrc_cpy, *lsrc_xor;
+  uintptr_t ltemp;
+#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
+  const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
+
+  /* Skip fast processing if buffers are unaligned.  */
+  if (((uintptr_t)src_cpy | (uintptr_t)src_xor | (uintptr_t)dst_xor |
+       (uintptr_t)srcdst_cpy) & longmask)
+    goto do_bytes;
+#endif
+
+  ldst_xor = (bufhelp_int_t *)(void *)dst_xor;
+  lsrc_xor = (const bufhelp_int_t *)(void *)src_xor;
+  lsrcdst_cpy = (bufhelp_int_t *)(void *)srcdst_cpy;
+  lsrc_cpy = (const bufhelp_int_t *)(const void *)src_cpy;
+
+  for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
+    {
+      ltemp = (lsrc_cpy++)->a;
+      (ldst_xor++)->a = (lsrcdst_cpy)->a ^ (lsrc_xor++)->a;
+      (lsrcdst_cpy++)->a = ltemp;
+    }
+
+  dst_xor = (byte *)ldst_xor;
+  src_xor = (const byte *)lsrc_xor;
+  srcdst_cpy = (byte *)lsrcdst_cpy;
+  src_cpy = (const byte *)lsrc_cpy;
+
+#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
+do_bytes:
+#endif
+  /* Handle tail.  */
+  for (; len; len--)
+    {
+      temp = *src_cpy++;
+      *dst_xor++ = *srcdst_cpy ^ *src_xor++;
+      *srcdst_cpy++ = temp;
+    }
+}
+
+
+/* Optimized function for combined buffer xoring and copying.  Used by mainly
+   CFB mode decryption.  */
+static inline void
+buf_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, size_t len)
+{
+  buf_xor_n_copy_2(_dst_xor, _src, _srcdst_cpy, _src, len);
+}
+
+
+/* Constant-time compare of two buffers.  Returns 1 if buffers are equal,
+   and 0 if buffers differ.  */
+static inline int
+buf_eq_const(const void *_a, const void *_b, size_t len)
+{
+  const byte *a = _a;
+  const byte *b = _b;
+  size_t diff, i;
+
+  /* Constant-time compare. */
+  for (i = 0, diff = 0; i < len; i++)
+    diff -= !!(a[i] - b[i]);
+
+  return !diff;
+}
+
+
+#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
+
+/* Functions for loading and storing unaligned u32 values of different
+   endianness.  */
+static inline u32 buf_get_be32(const void *_buf)
+{
+  const byte *in = _buf;
+  return ((u32)in[0] << 24) | ((u32)in[1] << 16) | \
+         ((u32)in[2] << 8) | (u32)in[3];
+}
+
+static inline u32 buf_get_le32(const void *_buf)
+{
+  const byte *in = _buf;
+  return ((u32)in[3] << 24) | ((u32)in[2] << 16) | \
+         ((u32)in[1] << 8) | (u32)in[0];
+}
+
+static inline void buf_put_be32(void *_buf, u32 val)
+{
+  byte *out = _buf;
+  out[0] = val >> 24;
+  out[1] = val >> 16;
+  out[2] = val >> 8;
+  out[3] = val;
+}
+
+static inline void buf_put_le32(void *_buf, u32 val)
+{
+  byte *out = _buf;
+  out[3] = val >> 24;
+  out[2] = val >> 16;
+  out[1] = val >> 8;
+  out[0] = val;
+}
+
+
+/* Functions for loading and storing unaligned u64 values of different
+   endianness.  */
+static inline u64 buf_get_be64(const void *_buf)
+{
+  const byte *in = _buf;
+  return ((u64)in[0] << 56) | ((u64)in[1] << 48) | \
+         ((u64)in[2] << 40) | ((u64)in[3] << 32) | \
+         ((u64)in[4] << 24) | ((u64)in[5] << 16) | \
+         ((u64)in[6] << 8) | (u64)in[7];
+}
+
+static inline u64 buf_get_le64(const void *_buf)
+{
+  const byte *in = _buf;
+  return ((u64)in[7] << 56) | ((u64)in[6] << 48) | \
+         ((u64)in[5] << 40) | ((u64)in[4] << 32) | \
+         ((u64)in[3] << 24) | ((u64)in[2] << 16) | \
+         ((u64)in[1] << 8) | (u64)in[0];
+}
+
+static inline void buf_put_be64(void *_buf, u64 val)
+{
+  byte *out = _buf;
+  out[0] = val >> 56;
+  out[1] = val >> 48;
+  out[2] = val >> 40;
+  out[3] = val >> 32;
+  out[4] = val >> 24;
+  out[5] = val >> 16;
+  out[6] = val >> 8;
+  out[7] = val;
+}
+
+static inline void buf_put_le64(void *_buf, u64 val)
+{
+  byte *out = _buf;
+  out[7] = val >> 56;
+  out[6] = val >> 48;
+  out[5] = val >> 40;
+  out[4] = val >> 32;
+  out[3] = val >> 24;
+  out[2] = val >> 16;
+  out[1] = val >> 8;
+  out[0] = val;
+}
+
+#else /*BUFHELP_FAST_UNALIGNED_ACCESS*/
+
+typedef struct bufhelp_u32_s
+{
+  u32 a;
+} __attribute__((packed, aligned(1))) bufhelp_u32_t;
+
+/* Functions for loading and storing unaligned u32 values of different
+   endianness.  */
+static inline u32 buf_get_be32(const void *_buf)
+{
+  return be_bswap32(((const bufhelp_u32_t *)_buf)->a);
+}
+
+static inline u32 buf_get_le32(const void *_buf)
+{
+  return le_bswap32(((const bufhelp_u32_t *)_buf)->a);
+}
+
+static inline void buf_put_be32(void *_buf, u32 val)
+{
+  bufhelp_u32_t *out = _buf;
+  out->a = be_bswap32(val);
+}
+
+static inline void buf_put_le32(void *_buf, u32 val)
+{
+  bufhelp_u32_t *out = _buf;
+  out->a = le_bswap32(val);
+}
+
+
+typedef struct bufhelp_u64_s
+{
+  u64 a;
+} __attribute__((packed, aligned(1))) bufhelp_u64_t;
+
+/* Functions for loading and storing unaligned u64 values of different
+   endianness.  */
+static inline u64 buf_get_be64(const void *_buf)
+{
+  return be_bswap64(((const bufhelp_u64_t *)_buf)->a);
+}
+
+static inline u64 buf_get_le64(const void *_buf)
+{
+  return le_bswap64(((const bufhelp_u64_t *)_buf)->a);
+}
+
+static inline void buf_put_be64(void *_buf, u64 val)
+{
+  bufhelp_u64_t *out = _buf;
+  out->a = be_bswap64(val);
+}
+
+static inline void buf_put_le64(void *_buf, u64 val)
+{
+  bufhelp_u64_t *out = _buf;
+  out->a = le_bswap64(val);
+}
+
+
+#endif /*BUFHELP_FAST_UNALIGNED_ACCESS*/
+
+#endif /*GCRYPT_BUFHELP_H*/
diff --git a/grub-core/tests/checksums.h b/grub-core/tests/checksums.h
index 68d8ce7c7753ff721ab0d5a12d40b2aff20c694c..8273bd105deec0bf21f507e0eddb867f104afc5d 100644
--- a/grub-core/tests/checksums.h
+++ b/grub-core/tests/checksums.h
@@ -1,129 +1,129 @@
-  { "cmdline_cat", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xcd5fc34e, 0xcd5fc34e, 0xeabbecab, 0xeabbecab, 0xc9950151, 0xc9950151, 0x2be222b6, 0x2be222b6, 0xe88c769e, 0xe88c769e, 0x6be4910e, 0x6be4910e, 0x1dc1fe4f, 0x1dc1fe4f, 0xd7613e8f, 0xd7613e8f, 0xf8124196, 0xf8124196, 0x130f5935, 0x130f5935, 0x2872330e, 0x2872330e, 0xaa7b7868, 0xaa7b7868, 0x558eaeea, 0x558eaeea, 0x92f7960f, 0x92f7960f, 0xc5bfc709, 0xc5bfc709, 0x699732fe, 0x699732fe, 0xc859125f, 0xc859125f, 0xfc6ac729, 0xfc6ac729, 0xcdab6cd4, 0xcdab6cd4, 0x58a8b7f8, 0x58a8b7f8, 0xc0e73385, 0x6560d6ef, 0x3be8bb5d, 0x3be8bb5d, }, 45 },
-  { "cmdline_cat", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x13029f94, 0x13029f94, 0x7785fdab, 0x7785fdab, 0x95a7c1e8, 0x95a7c1e8, 0x315ab3e3, 0x315ab3e3, 0x6787f012, 0x6787f012, 0x79b1ecdc, 0x79b1ecdc, 0xdbc67810, 0xdbc67810, 0xafaa982e, 0xafaa982e, 0xc5cd0157, 0xc5cd0157, 0x3c50dd64, 0x3c50dd64, 0x1056cac0, 0x1056cac0, 0x1d7a41fa, 0x1d7a41fa, 0x5690b1e8, 0x5690b1e8, 0x616831d6, 0x616831d6, 0xfaf8e726, 0xfaf8e726, 0xd1ec5e26, 0xd1ec5e26, 0x3c269e1f, 0x3c269e1f, 0x1aa7952d, 0x1aa7952d, 0x6e7e2f99, 0x6e7e2f99, 0x98f4c02, 0x98f4c02, 0xc3f1abf2, 0xe348bb73, 0xea53cd60, 0xea53cd60, }, 45 },
-  { "cmdline_cat", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0x8fbb4f4c, 0x8fbb4f4c, 0x5dc00167, 0x5dc00167, 0xbc124df8, 0xbc124df8, 0x31cf0f8e, 0x31cf0f8e, 0x798cc4ed, 0x798cc4ed, 0xc5d2a091, 0xc5d2a091, 0xb58a0591, 0xb58a0591, 0x4d118aca, 0x4d118aca, 0xbb06c7ee, 0xbb06c7ee, 0x42179db7, 0x42179db7, 0x65f2d81e, 0x65f2d81e, 0xa2628bcb, 0xa2628bcb, 0xbdb7f4b, 0xbdb7f4b, 0x66b10309, 0x66b10309, 0x1a550ea9, 0x1a550ea9, 0x377a297d, 0x377a297d, 0x2ea99015, 0x2ea99015, 0x4e20d7bc, 0x4e20d7bc, 0x8ecbde02, 0x8ecbde02, 0xdfa2195a, 0xdfa2195a, 0xe113d2a, 0xe204ee5b, 0x734679c1, 0x734679c1, }, 45 },
-  { "cmdline_cat", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0xe2f6bfe1, 0xe2f6bfe1, 0xf18aee15, 0xf18aee15, 0x5e83b689, 0x5e83b689, 0xb7e8b42c, 0xb7e8b42c, 0x85d78f92, 0x85d78f92, 0xd56fadae, 0xd56fadae, 0x7632f5bf, 0x7632f5bf, 0x2769a748, 0x2769a748, 0x4a6112cd, 0x4a6112cd, 0x4f9b66a4, 0x4f9b66a4, 0x70457d38, 0x70457d38, 0x8cadb1a7, 0x8cadb1a7, 0x451341f, 0x451341f, 0x8a62e741, 0x8a62e741, 0x1b1f9031, 0x1b1f9031, 0x75ab630e, 0x75ab630e, 0xd5ff53ac, 0xd5ff53ac, 0x73a2b3c7, 0x73a2b3c7, 0x7b52acd5, 0x7b52acd5, 0xf6f3e48c, 0xf6f3e48c, 0x8d0db133, 0x8db24310, 0x7aef56d4, 0x7aef56d4, }, 45 },
-  { "cmdline_cat", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0x838a3f40, 0x838a3f40, 0x7351ba96, 0x7351ba96, 0x660963bb, 0x660963bb, 0x6f3362a6, 0x6f3362a6, 0x915d35d9, 0x915d35d9, 0xc7edaee9, 0xc7edaee9, 0xbc8ec24c, 0xbc8ec24c, 0xeb120ffd, 0xeb120ffd, 0x8f6d8232, 0x8f6d8232, 0x2de5d515, 0x2de5d515, 0x4f2ecd91, 0x4f2ecd91, 0x555a9b90, 0x555a9b90, 0x8f7b0d77, 0x8f7b0d77, 0x5f9536af, 0x5f9536af, 0x3dd79dbe, 0x3dd79dbe, 0xb555a0, 0xb555a0, 0x75aec882, 0x75aec882, 0xd5da89cb, 0xd5da89cb, 0xb47b3257, 0xb47b3257, 0x7c97c046, 0x7c97c046, 0x726a7abe, 0x4c8b8a56, 0xcffa0854, 0xcffa0854, }, 45 },
-  { "cmdline_cat", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0x7bf761e, 0x7bf761e, 0xaf0b6dae, 0xaf0b6dae, 0x7db15930, 0x7db15930, 0xc9720d56, 0xc9720d56, 0x55590d6c, 0x55590d6c, 0xa0d193d9, 0xa0d193d9, 0x728987b2, 0x728987b2, 0x28aecde6, 0x28aecde6, 0xa59bb094, 0xa59bb094, 0x2d0b049d, 0x2d0b049d, 0xd8421240, 0xd8421240, 0x51fa339, 0x51fa339, 0xc625cc46, 0xc625cc46, 0x2c9e6fcc, 0x2c9e6fcc, 0x3d06ffd5, 0x3d06ffd5, 0x8dd72816, 0x8dd72816, 0xfcf2a982, 0xfcf2a982, 0x6ef2870f, 0x6ef2870f, 0xba2caab7, 0xba2caab7, 0x8e5a5872, 0x8e5a5872, 0x62b2fedc, 0x2bd3b588, 0x34ebdb15, 0x34ebdb15, }, 45 },
-  { "cmdline_cat", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0xa133280a, 0xa133280a, 0x1e8f4227, 0x1e8f4227, 0xa01cd911, 0xa01cd911, 0xdcb3d617, 0xdcb3d617, 0x51200351, 0x51200351, 0x609ba305, 0x609ba305, 0x5d96abfd, 0x5d96abfd, 0xd855cc70, 0xd855cc70, 0xdbfaf18d, 0xdbfaf18d, 0x84814843, 0x84814843, 0x4b00e630, 0x4b00e630, 0xd362b0f5, 0xd362b0f5, 0xec863355, 0xec863355, 0x195898d0, 0x195898d0, 0xe8c698c7, 0xe8c698c7, 0x884229e7, 0x884229e7, 0xb41ed3a9, 0xb41ed3a9, 0x2be1ce40, 0x2be1ce40, 0x8c33eb7c, 0x8c33eb7c, 0xbbce1da, 0xbbce1da, 0xef9415fa, 0x22fbc0d, 0xd82c182c, 0xd82c182c, }, 45 },
-  { "gfxterm_menu", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xbe029c, 0x6671ee1f, 0xbe029c, 0x4348cfdb, 0x59c36f00, 0x59c36f00, 0x3ad73295, 0x3ad73295, 0x3ad73295, 0x44575ff3, 0x44575ff3, 0x44575ff3, 0x26a14a21, 0x26a14a21, 0x26a14a21, 0x59c36f00, 0x4348cfdb, 0x4348cfdb, 0x59c36f00, }, 20 },
-  { "gfxterm_menu", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x14e228ef, 0xb0c8af57, 0x14e228ef, 0x3ae7ad90, 0xaa4593fe, 0xaa4593fe, 0xbec19c1b, 0xbec19c1b, 0xbec19c1b, 0x1834917c, 0x1834917c, 0x1834917c, 0x350c3a04, 0x350c3a04, 0x350c3a04, 0xaa4593fe, 0x3ae7ad90, 0x3ae7ad90, 0xaa4593fe, }, 20 },
-  { "gfxterm_menu", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0x651fb144, 0xdf93ee9c, 0x651fb144, 0x3808dcc0, 0xc9cbf769, 0xc9cbf769, 0xe4861949, 0xe4861949, 0xe4861949, 0x1a5ed885, 0x1a5ed885, 0x1a5ed885, 0xf314678d, 0xf314678d, 0xf314678d, 0xc9cbf769, 0x3808dcc0, 0x3808dcc0, 0xc9cbf769, }, 20 },
-  { "gfxterm_menu", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0xdfd0119e, 0x6c7018a9, 0xdfd0119e, 0x71865846, 0x9813a416, 0x9813a416, 0xb5e8801c, 0xb5e8801c, 0xb5e8801c, 0x2433062f, 0x2433062f, 0x2433062f, 0x3d893bff, 0x3d893bff, 0x3d893bff, 0x9813a416, 0x71865846, 0x71865846, 0x9813a416, }, 20 },
-  { "gfxterm_menu", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0x4e4844e0, 0x5ebe5f81, 0x4e4844e0, 0x38ee7153, 0x5fcf013d, 0x5fcf013d, 0x819b5c4e, 0x819b5c4e, 0x819b5c4e, 0x538b4438, 0x538b4438, 0x538b4438, 0x45f87ba7, 0x45f87ba7, 0x45f87ba7, 0x5fcf013d, 0x38ee7153, 0x38ee7153, 0x5fcf013d, }, 20 },
-  { "gfxterm_menu", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0x701427d4, 0x246c830a, 0x701427d4, 0x6b11fdd3, 0xdd28f52b, 0xdd28f52b, 0xcd83646c, 0xcd83646c, 0xcd83646c, 0xecbf9d88, 0xecbf9d88, 0xecbf9d88, 0x91075604, 0x91075604, 0x91075604, 0xdd28f52b, 0x6b11fdd3, 0x6b11fdd3, 0xdd28f52b, }, 20 },
-  { "gfxterm_menu", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x7b5bd4c, 0xac246af1, 0x7b5bd4c, 0xf80aa6cc, 0x43d1f34, 0x43d1f34, 0xb200c08a, 0xb200c08a, 0xb200c08a, 0xcd0a6922, 0xcd0a6922, 0xcd0a6922, 0x545b6ca4, 0x545b6ca4, 0x545b6ca4, 0x43d1f34, 0xf80aa6cc, 0xf80aa6cc, 0x43d1f34, }, 20 },
-  { "gfxmenu", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0x1027210c, 0x64e51c81, 0x1027210c, 0x45ca4a8a, 0x9a2e0d26, 0x12fd0f21, 0x12fd0f21, 0x12fd0f21, 0x4e25f9e1, 0x4e25f9e1, 0x4e25f9e1, 0x67bd3773, 0x67bd3773, 0x67bd3773, 0x59c36f00, 0x45ca4a8a, 0x45ca4a8a, }, 18 },
-  { "gfxmenu", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x8d12f697, 0xc5b32248, 0x8d12f697, 0x56720aa4, 0xa9d58ccd, 0xf766a14d, 0xf766a14d, 0xf766a14d, 0xa2390b47, 0xa2390b47, 0xa2390b47, 0xcb0ac30e, 0xcb0ac30e, 0xcb0ac30e, 0xaa4593fe, 0x56720aa4, 0x56720aa4, }, 18 },
-  { "gfxmenu", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xa5ec9f45, 0xdb7085d8, 0xa5ec9f45, 0x9caf1d3f, 0x5411be8b, 0xedc0ad83, 0xedc0ad83, 0xedc0ad83, 0x927e0b17, 0x927e0b17, 0x927e0b17, 0xd00a6b6f, 0xd00a6b6f, 0xd00a6b6f, 0xc9cbf769, 0x9caf1d3f, 0x9caf1d3f, }, 18 },
-  { "gfxmenu", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x1c3742c9, 0xce8e83bf, 0xeb96c838, 0xce8e83bf, 0x73cb3bc1, 0x740d78cf, 0xb35c7e64, 0xb35c7e64, 0xb35c7e64, 0x58f99418, 0x58f99418, 0x58f99418, 0x5eb294e8, 0x5eb294e8, 0x5eb294e8, 0x1c3742c9, 0x73cb3bc1, 0x73cb3bc1, }, 18 },
-  { "gfxmenu", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0xcc5a7bed, 0x56a03e51, 0xee7d8d4b, 0x56a03e51, 0x5bdf9413, 0xbcda144c, 0x220f7a5e, 0x220f7a5e, 0x220f7a5e, 0x4d46a64f, 0x4d46a64f, 0x4d46a64f, 0x40b0384c, 0x40b0384c, 0x40b0384c, 0xcc5a7bed, 0x5bdf9413, 0x5bdf9413, }, 18 },
-  { "gfxmenu", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xef4a3312, 0xea8a9cf0, 0x8929e522, 0xea8a9cf0, 0x78f3dfbc, 0x5d55a141, 0x377f1aeb, 0x377f1aeb, 0x377f1aeb, 0xf1cd5ef5, 0xf1cd5ef5, 0xf1cd5ef5, 0xe5a88e4a, 0xe5a88e4a, 0xe5a88e4a, 0xef4a3312, 0x78f3dfbc, 0x78f3dfbc, }, 18 },
-  { "gfxmenu", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x54e48d80, 0x6dcf1d57, 0x925a4c8f, 0x6dcf1d57, 0x69005b38, 0x6d6bb4bc, 0x756a36b9, 0x756a36b9, 0x756a36b9, 0xf499c068, 0xf499c068, 0xf499c068, 0x623d7907, 0x623d7907, 0x623d7907, 0x54e48d80, 0x69005b38, 0x69005b38, }, 18 },
-  { "gfxterm_ar", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xa49d26b0, 0xaa7d9b28, 0xa49d26b0, 0xe76bebf7, 0x59c36f00, 0x59c36f00, 0xea6ab252, 0xea6ab252, 0xea6ab252, 0x94eadf34, 0x94eadf34, 0x94eadf34, 0xf61ccae6, 0xf61ccae6, 0xf61ccae6, 0x59c36f00, 0xe76bebf7, 0xe76bebf7, 0x59c36f00, }, 20 },
-  { "gfxterm_ar", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x7a277db, 0xf3bf80f7, 0x7a277db, 0x29a7f2a4, 0xaa4593fe, 0xaa4593fe, 0xf1cd57e3, 0xf1cd57e3, 0xf1cd57e3, 0x57385a84, 0x57385a84, 0x57385a84, 0x7a00f1fc, 0x7a00f1fc, 0x7a00f1fc, 0xaa4593fe, 0x29a7f2a4, 0x29a7f2a4, 0xaa4593fe, }, 20 },
-  { "gfxterm_ar", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0x631edf85, 0x71926408, 0x631edf85, 0x3e09b201, 0xc9cbf769, 0xc9cbf769, 0xf224ab3, 0xf224ab3, 0xf224ab3, 0xf1fa8b7f, 0xf1fa8b7f, 0xf1fa8b7f, 0x18b03477, 0x18b03477, 0x18b03477, 0xc9cbf769, 0x3e09b201, 0x3e09b201, 0xc9cbf769, }, 20 },
-  { "gfxterm_ar", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0xfbaf4635, 0xe69ef474, 0xfbaf4635, 0x55f90fed, 0x9813a416, 0x9813a416, 0x3aad8f41, 0x3aad8f41, 0x3aad8f41, 0xab760972, 0xab760972, 0xab760972, 0xb2cc34a2, 0xb2cc34a2, 0xb2cc34a2, 0x9813a416, 0x55f90fed, 0x55f90fed, 0x9813a416, }, 20 },
-  { "gfxterm_ar", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0xdce50745, 0x1d8009e4, 0xdce50745, 0xaa4332f6, 0x5fcf013d, 0x5fcf013d, 0x354e5749, 0x354e5749, 0x354e5749, 0xe75e4f3f, 0xe75e4f3f, 0xe75e4f3f, 0xf12d70a0, 0xf12d70a0, 0xf12d70a0, 0x5fcf013d, 0xaa4332f6, 0xaa4332f6, 0x5fcf013d, }, 20 },
-  { "gfxterm_ar", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0x3efebeff, 0xf101dfe2, 0x3efebeff, 0x25fb64f8, 0xdd28f52b, 0xdd28f52b, 0x70c69ebd, 0x70c69ebd, 0x70c69ebd, 0x51fa6759, 0x51fa6759, 0x51fa6759, 0x2c42acd5, 0x2c42acd5, 0x2c42acd5, 0xdd28f52b, 0x25fb64f8, 0x25fb64f8, 0xdd28f52b, }, 20 },
-  { "gfxterm_ar", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x59a34c64, 0x281cca78, 0x59a34c64, 0xa61c57e4, 0x43d1f34, 0x43d1f34, 0x95131d4, 0x95131d4, 0x95131d4, 0x765b987c, 0x765b987c, 0x765b987c, 0xef0a9dfa, 0xef0a9dfa, 0xef0a9dfa, 0x43d1f34, 0xa61c57e4, 0xa61c57e4, 0x43d1f34, }, 20 },
-  { "gfxterm_cyr", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xa37c165, 0x72063383, 0xa37c165, 0x49c10c22, 0x59c36f00, 0x59c36f00, 0x4e53de8e, 0x4e53de8e, 0x4e53de8e, 0x30d3b3e8, 0x30d3b3e8, 0x30d3b3e8, 0x5225a63a, 0x5225a63a, 0x5225a63a, 0x59c36f00, 0x49c10c22, 0x49c10c22, 0x59c36f00, }, 20 },
-  { "gfxterm_cyr", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x45bba0ba, 0xe60fd0b6, 0x45bba0ba, 0x6bbe25c5, 0xaa4593fe, 0xaa4593fe, 0x28de2b41, 0x28de2b41, 0x28de2b41, 0x8e2b2626, 0x8e2b2626, 0x8e2b2626, 0xa3138d5e, 0xa3138d5e, 0xa3138d5e, 0xaa4593fe, 0x6bbe25c5, 0x6bbe25c5, 0xaa4593fe, }, 20 },
-  { "gfxterm_cyr", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xb43d4e9d, 0x16f88820, 0xb43d4e9d, 0xe92a2319, 0xc9cbf769, 0xc9cbf769, 0xb8959ec7, 0xb8959ec7, 0xb8959ec7, 0x464d5f0b, 0x464d5f0b, 0x464d5f0b, 0xaf07e003, 0xaf07e003, 0xaf07e003, 0xc9cbf769, 0xe92a2319, 0xe92a2319, 0xc9cbf769, }, 20 },
-  { "gfxterm_cyr", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x46760365, 0x685ae30e, 0x46760365, 0xe8204abd, 0x9813a416, 0x9813a416, 0x8896050a, 0x8896050a, 0x8896050a, 0x194d8339, 0x194d8339, 0x194d8339, 0xf7bee9, 0xf7bee9, 0xf7bee9, 0x9813a416, 0xe8204abd, 0xe8204abd, 0x9813a416, }, 20 },
-  { "gfxterm_cyr", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0x6859aa86, 0xf3f11deb, 0x6859aa86, 0x1eff9f35, 0x5fcf013d, 0x5fcf013d, 0xd72b1482, 0xd72b1482, 0xd72b1482, 0x53b0cf4, 0x53b0cf4, 0x53b0cf4, 0x1348336b, 0x1348336b, 0x1348336b, 0x5fcf013d, 0x1eff9f35, 0x1eff9f35, 0x5fcf013d, }, 20 },
-  { "gfxterm_cyr", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0x688451e7, 0xf6936b72, 0x688451e7, 0x73818be0, 0xdd28f52b, 0xdd28f52b, 0xf12a65ac, 0xf12a65ac, 0xf12a65ac, 0xd0169c48, 0xd0169c48, 0xd0169c48, 0xadae57c4, 0xadae57c4, 0xadae57c4, 0xdd28f52b, 0x73818be0, 0x73818be0, 0xdd28f52b, }, 20 },
-  { "gfxterm_cyr", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x9616af94, 0xd466be40, 0x9616af94, 0x69a9b414, 0x43d1f34, 0x43d1f34, 0xf3bb3240, 0xf3bb3240, 0xf3bb3240, 0x8cb19be8, 0x8cb19be8, 0x8cb19be8, 0x15e09e6e, 0x15e09e6e, 0x15e09e6e, 0x43d1f34, 0x69a9b414, 0x69a9b414, 0x43d1f34, }, 20 },
-  { "gfxterm_heb", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0x8708d1bd, 0x85dd5e9c, 0x8708d1bd, 0xc4fe1cfa, 0x59c36f00, 0x59c36f00, 0x7ae8aced, 0x7ae8aced, 0x7ae8aced, 0x468c18b, 0x468c18b, 0x468c18b, 0x669ed459, 0x669ed459, 0x669ed459, 0x59c36f00, 0xc4fe1cfa, 0xc4fe1cfa, 0x59c36f00, }, 20 },
-  { "gfxterm_heb", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0xa72b1043, 0x147d4ce0, 0xa72b1043, 0x892e953c, 0xaa4593fe, 0xaa4593fe, 0xb7b1dd40, 0xb7b1dd40, 0xb7b1dd40, 0x1144d027, 0x1144d027, 0x1144d027, 0x3c7c7b5f, 0x3c7c7b5f, 0x3c7c7b5f, 0xaa4593fe, 0x892e953c, 0x892e953c, 0xaa4593fe, }, 20 },
-  { "gfxterm_heb", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xc5fb1817, 0x745fb26c, 0xc5fb1817, 0x98ec7593, 0xc9cbf769, 0xc9cbf769, 0xf5f17e2d, 0xf5f17e2d, 0xf5f17e2d, 0xb29bfe1, 0xb29bfe1, 0xb29bfe1, 0xe26300e9, 0xe26300e9, 0xe26300e9, 0xc9cbf769, 0x98ec7593, 0x98ec7593, 0xc9cbf769, }, 20 },
-  { "gfxterm_heb", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x4be837e1, 0xbf4963ca, 0x4be837e1, 0xe5be7e39, 0x9813a416, 0x9813a416, 0xd886fca0, 0xd886fca0, 0xd886fca0, 0x495d7a93, 0x495d7a93, 0x495d7a93, 0x50e74743, 0x50e74743, 0x50e74743, 0x9813a416, 0xe5be7e39, 0xe5be7e39, 0x9813a416, }, 20 },
-  { "gfxterm_heb", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0x21a8ccb8, 0x17719be, 0x21a8ccb8, 0x570ef90b, 0x5fcf013d, 0x5fcf013d, 0x2a7b5333, 0x2a7b5333, 0x2a7b5333, 0xf86b4b45, 0xf86b4b45, 0xf86b4b45, 0xee1874da, 0xee1874da, 0xee1874da, 0x5fcf013d, 0x570ef90b, 0x570ef90b, 0x5fcf013d, }, 20 },
-  { "gfxterm_heb", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0x7001fe50, 0x4798153f, 0x7001fe50, 0x6b042457, 0xdd28f52b, 0xdd28f52b, 0x46489369, 0x46489369, 0x46489369, 0x67746a8d, 0x67746a8d, 0x67746a8d, 0x1acca101, 0x1acca101, 0x1acca101, 0xdd28f52b, 0x6b042457, 0x6b042457, 0xdd28f52b, }, 20 },
-  { "gfxterm_heb", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x6e10591c, 0x48bd926e, 0x6e10591c, 0x91af429c, 0x43d1f34, 0x43d1f34, 0x59cb829, 0x59cb829, 0x59cb829, 0x7a961181, 0x7a961181, 0x7a961181, 0xe3c71407, 0xe3c71407, 0xe3c71407, 0x43d1f34, 0x91af429c, 0x91af429c, 0x43d1f34, }, 20 },
-  { "gfxterm_gre", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0x67627ed5, 0xdb276cef, 0x67627ed5, 0x2494b392, 0x59c36f00, 0x59c36f00, 0x43f511f3, 0x43f511f3, 0x43f511f3, 0x3d757c95, 0x3d757c95, 0x3d757c95, 0x5f836947, 0x5f836947, 0x5f836947, 0x59c36f00, 0x2494b392, 0x2494b392, 0x59c36f00, }, 20 },
-  { "gfxterm_gre", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x987cbf71, 0x6e4c645c, 0x987cbf71, 0xb6793a0e, 0xaa4593fe, 0xaa4593fe, 0xb943d716, 0xb943d716, 0xb943d716, 0x1fb6da71, 0x1fb6da71, 0x1fb6da71, 0x328e7109, 0x328e7109, 0x328e7109, 0xaa4593fe, 0xb6793a0e, 0xb6793a0e, 0xaa4593fe, }, 20 },
-  { "gfxterm_gre", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xf9987c07, 0x4a92eed9, 0xf9987c07, 0xa48f1183, 0xc9cbf769, 0xc9cbf769, 0x5eb3ddf4, 0x5eb3ddf4, 0x5eb3ddf4, 0xa06b1c38, 0xa06b1c38, 0xa06b1c38, 0x4921a330, 0x4921a330, 0x4921a330, 0xc9cbf769, 0xa48f1183, 0xa48f1183, 0xc9cbf769, }, 20 },
-  { "gfxterm_gre", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0xccd804e2, 0xb99e8d91, 0xccd804e2, 0x628e4d3a, 0x9813a416, 0x9813a416, 0x5aec5acc, 0x5aec5acc, 0x5aec5acc, 0xcb37dcff, 0xcb37dcff, 0xcb37dcff, 0xd28de12f, 0xd28de12f, 0xd28de12f, 0x9813a416, 0x628e4d3a, 0x628e4d3a, 0x9813a416, }, 20 },
-  { "gfxterm_gre", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0x4990d896, 0x2b3aa242, 0x4990d896, 0x3f36ed25, 0x5fcf013d, 0x5fcf013d, 0x3cc6048d, 0x3cc6048d, 0x3cc6048d, 0xeed61cfb, 0xeed61cfb, 0xeed61cfb, 0xf8a52364, 0xf8a52364, 0xf8a52364, 0x5fcf013d, 0x3f36ed25, 0x3f36ed25, 0x5fcf013d, }, 20 },
-  { "gfxterm_gre", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0x4ff5c69f, 0x66586489, 0x4ff5c69f, 0x54f01c98, 0xdd28f52b, 0xdd28f52b, 0xc3ff0bf5, 0xc3ff0bf5, 0xc3ff0bf5, 0xe2c3f211, 0xe2c3f211, 0xe2c3f211, 0x9f7b399d, 0x9f7b399d, 0x9f7b399d, 0xdd28f52b, 0x54f01c98, 0x54f01c98, 0xdd28f52b, }, 20 },
-  { "gfxterm_gre", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x909b7bb4, 0x2bb2a58c, 0x909b7bb4, 0x6f246034, 0x43d1f34, 0x43d1f34, 0x2df40751, 0x2df40751, 0x2df40751, 0x52feaef9, 0x52feaef9, 0x52feaef9, 0xcbafab7f, 0xcbafab7f, 0xcbafab7f, 0x43d1f34, 0x6f246034, 0x6f246034, 0x43d1f34, }, 20 },
-  { "gfxterm_ru", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xc77bfcc6, 0xffcdf45d, 0xc77bfcc6, 0x848d3181, 0x59c36f00, 0x59c36f00, 0xd79cd5e, 0xd79cd5e, 0xd79cd5e, 0x73f9a038, 0x73f9a038, 0x73f9a038, 0x110fb5ea, 0x110fb5ea, 0x110fb5ea, 0x59c36f00, 0x848d3181, 0x848d3181, 0x59c36f00, }, 20 },
-  { "gfxterm_ru", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0xd5494aa5, 0xa0924ec, 0xd5494aa5, 0xfb4ccfda, 0xaa4593fe, 0xaa4593fe, 0x8692c636, 0x8692c636, 0x8692c636, 0x2067cb51, 0x2067cb51, 0x2067cb51, 0xd5f6029, 0xd5f6029, 0xd5f6029, 0xaa4593fe, 0xfb4ccfda, 0xfb4ccfda, 0xaa4593fe, }, 20 },
-  { "gfxterm_ru", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0x2436c4f, 0x2cde4e0c, 0x2436c4f, 0x5f5401cb, 0xc9cbf769, 0xc9cbf769, 0x558f50ae, 0x558f50ae, 0x558f50ae, 0xab579162, 0xab579162, 0xab579162, 0x421d2e6a, 0x421d2e6a, 0x421d2e6a, 0xc9cbf769, 0x5f5401cb, 0x5f5401cb, 0xc9cbf769, }, 20 },
-  { "gfxterm_ru", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x86f8a68c, 0xf4116451, 0x86f8a68c, 0x28aeef54, 0x9813a416, 0x9813a416, 0x7befbe43, 0x7befbe43, 0x7befbe43, 0xea343870, 0xea343870, 0xea343870, 0xf38e05a0, 0xf38e05a0, 0xf38e05a0, 0x9813a416, 0x28aeef54, 0x28aeef54, 0x9813a416, }, 20 },
-  { "gfxterm_ru", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0x156c292f, 0x3c8eb473, 0x156c292f, 0x63ca1c9c, 0x5fcf013d, 0x5fcf013d, 0x895ea16b, 0x895ea16b, 0x895ea16b, 0x5b4eb91d, 0x5b4eb91d, 0x5b4eb91d, 0x4d3d8682, 0x4d3d8682, 0x4d3d8682, 0x5fcf013d, 0x63ca1c9c, 0x63ca1c9c, 0x5fcf013d, }, 20 },
-  { "gfxterm_ru", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0xf57ebf12, 0x798b299b, 0xf57ebf12, 0xee7b6515, 0xdd28f52b, 0xdd28f52b, 0x22563fc6, 0x22563fc6, 0x22563fc6, 0x36ac622, 0x36ac622, 0x36ac622, 0x7ed20dae, 0x7ed20dae, 0x7ed20dae, 0xdd28f52b, 0xee7b6515, 0xee7b6515, 0xdd28f52b, }, 20 },
-  { "gfxterm_ru", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x2bc82eb1, 0x94064cc8, 0x2bc82eb1, 0xd4773531, 0x43d1f34, 0x43d1f34, 0x44cbf2f0, 0x44cbf2f0, 0x44cbf2f0, 0x3bc15b58, 0x3bc15b58, 0x3bc15b58, 0xa2905ede, 0xa2905ede, 0xa2905ede, 0x43d1f34, 0xd4773531, 0xd4773531, 0x43d1f34, }, 20 },
-  { "gfxterm_fr", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0x7f6dd146, 0x548af474, 0x7f6dd146, 0x3c9b1c01, 0x59c36f00, 0x59c36f00, 0x7d913e8d, 0x7d913e8d, 0x7d913e8d, 0x31153eb, 0x31153eb, 0x31153eb, 0x61e74639, 0x61e74639, 0x61e74639, 0x59c36f00, 0x3c9b1c01, 0x3c9b1c01, 0x59c36f00, }, 20 },
-  { "gfxterm_fr", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0xf29ad079, 0x50d47c0, 0xf29ad079, 0xdc9f5506, 0xaa4593fe, 0xaa4593fe, 0x6bcf4c90, 0x6bcf4c90, 0x6bcf4c90, 0xcd3a41f7, 0xcd3a41f7, 0xcd3a41f7, 0xe002ea8f, 0xe002ea8f, 0xe002ea8f, 0xaa4593fe, 0xdc9f5506, 0xdc9f5506, 0xaa4593fe, }, 20 },
-  { "gfxterm_fr", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xb25e3082, 0x2ed845dd, 0xb25e3082, 0xef495d06, 0xc9cbf769, 0xc9cbf769, 0xd5322575, 0xd5322575, 0xd5322575, 0x2beae4b9, 0x2beae4b9, 0x2beae4b9, 0xc2a05bb1, 0xc2a05bb1, 0xc2a05bb1, 0xc9cbf769, 0xef495d06, 0xef495d06, 0xc9cbf769, }, 20 },
-  { "gfxterm_fr", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x4cdfcd2e, 0x8bf091f, 0x4cdfcd2e, 0xe28984f6, 0x9813a416, 0x9813a416, 0x8217f630, 0x8217f630, 0x8217f630, 0x13cc7003, 0x13cc7003, 0x13cc7003, 0xa764dd3, 0xa764dd3, 0xa764dd3, 0x9813a416, 0xe28984f6, 0xe28984f6, 0x9813a416, }, 20 },
-  { "gfxterm_fr", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0xf2b49f88, 0x2eff252d, 0xf2b49f88, 0x8412aa3b, 0x5fcf013d, 0x5fcf013d, 0x5d3b9fe7, 0x5d3b9fe7, 0x5d3b9fe7, 0x8f2b8791, 0x8f2b8791, 0x8f2b8791, 0x9958b80e, 0x9958b80e, 0x9958b80e, 0x5fcf013d, 0x8412aa3b, 0x8412aa3b, 0x5fcf013d, }, 20 },
-  { "gfxterm_fr", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0x786673be, 0x536f1359, 0x786673be, 0x6363a9b9, 0xdd28f52b, 0xdd28f52b, 0x38653b12, 0x38653b12, 0x38653b12, 0x1959c2f6, 0x1959c2f6, 0x1959c2f6, 0x64e1097a, 0x64e1097a, 0x64e1097a, 0xdd28f52b, 0x6363a9b9, 0x6363a9b9, 0xdd28f52b, }, 20 },
-  { "gfxterm_fr", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0xac4a1127, 0x699c2ad8, 0xac4a1127, 0x53f50aa7, 0x43d1f34, 0x43d1f34, 0xfa47dfba, 0xfa47dfba, 0xfa47dfba, 0x854d7612, 0x854d7612, 0x854d7612, 0x1c1c7394, 0x1c1c7394, 0x1c1c7394, 0x43d1f34, 0x53f50aa7, 0x53f50aa7, 0x43d1f34, }, 20 },
-  { "gfxterm_quot", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xbc5f6633, 0xda908ab0, 0xbc5f6633, 0xffa9ab74, 0x59c36f00, 0x59c36f00, 0x3ad73295, 0x3ad73295, 0x3ad73295, 0x44575ff3, 0x44575ff3, 0x44575ff3, 0x26a14a21, 0x26a14a21, 0x26a14a21, 0x59c36f00, 0xffa9ab74, 0xffa9ab74, 0x59c36f00, }, 20 },
-  { "gfxterm_quot", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0xad820d6b, 0x9a88ad3, 0xad820d6b, 0x83878814, 0xaa4593fe, 0xaa4593fe, 0xbec19c1b, 0xbec19c1b, 0xbec19c1b, 0x1834917c, 0x1834917c, 0x1834917c, 0x350c3a04, 0x350c3a04, 0x350c3a04, 0xaa4593fe, 0x83878814, 0x83878814, 0xaa4593fe, }, 20 },
-  { "gfxterm_quot", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xe5774112, 0x5ffb1eca, 0xe5774112, 0xb8602c96, 0xc9cbf769, 0xc9cbf769, 0xe4861949, 0xe4861949, 0xe4861949, 0x1a5ed885, 0x1a5ed885, 0x1a5ed885, 0xf314678d, 0xf314678d, 0xf314678d, 0xc9cbf769, 0xb8602c96, 0xb8602c96, 0xc9cbf769, }, 20 },
-  { "gfxterm_quot", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x6af1a2bc, 0xd951ab8b, 0x6af1a2bc, 0xc4a7eb64, 0x9813a416, 0x9813a416, 0xb5e8801c, 0xb5e8801c, 0xb5e8801c, 0x2433062f, 0x2433062f, 0x2433062f, 0x3d893bff, 0x3d893bff, 0x3d893bff, 0x9813a416, 0xc4a7eb64, 0xc4a7eb64, 0x9813a416, }, 20 },
-  { "gfxterm_quot", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0xc6baa18, 0x1c9db179, 0xc6baa18, 0x7acd9fab, 0x5fcf013d, 0x5fcf013d, 0x819b5c4e, 0x819b5c4e, 0x819b5c4e, 0x538b4438, 0x538b4438, 0x538b4438, 0x45f87ba7, 0x45f87ba7, 0x45f87ba7, 0x5fcf013d, 0x7acd9fab, 0x7acd9fab, 0x5fcf013d, }, 20 },
-  { "gfxterm_quot", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0xe424a6ab, 0xb05c0275, 0xe424a6ab, 0xff217cac, 0xdd28f52b, 0xdd28f52b, 0xcd83646c, 0xcd83646c, 0xcd83646c, 0xecbf9d88, 0xecbf9d88, 0xecbf9d88, 0x91075604, 0x91075604, 0x91075604, 0xdd28f52b, 0xff217cac, 0xff217cac, 0xdd28f52b, }, 20 },
-  { "gfxterm_quot", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x4a7dff41, 0xe1ec28fc, 0x4a7dff41, 0xb5c2e4c1, 0x43d1f34, 0x43d1f34, 0xb200c08a, 0xb200c08a, 0xb200c08a, 0xcd0a6922, 0xcd0a6922, 0xcd0a6922, 0x545b6ca4, 0x545b6ca4, 0x545b6ca4, 0x43d1f34, 0xb5c2e4c1, 0xb5c2e4c1, 0x43d1f34, }, 20 },
-  { "gfxterm_piglatin", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xd3d3e4a2, 0x9c635046, 0xd3d3e4a2, 0x902529e5, 0x59c36f00, 0x59c36f00, 0x85e713, 0x85e713, 0x85e713, 0x7e058a75, 0x7e058a75, 0x7e058a75, 0x1cf39fa7, 0x1cf39fa7, 0x1cf39fa7, 0x59c36f00, 0x902529e5, 0x902529e5, 0x59c36f00, }, 20 },
-  { "gfxterm_piglatin", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0xd61c80f5, 0xdf78b496, 0xd61c80f5, 0xf819058a, 0xaa4593fe, 0xaa4593fe, 0xefc0f7e7, 0xefc0f7e7, 0xefc0f7e7, 0x4935fa80, 0x4935fa80, 0x4935fa80, 0x640d51f8, 0x640d51f8, 0x640d51f8, 0xaa4593fe, 0xf819058a, 0xf819058a, 0xaa4593fe, }, 20 },
-  { "gfxterm_piglatin", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0x936bc89d, 0x523a3e80, 0x936bc89d, 0xce7ca519, 0xc9cbf769, 0xc9cbf769, 0xaa99ffb1, 0xaa99ffb1, 0xaa99ffb1, 0x54413e7d, 0x54413e7d, 0x54413e7d, 0xbd0b8175, 0xbd0b8175, 0xbd0b8175, 0xc9cbf769, 0xce7ca519, 0xce7ca519, 0xc9cbf769, }, 20 },
-  { "gfxterm_piglatin", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x4fdd0291, 0x133fa83d, 0x4fdd0291, 0xe18b4b49, 0x9813a416, 0x9813a416, 0x74c38e90, 0x74c38e90, 0x74c38e90, 0xe51808a3, 0xe51808a3, 0xe51808a3, 0xfca23573, 0xfca23573, 0xfca23573, 0x9813a416, 0xe18b4b49, 0xe18b4b49, 0x9813a416, }, 20 },
-  { "gfxterm_piglatin", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0x538203b0, 0x2a92e789, 0x538203b0, 0x25243603, 0x5fcf013d, 0x5fcf013d, 0x5e4d3dd8, 0x5e4d3dd8, 0x5e4d3dd8, 0x8c5d25ae, 0x8c5d25ae, 0x8c5d25ae, 0x9a2e1a31, 0x9a2e1a31, 0x9a2e1a31, 0x5fcf013d, 0x25243603, 0x25243603, 0x5fcf013d, }, 20 },
-  { "gfxterm_piglatin", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0xcfc85125, 0xa5b0e11b, 0xcfc85125, 0xd4cd8b22, 0xdd28f52b, 0xdd28f52b, 0x1af8cddc, 0x1af8cddc, 0x1af8cddc, 0x3bc43438, 0x3bc43438, 0x3bc43438, 0x467cffb4, 0x467cffb4, 0x467cffb4, 0xdd28f52b, 0xd4cd8b22, 0xd4cd8b22, 0xdd28f52b, }, 20 },
-  { "gfxterm_piglatin", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0xf2469ffb, 0x1d0c1d2, 0xf2469ffb, 0xdf9847b, 0x43d1f34, 0x43d1f34, 0xa2837c7a, 0xa2837c7a, 0xa2837c7a, 0xdd89d5d2, 0xdd89d5d2, 0xdd89d5d2, 0x44d8d054, 0x44d8d054, 0x44d8d054, 0x43d1f34, 0xdf9847b, 0xdf9847b, 0x43d1f34, }, 20 },
-  { "gfxterm_ch", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0x27851cc1, 0x15f731b5, 0x27851cc1, 0x6473d186, 0x59c36f00, 0x59c36f00, 0x125bcddf, 0x125bcddf, 0x125bcddf, 0x6cdba0b9, 0x6cdba0b9, 0x6cdba0b9, 0xe2db56b, 0xe2db56b, 0xe2db56b, 0x59c36f00, 0x6473d186, 0x6473d186, 0x59c36f00, }, 20 },
-  { "gfxterm_ch", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0xfcb223c, 0x2c2e18b9, 0xfcb223c, 0x21cea743, 0xaa4593fe, 0xaa4593fe, 0xd700be1a, 0xd700be1a, 0xd700be1a, 0x71f5b37d, 0x71f5b37d, 0x71f5b37d, 0x5ccd1805, 0x5ccd1805, 0x5ccd1805, 0xaa4593fe, 0x21cea743, 0x21cea743, 0xaa4593fe, }, 20 },
-  { "gfxterm_ch", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0x807efaa5, 0xb673036a, 0x807efaa5, 0xdd699721, 0xc9cbf769, 0xc9cbf769, 0xdca3ed4b, 0xdca3ed4b, 0xdca3ed4b, 0x227b2c87, 0x227b2c87, 0x227b2c87, 0xcb31938f, 0xcb31938f, 0xcb31938f, 0xc9cbf769, 0xdd699721, 0xdd699721, 0xc9cbf769, }, 20 },
-  { "gfxterm_ch", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x651d0d50, 0xf0dc38fc, 0x651d0d50, 0xcb4b4488, 0x9813a416, 0x9813a416, 0x80d03ee8, 0x80d03ee8, 0x80d03ee8, 0x110bb8db, 0x110bb8db, 0x110bb8db, 0x8b1850b, 0x8b1850b, 0x8b1850b, 0x9813a416, 0xcb4b4488, 0xcb4b4488, 0x9813a416, }, 20 },
-  { "gfxterm_ch", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0xb9b068f, 0xdc68ac3c, 0xb9b068f, 0x7d3d333c, 0x5fcf013d, 0x5fcf013d, 0xa1f0a6e4, 0xa1f0a6e4, 0xa1f0a6e4, 0x73e0be92, 0x73e0be92, 0x73e0be92, 0x6593810d, 0x6593810d, 0x6593810d, 0x5fcf013d, 0x7d3d333c, 0x7d3d333c, 0x5fcf013d, }, 20 },
-  { "gfxterm_ch", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0xf0789d7e, 0x6f2f2b61, 0xf0789d7e, 0xeb7d4779, 0xdd28f52b, 0xdd28f52b, 0xb995630, 0xb995630, 0xb995630, 0x2aa5afd4, 0x2aa5afd4, 0x2aa5afd4, 0x571d6458, 0x571d6458, 0x571d6458, 0xdd28f52b, 0xeb7d4779, 0xeb7d4779, 0xdd28f52b, }, 20 },
-  { "gfxterm_ch", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x819821ff, 0xdd19128c, 0x819821ff, 0x7e273a7f, 0x43d1f34, 0x43d1f34, 0xf35981d3, 0xf35981d3, 0xf35981d3, 0x8c53287b, 0x8c53287b, 0x8c53287b, 0x15022dfd, 0x15022dfd, 0x15022dfd, 0x43d1f34, 0x7e273a7f, 0x7e273a7f, 0x43d1f34, }, 20 },
-  { "gfxterm_red", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xa99604d1, 0xcf59e852, 0xa99604d1, 0xfebbba0f, 0x59c36f00, 0x59c36f00, 0x53767ce3, 0x53767ce3, 0x53767ce3, 0x2df61185, 0x2df61185, 0x2df61185, 0x4f000457, 0x4f000457, 0x4f000457, 0x59c36f00, 0xfebbba0f, 0xfebbba0f, 0x59c36f00, }, 20 },
-  { "gfxterm_red", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x7d0a218, 0xa3fa25a0, 0x7d0a218, 0xb777784e, 0xaa4593fe, 0xaa4593fe, 0x35db26e1, 0x35db26e1, 0x35db26e1, 0x932e2b86, 0x932e2b86, 0x932e2b86, 0xbe1680fe, 0xbe1680fe, 0xbe1680fe, 0xaa4593fe, 0xb777784e, 0xb777784e, 0xaa4593fe, }, 20 },
-  { "gfxterm_red", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0x63be90f4, 0xd932cf2c, 0x63be90f4, 0x739b8e5a, 0xc9cbf769, 0xc9cbf769, 0x70a00efe, 0x70a00efe, 0x70a00efe, 0x8e78cf32, 0x8e78cf32, 0x8e78cf32, 0x6732703a, 0x6732703a, 0x6732703a, 0xc9cbf769, 0x739b8e5a, 0x739b8e5a, 0xc9cbf769, }, 20 },
-  { "gfxterm_red", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x53460c90, 0xe0e605a7, 0x53460c90, 0x6337f0bf, 0x9813a416, 0x9813a416, 0x4161864c, 0x4161864c, 0x4161864c, 0xd0ba007f, 0xd0ba007f, 0xd0ba007f, 0xc9003daf, 0xc9003daf, 0xc9003daf, 0x9813a416, 0x6337f0bf, 0x6337f0bf, 0x9813a416, }, 20 },
-  { "gfxterm_red", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0xf54761a0, 0xe5b17ac1, 0xf54761a0, 0x5b408e55, 0x5fcf013d, 0x5fcf013d, 0x580fda0e, 0x580fda0e, 0x580fda0e, 0x8a1fc278, 0x8a1fc278, 0x8a1fc278, 0x9c6cfde7, 0x9c6cfde7, 0x9c6cfde7, 0x5fcf013d, 0x5b408e55, 0x5b408e55, 0x5fcf013d, }, 20 },
-  { "gfxterm_red", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0xec78b0c1, 0xb800141f, 0xec78b0c1, 0x621c7b1b, 0xdd28f52b, 0xdd28f52b, 0x8f60179, 0x8f60179, 0x8f60179, 0x29caf89d, 0x29caf89d, 0x29caf89d, 0x54723311, 0x54723311, 0x54723311, 0xdd28f52b, 0x621c7b1b, 0x621c7b1b, 0xdd28f52b, }, 20 },
-  { "gfxterm_red", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0xf209411b, 0x599896a6, 0xf209411b, 0x6551c7bb, 0x43d1f34, 0x43d1f34, 0x5ac6bb4a, 0x5ac6bb4a, 0x5ac6bb4a, 0x25cc12e2, 0x25cc12e2, 0x25cc12e2, 0xbc9d1764, 0xbc9d1764, 0xbc9d1764, 0x43d1f34, 0x6551c7bb, 0x6551c7bb, 0x43d1f34, }, 20 },
-  { "gfxterm_high", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0x93b4fcd8, 0xf57b105b, 0x93b4fcd8, 0x2bfe5312, 0x59c36f00, 0x59c36f00, 0x3ad73295, 0x3ad73295, 0x3ad73295, 0x44575ff3, 0x44575ff3, 0x44575ff3, 0x26a14a21, 0x26a14a21, 0x26a14a21, 0x59c36f00, 0x2bfe5312, 0x2bfe5312, 0x59c36f00, }, 20 },
-  { "gfxterm_high", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x656c9044, 0xc14617fc, 0x656c9044, 0xa6ea58cb, 0xaa4593fe, 0xaa4593fe, 0xbec19c1b, 0xbec19c1b, 0xbec19c1b, 0x1834917c, 0x1834917c, 0x1834917c, 0x350c3a04, 0x350c3a04, 0x350c3a04, 0xaa4593fe, 0xa6ea58cb, 0xa6ea58cb, 0xaa4593fe, }, 20 },
-  { "gfxterm_high", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xa11479ed, 0x1b982635, 0xa11479ed, 0xe37185d0, 0xc9cbf769, 0xc9cbf769, 0xe4861949, 0xe4861949, 0xe4861949, 0x1a5ed885, 0x1a5ed885, 0x1a5ed885, 0xf314678d, 0xf314678d, 0xf314678d, 0xc9cbf769, 0xe37185d0, 0xe37185d0, 0xc9cbf769, }, 20 },
-  { "gfxterm_high", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x244770a7, 0x97e77990, 0x244770a7, 0x6a54d2ee, 0x9813a416, 0x9813a416, 0xb5e8801c, 0xb5e8801c, 0xb5e8801c, 0x2433062f, 0x2433062f, 0x2433062f, 0x3d893bff, 0x3d893bff, 0x3d893bff, 0x9813a416, 0x6a54d2ee, 0x6a54d2ee, 0x9813a416, }, 20 },
-  { "gfxterm_high", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0x8ca34476, 0x9c555f17, 0x8ca34476, 0x1fc54b41, 0x5fcf013d, 0x5fcf013d, 0x819b5c4e, 0x819b5c4e, 0x819b5c4e, 0x538b4438, 0x538b4438, 0x538b4438, 0x45f87ba7, 0x45f87ba7, 0x45f87ba7, 0x5fcf013d, 0x1fc54b41, 0x1fc54b41, 0x5fcf013d, }, 20 },
-  { "gfxterm_high", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0xf19f6af8, 0xa5e7ce26, 0xf19f6af8, 0x1619aea6, 0xdd28f52b, 0xdd28f52b, 0xcd83646c, 0xcd83646c, 0xcd83646c, 0xecbf9d88, 0xecbf9d88, 0xecbf9d88, 0x91075604, 0x91075604, 0x91075604, 0xdd28f52b, 0x1619aea6, 0x1619aea6, 0xdd28f52b, }, 20 },
-  { "gfxterm_high", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x5f75414f, 0xf4e496f2, 0x5f75414f, 0x27fd1fe0, 0x43d1f34, 0x43d1f34, 0xb200c08a, 0xb200c08a, 0xb200c08a, 0xcd0a6922, 0xcd0a6922, 0xcd0a6922, 0x545b6ca4, 0x545b6ca4, 0x545b6ca4, 0x43d1f34, 0x27fd1fe0, 0x27fd1fe0, 0x43d1f34, }, 20 },
-  { "videotest", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x1368a483, 0x1368a483, 0x1368a483, 0x1368a483, 0x1368a483, }, 5 },
-  { "videotest", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0x7033079c, 0x7033079c, 0x7033079c, 0x7033079c, 0x7033079c, }, 5 },
-  { "videotest", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xff583fbf, 0xff583fbf, 0xff583fbf, 0xff583fbf, 0xff583fbf, }, 5 },
-  { "videotest", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x4c2cef83, 0x1b215a88, 0xe2378595, 0xb53a309e, 0x15f64d5e, }, 5 },
-  { "videotest", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x758f388c, 0xd4442397, 0x33f5784b, 0x923e6350, 0xf97bb902, }, 5 },
-  { "videotest", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xb9f6f52a, 0x4e24e8b7, 0x53beb8e1, 0xa46ca57c, 0x688a184d, }, 5 },
-  { "videotest", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x5bd98ce3, 0x15df7962, 0xc7d467e1, 0x89d29260, 0x662e2c16, }, 5 },
-  { "videotest", 640, 480, 0x2, 256, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi256 */, (grub_uint32_t []) { 0xf9847b65, 0xf9847b65, 0xf9847b65, 0xf9847b65, 0xf9847b65, }, 5 },
-  { "videotest", 800, 600, 0x2, 256, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi256 */, (grub_uint32_t []) { 0xc421716d, 0xc421716d, 0xc421716d, 0xc421716d, 0xc421716d, }, 5 },
-  { "videotest", 1024, 768, 0x2, 256, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi256 */, (grub_uint32_t []) { 0x5d46f2a8, 0x5d46f2a8, 0x5d46f2a8, 0x5d46f2a8, 0x5d46f2a8, }, 5 },
-  { "videotest", 640, 480, 0x1, 256, 15, 2, 10, 5, 5, 5, 0, 5, 0, 0 /* 640x480xrgba5550 */, (grub_uint32_t []) { 0x25690db2, 0x25690db2, 0x25690db2, 0x25690db2, 0x25690db2, }, 5 },
-  { "videotest", 800, 600, 0x1, 256, 15, 2, 10, 5, 5, 5, 0, 5, 0, 0 /* 800x600xrgba5550 */, (grub_uint32_t []) { 0x7333f220, 0x7333f220, 0x7333f220, 0x7333f220, 0x7333f220, }, 5 },
-  { "videotest", 1024, 768, 0x1, 256, 15, 2, 10, 5, 5, 5, 0, 5, 0, 0 /* 1024x768xrgba5550 */, (grub_uint32_t []) { 0xac52d537, 0xac52d537, 0xac52d537, 0xac52d537, 0xac52d537, }, 5 },
-  { "videotest", 640, 480, 0x1, 256, 16, 2, 11, 5, 5, 6, 0, 5, 0, 0 /* 640x480xrgba5650 */, (grub_uint32_t []) { 0xd4cbcd66, 0xd4cbcd66, 0xd4cbcd66, 0xd4cbcd66, 0xd4cbcd66, }, 5 },
-  { "videotest", 800, 600, 0x1, 256, 16, 2, 11, 5, 5, 6, 0, 5, 0, 0 /* 800x600xrgba5650 */, (grub_uint32_t []) { 0x9d23f9d1, 0x9d23f9d1, 0x9d23f9d1, 0x9d23f9d1, 0x9d23f9d1, }, 5 },
-  { "videotest", 1024, 768, 0x1, 256, 16, 2, 11, 5, 5, 6, 0, 5, 0, 0 /* 1024x768xrgba5650 */, (grub_uint32_t []) { 0x89acbf88, 0x89acbf88, 0x89acbf88, 0x89acbf88, 0x89acbf88, }, 5 },
-  { "videotest", 640, 480, 0x1, 256, 24, 3, 16, 8, 8, 8, 0, 8, 0, 0 /* 640x480xrgba8880 */, (grub_uint32_t []) { 0x335fadcb, 0x1f517b5c, 0x6b4200e5, 0x474cd672, 0x8364f797, }, 5 },
-  { "videotest", 800, 600, 0x1, 256, 24, 3, 16, 8, 8, 8, 0, 8, 0, 0 /* 800x600xrgba8880 */, (grub_uint32_t []) { 0xcf9985f8, 0x1d92c7fc, 0x6e637701, 0xbc683505, 0x898016fb, }, 5 },
-  { "videotest", 1024, 768, 0x1, 256, 24, 3, 16, 8, 8, 8, 0, 8, 0, 0 /* 1024x768xrgba8880 */, (grub_uint32_t []) { 0xdb824190, 0x378d05dc, 0x670bff9, 0xea7ffbb5, 0x658bcbb3, }, 5 },
-  { "videotest", 640, 480, 0x1, 256, 15, 2, 0, 5, 5, 5, 10, 5, 0, 0 /* 640x480xbgra5550 */, (grub_uint32_t []) { 0x18ed532e, 0x18ed532e, 0x18ed532e, 0x18ed532e, 0x18ed532e, }, 5 },
-  { "videotest", 800, 600, 0x1, 256, 15, 2, 0, 5, 5, 5, 10, 5, 0, 0 /* 800x600xbgra5550 */, (grub_uint32_t []) { 0x2b35b09f, 0x2b35b09f, 0x2b35b09f, 0x2b35b09f, 0x2b35b09f, }, 5 },
-  { "videotest", 1024, 768, 0x1, 256, 15, 2, 0, 5, 5, 5, 10, 5, 0, 0 /* 1024x768xbgra5550 */, (grub_uint32_t []) { 0xa24c4d98, 0xa24c4d98, 0xa24c4d98, 0xa24c4d98, 0xa24c4d98, }, 5 },
-  { "videotest", 640, 480, 0x1, 256, 16, 2, 0, 5, 5, 6, 11, 5, 0, 0 /* 640x480xbgra5650 */, (grub_uint32_t []) { 0xc07dde33, 0xc07dde33, 0xc07dde33, 0xc07dde33, 0xc07dde33, }, 5 },
-  { "videotest", 800, 600, 0x1, 256, 16, 2, 0, 5, 5, 6, 11, 5, 0, 0 /* 800x600xbgra5650 */, (grub_uint32_t []) { 0x7e6ed757, 0x7e6ed757, 0x7e6ed757, 0x7e6ed757, 0x7e6ed757, }, 5 },
-  { "videotest", 1024, 768, 0x1, 256, 16, 2, 0, 5, 5, 6, 11, 5, 0, 0 /* 1024x768xbgra5650 */, (grub_uint32_t []) { 0x700255dd, 0x700255dd, 0x700255dd, 0x700255dd, 0x700255dd, }, 5 },
-  { "videotest", 640, 480, 0x1, 256, 24, 3, 0, 8, 8, 8, 16, 8, 0, 0 /* 640x480xbgra8880 */, (grub_uint32_t []) { 0x157232bd, 0x5e6bdacd, 0x8341e25d, 0xc8580a2d, 0x3cf9e58c, }, 5 },
-  { "videotest", 800, 600, 0x1, 256, 24, 3, 0, 8, 8, 8, 16, 8, 0, 0 /* 800x600xbgra8880 */, (grub_uint32_t []) { 0xbfafd7cd, 0x51650951, 0x67d61c04, 0x891cc298, 0xab036ae, }, 5 },
-  { "videotest", 1024, 768, 0x1, 256, 24, 3, 0, 8, 8, 8, 16, 8, 0, 0 /* 1024x768xbgra8880 */, (grub_uint32_t []) { 0x760580c9, 0xdc6d8205, 0x2739f3a0, 0x8d51f16c, 0xd47d661b, }, 5 },
-  { "videotest", 640, 480, 0x1, 256, 32, 4, 0, 8, 8, 8, 16, 8, 24, 8 /* 640x480xbgra8888 */, (grub_uint32_t []) { 0xada3b5f, 0x24cd61a6, 0x56f48ead, 0x78e3d454, 0xb28750bb, }, 5 },
-  { "videotest", 800, 600, 0x1, 256, 32, 4, 0, 8, 8, 8, 16, 8, 24, 8 /* 800x600xbgra8888 */, (grub_uint32_t []) { 0x827694e2, 0x9d97c3dd, 0xbdb43a9c, 0xa2556da3, 0xfdf3c81e, }, 5 },
-  { "videotest", 1024, 768, 0x1, 256, 32, 4, 0, 8, 8, 8, 16, 8, 24, 8 /* 1024x768xbgra8888 */, (grub_uint32_t []) { 0x664534a5, 0xcd0979a0, 0x3531d85e, 0x9e7d955b, 0xc0aced53, }, 5 },
+  { "cmdline_cat", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xc69be699, 0xc69be699, 0xe17fc97c, 0xe17fc97c, 0xc2512486, 0xc2512486, 0x20260761, 0x20260761, 0xe3485349, 0xe3485349, 0x6020b4d9, 0x6020b4d9, 0x1605db98, 0x1605db98, 0xdca51b58, 0xdca51b58, 0xf3d66441, 0xf3d66441, 0x18cb7ce2, 0x18cb7ce2, 0x23b616d9, 0x23b616d9, 0xa1bf5dbf, 0xa1bf5dbf, 0x5e4a8b3d, 0x5e4a8b3d, 0x9933b3d8, 0x9933b3d8, 0xce7be2de, 0xce7be2de, 0x62531729, 0x62531729, 0xc39d3788, 0xc39d3788, 0xf7aee2fe, 0xf7aee2fe, 0xc66f4903, 0xc66f4903, 0x536c922f, 0x536c922f, 0xcb231652, 0x4ae07b67, 0x146816d5, 0x146816d5, }, 45 },
+  { "cmdline_cat", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x29d0cfb7, 0x29d0cfb7, 0x4d57ad88, 0x4d57ad88, 0xaf7591cb, 0xaf7591cb, 0xb88e3c0, 0xb88e3c0, 0x5d55a031, 0x5d55a031, 0x4363bcff, 0x4363bcff, 0xe1142833, 0xe1142833, 0x9578c80d, 0x9578c80d, 0xff1f5174, 0xff1f5174, 0x6828d47, 0x6828d47, 0x2a849ae3, 0x2a849ae3, 0x27a811d9, 0x27a811d9, 0x6c42e1cb, 0x6c42e1cb, 0x5bba61f5, 0x5bba61f5, 0xc02ab705, 0xc02ab705, 0xeb3e0e05, 0xeb3e0e05, 0x6f4ce3c, 0x6f4ce3c, 0x2075c50e, 0x2075c50e, 0x54ac7fba, 0x54ac7fba, 0x335d1c21, 0x335d1c21, 0xf923fbd1, 0x1b489d4d, 0x1253eb5e, 0x1253eb5e, }, 45 },
+  { "cmdline_cat", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0x6ff92a98, 0x6ff92a98, 0xbd8264b3, 0xbd8264b3, 0x5c50282c, 0x5c50282c, 0xd18d6a5a, 0xd18d6a5a, 0x99cea139, 0x99cea139, 0x2590c545, 0x2590c545, 0x55c86045, 0x55c86045, 0xad53ef1e, 0xad53ef1e, 0x5b44a23a, 0x5b44a23a, 0xa255f863, 0xa255f863, 0x85b0bdca, 0x85b0bdca, 0x4220ee1f, 0x4220ee1f, 0xeb991a9f, 0xeb991a9f, 0x86f366dd, 0x86f366dd, 0xfa176b7d, 0xfa176b7d, 0xd7384ca9, 0xd7384ca9, 0xceebf5c1, 0xceebf5c1, 0xae62b268, 0xae62b268, 0x6e89bbd6, 0x6e89bbd6, 0x3fe07c8e, 0x3fe07c8e, 0xee5358fe, 0x162d1a8a, 0x876f8d10, 0x876f8d10, }, 45 },
+  { "cmdline_cat", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0xb96afaea, 0xb96afaea, 0xaa16ab1e, 0xaa16ab1e, 0x51ff382, 0x51ff382, 0xec74f127, 0xec74f127, 0xde4bca99, 0xde4bca99, 0x8ef3e8a5, 0x8ef3e8a5, 0x2daeb0b4, 0x2daeb0b4, 0x7cf5e243, 0x7cf5e243, 0x11fd57c6, 0x11fd57c6, 0x140723af, 0x140723af, 0x2bd93833, 0x2bd93833, 0xd731f4ac, 0xd731f4ac, 0x5fcd7114, 0x5fcd7114, 0xd1fea24a, 0xd1fea24a, 0x4083d53a, 0x4083d53a, 0x2e372605, 0x2e372605, 0x8e6316a7, 0x8e6316a7, 0x283ef6cc, 0x283ef6cc, 0x20cee9de, 0x20cee9de, 0xad6fa187, 0xad6fa187, 0xd691f438, 0xf3257e63, 0x4786ba7, 0x4786ba7, }, 45 },
+  { "cmdline_cat", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0x48acf1bf, 0x48acf1bf, 0xb8777469, 0xb8777469, 0xad2fad44, 0xad2fad44, 0xa415ac59, 0xa415ac59, 0x5a7bfb26, 0x5a7bfb26, 0xccb6016, 0xccb6016, 0x77a80cb3, 0x77a80cb3, 0x2034c102, 0x2034c102, 0x444b4ccd, 0x444b4ccd, 0xe6c31bea, 0xe6c31bea, 0x8408036e, 0x8408036e, 0x9e7c556f, 0x9e7c556f, 0x445dc388, 0x445dc388, 0x94b3f850, 0x94b3f850, 0xf6f15341, 0xf6f15341, 0xcb939b5f, 0xcb939b5f, 0xbe88067d, 0xbe88067d, 0x1efc4734, 0x1efc4734, 0x7f5dfca8, 0x7f5dfca8, 0xb7b10eb9, 0xb7b10eb9, 0xb94cb441, 0x9571329, 0x8a26912b, 0x8a26912b, }, 45 },
+  { "cmdline_cat", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0xc508d04e, 0xc508d04e, 0x6dbccbfe, 0x6dbccbfe, 0xbf06ff60, 0xbf06ff60, 0xbc5ab06, 0xbc5ab06, 0x97eeab3c, 0x97eeab3c, 0x62663589, 0x62663589, 0xb03e21e2, 0xb03e21e2, 0xea196bb6, 0xea196bb6, 0x672c16c4, 0x672c16c4, 0xefbca2cd, 0xefbca2cd, 0x1af5b410, 0x1af5b410, 0xc7a80569, 0xc7a80569, 0x4926a16, 0x4926a16, 0xee29c99c, 0xee29c99c, 0xffb15985, 0xffb15985, 0x4f608e46, 0x4f608e46, 0x3e450fd2, 0x3e450fd2, 0xac45215f, 0xac45215f, 0x789b0ce7, 0x789b0ce7, 0x4cedfe22, 0x4cedfe22, 0xa005588c, 0x701da05c, 0x6f25cec1, 0x6f25cec1, }, 45 },
+  { "cmdline_cat", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x29e7a7f, 0x29e7a7f, 0xbd221052, 0xbd221052, 0x3b18b64, 0x3b18b64, 0x7f1e8462, 0x7f1e8462, 0xf28d5124, 0xf28d5124, 0xc336f170, 0xc336f170, 0xfe3bf988, 0xfe3bf988, 0x7bf89e05, 0x7bf89e05, 0x7857a3f8, 0x7857a3f8, 0x272c1a36, 0x272c1a36, 0xe8adb445, 0xe8adb445, 0x70cfe280, 0x70cfe280, 0x4f2b6120, 0x4f2b6120, 0xbaf5caa5, 0xbaf5caa5, 0x4b6bcab2, 0x4b6bcab2, 0x2bef7b92, 0x2bef7b92, 0x17b381dc, 0x17b381dc, 0x884c9c35, 0x884c9c35, 0x2f9eb909, 0x2f9eb909, 0xa811b3af, 0xa811b3af, 0x4c39478f, 0x5a72c3ab, 0x8071678a, 0x8071678a, }, 45 },
+  { "gfxterm_menu", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xd9f04953, 0xbf3fa5d0, 0xd9f04953, 0x9a068414, 0x59c36f00, 0x59c36f00, 0x620c0067, 0x620c0067, 0x620c0067, 0x1c8c6d01, 0x1c8c6d01, 0x1c8c6d01, 0xc3269013, 0xc3269013, 0xc3269013, 0x59c36f00, 0x9a068414, 0x9a068414, 0x59c36f00, }, 20 },
+  { "gfxterm_menu", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x9254157f, 0x367e92c7, 0x9254157f, 0xbc519000, 0xaa4593fe, 0xaa4593fe, 0xa8a596c8, 0xa8a596c8, 0xa8a596c8, 0xe509baf, 0xe509baf, 0xe509baf, 0x16f0dc06, 0x16f0dc06, 0x16f0dc06, 0xaa4593fe, 0xbc519000, 0xbc519000, 0xaa4593fe, }, 20 },
+  { "gfxterm_menu", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0x354b1976, 0x8fc746ae, 0x354b1976, 0x685c74f2, 0xc9cbf769, 0xc9cbf769, 0x3ce35e1d, 0x3ce35e1d, 0x3ce35e1d, 0xc23b9fd1, 0xc23b9fd1, 0xc23b9fd1, 0x5b18528e, 0x5b18528e, 0x5b18528e, 0xc9cbf769, 0x685c74f2, 0x685c74f2, 0xc9cbf769, }, 20 },
+  { "gfxterm_menu", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x1c9ec014, 0xaf3ec923, 0x1c9ec014, 0x43f5296, 0x9813a416, 0x9813a416, 0x43fda3fa, 0x43fda3fa, 0x43fda3fa, 0xd22625c9, 0xd22625c9, 0xd22625c9, 0x76a62c0a, 0x76a62c0a, 0x76a62c0a, 0x9813a416, 0x43f5296, 0x43f5296, 0x9813a416, }, 20 },
+  { "gfxterm_menu", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0xa704f7ea, 0xb7f2ec8b, 0xa704f7ea, 0xb279bf59, 0x5fcf013d, 0x5fcf013d, 0xf3582c48, 0xf3582c48, 0xf3582c48, 0x2148343e, 0x2148343e, 0x2148343e, 0x9c719024, 0x9c719024, 0x9c719024, 0x5fcf013d, 0xb279bf59, 0xb279bf59, 0x5fcf013d, }, 20 },
+  { "gfxterm_menu", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0xf293ce36, 0xa6eb6ae8, 0xf293ce36, 0xcd87647e, 0xdd28f52b, 0xdd28f52b, 0xb3c7ef80, 0xb3c7ef80, 0xb3c7ef80, 0x92fb1664, 0x92fb1664, 0x92fb1664, 0xd15b5e2e, 0xd15b5e2e, 0xd15b5e2e, 0xdd28f52b, 0xcd87647e, 0xcd87647e, 0xdd28f52b, }, 20 },
+  { "gfxterm_menu", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x31e75bd7, 0x9a768c6a, 0x31e75bd7, 0xa8fc31a6, 0x43d1f34, 0x43d1f34, 0xa0717008, 0xa0717008, 0xa0717008, 0xdf7bd9a0, 0xdf7bd9a0, 0xdf7bd9a0, 0x8e5a9312, 0x8e5a9312, 0x8e5a9312, 0x43d1f34, 0xa8fc31a6, 0xa8fc31a6, 0x43d1f34, }, 20 },
+  { "gfxmenu", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0x1ce7bd78, 0x682580f5, 0x1ce7bd78, 0x490ad6fe, 0x9a2e0d26, 0x64eb71ba, 0x64eb71ba, 0x64eb71ba, 0x3833877a, 0x3833877a, 0x3833877a, 0xcfc14f0a, 0xcfc14f0a, 0xcfc14f0a, 0x59c36f00, 0x490ad6fe, 0x490ad6fe, }, 18 },
+  { "gfxmenu", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x2b6ff87d, 0x63ce2ca2, 0x2b6ff87d, 0xf00f044e, 0xa9d58ccd, 0xe2c46577, 0xe2c46577, 0xe2c46577, 0xb79bcf7d, 0xb79bcf7d, 0xb79bcf7d, 0xbc30ed71, 0xbc30ed71, 0xbc30ed71, 0xaa4593fe, 0xf00f044e, 0xf00f044e, }, 18 },
+  { "gfxmenu", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xe61cadba, 0x9880b727, 0xe61cadba, 0xdf5f2fc0, 0x5411be8b, 0x4449774e, 0x4449774e, 0x4449774e, 0x3bf7d1da, 0x3bf7d1da, 0x3bf7d1da, 0xd2ddee01, 0xd2ddee01, 0xd2ddee01, 0xc9cbf769, 0xdf5f2fc0, 0xdf5f2fc0, }, 18 },
+  { "gfxmenu", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x1c3742c9, 0xbe54acf7, 0x9b4ce770, 0xbe54acf7, 0x3111489, 0x740d78cf, 0x314c4c59, 0x314c4c59, 0x314c4c59, 0xdae9a625, 0xdae9a625, 0xdae9a625, 0xcbf8af57, 0xcbf8af57, 0xcbf8af57, 0x1c3742c9, 0x3111489, 0x3111489, }, 18 },
+  { "gfxmenu", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0xcc5a7bed, 0xee571de5, 0x568aaeff, 0xee571de5, 0xe328b7a7, 0xbcda144c, 0xf56e1b60, 0xf56e1b60, 0xf56e1b60, 0x9a27c771, 0x9a27c771, 0x9a27c771, 0xd6d05397, 0xd6d05397, 0xd6d05397, 0xcc5a7bed, 0xe328b7a7, 0xe328b7a7, }, 18 },
+  { "gfxmenu", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xef4a3312, 0x1db9877c, 0x7e1afeae, 0x1db9877c, 0x8fc0c430, 0x5d55a141, 0x96f335c6, 0x96f335c6, 0x96f335c6, 0x504171d8, 0x504171d8, 0x504171d8, 0x69f71c0, 0x69f71c0, 0x69f71c0, 0xef4a3312, 0x8fc0c430, 0x8fc0c430, }, 18 },
+  { "gfxmenu", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x54e48d80, 0x151819bd, 0xea8d4865, 0x151819bd, 0x11d75fd2, 0x6d6bb4bc, 0x650ccd09, 0x650ccd09, 0x650ccd09, 0xe4ff3bd8, 0xe4ff3bd8, 0xe4ff3bd8, 0xc5308b73, 0xc5308b73, 0xc5308b73, 0x54e48d80, 0x11d75fd2, 0x11d75fd2, }, 18 },
+  { "gfxterm_ar", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xd0b06c3d, 0xde50d1a5, 0xd0b06c3d, 0x9346a17a, 0x59c36f00, 0x59c36f00, 0xacff5d47, 0xacff5d47, 0xacff5d47, 0xd27f3021, 0xd27f3021, 0xd27f3021, 0xdd5cd33, 0xdd5cd33, 0xdd5cd33, 0x59c36f00, 0x9346a17a, 0x9346a17a, 0x59c36f00, }, 20 },
+  { "gfxterm_ar", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0xf32d50c1, 0x730a7ed, 0xf32d50c1, 0xdd28d5be, 0xaa4593fe, 0xaa4593fe, 0xba8a2d4c, 0xba8a2d4c, 0xba8a2d4c, 0x1c7f202b, 0x1c7f202b, 0x1c7f202b, 0x4df6782, 0x4df6782, 0x4df6782, 0xaa4593fe, 0xdd28d5be, 0xdd28d5be, 0xaa4593fe, }, 20 },
+  { "gfxterm_ar", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0x711a4ac1, 0x6396f14c, 0x711a4ac1, 0x2c0d2745, 0xc9cbf769, 0xc9cbf769, 0x6b6ccbb0, 0x6b6ccbb0, 0x6b6ccbb0, 0x95b40a7c, 0x95b40a7c, 0x95b40a7c, 0xc97c723, 0xc97c723, 0xc97c723, 0xc9cbf769, 0x2c0d2745, 0x2c0d2745, 0xc9cbf769, }, 20 },
+  { "gfxterm_ar", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x29baad6a, 0x348b1f2b, 0x29baad6a, 0x311b3fe8, 0x9813a416, 0x9813a416, 0xe8e982cc, 0xe8e982cc, 0xe8e982cc, 0x793204ff, 0x793204ff, 0x793204ff, 0xddb20d3c, 0xddb20d3c, 0xddb20d3c, 0x9813a416, 0x311b3fe8, 0x311b3fe8, 0x9813a416, }, 20 },
+  { "gfxterm_ar", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0xf834b3bb, 0x3951bd1a, 0xf834b3bb, 0xed49fb08, 0x5fcf013d, 0x5fcf013d, 0x5aefa2a7, 0x5aefa2a7, 0x5aefa2a7, 0x88ffbad1, 0x88ffbad1, 0x88ffbad1, 0x35c61ecb, 0x35c61ecb, 0x35c61ecb, 0x5fcf013d, 0xed49fb08, 0xed49fb08, 0x5fcf013d, }, 20 },
+  { "gfxterm_ar", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0x7e9a7a47, 0xb1651b5a, 0x7e9a7a47, 0x418ed00f, 0xdd28f52b, 0xdd28f52b, 0x83f9db69, 0x83f9db69, 0x83f9db69, 0xa2c5228d, 0xa2c5228d, 0xa2c5228d, 0xe1656ac7, 0xe1656ac7, 0xe1656ac7, 0xdd28f52b, 0x418ed00f, 0x418ed00f, 0xdd28f52b, }, 20 },
+  { "gfxterm_ar", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0xc6a0340, 0x7dd5855c, 0xc6a0340, 0x95716931, 0x43d1f34, 0x43d1f34, 0x5f1c24c0, 0x5f1c24c0, 0x5f1c24c0, 0x20168d68, 0x20168d68, 0x20168d68, 0x7137c7da, 0x7137c7da, 0x7137c7da, 0x43d1f34, 0x95716931, 0x95716931, 0x43d1f34, }, 20 },
+  { "gfxterm_cyr", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xd3798aaa, 0xab48784c, 0xd3798aaa, 0x908f47ed, 0x59c36f00, 0x59c36f00, 0x1688ec7c, 0x1688ec7c, 0x1688ec7c, 0x6808811a, 0x6808811a, 0x6808811a, 0xb7a27c08, 0xb7a27c08, 0xb7a27c08, 0x59c36f00, 0x908f47ed, 0x908f47ed, 0x59c36f00, }, 20 },
+  { "gfxterm_cyr", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0xc30d9d2a, 0x60b9ed26, 0xc30d9d2a, 0xed081855, 0xaa4593fe, 0xaa4593fe, 0x3eba2192, 0x3eba2192, 0x3eba2192, 0x984f2cf5, 0x984f2cf5, 0x984f2cf5, 0x80ef6b5c, 0x80ef6b5c, 0x80ef6b5c, 0xaa4593fe, 0xed081855, 0xed081855, 0xaa4593fe, }, 20 },
+  { "gfxterm_cyr", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xe469e6af, 0x46ac2012, 0xe469e6af, 0xb97e8b2b, 0xc9cbf769, 0xc9cbf769, 0x60f0d993, 0x60f0d993, 0x60f0d993, 0x9e28185f, 0x9e28185f, 0x9e28185f, 0x70bd500, 0x70bd500, 0x70bd500, 0xc9cbf769, 0xb97e8b2b, 0xb97e8b2b, 0xc9cbf769, }, 20 },
+  { "gfxterm_cyr", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x8538d2ef, 0xab143284, 0x8538d2ef, 0x9d99406d, 0x9813a416, 0x9813a416, 0x7e8326ec, 0x7e8326ec, 0x7e8326ec, 0xef58a0df, 0xef58a0df, 0xef58a0df, 0x4bd8a91c, 0x4bd8a91c, 0x4bd8a91c, 0x9813a416, 0x9d99406d, 0x9d99406d, 0x9813a416, }, 20 },
+  { "gfxterm_cyr", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0x8115198c, 0x1abdaee1, 0x8115198c, 0x9468513f, 0x5fcf013d, 0x5fcf013d, 0xa5e86484, 0xa5e86484, 0xa5e86484, 0x77f87cf2, 0x77f87cf2, 0x77f87cf2, 0xcac1d8e8, 0xcac1d8e8, 0xcac1d8e8, 0x5fcf013d, 0x9468513f, 0x9468513f, 0x5fcf013d, }, 20 },
+  { "gfxterm_cyr", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0xea03b805, 0x74148290, 0xea03b805, 0xd517124d, 0xdd28f52b, 0xdd28f52b, 0x8f6eee40, 0x8f6eee40, 0x8f6eee40, 0xae5217a4, 0xae5217a4, 0xae5217a4, 0xedf25fee, 0xedf25fee, 0xedf25fee, 0xdd28f52b, 0xd517124d, 0xd517124d, 0xdd28f52b, }, 20 },
+  { "gfxterm_cyr", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0xa044490f, 0xe23458db, 0xa044490f, 0x395f237e, 0x43d1f34, 0x43d1f34, 0xe1ca82c2, 0xe1ca82c2, 0xe1ca82c2, 0x9ec02b6a, 0x9ec02b6a, 0x9ec02b6a, 0xcfe161d8, 0xcfe161d8, 0xcfe161d8, 0x43d1f34, 0x395f237e, 0x395f237e, 0x43d1f34, }, 20 },
+  { "gfxterm_heb", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xf3259b30, 0xf1f01411, 0xf3259b30, 0xb0d35677, 0x59c36f00, 0x59c36f00, 0x97895f8e, 0x97895f8e, 0x97895f8e, 0xe90932e8, 0xe90932e8, 0xe90932e8, 0x36a3cffa, 0x36a3cffa, 0x36a3cffa, 0x59c36f00, 0xb0d35677, 0xb0d35677, 0x59c36f00, }, 20 },
+  { "gfxterm_heb", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x53a43759, 0xe0f26bfa, 0x53a43759, 0x7da1b226, 0xaa4593fe, 0xaa4593fe, 0xbf482a4e, 0xbf482a4e, 0xbf482a4e, 0x19bd2729, 0x19bd2729, 0x19bd2729, 0x11d6080, 0x11d6080, 0x11d6080, 0xaa4593fe, 0x7da1b226, 0x7da1b226, 0xaa4593fe, }, 20 },
+  { "gfxterm_heb", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xd7ff8d53, 0x665b2728, 0xd7ff8d53, 0x8ae8e0d7, 0xc9cbf769, 0xc9cbf769, 0x5a693e73, 0x5a693e73, 0x5a693e73, 0xa4b1ffbf, 0xa4b1ffbf, 0xa4b1ffbf, 0x3d9232e0, 0x3d9232e0, 0x3d9232e0, 0xc9cbf769, 0x8ae8e0d7, 0x8ae8e0d7, 0xc9cbf769, }, 20 },
+  { "gfxterm_heb", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x99fddcbe, 0x6d5c8895, 0x99fddcbe, 0x815c4e3c, 0x9813a416, 0x9813a416, 0x9bcf9821, 0x9bcf9821, 0x9bcf9821, 0xa141e12, 0xa141e12, 0xa141e12, 0xae9417d1, 0xae9417d1, 0xae9417d1, 0x9813a416, 0x815c4e3c, 0x815c4e3c, 0x9813a416, }, 20 },
+  { "gfxterm_heb", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0x5797846, 0x25a6ad40, 0x5797846, 0x100430f5, 0x5fcf013d, 0x5fcf013d, 0xddc86daf, 0xddc86daf, 0xddc86daf, 0xfd875d9, 0xfd875d9, 0xfd875d9, 0xb2e1d1c3, 0xb2e1d1c3, 0xb2e1d1c3, 0x5fcf013d, 0x100430f5, 0x100430f5, 0x5fcf013d, }, 20 },
+  { "gfxterm_heb", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0x30653ae8, 0x7fcd187, 0x30653ae8, 0xf7190a0, 0xdd28f52b, 0xdd28f52b, 0x24c3d325, 0x24c3d325, 0x24c3d325, 0x5ff2ac1, 0x5ff2ac1, 0x5ff2ac1, 0x465f628b, 0x465f628b, 0x465f628b, 0xdd28f52b, 0xf7190a0, 0xf7190a0, 0xdd28f52b, }, 20 },
+  { "gfxterm_heb", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x3bd91638, 0x1d74dd4a, 0x3bd91638, 0xa2c27c49, 0x43d1f34, 0x43d1f34, 0x53d1ad3d, 0x53d1ad3d, 0x53d1ad3d, 0x2cdb0495, 0x2cdb0495, 0x2cdb0495, 0x7dfa4e27, 0x7dfa4e27, 0x7dfa4e27, 0x43d1f34, 0xa2c27c49, 0xa2c27c49, 0x43d1f34, }, 20 },
+  { "gfxterm_gre", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xbe2c351a, 0x2692720, 0xbe2c351a, 0xfddaf85d, 0x59c36f00, 0x59c36f00, 0x1b2e2301, 0x1b2e2301, 0x1b2e2301, 0x65ae4e67, 0x65ae4e67, 0x65ae4e67, 0xba04b375, 0xba04b375, 0xba04b375, 0x59c36f00, 0xfddaf85d, 0xfddaf85d, 0x59c36f00, }, 20 },
+  { "gfxterm_gre", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x1eca82e1, 0xe8fa59cc, 0x1eca82e1, 0x30cf079e, 0xaa4593fe, 0xaa4593fe, 0xaf27ddc5, 0xaf27ddc5, 0xaf27ddc5, 0x9d2d0a2, 0x9d2d0a2, 0x9d2d0a2, 0x1172970b, 0x1172970b, 0x1172970b, 0xaa4593fe, 0x30cf079e, 0x30cf079e, 0xaa4593fe, }, 20 },
+  { "gfxterm_gre", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xa9ccd435, 0x1ac646eb, 0xa9ccd435, 0xf4dbb9b1, 0xc9cbf769, 0xc9cbf769, 0x86d69aa0, 0x86d69aa0, 0x86d69aa0, 0x780e5b6c, 0x780e5b6c, 0x780e5b6c, 0xe12d9633, 0xe12d9633, 0xe12d9633, 0xc9cbf769, 0xf4dbb9b1, 0xf4dbb9b1, 0xc9cbf769, }, 20 },
+  { "gfxterm_gre", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0xf96d568, 0x7ad05c1b, 0xf96d568, 0x173747ea, 0x9813a416, 0x9813a416, 0xacf9792a, 0xacf9792a, 0xacf9792a, 0x3d22ff19, 0x3d22ff19, 0x3d22ff19, 0x99a2f6da, 0x99a2f6da, 0x99a2f6da, 0x9813a416, 0x173747ea, 0x173747ea, 0x9813a416, }, 20 },
+  { "gfxterm_gre", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0xa0dc6b9c, 0xc2761148, 0xa0dc6b9c, 0xb5a1232f, 0x5fcf013d, 0x5fcf013d, 0x4e05748b, 0x4e05748b, 0x4e05748b, 0x9c156cfd, 0x9c156cfd, 0x9c156cfd, 0x212cc8e7, 0x212cc8e7, 0x212cc8e7, 0x5fcf013d, 0xb5a1232f, 0xb5a1232f, 0x5fcf013d, }, 20 },
+  { "gfxterm_gre", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0xcd722f7d, 0xe4df8d6b, 0xcd722f7d, 0xf2668535, 0xdd28f52b, 0xdd28f52b, 0xbdbb8019, 0xbdbb8019, 0xbdbb8019, 0x9c8779fd, 0x9c8779fd, 0x9c8779fd, 0xdf2731b7, 0xdf2731b7, 0xdf2731b7, 0xdd28f52b, 0xf2668535, 0xf2668535, 0xdd28f52b, }, 20 },
+  { "gfxterm_gre", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0xa6c99d2f, 0x1de04317, 0xa6c99d2f, 0x3fd2f75e, 0x43d1f34, 0x43d1f34, 0x3f85b7d3, 0x3f85b7d3, 0x3f85b7d3, 0x408f1e7b, 0x408f1e7b, 0x408f1e7b, 0x11ae54c9, 0x11ae54c9, 0x11ae54c9, 0x43d1f34, 0x3fd2f75e, 0x3fd2f75e, 0x43d1f34, }, 20 },
+  { "gfxterm_ru", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0x1e35b709, 0x2683bf92, 0x1e35b709, 0x5dc37a4e, 0x59c36f00, 0x59c36f00, 0xd697967f, 0xd697967f, 0xd697967f, 0xa817fb19, 0xa817fb19, 0xa817fb19, 0x77bd060b, 0x77bd060b, 0x77bd060b, 0x59c36f00, 0x5dc37a4e, 0x5dc37a4e, 0x59c36f00, }, 20 },
+  { "gfxterm_ru", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x53ff7735, 0x8cbf197c, 0x53ff7735, 0x7dfaf24a, 0xaa4593fe, 0xaa4593fe, 0x389a922, 0x389a922, 0x389a922, 0xa57ca445, 0xa57ca445, 0xa57ca445, 0xbddce3ec, 0xbddce3ec, 0xbddce3ec, 0xaa4593fe, 0x7dfaf24a, 0x7dfaf24a, 0xaa4593fe, }, 20 },
+  { "gfxterm_ru", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0x5217c47d, 0x7c8ae63e, 0x5217c47d, 0xf00a9f9, 0xc9cbf769, 0xc9cbf769, 0x3995409, 0x3995409, 0x3995409, 0xfd4195c5, 0xfd4195c5, 0xfd4195c5, 0x6462589a, 0x6462589a, 0x6462589a, 0xc9cbf769, 0xf00a9f9, 0xf00a9f9, 0xc9cbf769, }, 20 },
+  { "gfxterm_ru", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x45b67706, 0x375fb5db, 0x45b67706, 0x5d17e584, 0x9813a416, 0x9813a416, 0x8195719b, 0x8195719b, 0x8195719b, 0x104ef7a8, 0x104ef7a8, 0x104ef7a8, 0xb4cefe6b, 0xb4cefe6b, 0xb4cefe6b, 0x9813a416, 0x5d17e584, 0x5d17e584, 0x9813a416, }, 20 },
+  { "gfxterm_ru", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0xfc209a25, 0xd5c20779, 0xfc209a25, 0xe95dd296, 0x5fcf013d, 0x5fcf013d, 0xe5699efe, 0xe5699efe, 0xe5699efe, 0x37798688, 0x37798688, 0x37798688, 0x8a402292, 0x8a402292, 0x8a402292, 0x5fcf013d, 0xe95dd296, 0xe95dd296, 0x5fcf013d, }, 20 },
+  { "gfxterm_ru", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0x77f956f0, 0xfb0cc079, 0x77f956f0, 0x48edfcb8, 0xdd28f52b, 0xdd28f52b, 0xd51b1dc9, 0xd51b1dc9, 0xd51b1dc9, 0xf427e42d, 0xf427e42d, 0xf427e42d, 0xb787ac67, 0xb787ac67, 0xb787ac67, 0xdd28f52b, 0x48edfcb8, 0x48edfcb8, 0xdd28f52b, }, 20 },
+  { "gfxterm_ru", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x1d9ac82a, 0xa254aa53, 0x1d9ac82a, 0x8481a25b, 0x43d1f34, 0x43d1f34, 0xc304df68, 0xc304df68, 0xc304df68, 0xbc0e76c0, 0xbc0e76c0, 0xbc0e76c0, 0xed2f3c72, 0xed2f3c72, 0xed2f3c72, 0x43d1f34, 0x8481a25b, 0x8481a25b, 0x43d1f34, }, 20 },
+  { "gfxterm_fr", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xa6239a89, 0x8dc4bfbb, 0xa6239a89, 0xe5d557ce, 0x59c36f00, 0x59c36f00, 0x244cf807, 0x244cf807, 0x244cf807, 0x5acc9561, 0x5acc9561, 0x5acc9561, 0x85666873, 0x85666873, 0x85666873, 0x59c36f00, 0xe5d557ce, 0xe5d557ce, 0x59c36f00, }, 20 },
+  { "gfxterm_fr", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x742cede9, 0x83bb7a50, 0x742cede9, 0x5a296896, 0xaa4593fe, 0xaa4593fe, 0xd83f8aeb, 0xd83f8aeb, 0xd83f8aeb, 0x7eca878c, 0x7eca878c, 0x7eca878c, 0x666ac025, 0x666ac025, 0x666ac025, 0xaa4593fe, 0x5a296896, 0x5a296896, 0xaa4593fe, }, 20 },
+  { "gfxterm_fr", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xe20a98b0, 0x7e8cedef, 0xe20a98b0, 0xbf1df534, 0xc9cbf769, 0xc9cbf769, 0x2748b88c, 0x2748b88c, 0x2748b88c, 0xd9907940, 0xd9907940, 0xd9907940, 0x40b3b41f, 0x40b3b41f, 0x40b3b41f, 0xc9cbf769, 0xbf1df534, 0xbf1df534, 0xc9cbf769, }, 20 },
+  { "gfxterm_fr", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x8f911ca4, 0xcbf1d895, 0x8f911ca4, 0x97308e26, 0x9813a416, 0x9813a416, 0x5b359bf4, 0x5b359bf4, 0x5b359bf4, 0xcaee1dc7, 0xcaee1dc7, 0xcaee1dc7, 0x6e6e1404, 0x6e6e1404, 0x6e6e1404, 0x9813a416, 0x97308e26, 0x97308e26, 0x9813a416, }, 20 },
+  { "gfxterm_fr", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0x1bf82c82, 0xc7b39627, 0x1bf82c82, 0xe856431, 0x5fcf013d, 0x5fcf013d, 0xa9dbae99, 0xa9dbae99, 0xa9dbae99, 0x7bcbb6ef, 0x7bcbb6ef, 0x7bcbb6ef, 0xc6f212f5, 0xc6f212f5, 0xc6f212f5, 0x5fcf013d, 0xe856431, 0xe856431, 0x5fcf013d, }, 20 },
+  { "gfxterm_fr", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0xfae19a5c, 0xd1e8fabb, 0xfae19a5c, 0xc5f53014, 0xdd28f52b, 0xdd28f52b, 0xfa2c5565, 0xfa2c5565, 0xfa2c5565, 0xdb10ac81, 0xdb10ac81, 0xdb10ac81, 0x98b0e4cb, 0x98b0e4cb, 0x98b0e4cb, 0xdd28f52b, 0xc5f53014, 0xc5f53014, 0xdd28f52b, }, 20 },
+  { "gfxterm_fr", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x9a18f7bc, 0x5fcecc43, 0x9a18f7bc, 0x3039dcd, 0x43d1f34, 0x43d1f34, 0x287a2b96, 0x287a2b96, 0x287a2b96, 0x5770823e, 0x5770823e, 0x5770823e, 0x651c88c, 0x651c88c, 0x651c88c, 0x43d1f34, 0x3039dcd, 0x3039dcd, 0x43d1f34, }, 20 },
+  { "gfxterm_quot", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0x65112dfc, 0x3dec17f, 0x65112dfc, 0x26e7e0bb, 0x59c36f00, 0x59c36f00, 0x620c0067, 0x620c0067, 0x620c0067, 0x1c8c6d01, 0x1c8c6d01, 0x1c8c6d01, 0xc3269013, 0xc3269013, 0xc3269013, 0x59c36f00, 0x26e7e0bb, 0x26e7e0bb, 0x59c36f00, }, 20 },
+  { "gfxterm_quot", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x2b3430fb, 0x8f1eb743, 0x2b3430fb, 0x531b584, 0xaa4593fe, 0xaa4593fe, 0xa8a596c8, 0xa8a596c8, 0xa8a596c8, 0xe509baf, 0xe509baf, 0xe509baf, 0x16f0dc06, 0x16f0dc06, 0x16f0dc06, 0xaa4593fe, 0x531b584, 0x531b584, 0xaa4593fe, }, 20 },
+  { "gfxterm_quot", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xb523e920, 0xfafb6f8, 0xb523e920, 0xe83484a4, 0xc9cbf769, 0xc9cbf769, 0x3ce35e1d, 0x3ce35e1d, 0x3ce35e1d, 0xc23b9fd1, 0xc23b9fd1, 0xc23b9fd1, 0x5b18528e, 0x5b18528e, 0x5b18528e, 0xc9cbf769, 0xe83484a4, 0xe83484a4, 0xc9cbf769, }, 20 },
+  { "gfxterm_quot", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0xa9bf7336, 0x1a1f7a01, 0xa9bf7336, 0xb11ee1b4, 0x9813a416, 0x9813a416, 0x43fda3fa, 0x43fda3fa, 0x43fda3fa, 0xd22625c9, 0xd22625c9, 0xd22625c9, 0x76a62c0a, 0x76a62c0a, 0x76a62c0a, 0x9813a416, 0xb11ee1b4, 0xb11ee1b4, 0x9813a416, }, 20 },
+  { "gfxterm_quot", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0xe5271912, 0xf5d10273, 0xe5271912, 0xf05a51a1, 0x5fcf013d, 0x5fcf013d, 0xf3582c48, 0xf3582c48, 0xf3582c48, 0x2148343e, 0x2148343e, 0x2148343e, 0x9c719024, 0x9c719024, 0x9c719024, 0x5fcf013d, 0xf05a51a1, 0xf05a51a1, 0x5fcf013d, }, 20 },
+  { "gfxterm_quot", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0x66a34f49, 0x32dbeb97, 0x66a34f49, 0x59b7e501, 0xdd28f52b, 0xdd28f52b, 0xb3c7ef80, 0xb3c7ef80, 0xb3c7ef80, 0x92fb1664, 0x92fb1664, 0x92fb1664, 0xd15b5e2e, 0xd15b5e2e, 0xd15b5e2e, 0xdd28f52b, 0x59b7e501, 0x59b7e501, 0xdd28f52b, }, 20 },
+  { "gfxterm_quot", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x7c2f19da, 0xd7bece67, 0x7c2f19da, 0xe53473ab, 0x43d1f34, 0x43d1f34, 0xa0717008, 0xa0717008, 0xa0717008, 0xdf7bd9a0, 0xdf7bd9a0, 0xdf7bd9a0, 0x8e5a9312, 0x8e5a9312, 0x8e5a9312, 0x43d1f34, 0xe53473ab, 0xe53473ab, 0x43d1f34, }, 20 },
+  { "gfxterm_piglatin", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0x37943894, 0x78248c70, 0x37943894, 0x7462f5d3, 0x59c36f00, 0x59c36f00, 0xf4be229a, 0xf4be229a, 0xf4be229a, 0x8a3e4ffc, 0x8a3e4ffc, 0x8a3e4ffc, 0x5594b2ee, 0x5594b2ee, 0x5594b2ee, 0x59c36f00, 0x7462f5d3, 0x7462f5d3, 0x59c36f00, }, 20 },
+  { "gfxterm_piglatin", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0xd5158e6c, 0xdc71ba0f, 0xd5158e6c, 0xfb100b13, 0xaa4593fe, 0xaa4593fe, 0xd3ed72a3, 0xd3ed72a3, 0xd3ed72a3, 0x75187fc4, 0x75187fc4, 0x75187fc4, 0x6db8386d, 0x6db8386d, 0x6db8386d, 0xaa4593fe, 0xfb100b13, 0xfb100b13, 0xaa4593fe, }, 20 },
+  { "gfxterm_piglatin", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0x6277a9e6, 0xa3265ffb, 0x6277a9e6, 0x3f60c462, 0xc9cbf769, 0xc9cbf769, 0x2dcf8a8d, 0x2dcf8a8d, 0x2dcf8a8d, 0xd3174b41, 0xd3174b41, 0xd3174b41, 0x4a34861e, 0x4a34861e, 0x4a34861e, 0xc9cbf769, 0x3f60c462, 0x3f60c462, 0xc9cbf769, }, 20 },
+  { "gfxterm_piglatin", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0x81115dc4, 0xddf3f768, 0x81115dc4, 0x99b0cf46, 0x9813a416, 0x9813a416, 0x9b9d96df, 0x9b9d96df, 0x9b9d96df, 0xa4610ec, 0xa4610ec, 0xa4610ec, 0xaec6192f, 0xaec6192f, 0xaec6192f, 0x9813a416, 0x99b0cf46, 0x99b0cf46, 0x9813a416, }, 20 },
+  { "gfxterm_piglatin", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0x5e96a904, 0x27864d3d, 0x5e96a904, 0x4bebe1b7, 0x5fcf013d, 0x5fcf013d, 0x18cae7f4, 0x18cae7f4, 0x18cae7f4, 0xcadaff82, 0xcadaff82, 0xcadaff82, 0x77e35b98, 0x77e35b98, 0x77e35b98, 0x5fcf013d, 0x4bebe1b7, 0x4bebe1b7, 0x5fcf013d, }, 20 },
+  { "gfxterm_piglatin", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0xd00b19f8, 0xba73a9c6, 0xd00b19f8, 0xef1fb3b0, 0xdd28f52b, 0xdd28f52b, 0xb660046d, 0xb660046d, 0xb660046d, 0x975cfd89, 0x975cfd89, 0x975cfd89, 0xd4fcb5c3, 0xd4fcb5c3, 0xd4fcb5c3, 0xdd28f52b, 0xef1fb3b0, 0xef1fb3b0, 0xdd28f52b, }, 20 },
+  { "gfxterm_piglatin", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x8b4b98cd, 0x78ddc6e4, 0x8b4b98cd, 0x1250f2bc, 0x43d1f34, 0x43d1f34, 0x4889d3fd, 0x4889d3fd, 0x4889d3fd, 0x37837a55, 0x37837a55, 0x37837a55, 0x66a230e7, 0x66a230e7, 0x66a230e7, 0x43d1f34, 0x1250f2bc, 0x1250f2bc, 0x43d1f34, }, 20 },
+  { "gfxterm_ch", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0xfecb570e, 0xccb97a7a, 0xfecb570e, 0xbd3d9a49, 0x59c36f00, 0x59c36f00, 0x40281258, 0x40281258, 0x40281258, 0x3ea87f3e, 0x3ea87f3e, 0x3ea87f3e, 0xe102822c, 0xe102822c, 0xe102822c, 0x59c36f00, 0xbd3d9a49, 0xbd3d9a49, 0x59c36f00, }, 20 },
+  { "gfxterm_ch", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0x897d1fac, 0xaa982529, 0x897d1fac, 0xa7789ad3, 0xaa4593fe, 0xaa4593fe, 0xa482510, 0xa482510, 0xa482510, 0xacbd2877, 0xacbd2877, 0xacbd2877, 0xb41d6fde, 0xb41d6fde, 0xb41d6fde, 0xaa4593fe, 0xa7789ad3, 0xa7789ad3, 0xaa4593fe, }, 20 },
+  { "gfxterm_ch", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xd02a5297, 0xe627ab58, 0xd02a5297, 0x8d3d3f13, 0xc9cbf769, 0xc9cbf769, 0xbf0a8b7f, 0xbf0a8b7f, 0xbf0a8b7f, 0x41d24ab3, 0x41d24ab3, 0x41d24ab3, 0xd8f187ec, 0xd8f187ec, 0xd8f187ec, 0xc9cbf769, 0x8d3d3f13, 0x8d3d3f13, 0xc9cbf769, }, 20 },
+  { "gfxterm_ch", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0xa653dcda, 0x3392e976, 0xa653dcda, 0xbef24e58, 0x9813a416, 0x9813a416, 0x4f2bc106, 0x4f2bc106, 0x4f2bc106, 0xdef04735, 0xdef04735, 0xdef04735, 0x7a704ef6, 0x7a704ef6, 0x7a704ef6, 0x9813a416, 0xbef24e58, 0xbef24e58, 0x9813a416, }, 20 },
+  { "gfxterm_ch", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0xe2d7b585, 0x35241f36, 0xe2d7b585, 0xf7aafd36, 0x5fcf013d, 0x5fcf013d, 0xf2bd04db, 0xf2bd04db, 0xf2bd04db, 0x20ad1cad, 0x20ad1cad, 0x20ad1cad, 0x9d94b8b7, 0x9d94b8b7, 0x9d94b8b7, 0x5fcf013d, 0xf7aafd36, 0xf7aafd36, 0x5fcf013d, }, 20 },
+  { "gfxterm_ch", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0x72ff749c, 0xeda8c283, 0x72ff749c, 0x4debded4, 0xdd28f52b, 0xdd28f52b, 0xb8c9cc22, 0xb8c9cc22, 0xb8c9cc22, 0x99f535c6, 0x99f535c6, 0x99f535c6, 0xda557d8c, 0xda557d8c, 0xda557d8c, 0xdd28f52b, 0x4debded4, 0x4debded4, 0xdd28f52b, }, 20 },
+  { "gfxterm_ch", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0xb7cac764, 0xeb4bf417, 0xb7cac764, 0x2ed1ad15, 0x43d1f34, 0x43d1f34, 0xce718801, 0xce718801, 0xce718801, 0xb17b21a9, 0xb17b21a9, 0xb17b21a9, 0xe05a6b1b, 0xe05a6b1b, 0xe05a6b1b, 0x43d1f34, 0x2ed1ad15, 0x2ed1ad15, 0x43d1f34, }, 20 },
+  { "gfxterm_red", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0x930e8e13, 0xf5c16290, 0x930e8e13, 0x27f5f1c0, 0x59c36f00, 0x59c36f00, 0xbad4e11, 0xbad4e11, 0xbad4e11, 0x752d2377, 0x752d2377, 0x752d2377, 0xaa87de65, 0xaa87de65, 0xaa87de65, 0x59c36f00, 0x27f5f1c0, 0x27f5f1c0, 0x59c36f00, }, 20 },
+  { "gfxterm_red", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0xff9301f2, 0x5bb9864a, 0xff9301f2, 0x31c145de, 0xaa4593fe, 0xaa4593fe, 0x23bf2c32, 0x23bf2c32, 0x23bf2c32, 0x854a2155, 0x854a2155, 0x854a2155, 0x9dea66fc, 0x9dea66fc, 0x9dea66fc, 0xaa4593fe, 0x31c145de, 0x31c145de, 0xaa4593fe, }, 20 },
+  { "gfxterm_red", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xfc5938ef, 0x46d56737, 0xfc5938ef, 0x23cf2668, 0xc9cbf769, 0xc9cbf769, 0xa8c549aa, 0xa8c549aa, 0xa8c549aa, 0x561d8866, 0x561d8866, 0x561d8866, 0xcf3e4539, 0xcf3e4539, 0xcf3e4539, 0xc9cbf769, 0x23cf2668, 0x23cf2668, 0xc9cbf769, }, 20 },
+  { "gfxterm_red", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0xe7160822, 0x54b60115, 0xe7160822, 0x168efa6f, 0x9813a416, 0x9813a416, 0xb774a5aa, 0xb774a5aa, 0xb774a5aa, 0x26af2399, 0x26af2399, 0x26af2399, 0x822f2a5a, 0x822f2a5a, 0x822f2a5a, 0x9813a416, 0x168efa6f, 0x168efa6f, 0x9813a416, }, 20 },
+  { "gfxterm_red", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0xf655f9b2, 0xe6a3e2d3, 0xf655f9b2, 0xd1d7405f, 0x5fcf013d, 0x5fcf013d, 0x2accaa08, 0x2accaa08, 0x2accaa08, 0xf8dcb27e, 0xf8dcb27e, 0xf8dcb27e, 0x45e51664, 0x45e51664, 0x45e51664, 0x5fcf013d, 0xd1d7405f, 0xd1d7405f, 0x5fcf013d, }, 20 },
+  { "gfxterm_red", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0x2d85ebdc, 0x79fd4f02, 0x2d85ebdc, 0xc48ae2b6, 0xdd28f52b, 0xdd28f52b, 0x76b28a95, 0x76b28a95, 0x76b28a95, 0x578e7371, 0x578e7371, 0x578e7371, 0x142e3b3b, 0x142e3b3b, 0x142e3b3b, 0xdd28f52b, 0xc48ae2b6, 0xc48ae2b6, 0xdd28f52b, }, 20 },
+  { "gfxterm_red", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x29c00f98, 0x8251d825, 0x29c00f98, 0x35a750d1, 0x43d1f34, 0x43d1f34, 0x48b70bc8, 0x48b70bc8, 0x48b70bc8, 0x37bda260, 0x37bda260, 0x37bda260, 0x669ce8d2, 0x669ce8d2, 0x669ce8d2, 0x43d1f34, 0x35a750d1, 0x35a750d1, 0x43d1f34, }, 20 },
+  { "gfxterm_high", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0x59c36f00, 0x4afab717, 0x2c355b94, 0x4afab717, 0x1166d9d0, 0x59c36f00, 0x59c36f00, 0x620c0067, 0x620c0067, 0x620c0067, 0x1c8c6d01, 0x1c8c6d01, 0x1c8c6d01, 0xc3269013, 0xc3269013, 0xc3269013, 0x59c36f00, 0x1166d9d0, 0x1166d9d0, 0x59c36f00, }, 20 },
+  { "gfxterm_high", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xaa4593fe, 0xe3daadd4, 0x47f02a6c, 0xe3daadd4, 0x5ea9fb21, 0xaa4593fe, 0xaa4593fe, 0xa8a596c8, 0xa8a596c8, 0xa8a596c8, 0xe509baf, 0xe509baf, 0xe509baf, 0x16f0dc06, 0x16f0dc06, 0x16f0dc06, 0xaa4593fe, 0x5ea9fb21, 0x5ea9fb21, 0xaa4593fe, }, 20 },
+  { "gfxterm_high", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0xc9cbf769, 0xf140d1df, 0x4bcc8e07, 0xf140d1df, 0x7c962dcb, 0xc9cbf769, 0xc9cbf769, 0x3ce35e1d, 0x3ce35e1d, 0x3ce35e1d, 0xc23b9fd1, 0xc23b9fd1, 0xc23b9fd1, 0x5b18528e, 0x5b18528e, 0x5b18528e, 0xc9cbf769, 0x7c962dcb, 0x7c962dcb, 0xc9cbf769, }, 20 },
+  { "gfxterm_high", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x9813a416, 0xe709a12d, 0x54a9a81a, 0xe709a12d, 0xde04d65c, 0x9813a416, 0x9813a416, 0x43fda3fa, 0x43fda3fa, 0x43fda3fa, 0xd22625c9, 0xd22625c9, 0xd22625c9, 0x76a62c0a, 0x76a62c0a, 0x76a62c0a, 0x9813a416, 0xde04d65c, 0xde04d65c, 0x9813a416, }, 20 },
+  { "gfxterm_high", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0x5fcf013d, 0x65eff77c, 0x7519ec1d, 0x65eff77c, 0x1cd7d353, 0x5fcf013d, 0x5fcf013d, 0xf3582c48, 0xf3582c48, 0xf3582c48, 0x2148343e, 0x2148343e, 0x2148343e, 0x9c719024, 0x9c719024, 0x9c719024, 0x5fcf013d, 0x1cd7d353, 0x1cd7d353, 0x5fcf013d, }, 20 },
+  { "gfxterm_high", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0xdd28f52b, 0x7318831a, 0x276027c4, 0x7318831a, 0xd7e4f5bb, 0xdd28f52b, 0xdd28f52b, 0xb3c7ef80, 0xb3c7ef80, 0xb3c7ef80, 0x92fb1664, 0x92fb1664, 0x92fb1664, 0xd15b5e2e, 0xd15b5e2e, 0xd15b5e2e, 0xdd28f52b, 0xd7e4f5bb, 0xd7e4f5bb, 0xdd28f52b, }, 20 },
+  { "gfxterm_high", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x43d1f34, 0x6927a7d4, 0xc2b67069, 0x6927a7d4, 0xfc345163, 0x43d1f34, 0x43d1f34, 0xa0717008, 0xa0717008, 0xa0717008, 0xdf7bd9a0, 0xdf7bd9a0, 0xdf7bd9a0, 0x8e5a9312, 0x8e5a9312, 0x8e5a9312, 0x43d1f34, 0xfc345163, 0xfc345163, 0x43d1f34, }, 20 },
+  { "videotest", 640, 480, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi16 */, (grub_uint32_t []) { 0xe6012f70, 0xe6012f70, 0xe6012f70, 0xe6012f70, 0xe6012f70, }, 5 },
+  { "videotest", 800, 600, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi16 */, (grub_uint32_t []) { 0xfb6be77b, 0xfb6be77b, 0xfb6be77b, 0xfb6be77b, 0xfb6be77b, }, 5 },
+  { "videotest", 1024, 768, 0x2, 16, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi16 */, (grub_uint32_t []) { 0x67c0629f, 0x67c0629f, 0x67c0629f, 0x67c0629f, 0x67c0629f, }, 5 },
+  { "videotest", 640, 480, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 640x480xrgba8888 */, (grub_uint32_t []) { 0x8f20afbb, 0xd8f7abc, 0x8f937344, 0xd3ca643, 0x8e471645, }, 5 },
+  { "videotest", 800, 600, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 800x600xrgba8888 */, (grub_uint32_t []) { 0xdca764da, 0x9f76da9a, 0x5b04185a, 0x18d5a61a, 0xd60deb2b, }, 5 },
+  { "videotest", 1024, 768, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 1024x768xrgba8888 */, (grub_uint32_t []) { 0x7b87af36, 0x7cb96093, 0x75fa307c, 0x72c4ffd9, 0x677c91a2, }, 5 },
+  { "videotest", 2560, 1440, 0x1, 256, 32, 4, 16, 8, 8, 8, 0, 8, 24, 8 /* 2560x1440xrgba8888 */, (grub_uint32_t []) { 0x72981c65, 0x50120635, 0x378c28c5, 0x15063295, 0xf8b07525, }, 5 },
+  { "videotest", 640, 480, 0x2, 256, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 640x480xi256 */, (grub_uint32_t []) { 0xc8f64b58, 0xc8f64b58, 0xc8f64b58, 0xc8f64b58, 0xc8f64b58, }, 5 },
+  { "videotest", 800, 600, 0x2, 256, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 800x600xi256 */, (grub_uint32_t []) { 0x2b499dfa, 0x2b499dfa, 0x2b499dfa, 0x2b499dfa, 0x2b499dfa, }, 5 },
+  { "videotest", 1024, 768, 0x2, 256, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0 /* 1024x768xi256 */, (grub_uint32_t []) { 0x6156b420, 0x6156b420, 0x6156b420, 0x6156b420, 0x6156b420, }, 5 },
+  { "videotest", 640, 480, 0x1, 256, 15, 2, 10, 5, 5, 5, 0, 5, 0, 0 /* 640x480xrgba5550 */, (grub_uint32_t []) { 0x363285ca, 0x363285ca, 0x363285ca, 0x363285ca, 0x363285ca, }, 5 },
+  { "videotest", 800, 600, 0x1, 256, 15, 2, 10, 5, 5, 5, 0, 5, 0, 0 /* 800x600xrgba5550 */, (grub_uint32_t []) { 0x25bb37f4, 0x25bb37f4, 0x25bb37f4, 0x25bb37f4, 0x25bb37f4, }, 5 },
+  { "videotest", 1024, 768, 0x1, 256, 15, 2, 10, 5, 5, 5, 0, 5, 0, 0 /* 1024x768xrgba5550 */, (grub_uint32_t []) { 0xeeab9e91, 0xeeab9e91, 0xeeab9e91, 0xeeab9e91, 0xeeab9e91, }, 5 },
+  { "videotest", 640, 480, 0x1, 256, 16, 2, 11, 5, 5, 6, 0, 5, 0, 0 /* 640x480xrgba5650 */, (grub_uint32_t []) { 0x26a9a50b, 0x26a9a50b, 0x26a9a50b, 0x26a9a50b, 0x26a9a50b, }, 5 },
+  { "videotest", 800, 600, 0x1, 256, 16, 2, 11, 5, 5, 6, 0, 5, 0, 0 /* 800x600xrgba5650 */, (grub_uint32_t []) { 0x2c0f4fe7, 0x2c0f4fe7, 0x2c0f4fe7, 0x2c0f4fe7, 0x2c0f4fe7, }, 5 },
+  { "videotest", 1024, 768, 0x1, 256, 16, 2, 11, 5, 5, 6, 0, 5, 0, 0 /* 1024x768xrgba5650 */, (grub_uint32_t []) { 0x46c11052, 0x46c11052, 0x46c11052, 0x46c11052, 0x46c11052, }, 5 },
+  { "videotest", 640, 480, 0x1, 256, 24, 3, 16, 8, 8, 8, 0, 8, 0, 0 /* 640x480xrgba8880 */, (grub_uint32_t []) { 0xe56cf615, 0xcd2be572, 0xb5e2d0db, 0x9da5c3bc, 0x4470bb89, }, 5 },
+  { "videotest", 800, 600, 0x1, 256, 24, 3, 16, 8, 8, 8, 0, 8, 0, 0 /* 800x600xrgba8880 */, (grub_uint32_t []) { 0x2a25b871, 0x4bf85361, 0xe99e6e51, 0x88438541, 0xa8be62c0, }, 5 },
+  { "videotest", 1024, 768, 0x1, 256, 24, 3, 16, 8, 8, 8, 0, 8, 0, 0 /* 1024x768xrgba8880 */, (grub_uint32_t []) { 0x81523037, 0xd8c0bfd3, 0x32772fff, 0x6be5a01b, 0xe2f47956, }, 5 },
+  { "videotest", 640, 480, 0x1, 256, 15, 2, 0, 5, 5, 5, 10, 5, 0, 0 /* 640x480xbgra5550 */, (grub_uint32_t []) { 0x1833bb41, 0x1833bb41, 0x1833bb41, 0x1833bb41, 0x1833bb41, }, 5 },
+  { "videotest", 800, 600, 0x1, 256, 15, 2, 0, 5, 5, 5, 10, 5, 0, 0 /* 800x600xbgra5550 */, (grub_uint32_t []) { 0x2c39a0e8, 0x2c39a0e8, 0x2c39a0e8, 0x2c39a0e8, 0x2c39a0e8, }, 5 },
+  { "videotest", 1024, 768, 0x1, 256, 15, 2, 0, 5, 5, 5, 10, 5, 0, 0 /* 1024x768xbgra5550 */, (grub_uint32_t []) { 0xf0d4c23, 0xf0d4c23, 0xf0d4c23, 0xf0d4c23, 0xf0d4c23, }, 5 },
+  { "videotest", 640, 480, 0x1, 256, 16, 2, 0, 5, 5, 6, 11, 5, 0, 0 /* 640x480xbgra5650 */, (grub_uint32_t []) { 0x456d063c, 0x456d063c, 0x456d063c, 0x456d063c, 0x456d063c, }, 5 },
+  { "videotest", 800, 600, 0x1, 256, 16, 2, 0, 5, 5, 6, 11, 5, 0, 0 /* 800x600xbgra5650 */, (grub_uint32_t []) { 0x47e15a2e, 0x47e15a2e, 0x47e15a2e, 0x47e15a2e, 0x47e15a2e, }, 5 },
+  { "videotest", 1024, 768, 0x1, 256, 16, 2, 0, 5, 5, 6, 11, 5, 0, 0 /* 1024x768xbgra5650 */, (grub_uint32_t []) { 0x54d7300d, 0x54d7300d, 0x54d7300d, 0x54d7300d, 0x54d7300d, }, 5 },
+  { "videotest", 640, 480, 0x1, 256, 24, 3, 0, 8, 8, 8, 16, 8, 0, 0 /* 640x480xbgra8880 */, (grub_uint32_t []) { 0x770da211, 0x8ef2528e, 0x811e35de, 0x78e1c541, 0x9ec6fb7e, }, 5 },
+  { "videotest", 800, 600, 0x1, 256, 24, 3, 0, 8, 8, 8, 16, 8, 0, 0 /* 800x600xbgra8880 */, (grub_uint32_t []) { 0xeb181fbc, 0xae648cc1, 0x61e13946, 0x249daa3b, 0xfb0624b9, }, 5 },
+  { "videotest", 1024, 768, 0x1, 256, 24, 3, 0, 8, 8, 8, 16, 8, 0, 0 /* 1024x768xbgra8880 */, (grub_uint32_t []) { 0x2b6f64dc, 0xc25f8431, 0xfce2d3f7, 0x15d2331a, 0x81987c7b, }, 5 },
+  { "videotest", 640, 480, 0x1, 256, 32, 4, 0, 8, 8, 8, 16, 8, 24, 8 /* 640x480xbgra8888 */, (grub_uint32_t []) { 0xa260f7dd, 0x3e2f4980, 0x9f13fd96, 0x35c43cb, 0xd886e34b, }, 5 },
+  { "videotest", 800, 600, 0x1, 256, 32, 4, 0, 8, 8, 8, 16, 8, 24, 8 /* 800x600xbgra8888 */, (grub_uint32_t []) { 0x41a9bff8, 0xa0d3f7c3, 0x86b1597f, 0x67cb1144, 0xca740407, }, 5 },
+  { "videotest", 1024, 768, 0x1, 256, 32, 4, 0, 8, 8, 8, 16, 8, 24, 8 /* 1024x768xbgra8888 */, (grub_uint32_t []) { 0x8f7a3b6d, 0xcb84c6e3, 0x687c071, 0x42793dff, 0x996dbba4, }, 5 },
diff --git a/include/grub/aout.h b/include/grub/aout.h
index 10d7dde61ececf0e980c6ad62420764fcefd5e67..c8c1d94eca518042992a6fc5e3777f81a39b431d 100644
--- a/include/grub/aout.h
+++ b/include/grub/aout.h
@@ -52,6 +52,7 @@
 #define GRUB_AOUT_HEADER 1
 
 #include <grub/types.h>
+#include <grub/file.h>
 
 struct grub_aout32_header
 {
diff --git a/include/grub/arc/arc.h b/include/grub/arc/arc.h
index 7615a49a92cac0ac16326c188e438b789b09acec..999de7196753b58781a02c5311c9bc3834408021 100644
--- a/include/grub/arc/arc.h
+++ b/include/grub/arc/arc.h
@@ -53,7 +53,7 @@ enum grub_arc_memory_type
 #ifndef GRUB_CPU_WORDS_BIGENDIAN
     GRUB_ARC_MEMORY_FREE_CONTIGUOUS,
 #endif
-  } grub_arc_memory_type_t;
+  };
 
 struct grub_arc_timeinfo
 {
diff --git a/include/grub/arm/coreboot/console.h b/include/grub/arm/coreboot/console.h
new file mode 100644
index 0000000000000000000000000000000000000000..13a14b783839a6cae96845973ae3087bcaef670e
--- /dev/null
+++ b/include/grub/arm/coreboot/console.h
@@ -0,0 +1,29 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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_MACHINE_CONSOLE_HEADER
+#define GRUB_MACHINE_CONSOLE_HEADER	1
+
+void grub_video_coreboot_fb_init (void);
+void grub_video_coreboot_fb_early_init (void);
+void grub_video_coreboot_fb_late_init (void);
+void grub_video_coreboot_fb_fini (void);
+
+extern struct grub_linuxbios_table_framebuffer *grub_video_coreboot_fbtable;
+
+#endif /* ! GRUB_MACHINE_CONSOLE_HEADER */
diff --git a/include/grub/arm/coreboot/kernel.h b/include/grub/arm/coreboot/kernel.h
new file mode 100644
index 0000000000000000000000000000000000000000..2695053427050f306b8ca86ba066df90c519e8e0
--- /dev/null
+++ b/include/grub/arm/coreboot/kernel.h
@@ -0,0 +1,44 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013 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_KERNEL_MACHINE_HEADER
+#define GRUB_KERNEL_MACHINE_HEADER	1
+
+#ifndef ASM_FILE
+
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+struct grub_fdt_board
+{
+  const char *vendor, *part;
+  const grub_uint8_t *dtb;
+  grub_size_t dtb_size;
+};
+
+extern struct grub_fdt_board grub_fdt_boards[];
+void grub_machine_timer_init (void);
+void grub_pl050_init (void);
+void grub_cros_init (void);
+void grub_rk3288_spi_init (void);
+extern grub_addr_t EXPORT_VAR (start_of_ram);
+#endif /* ! ASM_FILE */
+
+#define GRUB_KERNEL_MACHINE_STACK_SIZE GRUB_KERNEL_ARM_STACK_SIZE
+
+#endif /* ! GRUB_KERNEL_MACHINE_HEADER */
diff --git a/include/grub/arm/cros_ec.h b/include/grub/arm/cros_ec.h
new file mode 100644
index 0000000000000000000000000000000000000000..45a372572a5c3c411c9b2b7f328135f5cbe551c8
--- /dev/null
+++ b/include/grub/arm/cros_ec.h
@@ -0,0 +1,21 @@
+#ifndef GRUB_ARM_CROS_EC_H
+#define GRUB_ARM_CROS_EC_H 1
+
+#include <grub/types.h>
+#include <grub/fdtbus.h>
+
+#define GRUB_CROS_EC_KEYSCAN_COLS 13
+#define GRUB_CROS_EC_KEYSCAN_ROWS 8
+
+struct grub_cros_ec_keyscan {
+  grub_uint8_t data[GRUB_CROS_EC_KEYSCAN_COLS];
+};
+
+int
+grub_cros_ec_scan_keyboard (const struct grub_fdtbus_dev *dev,
+			    struct grub_cros_ec_keyscan *scan);
+
+int
+grub_cros_ec_validate (const struct grub_fdtbus_dev *dev);
+
+#endif
diff --git a/include/grub/arm/linux.h b/include/grub/arm/linux.h
index a66caad13db8c5c3b0da10f624d01a81640eab44..712ba17b9ba30cf850b6a9011d08a04d57816227 100644
--- a/include/grub/arm/linux.h
+++ b/include/grub/arm/linux.h
@@ -17,14 +17,28 @@
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef GRUB_LINUX_CPU_HEADER
-#define GRUB_LINUX_CPU_HEADER 1
-
-#define LINUX_ZIMAGE_OFFSET 0x24
-#define LINUX_ZIMAGE_MAGIC  0x016f2818
+#ifndef GRUB_ARM_LINUX_HEADER
+#define GRUB_ARM_LINUX_HEADER 1
 
 #include "system.h"
 
+#define GRUB_LINUX_ARM_MAGIC_SIGNATURE 0x016f2818
+
+struct linux_arm_kernel_header {
+  grub_uint32_t code0;
+  grub_uint32_t reserved1[8];
+  grub_uint32_t magic;
+  grub_uint32_t start; /* _start */
+  grub_uint32_t end;   /* _edata */
+  grub_uint32_t reserved2[4];
+  grub_uint32_t hdr_offset;
+};
+
+#if defined(__arm__)
+# define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM_MAGIC_SIGNATURE
+# define linux_armxx_kernel_header linux_arm_kernel_header
+#endif
+
 #if defined GRUB_MACHINE_UBOOT
 # include <grub/uboot/uboot.h>
 # define LINUX_ADDRESS        (start_of_ram + 0x8000)
@@ -32,15 +46,17 @@
 # define LINUX_FDT_ADDRESS    (LINUX_INITRD_ADDRESS - 0x10000)
 # define grub_arm_firmware_get_boot_data grub_uboot_get_boot_data
 # define grub_arm_firmware_get_machine_type grub_uboot_get_machine_type
-#elif defined GRUB_MACHINE_EFI
-# include <grub/efi/efi.h>
-# include <grub/machine/loader.h>
-/* On UEFI platforms - load the images at the lowest available address not
-   less than *_PHYS_OFFSET from the first available memory location. */
-# define LINUX_PHYS_OFFSET        (0x00008000)
-# define LINUX_INITRD_PHYS_OFFSET (LINUX_PHYS_OFFSET + 0x02000000)
-# define LINUX_FDT_PHYS_OFFSET    (LINUX_INITRD_PHYS_OFFSET - 0x10000)
-# define grub_arm_firmware_get_boot_data (grub_addr_t)grub_efi_get_firmware_fdt
+#elif defined (GRUB_MACHINE_COREBOOT)
+#include <grub/fdtbus.h>
+#include <grub/arm/coreboot/kernel.h>
+# define LINUX_ADDRESS        (start_of_ram + 0x8000)
+# define LINUX_INITRD_ADDRESS (start_of_ram + 0x02000000)
+# define LINUX_FDT_ADDRESS    (LINUX_INITRD_ADDRESS - 0x10000)
+static inline const void *
+grub_arm_firmware_get_boot_data (void)
+{
+  return grub_fdtbus_get_fdt ();
+}
 static inline grub_uint32_t
 grub_arm_firmware_get_machine_type (void)
 {
@@ -48,6 +64,4 @@ grub_arm_firmware_get_machine_type (void)
 }
 #endif
 
-#define FDT_ADDITIONAL_ENTRIES_SIZE	0x300
-
-#endif /* ! GRUB_LINUX_CPU_HEADER */
+#endif /* ! GRUB_ARM_LINUX_HEADER */
diff --git a/include/grub/arm/startup.h b/include/grub/arm/startup.h
new file mode 100644
index 0000000000000000000000000000000000000000..9afb6c57c0bc4c53e96f711bf545d94a8ed07aa5
--- /dev/null
+++ b/include/grub/arm/startup.h
@@ -0,0 +1,16 @@
+#ifndef GRUB_STARTUP_CPU_HEADER
+#define GRUB_STARTUP_CPU_HEADER
+
+struct grub_arm_startup_registers
+{
+  /* registers 0-11 */
+  /* for U-boot r[1] is machine type */
+  /* for U-boot r[2] is boot data */
+  grub_uint32_t r[12];
+  grub_uint32_t sp;
+  grub_uint32_t lr;
+};
+
+extern struct grub_arm_startup_registers grub_arm_saved_registers;
+
+#endif
diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h
index 1ea23696e7a096e53075af2314da11ecce91f8d7..8655067e03924793293ba86cb1bae2e44efa5fee 100644
--- a/include/grub/arm64/linux.h
+++ b/include/grub/arm64/linux.h
@@ -16,17 +16,13 @@
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef GRUB_LINUX_CPU_HEADER
-#define GRUB_LINUX_CPU_HEADER 1
+#ifndef GRUB_ARM64_LINUX_HEADER
+#define GRUB_ARM64_LINUX_HEADER 1
 
-#include <grub/efi/efi.h>
-
-#define GRUB_ARM64_LINUX_MAGIC 0x644d5241 /* 'ARM\x64' */
-
-#define GRUB_EFI_PE_MAGIC	0x5A4D
+#define GRUB_LINUX_ARM64_MAGIC_SIGNATURE 0x644d5241 /* 'ARM\x64' */
 
 /* From linux/Documentation/arm64/booting.txt */
-struct grub_arm64_linux_kernel_header
+struct linux_arm64_kernel_header
 {
   grub_uint32_t code0;		/* Executable code */
   grub_uint32_t code1;		/* Executable code */
@@ -40,9 +36,9 @@ struct grub_arm64_linux_kernel_header
   grub_uint32_t hdr_offset;	/* Offset of PE/COFF header */
 };
 
-grub_err_t grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header
-                                        *lh);
-grub_err_t grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size,
-                                       char *args);
+#if defined(__aarch64__)
+# define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM64_MAGIC_SIGNATURE
+# define linux_armxx_kernel_header linux_arm64_kernel_header
+#endif
 
-#endif /* ! GRUB_LINUX_CPU_HEADER */
+#endif /* ! GRUB_ARM64_LINUX_HEADER */
diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h
index b4f8ff0a06117756a770129683796edf0050b867..bcb4d9ba78f1376bdaa82249418f847eb4e543a6 100644
--- a/include/grub/at_keyboard.h
+++ b/include/grub/at_keyboard.h
@@ -23,13 +23,11 @@
 #define KEYBOARD_COMMAND_ISREADY(x)	!((x) & 0x02)
 #define KEYBOARD_COMMAND_READ		0x20
 #define KEYBOARD_COMMAND_WRITE		0x60
+#define KEYBOARD_COMMAND_ENABLE		0xf4
 #define KEYBOARD_COMMAND_REBOOT		0xfe
 
 #define KEYBOARD_AT_TRANSLATE		0x40
-
-#define GRUB_AT_ACK                     0xfa
-#define GRUB_AT_NACK                    0xfe
-#define GRUB_AT_TRIES                   5
+#define KEYBOARD_AT_DISABLE		0x10
 
 #define KEYBOARD_ISMAKE(x)	!((x) & 0x80)
 #define KEYBOARD_ISREADY(x)	((x) & 0x01)
diff --git a/include/grub/autoefi.h b/include/grub/autoefi.h
index b75591176eb9d785de3f2867e32edc1b9a626280..b7a252e079e2137b4d27639b5c981e9085cb8a82 100644
--- a/include/grub/autoefi.h
+++ b/include/grub/autoefi.h
@@ -55,7 +55,7 @@ static inline grub_err_t grub_autoefi_prepare (void)
 # define SYSTEM_TABLE_PTR GRUB_EFIEMU_SYSTEM_TABLE_PTR
 # define SIZEOF_OF_UINTN GRUB_EFIEMU_SIZEOF_OF_UINTN
 # define SYSTEM_TABLE GRUB_EFIEMU_SYSTEM_TABLE
-# define grub_efi_allocate_pages(x,y) (x)
+# define grub_efi_allocate_fixed(x,y) (x)
 # define grub_efi_free_pages(x,y) GRUB_EFI_SUCCESS
 # define grub_autoefi_finish_boot_services grub_efiemu_finish_boot_services
 # define EFI_PRESENT 1
diff --git a/include/grub/cache.h b/include/grub/cache.h
index fc669dfd1892c14bb43c6230e48067a0ff8e7c23..ccfa717e669625e0db96df0692c65f5a4c5ff916 100644
--- a/include/grub/cache.h
+++ b/include/grub/cache.h
@@ -34,15 +34,16 @@ void EXPORT_FUNC(grub_arch_sync_caches) (void *address, grub_size_t len);
 #endif
 
 #ifndef GRUB_MACHINE_EMU
-#ifdef _mips
-void EXPORT_FUNC(grub_arch_sync_dma_caches) (volatile void *address,
-					     grub_size_t len);
-#else
+#if defined (__aarch64__) || defined (__powerpc__) || defined (__sparc__)
+
+#elif defined (__i386__) || defined (__x86_64__)
 static inline void
 grub_arch_sync_dma_caches (volatile void *address __attribute__ ((unused)),
 			   grub_size_t len __attribute__ ((unused)))
 {
 }
+#else
+void EXPORT_FUNC(grub_arch_sync_dma_caches) (volatile void *address, grub_size_t len);
 #endif
 #endif
 
diff --git a/include/grub/i386/coreboot/lbio.h b/include/grub/coreboot/lbio.h
similarity index 93%
rename from include/grub/i386/coreboot/lbio.h
rename to include/grub/coreboot/lbio.h
index 1c3fa6f1953c3a6b41ea3644c30f000c98524224..5076d36c71ba32e5c55a6242287e5fe159e09b4f 100644
--- a/include/grub/i386/coreboot/lbio.h
+++ b/include/grub/coreboot/lbio.h
@@ -20,6 +20,9 @@
 #ifndef _GRUB_MACHINE_LBIO_HEADER
 #define _GRUB_MACHINE_LBIO_HEADER      1
 
+#include <grub/types.h>
+#include <grub/err.h>
+
 struct grub_linuxbios_table_header
 {
   grub_uint8_t signature[4];
@@ -102,4 +105,10 @@ EXPORT_FUNC(grub_linuxbios_table_iterate) (int (*hook) (grub_linuxbios_table_ite
 					   void *),
 					   void *hook_data);
 
+grub_linuxbios_table_header_t
+grub_linuxbios_get_tables (void);
+
+int
+grub_linuxbios_check_signature (grub_linuxbios_table_header_t tbl_header);
+
 #endif
diff --git a/include/grub/dma.h b/include/grub/dma.h
new file mode 100644
index 0000000000000000000000000000000000000000..19992ebc131d4fc93a45f31992ad3c03b9de2821
--- /dev/null
+++ b/include/grub/dma.h
@@ -0,0 +1,44 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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_DMA_H
+#define	GRUB_DMA_H	1
+
+struct grub_pci_dma_chunk;
+
+struct grub_pci_dma_chunk *EXPORT_FUNC(grub_memalign_dma32) (grub_size_t align,
+							     grub_size_t size);
+void EXPORT_FUNC(grub_dma_free) (struct grub_pci_dma_chunk *ch);
+volatile void *EXPORT_FUNC(grub_dma_get_virt) (struct grub_pci_dma_chunk *ch);
+grub_uint32_t EXPORT_FUNC(grub_dma_get_phys) (struct grub_pci_dma_chunk *ch);
+
+static inline void *
+grub_dma_phys2virt (grub_uint32_t phys, struct grub_pci_dma_chunk *chunk)
+{
+  return ((grub_uint8_t *) grub_dma_get_virt (chunk)
+	  + (phys - grub_dma_get_phys (chunk)));
+}
+
+static inline grub_uint32_t
+grub_dma_virt2phys (volatile void *virt, struct grub_pci_dma_chunk *chunk)
+{
+  return (((grub_uint8_t *) virt - (grub_uint8_t *) grub_dma_get_virt (chunk))
+	  + grub_dma_get_phys (chunk));
+}
+
+#endif
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index e9c601f34103ae1a4ced7e93be8204970bfef193..2c6648d46fc1a377312c81220c38470d9d1cc99a 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -38,16 +38,25 @@ void *EXPORT_FUNC(grub_efi_open_protocol) (grub_efi_handle_t handle,
 int EXPORT_FUNC(grub_efi_set_text_mode) (int on);
 void EXPORT_FUNC(grub_efi_stall) (grub_efi_uintn_t microseconds);
 void *
-EXPORT_FUNC(grub_efi_allocate_pages) (grub_efi_physical_address_t address,
+EXPORT_FUNC(grub_efi_allocate_pages_real) (grub_efi_physical_address_t address,
+				           grub_efi_uintn_t pages,
+					   grub_efi_allocate_type_t alloctype,
+					   grub_efi_memory_type_t memtype);
+void *
+EXPORT_FUNC(grub_efi_allocate_fixed) (grub_efi_physical_address_t address,
 				      grub_efi_uintn_t pages);
+void *
+EXPORT_FUNC(grub_efi_allocate_any_pages) (grub_efi_uintn_t pages);
 void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address,
 				       grub_efi_uintn_t pages);
+grub_efi_uintn_t EXPORT_FUNC(grub_efi_find_mmap_size) (void);
 int
 EXPORT_FUNC(grub_efi_get_memory_map) (grub_efi_uintn_t *memory_map_size,
 				      grub_efi_memory_descriptor_t *memory_map,
 				      grub_efi_uintn_t *map_key,
 				      grub_efi_uintn_t *descriptor_size,
 				      grub_efi_uint32_t *descriptor_version);
+void grub_efi_memory_fini (void);
 grub_efi_loaded_image_t *EXPORT_FUNC(grub_efi_get_loaded_image) (grub_efi_handle_t image_handle);
 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);
@@ -83,6 +92,11 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd,
 
 #if defined(__arm__) || defined(__aarch64__)
 void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void);
+grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *);
+#include <grub/cpu/linux.h>
+grub_err_t grub_armxx_efi_linux_check_image(struct linux_armxx_kernel_header *lh);
+grub_err_t grub_armxx_efi_linux_boot_image(grub_addr_t addr, grub_size_t size,
+                                           char *args);
 #endif
 
 grub_addr_t grub_efi_modules_addr (void);
diff --git a/include/grub/arm64/fdtload.h b/include/grub/efi/fdtload.h
similarity index 89%
rename from include/grub/arm64/fdtload.h
rename to include/grub/efi/fdtload.h
index 7b9ddba916d9980fbad51e7b02d99f0737ebc3fa..713c9424d0a9ebe47b1923a247e691566842b2d0 100644
--- a/include/grub/arm64/fdtload.h
+++ b/include/grub/efi/fdtload.h
@@ -29,7 +29,4 @@ grub_fdt_unload (void);
 grub_err_t
 grub_fdt_install (void);
 
-#define GRUB_EFI_PAGE_SHIFT	12
-#define GRUB_EFI_BYTES_TO_PAGES(bytes)   (((bytes) + 0xfff) >> GRUB_EFI_PAGE_SHIFT)
-
 #endif
diff --git a/include/grub/efi/memory.h b/include/grub/efi/memory.h
index 20526b14676de9295d17968f5ddc837a06bc56b6..08fe62277839dde3434e506cde78174f1977e9c9 100644
--- a/include/grub/efi/memory.h
+++ b/include/grub/efi/memory.h
@@ -22,6 +22,13 @@
 #include <grub/err.h>
 #include <grub/types.h>
 
+/* The term "page" in UEFI refers only to a 4 KiB-aligned 4 KiB size region of
+   memory. It is not concerned with underlying translation management concepts,
+   but only used as the granule for memory allocations. */
+#define GRUB_EFI_PAGE_SHIFT             12
+#define GRUB_EFI_PAGE_SIZE              (1 << GRUB_EFI_PAGE_SHIFT)
+#define GRUB_EFI_BYTES_TO_PAGES(bytes)  (((bytes) + 0xfff) >> GRUB_EFI_PAGE_SHIFT)
+
 #define GRUB_MMAP_REGISTER_BY_FIRMWARE  1
 
 grub_err_t grub_machine_mmap_register (grub_uint64_t start, grub_uint64_t size,
diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
index f79c36c026e0a518b3f9edaca36251d6d4943757..7d44732d2c353b74271262a1cf094d4aafd8dd10 100644
--- a/include/grub/efi/pe32.h
+++ b/include/grub/efi/pe32.h
@@ -45,6 +45,8 @@
 
 #define GRUB_PE32_MSDOS_STUB_SIZE	0x80
 
+#define GRUB_PE32_MAGIC			0x5a4d
+
 /* According to the spec, the minimal alignment is 512 bytes...
    But some examples (such as EFI drivers in the Intel
    Sample Implementation) use 32 bytes (0x20) instead, and it seems
diff --git a/include/grub/efiemu/runtime.h b/include/grub/efiemu/runtime.h
index 9b6b729f4ccde7274678b1324c16c9f6854477a2..36d2dedf47e4346b86f17882dc554207201b6401 100644
--- a/include/grub/efiemu/runtime.h
+++ b/include/grub/efiemu/runtime.h
@@ -29,7 +29,7 @@ struct grub_efiemu_ptv_rel
 
 struct efi_variable
 {
-  grub_efi_guid_t guid;
+  grub_efi_packed_guid_t guid;
   grub_uint32_t namelen;
   grub_uint32_t size;
   grub_efi_uint32_t attributes;
diff --git a/include/grub/fat.h b/include/grub/fat.h
index 4a5aab7934652cfde20c6fb291e00c29170b8753..8d7e4a1e54d644e6d70bb249802c699d5092728e 100644
--- a/include/grub/fat.h
+++ b/include/grub/fat.h
@@ -28,20 +28,15 @@ struct grub_fat_bpb
   grub_uint16_t bytes_per_sector;
   grub_uint8_t sectors_per_cluster;
   grub_uint16_t num_reserved_sectors;
-  grub_uint8_t num_fats;
-  /* 0x10 */
+  grub_uint8_t num_fats;		/* 0x10 */
   grub_uint16_t num_root_entries;
   grub_uint16_t num_total_sectors_16;
-  grub_uint8_t media;
-  /*0 x15 */
+  grub_uint8_t media;			/* 0x15 */
   grub_uint16_t sectors_per_fat_16;
-  grub_uint16_t sectors_per_track;
-  /*0 x19 */
-  grub_uint16_t num_heads;
-  /*0 x1b */
-  grub_uint32_t num_hidden_sectors;
-  /* 0x1f */
-  grub_uint32_t num_total_sectors_32;
+  grub_uint16_t sectors_per_track;	/* 0x18 */
+  grub_uint16_t num_heads;		/* 0x1A */
+  grub_uint32_t num_hidden_sectors;	/* 0x1C */
+  grub_uint32_t num_total_sectors_32;	/* 0x20 */
   union
   {
     struct
diff --git a/include/grub/fdt.h b/include/grub/fdt.h
index fdfca75bf487f17e8621fee5d1642f4874a2bf16..158b1bc4b3ad8bac60860e298b816781d6c57090 100644
--- a/include/grub/fdt.h
+++ b/include/grub/fdt.h
@@ -20,6 +20,7 @@
 #define GRUB_FDT_HEADER	1
 
 #include <grub/types.h>
+#include <grub/symbol.h>
 
 #define FDT_MAGIC 0xD00DFEED
 
@@ -49,6 +50,11 @@ struct grub_fdt_empty_tree {
 
 #define GRUB_FDT_EMPTY_TREE_SZ  sizeof (struct grub_fdt_empty_tree)
 
+/* Size needed by a property entry: 1 token (FDT_PROPERTY), plus len and nameoff
+   fields, plus the property value, plus padding if needed. */
+#define grub_fdt_prop_entry_size(prop_len)						\
+  (3 * sizeof(grub_uint32_t) + ALIGN_UP(prop_len, sizeof(grub_uint32_t)))
+
 #define grub_fdt_get_header(fdt, field)	\
 	grub_be_to_cpu32(((const grub_fdt_header_t *)(fdt))->field)
 #define grub_fdt_set_header(fdt, field, value)	\
@@ -95,16 +101,22 @@ struct grub_fdt_empty_tree {
 #define grub_fdt_set_size_dt_struct(fdt, value)	\
 	grub_fdt_set_header(fdt, size_dt_struct, value)
 
-int grub_fdt_create_empty_tree (void *fdt, unsigned int size);
-int grub_fdt_check_header (void *fdt, unsigned int size);
-int grub_fdt_check_header_nosize (void *fdt);
-int grub_fdt_find_subnode (const void *fdt, unsigned int parentoffset,
-			   const char *name);
-int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset,
+int EXPORT_FUNC(grub_fdt_create_empty_tree) (void *fdt, unsigned int size);
+int EXPORT_FUNC(grub_fdt_check_header) (const void *fdt, unsigned int size);
+int EXPORT_FUNC(grub_fdt_check_header_nosize) (const void *fdt);
+int EXPORT_FUNC(grub_fdt_find_subnode) (const void *fdt, unsigned int parentoffset,
+					const char *name);
+int EXPORT_FUNC(grub_fdt_first_node) (const void *fdt, unsigned int parentoffset);
+int EXPORT_FUNC(grub_fdt_next_node) (const void *fdt, unsigned int currentoffset);
+int EXPORT_FUNC(grub_fdt_add_subnode) (void *fdt, unsigned int parentoffset,
 			  const char *name);
+const char *
+EXPORT_FUNC(grub_fdt_get_nodename) (const void *fdt, unsigned int nodeoffset);
+const void *EXPORT_FUNC(grub_fdt_get_prop) (const void *fdt, unsigned int nodeoffset, const char *name,
+					    grub_uint32_t *len);
 
-int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
-		      const void *val, grub_uint32_t len);
+int EXPORT_FUNC(grub_fdt_set_prop) (void *fdt, unsigned int nodeoffset, const char *name,
+				    const void *val, grub_uint32_t len);
 #define grub_fdt_set_prop32(fdt, nodeoffset, name, val)	\
 ({ \
   grub_uint32_t _val = grub_cpu_to_be32(val); \
diff --git a/include/grub/fdtbus.h b/include/grub/fdtbus.h
new file mode 100644
index 0000000000000000000000000000000000000000..f519c40ec35faea9aeedca055164012d9d9b3fb5
--- /dev/null
+++ b/include/grub/fdtbus.h
@@ -0,0 +1,89 @@
+/*
+ *  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_FDTBUS_HEADER
+#define GRUB_FDTBUS_HEADER	1
+
+#include <grub/fdt.h>
+#include <grub/err.h>
+
+struct grub_fdtbus_dev
+{
+  struct grub_fdtbus_dev *next;
+  struct grub_fdtbus_dev *parent;
+  int node;
+  struct grub_fdtbus_driver *driver;
+};
+
+struct grub_fdtbus_driver
+{
+  struct grub_fdtbus_driver *next;
+  struct grub_fdtbus_driver **prev;
+
+  const char *compatible;
+
+  grub_err_t (*attach) (const struct grub_fdtbus_dev *dev);
+  void (*detach) (const struct grub_fdtbus_dev *dev);
+
+  /* Message bus operations.  */
+  grub_err_t (*send) (const struct grub_fdtbus_dev *dev, const void *data, grub_size_t sz);
+  grub_err_t (*receive) (const struct grub_fdtbus_dev *dev, void *data, grub_size_t sz);
+  grub_err_t (*start) (const struct grub_fdtbus_dev *dev);
+  void (*stop) (const struct grub_fdtbus_dev *dev);
+};
+
+extern char EXPORT_VAR(grub_fdtbus_invalid_mapping)[1];
+
+static inline int
+grub_fdtbus_is_mapping_valid (volatile void *m)
+{
+  return m != grub_fdtbus_invalid_mapping;
+}
+
+volatile void *
+EXPORT_FUNC(grub_fdtbus_map_reg) (const struct grub_fdtbus_dev *dev, int reg, grub_size_t *size);
+
+const void *
+EXPORT_FUNC(grub_fdtbus_get_fdt) (void);
+
+const char *
+EXPORT_FUNC(grub_fdtbus_get_name) (const struct grub_fdtbus_dev *dev);
+
+const void *
+EXPORT_FUNC(grub_fdtbus_get_prop) (const struct grub_fdtbus_dev *dev,
+		      const char *name,
+		      grub_uint32_t *len);
+
+void
+EXPORT_FUNC(grub_fdtbus_register) (struct grub_fdtbus_driver *driver);
+
+void
+EXPORT_FUNC(grub_fdtbus_unregister) (struct grub_fdtbus_driver *driver);
+
+int
+EXPORT_FUNC(grub_fdtbus_is_compatible) (const char *compat_string,
+					const struct grub_fdtbus_dev *dev);
+
+/* Must be called before any register(). */
+/* dtb is assumed to be unfreeable and must remain
+   valid for lifetime of GRUB.
+ */
+void
+grub_fdtbus_init (const void *dtb, grub_size_t size);
+
+#endif
diff --git a/include/grub/gpt_partition.h b/include/grub/gpt_partition.h
index 1b32f6725a498f16941991771efe6a7a04ed6f5e..7a93f43291cce490cbaecc140ef2e5e0577ae274 100644
--- a/include/grub/gpt_partition.h
+++ b/include/grub/gpt_partition.h
@@ -22,14 +22,14 @@
 #include <grub/types.h>
 #include <grub/partition.h>
 
-struct grub_gpt_part_type
+struct grub_gpt_part_guid
 {
   grub_uint32_t data1;
   grub_uint16_t data2;
   grub_uint16_t data3;
   grub_uint8_t data4[8];
-} __attribute__ ((aligned(8)));
-typedef struct grub_gpt_part_type grub_gpt_part_type_t;
+} GRUB_PACKED;
+typedef struct grub_gpt_part_guid grub_gpt_part_guid_t;
 
 #define GRUB_GPT_PARTITION_TYPE_EMPTY \
   { 0x0, 0x0, 0x0, \
@@ -70,8 +70,8 @@ struct grub_gpt_header
 
 struct grub_gpt_partentry
 {
-  grub_gpt_part_type_t type;
-  grub_uint8_t guid[16];
+  grub_gpt_part_guid_t type;
+  grub_gpt_part_guid_t guid;
   grub_uint64_t start;
   grub_uint64_t end;
   grub_uint64_t attrib;
diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
index da0ca3b83cdc7355fc5b9815415ad7fc8732d153..60c7c3b5e660276dc11d23f4a53ccc2f1e5536a5 100644
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -16,10 +16,10 @@
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef GRUB_LINUX_MACHINE_HEADER
-#define GRUB_LINUX_MACHINE_HEADER	1
+#ifndef GRUB_I386_LINUX_HEADER
+#define GRUB_I386_LINUX_HEADER	1
 
-#define GRUB_LINUX_MAGIC_SIGNATURE	0x53726448      /* "HdrS" */
+#define GRUB_LINUX_I386_MAGIC_SIGNATURE	0x53726448      /* "HdrS" */
 #define GRUB_LINUX_DEFAULT_SETUP_SECTS	4
 #define GRUB_LINUX_INITRD_MAX_ADDRESS	0x37FFFFFF
 #define GRUB_LINUX_MAX_SETUP_SECTS	64
@@ -43,6 +43,9 @@
 
 #define GRUB_LINUX_CL_MAGIC		0xA33F
 
+#define VIDEO_CAPABILITY_SKIP_QUIRKS	(1 << 0)
+#define VIDEO_CAPABILITY_64BIT_BASE	(1 << 1)	/* Frame buffer base is 64-bit. */
+
 #ifdef __x86_64__
 
 #define GRUB_LINUX_EFI_SIGNATURE	\
@@ -85,7 +88,7 @@ enum
   };
 
 /* For the Linux/i386 boot protocol version 2.10.  */
-struct linux_kernel_header
+struct linux_i386_kernel_header
 {
   grub_uint8_t code1[0x0020];
   grub_uint16_t cl_magic;		/* Magic number 0xA33F */
@@ -188,8 +191,9 @@ struct linux_kernel_params
   grub_uint16_t lfb_pages;		/* 32 */
   grub_uint16_t vesa_attrib;		/* 34 */
   grub_uint32_t capabilities;		/* 36 */
+  grub_uint32_t ext_lfb_base;		/* 3a */
 
-  grub_uint8_t padding3[0x40 - 0x3a];
+  grub_uint8_t padding3[0x40 - 0x3e];
 
   grub_uint16_t apm_version;		/* 40 */
   grub_uint16_t apm_code_segment;	/* 42 */
@@ -312,4 +316,4 @@ struct linux_kernel_params
 } GRUB_PACKED;
 #endif /* ! ASM_FILE */
 
-#endif /* ! GRUB_LINUX_MACHINE_HEADER */
+#endif /* ! GRUB_I386_LINUX_HEADER */
diff --git a/include/grub/i386/multiboot.h b/include/grub/i386/multiboot.h
index 807a1de27f900c8393476736051e20ee1af6717c..0b596fc2060a63f2fd9e1c67cb002279454aebe5 100644
--- a/include/grub/i386/multiboot.h
+++ b/include/grub/i386/multiboot.h
@@ -19,6 +19,13 @@
 #ifndef GRUB_MULTIBOOT_CPU_HEADER
 #define GRUB_MULTIBOOT_CPU_HEADER	1
 
+#define MULTIBOOT2_INITIAL_STATE  { .eax = MULTIBOOT2_BOOTLOADER_MAGIC,	\
+    .ecx = 0,								\
+    .edx = 0,								\
+    /* Set esp to some random location in low memory to avoid breaking */ \
+    /* non-compliant kernels.  */					\
+    .esp = 0x7ff00							\
+      }
 #define MULTIBOOT_INITIAL_STATE  { .eax = MULTIBOOT_BOOTLOADER_MAGIC,	\
     .ecx = 0,								\
     .edx = 0,								\
@@ -28,7 +35,7 @@
       }
 #define MULTIBOOT_ENTRY_REGISTER eip
 #define MULTIBOOT_MBI_REGISTER ebx
-#define MULTIBOOT_ARCHITECTURE_CURRENT MULTIBOOT_ARCHITECTURE_I386
+#define MULTIBOOT2_ARCHITECTURE_CURRENT MULTIBOOT2_ARCHITECTURE_I386
 
 #ifdef GRUB_MACHINE_EFI
 #ifdef __x86_64__
@@ -36,6 +43,10 @@
     .rcx = 0,									\
     .rdx = 0,									\
       }
+#define MULTIBOOT2_EFI_INITIAL_STATE  { .rax = MULTIBOOT2_BOOTLOADER_MAGIC,	\
+    .rcx = 0,									\
+    .rdx = 0,									\
+      }
 #define MULTIBOOT_EFI_ENTRY_REGISTER rip
 #define MULTIBOOT_EFI_MBI_REGISTER rbx
 #endif
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
index 8e425130327e193af1c1e34760e7255c9d6e6223..8868f3a756fe57b90188e25aaba2b203edacde13 100644
--- a/include/grub/ieee1275/ieee1275.h
+++ b/include/grub/ieee1275/ieee1275.h
@@ -210,7 +210,25 @@ int EXPORT_FUNC(grub_ieee1275_set_property) (grub_ieee1275_phandle_t phandle,
 int EXPORT_FUNC(grub_ieee1275_set_color) (grub_ieee1275_ihandle_t ihandle,
 					  int index, int r, int g, int b);
 int EXPORT_FUNC(grub_ieee1275_milliseconds) (grub_uint32_t *msecs);
-
+int EXPORT_FUNC(grub_ieee1275_set_address) (grub_ieee1275_ihandle_t ihandle,
+                                            grub_uint32_t target,
+                                            grub_uint32_t lun);
+int EXPORT_FUNC(grub_ieee1275_no_data_command) (grub_ieee1275_ihandle_t ihandle,
+                                                const void *cmd_addr,
+                                                grub_ssize_t *result);
+int EXPORT_FUNC(grub_ieee1275_decode_unit4) (grub_ieee1275_ihandle_t ihandle,
+                                             void *addr, grub_size_t size,
+                                             grub_uint32_t *phy_lo,
+                                             grub_uint32_t *phy_hi,
+                                             grub_uint32_t *lun_lo,
+                                             grub_uint32_t *lun_hi);
+char *EXPORT_FUNC(grub_ieee1275_encode_uint4) (grub_ieee1275_ihandle_t ihandle,
+                                             grub_uint32_t phy_lo,
+                                             grub_uint32_t phy_hi,
+                                             grub_uint32_t lun_lo,
+                                             grub_uint32_t lun_hi,
+                                             grub_size_t *size);
+int EXPORT_FUNC(grub_ieee1275_get_block_size) (grub_ieee1275_ihandle_t ihandle);
 
 grub_err_t EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size);
 
@@ -235,6 +253,8 @@ void EXPORT_FUNC(grub_ieee1275_children_peer) (struct grub_ieee1275_devalias *al
 void EXPORT_FUNC(grub_ieee1275_children_first) (const char *devpath,
 						struct grub_ieee1275_devalias *alias);
 
+char *EXPORT_FUNC(grub_ieee1275_get_boot_dev) (void);
+
 #define FOR_IEEE1275_DEVALIASES(alias) for (grub_ieee1275_devalias_init_iterator (&(alias)); grub_ieee1275_devalias_next (&(alias));)
 
 #define FOR_IEEE1275_DEVCHILDREN(devpath, alias) for (grub_ieee1275_children_first ((devpath), &(alias)); \
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
index 20ddf2da297d5c883ed5b5542f2cfd99ee9c18da..ecd88ca72c6dea39be9f046463e7c51c874cb351 100644
--- a/include/grub/kernel.h
+++ b/include/grub/kernel.h
@@ -28,7 +28,8 @@ enum
   OBJ_TYPE_MEMDISK,
   OBJ_TYPE_CONFIG,
   OBJ_TYPE_PREFIX,
-  OBJ_TYPE_PUBKEY
+  OBJ_TYPE_PUBKEY,
+  OBJ_TYPE_DTB
 };
 
 /* The module header.  */
diff --git a/include/grub/mips/multiboot.h b/include/grub/mips/multiboot.h
index 4aebf29e73240b575bb90c699fd02e8185ab5171..cdfb41e315af4aa22d549f76fb0131835abd957e 100644
--- a/include/grub/mips/multiboot.h
+++ b/include/grub/mips/multiboot.h
@@ -19,11 +19,11 @@
 #ifndef GRUB_MULTIBOOT_CPU_HEADER
 #define GRUB_MULTIBOOT_CPU_HEADER	1
 
-#define MULTIBOOT_INITIAL_STATE  { .gpr[4] = MULTIBOOT_BOOTLOADER_MAGIC, \
+#define MULTIBOOT2_INITIAL_STATE  { .gpr[4] = MULTIBOOT2_BOOTLOADER_MAGIC, \
     .jumpreg = 1 }
 #define MULTIBOOT_ENTRY_REGISTER gpr[1]
 #define MULTIBOOT_MBI_REGISTER gpr[5]
-#define MULTIBOOT_ARCHITECTURE_CURRENT MULTIBOOT_ARCHITECTURE_MIPS32
+#define MULTIBOOT2_ARCHITECTURE_CURRENT MULTIBOOT2_ARCHITECTURE_MIPS32
 
 #define MULTIBOOT_ELF32_MACHINE EM_MIPS
 #define MULTIBOOT_ELF64_MACHINE EM_MIPS
diff --git a/include/grub/misc.h b/include/grub/misc.h
index 2a9f87cc255eda94476733513807ec757c6d9cd9..372f009e84f12a58c3185dda63216bab7325be8f 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -396,7 +396,8 @@ grub_abs (int x)
 }
 
 /* Reboot the machine.  */
-#if defined (GRUB_MACHINE_EMU) || defined (GRUB_MACHINE_QEMU_MIPS)
+#if defined (GRUB_MACHINE_EMU) || defined (GRUB_MACHINE_QEMU_MIPS) || \
+    defined (GRUB_MACHINE_EFI)
 void EXPORT_FUNC(grub_reboot) (void) __attribute__ ((noreturn));
 #else
 void grub_reboot (void) __attribute__ ((noreturn));
diff --git a/include/grub/multiboot.h b/include/grub/multiboot.h
index c96492bb5fa771831a62d4ab1bac3798328093f0..bd0a9873e6c158f77190c38546007c544cb0d6c9 100644
--- a/include/grub/multiboot.h
+++ b/include/grub/multiboot.h
@@ -22,19 +22,11 @@
 
 #include <grub/file.h>
 
-#ifdef GRUB_USE_MULTIBOOT2
-#include <multiboot2.h>
-/* Same thing as far as our loader is concerned.  */
-#define MULTIBOOT_BOOTLOADER_MAGIC	MULTIBOOT2_BOOTLOADER_MAGIC
-#define MULTIBOOT_HEADER_MAGIC		MULTIBOOT2_HEADER_MAGIC
-#else
 #include <multiboot.h>
-#endif
 
 #include <grub/types.h>
 #include <grub/err.h>
 
-#ifndef GRUB_USE_MULTIBOOT2
 typedef enum
   {
     GRUB_MULTIBOOT_QUIRKS_NONE = 0,
@@ -42,7 +34,6 @@ typedef enum
     GRUB_MULTIBOOT_QUIRK_MODULES_AFTER_KERNEL = 2
   } grub_multiboot_quirks_t;
 extern grub_multiboot_quirks_t grub_multiboot_quirks;
-#endif
 
 extern struct grub_relocator *grub_multiboot_relocator;
 
@@ -60,7 +51,7 @@ void
 grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize,
 			    unsigned shndx, void *data);
 
-grub_uint32_t grub_get_multiboot_mmap_count (void);
+grub_uint32_t grub_multiboot_get_mmap_count (void);
 grub_err_t grub_multiboot_set_video_mode (void);
 
 /* FIXME: support coreboot as well.  */
diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h
new file mode 100644
index 0000000000000000000000000000000000000000..502d34ef18045e898680f2198522139c3066b587
--- /dev/null
+++ b/include/grub/multiboot2.h
@@ -0,0 +1,104 @@
+/* multiboot.h - multiboot header file with grub definitions. */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2007,2008,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/>.
+ */
+
+#ifndef GRUB_MULTIBOOT2_HEADER
+#define GRUB_MULTIBOOT2_HEADER 1
+
+#include <grub/file.h>
+
+#include <multiboot2.h>
+
+#include <grub/types.h>
+#include <grub/err.h>
+
+extern struct grub_relocator *grub_multiboot2_relocator;
+
+void grub_multiboot2 (int argc, char *argv[]);
+void grub_module2 (int argc, char *argv[]);
+
+void grub_multiboot2_set_accepts_video (int val);
+grub_err_t grub_multiboot2_make_mbi (grub_uint32_t *target);
+void grub_multiboot2_free_mbi (void);
+grub_err_t grub_multiboot2_init_mbi (int argc, char *argv[]);
+grub_err_t grub_multiboot2_add_module (grub_addr_t start, grub_size_t size,
+				      int argc, char *argv[]);
+void grub_multiboot2_set_bootdev (void);
+void
+grub_multiboot2_add_elfsyms (grub_size_t num, grub_size_t entsize,
+			    unsigned shndx, void *data);
+
+grub_uint32_t grub_multiboot2_get_mmap_count (void);
+grub_err_t grub_multiboot2_set_video_mode (void);
+
+/* FIXME: support coreboot as well.  */
+#if defined (GRUB_MACHINE_PCBIOS)
+#define GRUB_MACHINE_HAS_VBE 1
+#else
+#define GRUB_MACHINE_HAS_VBE 0
+#endif
+
+#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU)
+#define GRUB_MACHINE_HAS_VGA_TEXT 1
+#else
+#define GRUB_MACHINE_HAS_VGA_TEXT 0
+#endif
+
+#if defined (GRUB_MACHINE_EFI) || defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT)
+#define GRUB_MACHINE_HAS_ACPI 1
+#else
+#define GRUB_MACHINE_HAS_ACPI 0
+#endif
+
+#define GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT 1
+#define GRUB_MULTIBOOT2_CONSOLE_FRAMEBUFFER 2 
+
+grub_err_t
+grub_multiboot2_set_console (int console_type, int accepted_consoles,
+			    int width, int height, int depth,
+			    int console_required);
+grub_err_t
+grub_multiboot2_load (grub_file_t file, const char *filename);
+
+struct mbi_load_data
+{
+  grub_file_t file;
+  const char *filename;
+  void *buffer;
+  unsigned int mbi_ver;
+  int relocatable;
+  grub_uint32_t min_addr;
+  grub_uint32_t max_addr;
+  grub_size_t align;
+  grub_uint32_t preference;
+  grub_uint32_t link_base_addr;
+  grub_uint32_t load_base_addr;
+  int avoid_efi_boot_services;
+};
+typedef struct mbi_load_data mbi_load_data_t;
+
+/* Load ELF32 or ELF64.  */
+grub_err_t
+grub_multiboot2_load_elf (mbi_load_data_t *mld);
+
+extern grub_size_t grub_multiboot2_pure_size;
+extern grub_size_t grub_multiboot2_alloc_mbi;
+extern grub_uint32_t grub_multiboot2_payload_eip;
+
+
+#endif /* ! GRUB_MULTIBOOT_HEADER */
diff --git a/include/grub/net.h b/include/grub/net.h
index 2192fa18628862e8e3a6046d854b12613e914ff9..1096b24322eb1ba36e8c996872fce2a255e6bccc 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -291,6 +291,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_uint16_t vlantag;
   void *data;
 };
 
@@ -561,4 +562,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/include/grub/net/arp.h b/include/grub/net/arp.h
index bb1703622e1529479618e7f71b0d5e88adb631d1..8d9d081134f52e2d33c23928baae7f6b4c08470f 100644
--- a/include/grub/net/arp.h
+++ b/include/grub/net/arp.h
@@ -22,10 +22,11 @@
 #include <grub/net.h>
 
 extern grub_err_t grub_net_arp_receive (struct grub_net_buff *nb,
-					struct grub_net_card *card);
+                                        struct grub_net_card *card,
+                                        grub_uint16_t *vlantag);
 
 grub_err_t
 grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
-			   const grub_net_network_level_address_t *proto_addr);
+                           const grub_net_network_level_address_t *proto_addr);
 
 #endif 
diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h
index dcceaa56894605a39f87858964da7af11951ff11..ab9d68f98252b9772853a712ff1e8556162002ee 100644
--- a/include/grub/net/ip.h
+++ b/include/grub/net/ip.h
@@ -48,7 +48,8 @@ grub_err_t
 grub_net_recv_ip_packets (struct grub_net_buff *nb,
 			  struct grub_net_card *card,
 			  const grub_net_link_level_address_t *hwaddress,
-			  const grub_net_link_level_address_t *src_hwaddress);
+			  const grub_net_link_level_address_t *src_hwaddress,
+                          grub_uint16_t *vlantag);
 
 grub_err_t
 grub_net_send_ip_packet (struct grub_net_network_level_interface *inf,
diff --git a/include/grub/offsets.h b/include/grub/offsets.h
index c88c86d4d2ebddddb23f25c50ad2c29b52e54ccb..330e4c70738abcacc3c1d53fb16ae1ec8896d9e3 100644
--- a/include/grub/offsets.h
+++ b/include/grub/offsets.h
@@ -50,7 +50,7 @@
 /* The offset of GRUB_CORE_ENTRY_ADDR.  */
 #define GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR	0x8
 
-#define GRUB_KERNEL_I386_QEMU_LINK_ADDR         0x8200
+#define GRUB_KERNEL_I386_QEMU_LINK_ADDR         0x9000
 
 /* The offset of GRUB_TOTAL_MODULE_SIZE.  */
 #define GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE	0x8
@@ -91,7 +91,7 @@
 
 #define GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE	0x08
 
-#define GRUB_KERNEL_I386_COREBOOT_LINK_ADDR	0x8200
+#define GRUB_KERNEL_I386_COREBOOT_LINK_ADDR	0x9000
 #define GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR  0x100000
 
 #define GRUB_KERNEL_I386_IEEE1275_LINK_ADDR	0x10000
@@ -122,6 +122,12 @@
 #define GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN 	0x8
 #define GRUB_KERNEL_ARM_UBOOT_TOTAL_MODULE_SIZE	0x4
 
+#define GRUB_KERNEL_ARM_COREBOOT_MOD_ALIGN 	0x8
+#define GRUB_KERNEL_ARM_COREBOOT_TOTAL_MODULE_SIZE	0x4
+
+#define GRUB_KERNEL_ARM_STACK_SIZE 0x40000
+#define GRUB_KERNEL_ARM_COREBOOT_MOD_GAP (GRUB_KERNEL_ARM_STACK_SIZE + 1024)
+
 /* Minimal gap between _end and the start of the modules.  It's a hack
    for PowerMac to prevent "CLAIM failed" error.  The real fix is to
    rewrite grub-mkimage to generate valid ELF files.  */
diff --git a/include/grub/pci.h b/include/grub/pci.h
index 70d9a05131b240bbe3c7fe12df899c8e3de237ce..262c89b748bbfccc98ffa27912ce7e2a5005f545 100644
--- a/include/grub/pci.h
+++ b/include/grub/pci.h
@@ -142,27 +142,7 @@ grub_pci_address_t EXPORT_FUNC(grub_pci_make_address) (grub_pci_device_t dev,
 void EXPORT_FUNC(grub_pci_iterate) (grub_pci_iteratefunc_t hook,
 				    void *hook_data);
 
-struct grub_pci_dma_chunk;
-
-struct grub_pci_dma_chunk *EXPORT_FUNC(grub_memalign_dma32) (grub_size_t align,
-							     grub_size_t size);
-void EXPORT_FUNC(grub_dma_free) (struct grub_pci_dma_chunk *ch);
-volatile void *EXPORT_FUNC(grub_dma_get_virt) (struct grub_pci_dma_chunk *ch);
-grub_uint32_t EXPORT_FUNC(grub_dma_get_phys) (struct grub_pci_dma_chunk *ch);
-
-static inline void *
-grub_dma_phys2virt (grub_uint32_t phys, struct grub_pci_dma_chunk *chunk)
-{
-  return ((grub_uint8_t *) grub_dma_get_virt (chunk)
-	  + (phys - grub_dma_get_phys (chunk)));
-}
-
-static inline grub_uint32_t
-grub_dma_virt2phys (volatile void *virt, struct grub_pci_dma_chunk *chunk)
-{
-  return (((grub_uint8_t *) virt - (grub_uint8_t *) grub_dma_get_virt (chunk))
-	  + grub_dma_get_phys (chunk));
-}
+#include <grub/dma.h>
 
 grub_uint8_t
 EXPORT_FUNC (grub_pci_find_capability) (grub_pci_device_t dev, grub_uint8_t cap);
diff --git a/include/grub/ps2.h b/include/grub/ps2.h
new file mode 100644
index 0000000000000000000000000000000000000000..4f2e527e49767c297646f1ea3d0e09bdc2855892
--- /dev/null
+++ b/include/grub/ps2.h
@@ -0,0 +1,43 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 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_PS2_HEADER
+#define GRUB_PS2_HEADER	1
+
+#include <grub/types.h>
+
+#define GRUB_AT_ACK                     0xfa
+#define GRUB_AT_NACK                    0xfe
+#define GRUB_AT_TRIES                   5
+
+/* Make sure it's zeroed-out and set current_set at init.  */
+struct grub_ps2_state
+{
+  int e0_received;
+  int f0_received;
+  grub_uint8_t led_status;
+  short at_keyboard_status;
+  grub_uint8_t current_set;
+};
+
+/* If there is a key pending, return it; otherwise return GRUB_TERM_NO_KEY.  */
+int
+grub_ps2_process_incoming_byte (struct grub_ps2_state *ps2_state,
+				grub_uint8_t data);
+
+#endif
diff --git a/include/grub/sparc64/ieee1275/ieee1275.h b/include/grub/sparc64/ieee1275/ieee1275.h
index 32c77f80f1a136c0127aecb6d5643ebd64cb5e88..4b18468d8d654bb3fe62050e7a4f439e1544889c 100644
--- a/include/grub/sparc64/ieee1275/ieee1275.h
+++ b/include/grub/sparc64/ieee1275/ieee1275.h
@@ -42,6 +42,8 @@ extern int EXPORT_FUNC(grub_ieee1275_claim_vaddr) (grub_addr_t vaddr,
 extern int EXPORT_FUNC(grub_ieee1275_alloc_physmem) (grub_addr_t *paddr,
 						     grub_size_t size,
 						     grub_uint32_t align);
+extern grub_uint64_t EXPORT_FUNC(grub_ieee1275_num_blocks) (grub_uint32_t ihandle);
+extern grub_uint64_t EXPORT_FUNC(grub_ieee1275_num_blocks64) (grub_uint32_t ihandle);
 
 extern grub_addr_t EXPORT_VAR (grub_ieee1275_original_stack);
 
diff --git a/include/grub/term.h b/include/grub/term.h
index 5ffb38f69aaa8911a66bdc6f417a72666b19e514..8117e2a24dac3f270d05408f1897fae9f0fa1593 100644
--- a/include/grub/term.h
+++ b/include/grub/term.h
@@ -55,7 +55,8 @@
 #define GRUB_TERM_KEY_INSERT    (GRUB_TERM_EXTENDED | 0x52)
 #define GRUB_TERM_KEY_CENTER    (GRUB_TERM_EXTENDED | 0x4c)
 
-#define GRUB_TERM_ESC		'\e'
+/* Hex value is used for ESC, since '\e' is nonstandard */
+#define GRUB_TERM_ESC		0x1b
 #define GRUB_TERM_TAB		'\t'
 #define GRUB_TERM_BACKSPACE	'\b'
 
diff --git a/include/grub/usb.h b/include/grub/usb.h
index 11d96481ff6b58cc43f468bcb2020475663fa098..512ae1dd0e64931c852847c9d52efdbd6b2caccb 100644
--- a/include/grub/usb.h
+++ b/include/grub/usb.h
@@ -321,5 +321,9 @@ grub_usb_err_t
 grub_usb_check_transfer (grub_usb_transfer_t trans, grub_size_t *actual);
 void
 grub_usb_cancel_transfer (grub_usb_transfer_t trans);
+void
+grub_ehci_init_device (volatile void *regs);
+void
+grub_ehci_pci_scan (void);
 
 #endif /* GRUB_USB_H */
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 5ca4811cd130f6810f07e6fbce89af1de36827c7..0dba8b67f93d44f875f2d1065ed5bf745f7813a5 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -29,6 +29,8 @@
 #define GRUB_INSTALL_OPTIONS					  \
   { "modules",      GRUB_INSTALL_OPTIONS_MODULES, N_("MODULES"),	  \
     0, N_("pre-load specified modules MODULES"), 1 },			  \
+  { "dtb",      GRUB_INSTALL_OPTIONS_DTB, N_("FILE"),	  \
+    0, N_("embed a specific DTB"), 1 },			  \
   { "install-modules", GRUB_INSTALL_OPTIONS_INSTALL_MODULES,	  \
     N_("MODULES"), 0,							  \
     N_("install only MODULES and their dependencies [default=all]"), 1 }, \
@@ -99,6 +101,7 @@ enum grub_install_plat
     GRUB_INSTALL_PLATFORM_I386_XEN,
     GRUB_INSTALL_PLATFORM_X86_64_XEN,
     GRUB_INSTALL_PLATFORM_ARM64_EFI,
+    GRUB_INSTALL_PLATFORM_ARM_COREBOOT,
     GRUB_INSTALL_PLATFORM_MAX
   };
 
@@ -115,7 +118,8 @@ enum grub_install_options {
   GRUB_INSTALL_OPTIONS_LOCALE_DIRECTORY,
   GRUB_INSTALL_OPTIONS_THEMES_DIRECTORY,
   GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE,
-  GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS
+  GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS,
+  GRUB_INSTALL_OPTIONS_DTB
 };
 
 extern char *grub_install_source_directory;
@@ -176,7 +180,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
 			     char *config_path,
 			     const struct grub_install_image_target_desc *image_target,
 			     int note,
-			     grub_compression_t comp);
+			     grub_compression_t comp, const char *dtb_file);
 
 const struct grub_install_image_target_desc *
 grub_install_get_image_target (const char *arg);
@@ -206,7 +210,7 @@ grub_install_create_envblk_file (const char *name);
 const char *
 grub_install_get_default_x86_platform (void);
 
-void
+int
 grub_install_register_efi (grub_device_t efidir_grub_dev,
 			   const char *efifile_path,
 			   const char *efi_distributor);
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
index 1a18708a89c6e5503dd29b0b76f5098cef3ac893..b3a5ca132bc4d336f8d85158726bcce77fd7cd37 100644
--- a/include/grub/util/mkimage.h
+++ b/include/grub/util/mkimage.h
@@ -51,13 +51,13 @@ grub_mkimage_load_image64 (const char *kernel_path,
 void
 grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target,
 			     int note, char **core_img, size_t *core_size,
-			     Elf32_Addr target_addr, grub_size_t align,
-			     size_t kernel_size, size_t bss_size);
+			     Elf32_Addr target_addr,
+			     struct grub_mkimage_layout *layout);
 void
 grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target,
 			     int note, char **core_img, size_t *core_size,
-			     Elf64_Addr target_addr, grub_size_t align,
-			     size_t kernel_size, size_t bss_size);
+			     Elf64_Addr target_addr,
+			     struct grub_mkimage_layout *layout);
 
 struct grub_install_image_target_desc
 {
diff --git a/include/multiboot2.h b/include/multiboot2.h
index 5a3db5a7cae38c26be516dc76a4fa6a9ad4ed354..5693923c014f2fa9e855dcc89c7328a19e0e6408 100644
--- a/include/multiboot2.h
+++ b/include/multiboot2.h
@@ -75,8 +75,8 @@
 #define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64  9
 #define MULTIBOOT_HEADER_TAG_RELOCATABLE  10
 
-#define MULTIBOOT_ARCHITECTURE_I386  0
-#define MULTIBOOT_ARCHITECTURE_MIPS32  4
+#define MULTIBOOT2_ARCHITECTURE_I386  0
+#define MULTIBOOT2_ARCHITECTURE_MIPS32  4
 #define MULTIBOOT_HEADER_TAG_OPTIONAL 1
 
 #define MULTIBOOT_LOAD_PREFERENCE_NONE 0
diff --git a/grub-core/boot/i386/pc/diskboot.S b/grub-core/boot/i386/pc/diskboot.S
index 1ee4cf5b2e0fd03ba177e953fafdaf5e0ca457a6..c1addc0df29bc78009238690a9514ea301bf3a29 100644
--- a/grub-core/boot/i386/pc/diskboot.S
+++ b/grub-core/boot/i386/pc/diskboot.S
@@ -37,8 +37,8 @@
 start:
 _start:
 	/*
-	 * _start is loaded at 0x2000 and is jumped to with
-	 * CS:IP 0:0x2000 in kernel.
+	 * _start is loaded at 0x8000 and is jumped to with
+	 * CS:IP 0:0x8000 in kernel.
 	 */
 
 	/*
diff --git a/grub-core/boot/sparc64/ieee1275/boot.S b/grub-core/boot/sparc64/ieee1275/boot.S
index 586efb4014e8648e560fb43eee8eea8b09da669b..9ea9b4e06627bbd8b7da422ffba3357b4fba0a6a 100644
--- a/grub-core/boot/sparc64/ieee1275/boot.S
+++ b/grub-core/boot/sparc64/ieee1275/boot.S
@@ -69,6 +69,10 @@ prom_seek_name:		.asciz "seek"
 prom_read_name:		.asciz "read"
 prom_exit_name:		.asciz "exit"
 grub_name:		.asciz "GRUB "
+#ifdef CDBOOT
+prom_close_name:	.asciz "close"
+#endif
+
 #define GRUB_NAME_LEN	5
 
 	.align	4
@@ -213,6 +217,12 @@ bootpath_known:
 	call	prom_call_3_1_o1
 #ifdef CDBOOT
 	 LDUW_ABS(kernel_size, 0x00, %o3)
+
+	GET_ABS(prom_close_name, %o0)
+	mov	1, %g1
+	mov	0, %o5
+	call	prom_call
+	 mov	BOOTDEV_REG, %o1
 #else
 	 mov	512, %o3
 #endif
diff --git a/grub-core/kern/arm/cache_armv7.S b/grub-core/kern/arm/cache_armv7.S
index 1ef2754af8a7612c35c26011fab442dbba074dfd..5ae76a3d819c002676f54db3311f517791e0c4e8 100644
--- a/grub-core/kern/arm/cache_armv7.S
+++ b/grub-core/kern/arm/cache_armv7.S
@@ -33,6 +33,18 @@
 # define ISB	isb
 #define ARMV7 1
 
+FUNCTION(grub_arm_clean_dcache_range_poc_armv7)
+	DSB
+	@ Clean data cache for range to point-of-coherence
+1:	cmp	r0, r1
+	bge	2f
+	mcr	p15, 0, r0, c7, c14, 1	@ DCCMVAC
+	add	r0, r0, r2		@ Next line
+	b	1b
+2:	DSB
+	bx	lr
+
+
 	@ r0  - CLIDR
 	@ r1  - LoC
 	@ r2  - current level
diff --git a/include/grub/arm/efi/loader.h b/grub-core/kern/arm/coreboot/coreboot.S
similarity index 62%
rename from include/grub/arm/efi/loader.h
rename to grub-core/kern/arm/coreboot/coreboot.S
index 4bab18e83ee833d6932fea917d839fe7dcc212d1..a1104526c154bd5a9dfd9e3680d8bb787c1088ef 100644
--- a/include/grub/arm/efi/loader.h
+++ b/grub-core/kern/arm/coreboot/coreboot.S
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2013  Free Software Foundation, Inc.
+ *  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
@@ -16,11 +16,29 @@
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef GRUB_LOADER_MACHINE_HEADER
-#define GRUB_LOADER_MACHINE_HEADER	1
+#include <grub/symbol.h>
 
-grub_err_t EXPORT_FUNC (grub_efi_prepare_platform) (void);
-void * EXPORT_FUNC (grub_efi_allocate_loader_memory) (grub_uint32_t min_offset,
-						      grub_uint32_t size);
+	.file	"coreboot.S"
+	.text
+	.syntax	unified
+#if !defined (__thumb2__)
+	.arch	armv7a
+	.arm
+#else
+	.arch	armv7
+	.thumb
+#endif
+
+FUNCTION(grub_arm_pfr1)
+	mrc p15, 0, r0, c0, c1, 1
+	bx	lr
+
+FUNCTION(grub_armv7_get_timer_value)
+	isb
+	mrrc p15, 1, r0, r1, c14
+	bx	lr
+
+FUNCTION(grub_armv7_get_timer_frequency)
+	mrc p15, 0, r0, c14, c0, 0
+	bx	lr
 
-#endif /* ! GRUB_LOADER_MACHINE_HEADER */
diff --git a/grub-core/kern/arm/uboot/startup.S b/grub-core/kern/arm/startup.S
similarity index 77%
rename from grub-core/kern/arm/uboot/startup.S
rename to grub-core/kern/arm/startup.S
index 5efaae16e838b48dd4d9a5debfc2937a558c65ba..3946fe8e183023f80e3a90ae4ee7b942f02f204d 100644
--- a/grub-core/kern/arm/uboot/startup.S
+++ b/grub-core/kern/arm/startup.S
@@ -24,6 +24,7 @@
  * GRUB is called from U-Boot as a Linux Kernel type image, which
  * means among other things that it always enters in ARM state.
  *
+ * coreboot starts in ARM mode as well.
  *
  * Overview of GRUB image layout:
  *
@@ -86,7 +87,7 @@ FUNCTION(codestart)
 	@ Stack pointer used as start address for signature probing
 	mov	r12, sp
 	adr	sp, entry_state
-	push	{r1-r12,lr}	@ store U-Boot context (sp in r12)
+	push	{r0-r12,lr}	@ store U-Boot context (sp in r12)
 
 	adr     r1, _start
 	ldr	r0, bss_start_ptr		@ src
@@ -127,6 +128,8 @@ reloc_done:
 
 	str     r1, EXT_C(grub_modbase)
 
+	/* Coreboot already places modules at right place.  */
+#ifndef GRUB_MACHINE_COREBOOT
 	add	r1, r1, r2
 	add	r0, r0, r2
 	sub     r1, r1, #4
@@ -136,6 +139,7 @@ reloc_done:
 	str	r3, [r1], #-4			@ *dst-- = r3 
 	subs	r2, #4				@ remaining -= 4
 	bne	1b				@ while remaining != 0
+#endif
 
 	@ Since we _are_ the C run-time, we need to manually zero the BSS
 	@ region before continuing
@@ -153,69 +157,21 @@ reloc_done:
 	
 	b	EXT_C(grub_main)
 
-	/*
-	 * uboot_syscall():
-	 *   This function is effectively a veneer, so it cannot
-	 *   modify the stack or corrupt any registers other than
-	 *   r12 (ip). Furthermore it needs to restore r8 for
-	 *   U-Boot (Global Data Pointer) and preserve it for Grub.
-	 */
-FUNCTION(grub_uboot_syscall)
-	str     r8, transition_space
-	str     lr, transition_space + 4
-	str     r9, transition_space + 8
-
-	ldr	r8, gd_backup
-	ldr	r9, gd_backup + 4
-
-	bl	do_syscall
-
-	ldr     r8, transition_space
-	ldr     lr, transition_space + 4
-	ldr     r9, transition_space + 8
-
-	bx	lr
-do_syscall:
-
-	ldr	ip, grub_uboot_syscall_ptr
-	bx	ip
-	
-FUNCTION(grub_uboot_return)
-	adr	sp, entry_state_end
-	pop	{r4-r12, lr}
-	mov	sp, r12
-	bx	lr
-
-	
 	.align	3
-@ U-boot context stack space
-entry_state_end:
-VARIABLE(grub_uboot_machine_type)
+@ U-boot/coreboot context stack space
+VARIABLE(grub_arm_saved_registers)
+	.long	0	@ r0
 	.long	0	@ r1
-VARIABLE(grub_uboot_boot_data)
 	.long	0	@ r2
 	.long	0	@ r3
 	.long	0	@ r4
 	.long	0	@ r5
 	.long	0	@ r6
 	.long	0	@ r7
-gd_backup:	
-	.long	0	@ r8 - U-Boot global data pointer up to 2013-09-21
-	.long	0	@ r9 - U-Boot global data pointer 2013-09-21 onwards
-	.long	0	@ r10
-	.long	0	@ r11
-VARIABLE(grub_uboot_search_hint)@ U-Boot stack pointer - 
-	.long	0	@ also API signature address hint.
-	.long	0	@ lr
-entry_state:		@ backup for U-Boot context
-
-@ GRUB context stack space
-transition_space:	
 	.long	0	@ r8
-	.long	0	@ lr
 	.long	0	@ r9
-
-VARIABLE(grub_uboot_syscall_ptr)
-	.long	0	@
-
-	END
+	.long	0	@ r10
+	.long	0	@ r11
+	.long	0	@ sp
+	.long	0	@ lr
+entry_state:
diff --git a/grub-core/kern/arm/uboot/uboot.S b/grub-core/kern/arm/uboot/uboot.S
new file mode 100644
index 0000000000000000000000000000000000000000..d128775f19ea1f862b46bc82b05b453be577d741
--- /dev/null
+++ b/grub-core/kern/arm/uboot/uboot.S
@@ -0,0 +1,73 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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/offsets.h>
+#include <grub/symbol.h>
+#include <grub/machine/kernel.h>
+
+	/*
+	 * uboot_syscall():
+	 *   This function is effectively a veneer, so it cannot
+	 *   modify the stack or corrupt any registers other than
+	 *   r12 (ip). Furthermore it needs to restore r8 for
+	 *   U-Boot (Global Data Pointer) and preserve it for Grub.
+	 */
+FUNCTION(grub_uboot_syscall)
+	str     r8, transition_space
+	str     lr, transition_space + 4
+	str     r9, transition_space + 8
+
+	ldr	ip, saved_registers_ptr
+	ldr	r8, [ip, #4 * 8]
+	ldr	r9, [ip, #4 * 9]
+
+	bl	do_syscall
+
+	ldr     r8, transition_space
+	ldr     lr, transition_space + 4
+	ldr     r9, transition_space + 8
+
+	bx	lr
+do_syscall:
+
+	ldr	ip, grub_uboot_syscall_ptr
+	bx	ip
+	
+FUNCTION(grub_uboot_return)
+	ldr	ip, saved_registers_ptr
+	ldr	sp, [ip, #4 * 4]
+	pop	{r4-r12, lr}
+	mov	sp, r12
+	bx	lr
+
+	
+	.align	3
+
+@ GRUB context stack space
+transition_space:	
+	.long	0	@ r8
+	.long	0	@ lr
+	.long	0	@ r9
+
+saved_registers_ptr:
+	.long EXT_C(grub_arm_saved_registers)
+
+VARIABLE(grub_uboot_syscall_ptr)
+	.long	0	@
+
+	END
diff --git a/conf/Makefile.common b/conf/Makefile.common
index 11296b550a7cd40ded498613620f556d78c67d84..311da61c6c59fed3de8cba06c2c581b217d8273f 100644
--- a/conf/Makefile.common
+++ b/conf/Makefile.common
@@ -86,9 +86,11 @@ CPPFLAGS_TERMINAL_LIST += '-Dgrub_term_register_output(...)=OUTPUT_TERMINAL_LIST
 CPPFLAGS_COMMAND_LIST = '-Dgrub_register_command(...)=COMMAND_LIST_MARKER(__VA_ARGS__)'
 CPPFLAGS_COMMAND_LIST += '-Dgrub_register_extcmd(...)=EXTCOMMAND_LIST_MARKER(__VA_ARGS__)'
 CPPFLAGS_COMMAND_LIST += '-Dgrub_register_command_p1(...)=P1COMMAND_LIST_MARKER(__VA_ARGS__)'
+CPPFLAGS_FDT_LIST := '-Dgrub_fdtbus_register(...)=FDT_DRIVER_LIST_MARKER(__VA_ARGS__)'
 CPPFLAGS_MARKER = $(CPPFLAGS_FS_LIST) $(CPPFLAGS_VIDEO_LIST) \
 	$(CPPFLAGS_PARTTOOL_LIST) $(CPPFLAGS_PARTMAP_LIST) \
-	$(CPPFLAGS_TERMINAL_LIST) $(CPPFLAGS_COMMAND_LIST)
+	$(CPPFLAGS_TERMINAL_LIST) $(CPPFLAGS_COMMAND_LIST) \
+	$(CPPFLAGS_FDT_LIST)
 
 # Define these variables to calm down automake
 
diff --git a/docs/grub.texi b/docs/grub.texi
index e935af33ea5e24d832e588d1345e3721b826d5a0..2adfa97bee8f8b2dcd53ead368dfd6f115b8cb82 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -360,8 +360,9 @@ blocklist notation. The currently supported filesystem types are @dfn{Amiga
 Fast FileSystem (AFFS)}, @dfn{AtheOS fs}, @dfn{BeFS},
 @dfn{BtrFS} (including raid0, raid1, raid10, gzip and lzo),
 @dfn{cpio} (little- and big-endian bin, odc and newc variants),
-@dfn{Linux ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, @dfn{exFAT}, @dfn{HFS},
-@dfn{HFS+}, @dfn{ISO9660} (including Joliet, Rock-ridge and multi-chunk files),
+@dfn{Linux ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32},
+@dfn{exFAT}, @dfn{F2FS}, @dfn{HFS}, @dfn{HFS+},
+@dfn{ISO9660} (including Joliet, Rock-ridge and multi-chunk files),
 @dfn{JFS}, @dfn{Minix fs} (versions 1, 2 and 3), @dfn{nilfs2},
 @dfn{NTFS} (including compression), @dfn{ReiserFS}, @dfn{ROMFS},
 @dfn{Amiga Smart FileSystem (SFS)}, @dfn{Squash4}, @dfn{tar}, @dfn{UDF},
@@ -1213,10 +1214,11 @@ GRUB is configured using @file{grub.cfg}, usually located under
 need to write the whole thing by hand.
 
 @menu
-* Simple configuration::        Recommended for most users
-* Shell-like scripting::        For power users and developers
-* Multi-boot manual config::    For non-standard multi-OS scenarios
-* Embedded configuration::      Embedding a configuration file into GRUB
+* Simple configuration::            Recommended for most users
+* Root Identifcation Heuristics::   Summary on how the root file system is identified.
+* Shell-like scripting::            For power users and developers
+* Multi-boot manual config::        For non-standard multi-OS scenarios
+* Embedded configuration::          Embedding a configuration file into GRUB
 @end menu
 
 
@@ -1398,6 +1400,25 @@ for all respectively normal entries.
 The values of these options replace the values of @samp{GRUB_CMDLINE_LINUX}
 and @samp{GRUB_CMDLINE_LINUX_DEFAULT} for Linux and Xen menu entries.
 
+@item GRUB_EARLY_INITRD_LINUX_CUSTOM
+@itemx GRUB_EARLY_INITRD_LINUX_STOCK
+List of space-separated early initrd images to be loaded from @samp{/boot}.
+This is for loading things like CPU microcode, firmware, ACPI tables, crypto
+keys, and so on. These early images will be loaded in the order declared,
+and all will be loaded before the actual functional initrd image.
+
+@samp{GRUB_EARLY_INITRD_LINUX_STOCK} is for your distribution to declare
+images that are provided by the distribution. It should not be modified
+without understanding the consequences. They will be loaded first.
+
+@samp{GRUB_EARLY_INITRD_LINUX_CUSTOM} is for your custom created images.
+
+The default stock images are as follows, though they may be overridden by
+your distribution:
+@example
+intel-uc.img intel-ucode.img amd-uc.img amd-ucode.img early_ucode.cpio microcode.cpio
+@end example
+
 @item GRUB_DISABLE_LINUX_UUID
 Normally, @command{grub-mkconfig} will generate menu entries that use
 universally-unique identifiers (UUIDs) to identify the root filesystem to
@@ -1405,6 +1426,17 @@ the Linux kernel, using a @samp{root=UUID=...} kernel parameter.  This is
 usually more reliable, but in some cases it may not be appropriate.  To
 disable the use of UUIDs, set this option to @samp{true}.
 
+@item GRUB_DISABLE_LINUX_PARTUUID
+If @command{grub-mkconfig} cannot identify the root filesystem via its
+universally-unique indentifier (UUID), @command{grub-mkconfig} can use the UUID
+of the partition containing the filesystem to identify the root filesystem to
+the Linux kernel via a @samp{root=PARTUUID=...} kernel parameter.  This is not
+as reliable as using the filesystem UUID, but is more reliable than using the
+Linux device names. When @samp{GRUB_DISABLE_LINUX_PARTUUID} is set to
+@samp{false}, the Linux kernel version must be 2.6.37 (3.10 for systems using
+the MSDOS partition scheme) or newer.  This option defaults to @samp{true}.  To
+enable the use of partition UUIDs, set this option to @samp{false}.
+
 @item GRUB_DISABLE_RECOVERY
 If this option is set to @samp{true}, disable the generation of recovery
 mode menu entries.
@@ -1536,6 +1568,53 @@ edit the scripts in @file{/etc/grub.d} directly.
 menu entries; simply type the menu entries you want to add at the end of
 that file, making sure to leave at least the first two lines intact.
 
+@node Root Identifcation Heuristics
+@section Root Identifcation Heuristics
+If the target operating system uses the Linux kernel, @command{grub-mkconfig}
+attempts to identify the root file system via a heuristic algoirthm.  This
+algorithm selects the identification method of the root file system by
+considering three factors.  The first is if an initrd for the target operating
+system is also present.  The second is @samp{GRUB_DISABLE_LINUX_UUID} and if set
+to @samp{true}, prevents @command{grub-mkconfig} from identifying the root file
+system by its UUID.  The third is @samp{GRUB_DISABLE_LINUX_PARTUUID} and if set
+to @samp{true}, prevents @command{grub-mkconfig} from identifying the root file
+system via the UUID of its enclosing partition.  If the variables are assigned
+any other value, that value is considered equivalent to @samp{false}.  The
+variables are also considered to be set to @samp{false} if they are not set.
+
+When booting, the Linux kernel will delegate the task of mounting the root
+filesystem to the initrd.  Most initrd images determine the root file system by
+checking the Linux kernel's command-line for the @samp{root} key and use its
+value as the identification method of the root file system.  To improve the
+reliability of booting, most initrd images also allow the root file system to be
+identified by its UUID.  Because of this behavior, the @command{grub-mkconfig}
+command will set @samp{root} to @samp{root=UUID=...} to provide the initrd with
+the filesystem UUID of the root file system.
+
+If no initrd is detected or @samp{GRUB_DISABLE_LINUX_UUID} is set to @samp{true}
+then @command{grub-command} will identify the root filesystem by setting the
+kernel command-line variable @samp{root} to @samp{root=PARTUUID=...} unless
+@samp{GRUB_DISABLE_LINUX_PARTUUID} is also set to @samp{true}.  If
+@samp{GRUB_DISABLE_LINUX_PARTUUID} is also set to @samp{true},
+@command{grub-command} will identify by its Linux device name.
+
+The following table summarizes the behavior of the @command{grub-mkconfig}
+command.
+
+@multitable {detected} {GRUB_DISABLE_LINUX_PARTUUID} {GRUB_DISABLE_LINUX_UUID} {Linux Root}
+@headitem Initrd detected @tab GRUB_DISABLE_LINUX_PARTUUID Set To @tab GRUB_DISABLE_LINUX_UUID Set To @tab Linux Root ID Method
+@item false         @tab false                       @tab false                   @tab part UUID
+@item false         @tab false                       @tab true                    @tab part UUID
+@item false         @tab true                        @tab false                   @tab dev name
+@item false         @tab true                        @tab true                    @tab dev name
+@item true          @tab false                       @tab false                   @tab fs UUID
+@item true          @tab false                       @tab true                    @tab part UUID
+@item true          @tab true                        @tab false                   @tab fs UUID
+@item true          @tab true                        @tab true                    @tab dev name
+@end multitable
+
+Remember, @samp{GRUB_DISABLE_LINUX_PARTUUID} and @samp{GRUB_DISABLE_LINUX_UUID}
+are also considered to be set to @samp{false} when they are unset.
 
 @node Shell-like scripting
 @section Writing full configuration files directly
@@ -3873,11 +3952,9 @@ you forget a command, you can run the command @command{help}
 @comment * vbeinfo::                     List available video modes
 * verify_detached::             Verify detached digital signature
 * videoinfo::                   List available video modes
-@comment * xen_*::              Xen boot commands
-* xen_hypervisor::              Load xen hypervisor binary
-* xen_linux::                   Load dom0 kernel for xen hypervisor
-* xen_initrd::                  Load dom0 initrd for dom0 kernel
-* xen_xsm::                     Load xen security module for xen hypervisor
+@comment * xen_*::              Xen boot commands for AArch64
+* xen_hypervisor::              Load xen hypervisor binary (only on AArch64)
+* xen_module::                  Load xen modules for xen hypervisor (only on AArch64)
 @end menu
 
 
@@ -4645,7 +4722,7 @@ range 0-0xFF (prefix with @samp{0x} to enter it in hexadecimal).
 When enabled, this hides the selected partition by setting the @dfn{hidden}
 bit in its partition type code; when disabled, unhides the selected
 partition by clearing this bit.  This is useful only when booting DOS or
-Wwindows and multiple primary FAT partitions exist in one disk.  See also
+Windows and multiple primary FAT partitions exist in one disk.  See also
 @ref{DOS/Windows}.
 @end table
 @end deffn
@@ -5153,32 +5230,22 @@ List available video modes. If resolution is given, show only matching modes.
 Load a Xen hypervisor binary from @var{file}. The rest of the line is passed
 verbatim as the @dfn{kernel command-line}. Any other binaries must be
 reloaded after using this command.
+This command is only available on AArch64 systems.
 @end deffn
 
-@node xen_linux
-@subsection xen_linux
+@node xen_module
+@subsection xen_module
 
-@deffn Command xen_linux file [arguments]
-Load a dom0 kernel image for xen hypervisor at the booting process of xen.
+@deffn Command xen_module [--nounzip] file [arguments]
+Load a module for xen hypervisor at the booting process of xen.
 The rest of the line is passed verbatim as the module command line.
+Modules should be loaded in the following order:
+ - dom0 kernel image
+ - dom0 ramdisk if present
+ - XSM policy if present
+This command is only available on AArch64 systems.
 @end deffn
 
-@node xen_initrd
-@subsection xen_initrd
-
-@deffn Command xen_initrd file
-Load a initrd image for dom0 kernel at the booting process of xen.
-@end deffn
-
-@node xen_xsm
-@subsection xen_xsm
-
-@deffn Command xen_xsm file
-Load a xen security module for xen hypervisor at the booting process of xen.
-See @uref{http://wiki.xen.org/wiki/XSM} for more detail.
-@end deffn
-
-
 @node Networking commands
 @section The list of networking commands
 
@@ -5368,7 +5435,7 @@ NTFS, JFS, UDF, HFS+, exFAT, long filenames in FAT, Joliet part of
 ISO9660 are treated as UTF-16 as per specification. AFS and BFS are read
 as UTF-8, again according to specification. BtrFS, cpio, tar, squash4, minix,
 minix2, minix3, ROMFS, ReiserFS, XFS, ext2, ext3, ext4, FAT (short names),
-RockRidge part of ISO9660, nilfs2, UFS1, UFS2 and ZFS are assumed
+F2FS, RockRidge part of ISO9660, nilfs2, UFS1, UFS2 and ZFS are assumed
 to be UTF-8. This might be false on systems configured with legacy charset
 but as long as the charset used is superset of ASCII you should be able to
 access ASCII-named files. And it's recommended to configure your system to use
diff --git a/gentpl.py b/gentpl.py
index f08bcc404f6a8bd8c3b13a6d5bb041ee32422776..da67965a41a40cde7c987b719fea39cd02ba10e5 100644
--- a/gentpl.py
+++ b/gentpl.py
@@ -31,7 +31,8 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot",
                    "i386_xen", "x86_64_xen",
                    "mips_loongson", "sparc64_ieee1275",
                    "powerpc_ieee1275", "mips_arc", "ia64_efi",
-                   "mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi" ]
+                   "mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi",
+                   "arm_coreboot"]
 
 GROUPS = {}
 
@@ -44,7 +45,7 @@ GROUPS["x86"]      = GROUPS["i386"] + GROUPS["x86_64"]
 GROUPS["mips"]     = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ]
 GROUPS["sparc64"]  = [ "sparc64_ieee1275" ]
 GROUPS["powerpc"]  = [ "powerpc_ieee1275" ]
-GROUPS["arm"]      = [ "arm_uboot", "arm_efi" ]
+GROUPS["arm"]      = [ "arm_uboot", "arm_efi", "arm_coreboot" ]
 GROUPS["arm64"]    = [ "arm64_efi" ]
 
 # Groups based on firmware
@@ -52,6 +53,7 @@ GROUPS["efi"]  = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi"
 GROUPS["ieee1275"]   = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ]
 GROUPS["uboot"] = [ "arm_uboot" ]
 GROUPS["xen"]  = [ "i386_xen", "x86_64_xen" ]
+GROUPS["coreboot"]  = [ "i386_coreboot", "arm_coreboot" ]
 
 # emu is a special case so many core functionality isn't needed on this platform
 GROUPS["noemu"]   = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu")
@@ -61,10 +63,10 @@ GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips",
                                      "sparc64_ieee1275", "powerpc_ieee1275"]
 GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi");
 GROUPS["pci"]      = GROUPS["x86"] + ["mips_loongson"]
-GROUPS["usb"]      = GROUPS["pci"]
+GROUPS["usb"]      = GROUPS["pci"] + ["arm_coreboot"]
 
 # If gfxterm is main output console integrate it into kernel
-GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot" ]
+GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot", "arm_coreboot" ]
 GROUPS["videomodules"]   = GRUB_PLATFORMS[:];
 for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i)
 
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 04e9395fd949460672c1113c3d49c90a5d4471ec..f4ff62b769ae99f1d9b2fadf51378966c93d835c 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -112,7 +112,7 @@ endif
 
 if COND_i386_coreboot
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
-KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/coreboot/lbio.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/coreboot/lbio.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h
@@ -239,8 +239,21 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
 endif
 
+if COND_arm_coreboot
+KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdt.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dma.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/coreboot/kernel.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdtbus.h
+endif
+
 if COND_arm_efi
-KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/efi/loader.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
@@ -278,7 +291,7 @@ BUILT_SOURCES += symlist.h
 
 symlist.c: symlist.h gensymlist.sh
 	$(TARGET_CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) $(CPPFLAGS) -DGRUB_SYMBOL_GENERATOR=1 symlist.h > symlist.p || (rm -f symlist.p; exit 1)
-	cat symlist.p | /bin/sh $(srcdir)/gensymlist.sh $(top_builddir)/config.h $(KERNEL_HEADER_FILES) >$@ || (rm -f $@; exit 1)
+	cat symlist.p | $(SHELL) $(srcdir)/gensymlist.sh $(top_builddir)/config.h $(KERNEL_HEADER_FILES) >$@ || (rm -f $@; exit 1)
 	rm -f symlist.p
 CLEANFILES += symlist.c
 BUILT_SOURCES += symlist.c
@@ -358,6 +371,16 @@ terminal.lst: $(MARKER_FILES)
 platform_DATA += terminal.lst
 CLEANFILES += terminal.lst
 
+fdt.lst: $(MARKER_FILES)
+	(for pp in $^; do \
+	  b=`basename $$pp .marker`; \
+	  sed -n \
+	    -e "/FDT_DRIVER_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $$b/;p;}" \
+	    -e "/FDT_DRIVER_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $$b/;p;}" $$pp; \
+	done) | sort -u > $@
+platform_DATA += fdt.lst
+CLEANFILES += fdt.lst
+
 parttool.lst: $(MARKER_FILES)
 	(for pp in $^; do \
 	  b=`basename $$pp .marker`; \
diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in
index 03cc3b7f69ed3cfb69b744f8114895fd0e14fde7..1250589b3f5f88b52d7ea6de361427339fe7e578 100644
--- a/grub-core/genmod.sh.in
+++ b/grub-core/genmod.sh.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 set -e
 
 # Copyright (C) 2010 Free Software Foundation, Inc.
@@ -58,6 +58,10 @@ 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 .gnu.build.attributes \
+		-R .rel.gnu.build.attributes \
+		-R .rela.gnu.build.attributes \
+		-R .eh_frame -R .rela.eh_frame -R .rel.eh_frame \
 		-R .note -R .comment -R .ARM.exidx $tmpfile || exit 1
 	fi
 	if ! test -z "${TARGET_OBJ2ELF}"; then
diff --git a/grub-core/genmoddep.awk b/grub-core/genmoddep.awk
index bd98d84cdd7427eef2f3651f455377d469955250..04c2863e5abfa4d950df2c41d579dea03a361927 100644
--- a/grub-core/genmoddep.awk
+++ b/grub-core/genmoddep.awk
@@ -18,6 +18,10 @@ BEGIN {
 
 {
   if ($1 == "defined") {
+    if ($3 !~ /^\.refptr\./ && $3 in symtab) {
+      printf "%s in %s is duplicated in %s\n", $3, $2, symtab[$3] >"/dev/stderr";
+      error++;
+    }
     symtab[$3] = $2;
     modtab[$2] = "" modtab[$2]
   } else if ($1 == "undefined") {
diff --git a/grub-core/gensyminfo.sh.in b/grub-core/gensyminfo.sh.in
index 2e8716b425cb04d9379ef5e2c629283d0f346c90..9bc7675327a6d9229492548671dd004054282434 100644
--- a/grub-core/gensyminfo.sh.in
+++ b/grub-core/gensyminfo.sh.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 set -e
 
 # Copyright (C) 2010 Free Software Foundation, Inc.
diff --git a/grub-core/modinfo.sh.in b/grub-core/modinfo.sh.in
index faf0ad30edbe878270a185add45aa70e245d8b3a..f6cd657ce0f8307547fc5d011efa35622c318e63 100644
--- a/grub-core/modinfo.sh.in
+++ b/grub-core/modinfo.sh.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 # User-controllable options
 grub_modinfo_target_cpu=@target_cpu@
diff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l
index 95b2191705ac826833e0951fa323242a9f8859d1..7b44c37b76ffa87f24b6f04260b9519f0c8654c0 100644
--- a/grub-core/script/yylex.l
+++ b/grub-core/script/yylex.l
@@ -91,7 +91,7 @@ typedef size_t yy_size_t;
 #define stdin  0
 #define stdout 0
 
-#define fprintf(...) 0
+#define fprintf(...) (void)0
 #define exit(...) grub_fatal("fatal error in lexer")
 #endif
 
diff --git a/po/Makefile.in.in b/po/Makefile.in.in
index 3619458e85f2bed3f92a76a9d919c26a30116dee..e68e9da843d927bfb6bbd519f4b3923c733abd7c 100644
--- a/po/Makefile.in.in
+++ b/po/Makefile.in.in
@@ -15,7 +15,7 @@ PACKAGE = @PACKAGE@
 VERSION = @VERSION@
 PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
 
-SHELL = /bin/sh
+SHELL = @SHELL@
 @SET_MAKE@
 
 srcdir = @srcdir@
diff --git a/po/exclude.pot b/po/exclude.pot
index 0a9b215eaf1971bf2a2af8a36e9605043de38e36..816089c30cbd36939b2a72724b3d591a0ac8a290 100644
GIT binary patch
delta 49
zcmaEUhNJl`#|G_WNh^i)qS7SY<ou#k{j_5JG^4a)y<{sxBh%><eHg`>?UJ|KB{OOs
F1^~&~5lR36

delta 27
jcmZoZ%klgS#|G`>=`Ng%LX#(mur$XeZ;wr8R67g+m_Q0B

diff --git a/tests/ahci_test.in b/tests/ahci_test.in
index 1d01d1f59a0aac8911ff7ca3e62565f2dee5954d..7df56046201e4c2e4a55bdcdd403853cde902268 100644
--- a/tests/ahci_test.in
+++ b/tests/ahci_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2013  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/btrfs_test.in b/tests/btrfs_test.in
index c55d9477f78e01b6556bc0da9695f038523936f4..2b37ddd3324cc77f1edeb03feb369c22d03204a2 100644
--- a/tests/btrfs_test.in
+++ b/tests/btrfs_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/cdboot_test.in b/tests/cdboot_test.in
index 1cc901977c229dcf839bf58bede2b34f04252d57..75acdfedb7fe4a634d4122e44b3cd01778ed6f35 100644
--- a/tests/cdboot_test.in
+++ b/tests/cdboot_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2013  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/core_compress_test.in b/tests/core_compress_test.in
index 1003587ccca65616b0c7e3c1b90353ef7f459299..9d216ebcff60bfce04e3be4dbd1f8834800a6948 100644
--- a/tests/core_compress_test.in
+++ b/tests/core_compress_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2013  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/cpio_test.in b/tests/cpio_test.in
index 0b09db549f07868a524376f0eb25fd6a2cac9e40..5742cf17b9d8f587d00590d481f0a00aaf6cada8 100644
--- a/tests/cpio_test.in
+++ b/tests/cpio_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/ehci_test.in b/tests/ehci_test.in
index 7dd8d3e8fbd4a76b8efb88d69ecd8989546dc543..b197f8cdc922628ed35863dfa384eeef4cc4cc09 100644
--- a/tests/ehci_test.in
+++ b/tests/ehci_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2013  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/example_scripted_test.in b/tests/example_scripted_test.in
index 09633e89341e079a05fda7461d867e1541df4287..783b7f13853f39f9ec63b8da1da6e8a1b3a887a5 100644
--- a/tests/example_scripted_test.in
+++ b/tests/example_scripted_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 set -e
 
 true
diff --git a/tests/exfat_test.in b/tests/exfat_test.in
index fc1a0fe5ec0306434434f0b49b20c44a1736dca1..cd3cd4cb2f70bb99df7edbfa8b5697f4316548ac 100644
--- a/tests/exfat_test.in
+++ b/tests/exfat_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/ext234_test.in b/tests/ext234_test.in
index c986960a8bec696deb37a55cba00915219d77215..4f1eb527eb2ed41095266dba6d5013ead77d9be3 100644
--- a/tests/ext234_test.in
+++ b/tests/ext234_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
@@ -30,3 +30,4 @@ fi
 "@builddir@/grub-fs-tester" ext3
 "@builddir@/grub-fs-tester" ext4
 "@builddir@/grub-fs-tester" ext4_metabg
+"@builddir@/grub-fs-tester" ext4_encrypt
diff --git a/tests/f2fs_test.in b/tests/f2fs_test.in
new file mode 100644
index 0000000000000000000000000000000000000000..1ea77c826d32bd01e33d13ea7ad6639eb1cb77b0
--- /dev/null
+++ b/tests/f2fs_test.in
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+set -e
+
+if [ "x$EUID" = "x" ] ; then
+ EUID=`id -u`
+fi
+
+if [ "$EUID" != 0 ] ; then
+ exit 77
+fi
+
+if ! which mkfs.f2fs >/dev/null 2>&1; then
+ echo "mkfs.f2fs not installed; cannot test f2fs."
+ exit 77
+fi
+
+
+"@builddir@/grub-fs-tester" f2fs
diff --git a/tests/fat_test.in b/tests/fat_test.in
index 1d132b51703c43e269d5500ca1740fa1e6b9a42c..b6b4748ca694b59337441a2f3111863e01799884 100644
--- a/tests/fat_test.in
+++ b/tests/fat_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/fddboot_test.in b/tests/fddboot_test.in
index a59645b7f873872490ac2474a30420c2df7a5caf..2d7dfc8891f6d7fdf42f88dea1213428e23b6f2e 100644
--- a/tests/fddboot_test.in
+++ b/tests/fddboot_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2013  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/file_filter_test.in b/tests/file_filter_test.in
index 8909e4021fb1d507cd5bf3b63319824fdc005dd5..bfb6382274e48d409d6cf6f918fc252f993f717f 100644
--- a/tests/file_filter_test.in
+++ b/tests/file_filter_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2014  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/gettext_strings_test.in b/tests/gettext_strings_test.in
index 5c305e75b7e9583f6be8a23d389051cf1fe2c243..813999ebe6ea5ee35796669e58baa57d0a2ace95 100644
--- a/tests/gettext_strings_test.in
+++ b/tests/gettext_strings_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 cd '@srcdir@'
 
diff --git a/tests/grub_cmd_date.in b/tests/grub_cmd_date.in
index a459353e8a51c22fb966a842af532cff904de2a3..f7c9ca00432fa3307a2fb53ac88ca11115d7f73f 100644
--- a/tests/grub_cmd_date.in
+++ b/tests/grub_cmd_date.in
@@ -1,4 +1,4 @@
-#! /bin/bash
+#! @BUILD_SHEBANG@
 set -e
 
 . "@builddir@/grub-core/modinfo.sh"
@@ -9,7 +9,7 @@ if [ "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" = sparc64-ieee1275 ];
 fi
 
 pdt="$(date -u +%s)"
-dt=`echo date | @builddir@/grub-shell`
+dt=`echo date | @builddir@/grub-shell | sed 's, [A-Z][a-z]*$,,'`
 dtg="$(date -u -d "$dt" +%s)"
 ndt="$(date -u +%s)"
 
diff --git a/tests/grub_cmd_regexp.in b/tests/grub_cmd_regexp.in
index e7e6257011525ee42ca6945485208155fe717d24..6520bd6d79acc0c8f5bfddc443912d74e826a0c8 100644
--- a/tests/grub_cmd_regexp.in
+++ b/tests/grub_cmd_regexp.in
@@ -1,4 +1,4 @@
-#! /bin/bash
+#! @BUILD_SHEBANG@
 set -e
 
 # Run GRUB script in a Qemu instance
diff --git a/tests/grub_cmd_set_date.in b/tests/grub_cmd_set_date.in
index c594ae3fc14ebf7a6be86b90f4d048747383a69f..aac120a6c52731649678549d34372af14fef52d9 100644
--- a/tests/grub_cmd_set_date.in
+++ b/tests/grub_cmd_set_date.in
@@ -1,4 +1,4 @@
-#! /bin/bash
+#! @BUILD_SHEBANG@
 set -e
 
 . "@builddir@/grub-core/modinfo.sh"
diff --git a/tests/grub_cmd_sleep.in b/tests/grub_cmd_sleep.in
index eb362aa2439d713bf4246e2c56932bbc6200d710..8797f6632845f5a76ac22b813c223897ceddd672 100644
--- a/tests/grub_cmd_sleep.in
+++ b/tests/grub_cmd_sleep.in
@@ -1,4 +1,4 @@
-#! /bin/bash
+#! @BUILD_SHEBANG@
 set -e
 
 . "@builddir@/grub-core/modinfo.sh"
@@ -11,8 +11,8 @@ fi
 # Compare RTC with interval timer.
 # Not 100% proper but should check that timer is running ok
 dt=`echo 'date; sleep 10; date' | @builddir@/grub-shell`
-dt1="$(date -u -d "$(echo "$dt" | head -n 1)" +%s)"
-dt2="$(date -u -d "$(echo "$dt" | tail -n 1)" +%s)"
+dt1="$(date -u -d "$(echo "$dt" | head -n 1 | sed 's, [A-Z][a-z]*$,,')" +%s)"
+dt2="$(date -u -d "$(echo "$dt" | tail -n 1 | sed 's, [A-Z][a-z]*$,,')" +%s)"
 
 # Ignore QEMU bug
 if [ "${grub_modinfo_target_cpu}" = arm ] && [ $((dt2 - dt1)) -ge 15 ] && [ $((dt2 - dt1)) -le 17 ]; then
diff --git a/tests/grub_cmd_test.in b/tests/grub_cmd_test.in
index 6269891c9eeddb70f42da372e5636089e666818d..3399eb2929408570e9dad99db8dbc7215b41aea4 100644
--- a/tests/grub_cmd_test.in
+++ b/tests/grub_cmd_test.in
@@ -1,4 +1,4 @@
-#! /bin/bash
+#! @BUILD_SHEBANG@
 
 # create a randome file
 empty="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1
diff --git a/tests/grub_cmd_tr.in b/tests/grub_cmd_tr.in
index 3fb15e35c8ac3ac218abf580f8ff5cdcaa2925ca..bed469c03ddc9a762112896d75af399678af711e 100644
--- a/tests/grub_cmd_tr.in
+++ b/tests/grub_cmd_tr.in
@@ -1,4 +1,4 @@
-#! /bin/bash -e
+#! @BUILD_SHEBANG@ -e
 
 # Run GRUB script in a Qemu instance
 # Copyright (C) 2010  Free Software Foundation, Inc.
diff --git a/tests/grub_func_test.in b/tests/grub_func_test.in
index c8cc263763377fd23d6c7f1eca49c1edafe530a7..c67f9e422534a402614eb280fe67d165fd0bb906 100644
--- a/tests/grub_func_test.in
+++ b/tests/grub_func_test.in
@@ -1,4 +1,4 @@
-#! /bin/bash
+#! @BUILD_SHEBANG@
 set -e
 
 . "@builddir@/grub-core/modinfo.sh"
diff --git a/tests/grub_script_blanklines.in b/tests/grub_script_blanklines.in
index 89ed763d3f4e0bb2a3ac3a61de9e0ec49b2eaccf..bd8735491be3b947c72fffbf5767d7ab6bcf91ae 100644
--- a/tests/grub_script_blanklines.in
+++ b/tests/grub_script_blanklines.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 set -e
 
 @builddir@/grub-script-check <<EOF
diff --git a/tests/grub_script_blockarg.in b/tests/grub_script_blockarg.in
index 2765b61acbb8c1081f620960e0350c5489dc2875..6ea9b8c3d87cb2e9fc5693da93cb9885cfdd20e2 100644
--- a/tests/grub_script_blockarg.in
+++ b/tests/grub_script_blockarg.in
@@ -1,4 +1,4 @@
-#! /bin/bash
+#! @BUILD_SHEBANG@
 
 # Run GRUB script in a Qemu instance
 # Copyright (C) 2010  Free Software Foundation, Inc.
diff --git a/tests/grub_script_dollar.in b/tests/grub_script_dollar.in
index 2e076427afbc86e05260b58e9f22f7e3fe48ce4e..392fe2e7ab0f773ef3ba04366386d799cda3f83c 100644
--- a/tests/grub_script_dollar.in
+++ b/tests/grub_script_dollar.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 set -e
 
 @builddir@/grub-script-check << EOF
diff --git a/tests/grub_script_expansion.in b/tests/grub_script_expansion.in
index e46401c4c9f1b6bea3c7bed452882d373e51bd61..9d0dcdd29100904bfba93ccd429340d4a5afbcf3 100644
--- a/tests/grub_script_expansion.in
+++ b/tests/grub_script_expansion.in
@@ -1,4 +1,4 @@
-#! /bin/bash
+#! @BUILD_SHEBANG@
 set -e
 
 # Run GRUB script in a Qemu instance
diff --git a/tests/grub_script_final_semicolon.in b/tests/grub_script_final_semicolon.in
index 3ac26540bbd7cf4614dc199534417b139c2bb7f0..f17a9bf95e6db3d710d683fdbdc749fdab7e3a0a 100644
--- a/tests/grub_script_final_semicolon.in
+++ b/tests/grub_script_final_semicolon.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 set -e
 
 @builddir@/grub-script-check <<EOF
diff --git a/tests/grub_script_no_commands.in b/tests/grub_script_no_commands.in
index c31d267e5fdf090fda15878cbe0b794b2f4e8b9f..996bb181043dcbddd95ab98c8cbcc57b0fe91f4d 100644
--- a/tests/grub_script_no_commands.in
+++ b/tests/grub_script_no_commands.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 set -e
 
 # grub-script-check refuses to pass a file with no commands; this usually
diff --git a/tests/gzcompress_test.in b/tests/gzcompress_test.in
index 11b6bb208302e03e0c5198f678bc7cc119862898..42c8fe7c4e8fc83022f656c0be7963aab3166a75 100644
--- a/tests/gzcompress_test.in
+++ b/tests/gzcompress_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2013  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/hddboot_test.in b/tests/hddboot_test.in
index c229716a642942d1eba6cc9d00867c0292c8e7a4..6d70847a5dec394fec13e6b21a9dd0d890cf2a4d 100644
--- a/tests/hddboot_test.in
+++ b/tests/hddboot_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2013  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/help_test.in b/tests/help_test.in
index e780924ef7b02245b6009956bd2baab3623aa5a8..b08cf201382e043e6b2fc07fd6f7a410aa051dca 100644
--- a/tests/help_test.in
+++ b/tests/help_test.in
@@ -1,4 +1,4 @@
-#! /bin/bash
+#! @BUILD_SHEBANG@
 set -e
 
 . "@builddir@/grub-core/modinfo.sh"
diff --git a/tests/hfs_test.in b/tests/hfs_test.in
index e3e88f190677d24699def63ba666df3b2748b045..d7ec56beffa7909c28636a4af5142a2c8ee334de 100644
--- a/tests/hfs_test.in
+++ b/tests/hfs_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/hfsplus_test.in b/tests/hfsplus_test.in
index f947c4a447fe1a310761a3606257c793b9e2358a..85f1c37dce6a0c5a217d75b051b1ab426d06a2be 100644
--- a/tests/hfsplus_test.in
+++ b/tests/hfsplus_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/iso9660_test.in b/tests/iso9660_test.in
index fdcc9e124208dd3b8d5a997c8522ffb52bc3ced1..571b938d7a08b14ca21dd6497bd0092f3d6d40cb 100644
--- a/tests/iso9660_test.in
+++ b/tests/iso9660_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/jfs_test.in b/tests/jfs_test.in
index c2e5eceddcd2cb433dcdc120fe44dc9d8bd2b45e..6cf7576b35ed8ce4b86036ed67df02b698fbc062 100644
--- a/tests/jfs_test.in
+++ b/tests/jfs_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/lzocompress_test.in b/tests/lzocompress_test.in
index 41984c25419b78c727b3b8957bde3ac611cbd76e..4e5f7e078d5116f0794b035cabe1002420fb1d2c 100644
--- a/tests/lzocompress_test.in
+++ b/tests/lzocompress_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2013  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/minixfs_test.in b/tests/minixfs_test.in
index 1784b1261f7592a78820dbd9f1900f89df133f9b..3b16a4de09314b95eb45ee21fe9441789b429e51 100644
--- a/tests/minixfs_test.in
+++ b/tests/minixfs_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/netboot_test.in b/tests/netboot_test.in
index c757023d989e89a9400dbbc79e674edd5bea9fd6..9f71e3d88542ae9b87e9218c1c1197aeef29989a 100644
--- a/tests/netboot_test.in
+++ b/tests/netboot_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2013  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/nilfs2_test.in b/tests/nilfs2_test.in
index 780b60ec1ac980ea1e40af3a319c83a86a6415e6..ad44d5b33c8af3ab9f62b7c8ca866c025a51d24a 100644
--- a/tests/nilfs2_test.in
+++ b/tests/nilfs2_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/ntfs_test.in b/tests/ntfs_test.in
index e25c6384a9cd6e086961116c83db4a31353d6e7c..9eb7b01f66e923009939abf7b839276a15fa67a3 100644
--- a/tests/ntfs_test.in
+++ b/tests/ntfs_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/ohci_test.in b/tests/ohci_test.in
index 7fede6f262c1fdac41609dc660017e279a06f3a1..8693f8c472879fcbd43f52d4e61973d19b52ddc1 100644
--- a/tests/ohci_test.in
+++ b/tests/ohci_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2013  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/partmap_test.in b/tests/partmap_test.in
index f8dc456fb8c6c25d034c53821066ad618664afa0..6ef518b0adc1e001bfc64c853ffb5c490d02330d 100644
--- a/tests/partmap_test.in
+++ b/tests/partmap_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 set -e
 
 # Copyright (C) 2010  Free Software Foundation, Inc.
diff --git a/tests/pata_test.in b/tests/pata_test.in
index c1d0f63ea21b5cdc6d818a1aabbd691a2e7a2fa5..4b18fdef3d3594ccb105dd0d265e8517890d9853 100644
--- a/tests/pata_test.in
+++ b/tests/pata_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2013  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/pseries_test.in b/tests/pseries_test.in
index 226494593d1514112f33eee695c3c418421198c1..655eb4f3a63a210ffd1271ac16da47bcbad70434 100644
--- a/tests/pseries_test.in
+++ b/tests/pseries_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2013  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/reiserfs_test.in b/tests/reiserfs_test.in
index 678efe7b36662dfb1325b969e7451ccb5024c3dc..b5fed7635673467d5c46409625463e50498b9807 100644
--- a/tests/reiserfs_test.in
+++ b/tests/reiserfs_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/romfs_test.in b/tests/romfs_test.in
index 83e09315acf62eb00c54faa95e785b114b08017a..98bb50c324b6e8cd1163c772a78271b64768ae57 100644
--- a/tests/romfs_test.in
+++ b/tests/romfs_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/squashfs_test.in b/tests/squashfs_test.in
index ec34e0108c3bfb663e1a8959fb4cd3bb736bff76..2f044f95d99b2ee7a6ddf1d2b2e54be3944f235f 100644
--- a/tests/squashfs_test.in
+++ b/tests/squashfs_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/syslinux_test.in b/tests/syslinux_test.in
index fc4edd8ef6b91f7d0759c85c7a657402248fd120..4ea86390e0a320ed9afdf77ecc42e4d328e17e28 100644
--- a/tests/syslinux_test.in
+++ b/tests/syslinux_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/tar_test.in b/tests/tar_test.in
index 46ba3bce295b256631eaa8ab12c581f2bdafb7f6..6e2f2de8b7ff78ca84401213dadd011a0b65f281 100644
--- a/tests/tar_test.in
+++ b/tests/tar_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/test_sha512sum.in b/tests/test_sha512sum.in
index d5ef7f9ea62d1c9749c6a134580dace95fa7624a..027092a8b17f398776e605251fcd8d48b7b4965e 100644
--- a/tests/test_sha512sum.in
+++ b/tests/test_sha512sum.in
@@ -1,4 +1,4 @@
-#! /bin/bash
+#! @BUILD_SHEBANG@
 
 # create a randome file
 file="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1
diff --git a/tests/udf_test.in b/tests/udf_test.in
index fe244e2bdfc8b7d17ec25ac80d12724dcdbb1cba..fb92f0173cc74151d7fdc722522d654efa2233b5 100644
--- a/tests/udf_test.in
+++ b/tests/udf_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/uhci_test.in b/tests/uhci_test.in
index 89e2c18051ac00f414edd0e80bdcfd911c8f9842..4af72fd8fea5ab2b3e2059d2a89f0b0dfaa74c9a 100644
--- a/tests/uhci_test.in
+++ b/tests/uhci_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2013  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/util/grub-fs-tester.in b/tests/util/grub-fs-tester.in
index 2337771a1b9ce287c3e5e24e49c7c27baee7edb8..ef65fbc93414daf310b842f0d9a360ca10a0e5a3 100644
--- a/tests/util/grub-fs-tester.in
+++ b/tests/util/grub-fs-tester.in
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!@BUILD_SHEBANG@
 
 set -e
 
@@ -13,8 +13,29 @@ run_it () {
     LC_ALL=C "$GRUBFSTEST" "$@"
 }
 
+range() {
+    range_counter="$1"
+    while test "$range_counter" -le "$2"; do
+	echo "$range_counter"
+	range_counter="$((range_counter + $3))"
+    done
+}
+
+powrange() {
+    range_counter="$1"
+    while test "$range_counter" -le "$2"; do
+	echo "$range_counter"
+	range_counter="$((range_counter * 2))"
+    done
+}
+
 run_grubfstest () {
-    run_it -c $NEED_IMAGES_N "${NEED_IMAGES[@]}"  "$@"
+    need_images=
+    for i in $(range 0 $((NEED_IMAGES_N-1)) 1); do
+	need_images="$need_images $FSIMAGEP${i}.img";
+    done
+
+    run_it -c $NEED_IMAGES_N $need_images  "$@"
 }
 
 # OS LIMITATION: GNU/Linux has no AFS support, so we use a premade image and a reference tar file. I.a. no multiblocksize test
@@ -51,7 +72,7 @@ case x"$fs" in
 	# OS limitation: zfs-fuse always uses ashift=9 with loop devices
 	MAXLOGSECSIZE=9;;
 esac
-for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE + 1)); do
+for LOGSECSIZE in $(range "$MINLOGSECSIZE" "$MAXLOGSECSIZE" 1); do
     SECSIZE="$((1 << LOGSECSIZE))"
     MINBLKSIZE=512
     MAXBLKSIZE=512
@@ -135,6 +156,12 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		# Could go further but what's the point?
 	    MAXBLKSIZE=$((65536*1024))
 	    ;;
+       xext4_encrypt)
+           # OS LIMITATION: Linux currently only allows the 'encrypt' feature
+           # in combination with block_size = PAGE_SIZE (4096 bytes on x86).
+           MINBLKSIZE=$(getconf PAGE_SIZE)
+           MAXBLKSIZE=$MINBLKSIZE
+           ;;
 	xext*)
 	    MINBLKSIZE=1024
 	    if [ $MINBLKSIZE -lt $SECSIZE ]; then
@@ -145,7 +172,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	xsquash*)
 	    MINBLKSIZE=4096
 	    MAXBLKSIZE=1048576;;
-	xxfs)
+	xxfs|xf2fs)
 	    MINBLKSIZE=$SECSIZE
 		# OS Limitation: GNU/Linux doesn't accept > 4096
 	    MAXBLKSIZE=4096;;
@@ -169,7 +196,12 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    MINBLKSIZE=1024
 	    MAXBLKSIZE=4096;;
     esac
-    for ((BLKSIZE=MINBLKSIZE;BLKSIZE<=MAXBLKSIZE;BLKSIZE=BLKSTEP?BLKSIZE+BLKSTEP:2*BLKSIZE)); do
+    if test "$BLKSTEP" -eq 0; then
+	blksizes="$(powrange "$MINBLKSIZE" "$MAXBLKSIZE")"
+    else
+	blksizes="$(range "$MINBLKSIZE" "$MAXBLKSIZE" "$BLKSTEP")"
+    fi
+    for BLKSIZE in $blksizes; do
 	MAXDEVICES=1
 	MINDEVICES=1
 	export fs
@@ -199,13 +231,11 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		MAXDEVICES=7;;
 	esac
 
-	for ((NDEVICES=MINDEVICES; NDEVICES <= MAXDEVICES; NDEVICES++)); do
+	for NDEVICES in $(range "$MINDEVICES" "$MAXDEVICES" 1); do
 	    export NDEVICES
-	    unset FSIMAGES
-	    for ((i=0; i < NDEVICES; i++)); do
-		FSIMAGES[i]="${tempdir}/${fs}_${SECSIZE}_${BLKSIZE}_${NDEVICES}_$i.img"
-	    done
-	    export FSIMAGES
+	    unset FSIMAGEP
+	    FSIMAGEP="${tempdir}/${fs}_${SECSIZE}_${BLKSIZE}_${NDEVICES}_"
+	    export FSIMAGEP
 	    unset NEED_IMAGES;
 
 	    case x$fs in
@@ -226,11 +256,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		*)
 		    NEED_IMAGES_N=$NDEVICES;;
 	    esac
-	    for ((i=0;i < NEED_IMAGES_N; i++)); do
-		NEED_IMAGES[i]="${FSIMAGES[i]}";
-	    done
 	    export NEED_IMAGES_N
-	    export NEED_IMAGES
 
 	    MNTPOINTRO="${tempdir}/${fs}_ro"
 	    MNTPOINTRW="${tempdir}/${fs}_rw"
@@ -238,20 +264,25 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    MOUNTFS="$fs"
 	    MASTER="${tempdir}/master"
 	    FSLABEL="grub_;/testé莭莽茝😁киритi urewfceniuewruevrewnuuireurevueurnievrewfnerfcnevirivinrewvnirewnivrewiuvcrewvnuewvrrrewniuerwreiuviurewiuviurewnuvewnvrenurnunuvrevuurerejiremvreijnvcreivire nverivnreivrevnureiorfnfrvoeoiroireoireoifrefoieroifoireoifoirefoireoifoijfoirereoireoivoioirevoinvoinreoinvnoieoinreoinveoinveoinreoinvoineoinoinoineoinernoiveoinvreoiioewdioewoirvnoireoivfoirewfewoifoijewoijfoijewfoijfewoijoijoijoijoijoijoijfewceniuewruevrewnuuireurevueurnievrewfnerfcnevirivinrewvnirewnivrewiuvcrewvnuewvrrrewniuerwreiuviurewiuviurewnuvewnvrenurnunuvrevuurerejiremvreijnvcreivire nverivnreivrevnureiorfnfrvoeoiroireoireoifrefoieroifoireoifoirefoireoifoijfoirereoireoivoioirevoinvoinreoinvnoieoinreoinveoinveoinreoinvoineoinoinoineoinernoiveoinvreoiioewdioewoirvnoireoivfoirewfewoifoijewoijfoijewfoijfewoijoijoijoijoijoijoijfewrewfceniuewruevrewnuuireurevueurnievrewfnerfcnevirivinrewvnirewnivrewiuvcrewvnuewvrrrewniuerwreiuviurewiuviurewnuvewnvrenurnunuvrevuurerejiremvreijnvcreivire nverivnreivrevnureiorfnfrvoeoiroireoireoifrefoieroifoireoifoirefoireoifoijfoirereoireoivoioirevoinvoinreoinvnoieoinreoinveoinveoinreoinvoineoinoinoineoinernoiveoinvreoiioewdioewoirvnoireoivfoirewfewoifoijewoijfoijewfoijfewoijoijoijoijoijoijoijfewceniuewruevrewnuuireurevueurnievrewfnerfcnevirivinrewvnirewnivrewiuvcrewvnuewvrrrewniuerwreiuviurewiuviurewnuvewnvrenurnunuvrevuurerejiremvreijnvcreivire nverivnreivrevnureiorfnfrvoeoiroireoireoifrefoieroifoireoifoirefoireoifoijfoirereoireoivoioirevoinvoinreoinvnoieoinreoinveoinveoinreoinvoineoinoinoineoinernoiveoinvreoiioewdioewoirvnoireoivfoirewfewoifoijewoijfoijewfoijfewoijoijoijoijoijoijoijfew"
-	    CFILESN=1
-	    if test -f /usr/share/dict/american-english; then
-		CFILESSRC[0]="/usr/share/dict/american-english"
-	    else
-		CFILESSRC[0]="/usr/share/dict/linux.words"
+	    CFILESRC=
+	    for cand in /usr/share/dict/american-english /usr/share/dict/linux.words /data/data/com.termux/files/usr/share/hunspell/en_US.dic; do
+		if test -f "$cand" ; then
+		    CFILESRC="$cand"
+		    break
+		fi
+	    done
+	    if test "$CFILESRC" = "" ; then
+		echo "Couldn't find compressible file" >&2
+		exit 1
 	    fi
 	    case x"$fs" in
 		    # FS LIMITATION: 8.3 names
 		xmsdos*)
-		    CFILES[0]="american.eng";;
+		    CFILE="american.eng";;
 		xiso9660)
-		    CFILES[0]="american_english";;
+		    CFILE="american_english";;
 		*)
-		    CFILES[0]="american-english";;
+		    CFILE="american-english";;
 	    esac
         # OS LIMITATION: Limited by NAME_MAX (usually 255) in GNU/Linux
 	    LONGNAME="qwertzuiopasdfghjklyxcvbnm1234567890qwertzuiopasdfghjklyxcvbnm1234567890oiewqfiewioqoiqoiurqruewqoiuwoieoiiuewqroreqiufieiuwrnureweriuvceoiroiewqoiricdsalkcndsakfirefoiwqeoircorejwoijfreoijojoiewjfwnfcoirenfoirefnreoifenoiwfnoi"
@@ -268,6 +299,10 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		x"btrfs"*)
 		    FSLABEL="grub_;/testé莭莽😁киритi urewfceniuewruevrewnuuireurevueurnievrewfnerfcnevirivinrewvnirewnivrewiuvcrewvnuewvrrrewniuerwreiuviurewiuviurewnuvewnvrenurnunuvrevuurerejiremvreijnvcreivire nverivnreivrevnureiorfnfrvoeoiroireoireoifrefoieroifoireoi";;
 
+	    # FS LIMITATION: f2fs label is at most 512 UTF-16 chars
+		x"f2fs")
+		    FSLABEL="grub_;/testé䏌䐓䏕киритiurewfceniuewruewnuuireurevueurnievrewfnerfcnevirivinrewvnirewnivrewiuvcrewvnuewvrrrewniuerwreiuviurewiuviurewnuvewnvrenurnunuvrevuurerejiremvreijnvvcreivire nverivnreivrevnureiorfnfrvoeoiroireoireoifrefoieroifoirvcreivire nverivnreivrevnureiorfnfrvoeoiroireoireoifrefoieroifoircreivire nverivnreivrevnureiorfnfrvoeoiroireoireoifrefoieroifoireoifoiq";;
+
 	    # FS LIMITATION: exfat is at most 15 UTF-16 chars
 		x"exfat")
 		    FSLABEL="géт ;/莭莽😁кир";;
@@ -388,8 +423,8 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		    ;;
 		x"vfat16" | xmsdos16)
 		    BIGBLOCKCNT=$((25000 * BLKSIZE))
-		    if [ $BIGBLOCKCNT -gt $((16#ffffffff)) ]; then
-			BIGBLOCKCNT=$((16#ffffffff))
+		    if [ $BIGBLOCKCNT -gt 4294967295 ]; then
+			BIGBLOCKCNT=4294967295
 		    fi
 		    ;;
 		x"minix")
@@ -410,7 +445,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		    BIGBLOCKCNT=$((4000 * 1048576));;
 		    # FS LIMITATION: These FS have uint32 as file size field
 		x"vfat"* | xmsdos* | x"cpio_crc" | x"cpio_newc" | x"cpio_bin" | x"cpio_hpbin" | xsfs*)
-		    BIGBLOCKCNT=$((16#ffffffff));;
+		    BIGBLOCKCNT=4294967295;;
 		    # FS LIMITATION: These FS have int32 as file size field
 		    # FIXME: not so sure about AFFS
 		    # OS LIMITATION: minix2/minix3 could be formatted in a way to permit more.
@@ -477,7 +512,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    # FIXME: Not sure about BtrFS, NTFS, JFS, AFS, UDF and SFS. Check it.
 	# FS LIMITATION: as far as I know those FS don't store their last modification date.
 		x"jfs_caseins" | x"jfs" | x"xfs" | x"xfs_crc" | x"btrfs"* | x"reiserfs_old" | x"reiserfs" \
-		    | x"bfs" | x"afs" \
+		    | x"bfs" | x"afs" | x"f2fs" \
 		    | x"tarfs" | x"cpio_"* | x"minix" | x"minix2" \
 		    | x"minix3" | x"ntfs"* | x"udf" | x"sfs"*)
 		    NOFSTIME=y;;
@@ -543,18 +578,18 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 
 	    PDIR=""
 		# OS LIMITATION: Limited by PATH_MAX (usually 1024)
-	    for ((i=0;i<PDIRCOMPNUM;i++)); do
+	    for i in $(range 0 $((PDIRCOMPNUM-1)) 1); do
 		PDIR="$PDIR/$i";
-		if [ $((i%3)) == 0 ]; then
+		if test $((i%3)) = 0; then
 		    PDIR="$PDIR/"
 		fi
 	    done
 
 	    PDIR2=""
 		# OS LIMITATION: Limited by PATH_MAX (usually 1024)
-	    for ((i=0;i<PDIR2COMPNUM;i++)); do
+	    for i in $(range 0 $((PDIR2COMPNUM-1)) 1); do
 		PDIR2="${PDIR2}/$i";
-		if [ $((i%3)) == 0 ]; then
+		if test $((i%3)) = 0; then
 		    PDIR2="${PDIR2}/"
 		fi
 	    done
@@ -563,7 +598,9 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 
 	    unset LODEVICES
 	    GENERATED=n
-
+	    LODEVICES=
+	    MOUNTDEVICE=
+	    
 	    case x"$fs" in
 		x"tarfs" | x"cpio_"*| x"ziso9660" | x"romfs" | x"squash4_"*\
                     | x"iso9660" | xjoliet | xrockridge | xrockridge_joliet \
@@ -577,62 +614,64 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		*)
 		    mkdir -p "$MNTPOINTRW"
 		    mkdir -p "$MNTPOINTRO"
-		    for ((i=0; i < NDEVICES; i++)); do
-			dd if=/dev/zero of="${FSIMAGES[i]}" count=1 bs=1 seek=$((DISKSIZE-1)) &> /dev/null
-			LODEVICES[i]=`losetup -f`
-			losetup "${LODEVICES[i]}" "${FSIMAGES[i]}"
+		    for i in $(range 0 $((NDEVICES-1)) 1); do
+			dd if=/dev/zero of="$FSIMAGEP${i}.img" count=1 bs=1 seek=$((DISKSIZE-1)) &> /dev/null
+			LODEVICE=$(losetup --find --show "$FSIMAGEP${i}.img")
+			LODEVICES="$LODEVICES $LODEVICE"
+			if test "$i" = 0; then
+			    MOUNTDEVICE="$LODEVICE"
+			fi
 		    done ;;
 	    esac
 
-	    MOUNTDEVICE="${LODEVICES[0]}"
 	    case x"$fs" in
 		x"afs")
 		    ;;
 		x"btrfs")
-		    "mkfs.btrfs" -s $SECSIZE -L "$FSLABEL" "${LODEVICES[0]}" ;;
+		    "mkfs.btrfs" -s $SECSIZE -L "$FSLABEL" "${MOUNTDEVICE}" ;;
 		x"btrfs_zlib" | x"btrfs_lzo")
-		    "mkfs.btrfs" -s $SECSIZE -L "$FSLABEL" "${LODEVICES[0]}"
+		    "mkfs.btrfs" -s $SECSIZE -L "$FSLABEL" "${MOUNTDEVICE}"
 		    MOUNTOPTS="compress=${fs/btrfs_/},"
 		    MOUNTFS="btrfs"
 		    ;;
 		x"btrfs_raid0")
-		    "mkfs.btrfs" -s $SECSIZE -d raid0 -m raid0 -L "$FSLABEL" "${LODEVICES[@]}"
+		    "mkfs.btrfs" -s $SECSIZE -d raid0 -m raid0 -L "$FSLABEL" $LODEVICES
 		    MOUNTFS="btrfs"
 		    ;;
 		x"btrfs_raid1")
-		    "mkfs.btrfs" -s $SECSIZE -d raid1 -m raid1 -L "$FSLABEL" "${LODEVICES[@]}"
+		    "mkfs.btrfs" -s $SECSIZE -d raid1 -m raid1 -L "$FSLABEL" $LODEVICES
 		    MOUNTFS="btrfs"
 		    ;;
 		x"btrfs_raid10")
-		    "mkfs.btrfs" -s $SECSIZE -d raid10 -m raid10 -L "$FSLABEL" "${LODEVICES[@]}"
+		    "mkfs.btrfs" -s $SECSIZE -d raid10 -m raid10 -L "$FSLABEL" $LODEVICES
 		    MOUNTFS="btrfs"
 		    ;;
 		x"btrfs_single")
-		    "mkfs.btrfs" -s $SECSIZE -d single -L "$FSLABEL" "${LODEVICES[@]}"
+		    "mkfs.btrfs" -s $SECSIZE -d single -L "$FSLABEL" $LODEVICES
 		    MOUNTFS="btrfs"
 		    ;;
 		x"exfat")
-		    "mkfs.$fs" -s $((BLKSIZE/512)) -n "$FSLABEL" "${LODEVICES[0]}"
+		    "mkfs.$fs" -s $((BLKSIZE/512)) -n "$FSLABEL" "${MOUNTDEVICE}"
 		    MOUNTOPTS="iocharset=utf8,"
 		    MOUNTFS="exfat-fuse";;
 		x"minix")
-		    "mkfs.minix" "${LODEVICES[0]}"
+		    "mkfs.minix" "${MOUNTDEVICE}"
 		    ;;
 	# mkfs.hfs and mkfs.hfsplus don't fill UUID.
 		x"hfsplus")
-		    "mkfs.hfsplus" -b $BLKSIZE -v "$FSLABEL" "${LODEVICES[0]}"
-		    dd if=/dev/urandom of="${LODEVICES[0]}" bs=1 seek=$((16#468)) conv=notrunc count=8 ;;
+		    "mkfs.hfsplus" -b $BLKSIZE -v "$FSLABEL" "${MOUNTDEVICE}"
+		    dd if=/dev/urandom of="${MOUNTDEVICE}" bs=1 seek=$((16#468)) conv=notrunc count=8 ;;
 		x"hfsplus_wrap")
-		    "mkfs.hfsplus" -w -b $BLKSIZE -v "$FSLABEL" "${LODEVICES[0]}"
-		    dd if=/dev/urandom of="${LODEVICES[0]}" bs=1 seek=$((16#468)) conv=notrunc count=8
+		    "mkfs.hfsplus" -w -b $BLKSIZE -v "$FSLABEL" "${MOUNTDEVICE}"
+		    dd if=/dev/urandom of="${MOUNTDEVICE}" bs=1 seek=$((16#468)) conv=notrunc count=8
 		    MOUNTFS="hfsplus";;
 		x"hfsplus_casesens")
-		    "mkfs.hfsplus" -s -b $BLKSIZE -v "$FSLABEL" "${LODEVICES[0]}"
-		    dd if=/dev/urandom of="${LODEVICES[0]}" bs=1 seek=$((16#468)) conv=notrunc count=8
+		    "mkfs.hfsplus" -s -b $BLKSIZE -v "$FSLABEL" "${MOUNTDEVICE}"
+		    dd if=/dev/urandom of="${MOUNTDEVICE}" bs=1 seek=$((16#468)) conv=notrunc count=8
 		    MOUNTFS="hfsplus";;
 		x"hfs")
-		    "mkfs.hfs" -b $BLKSIZE -v "`echo $FSLABEL |recode utf8..macroman`" -h "${LODEVICES[0]}"
-		    dd if=/dev/urandom of="${LODEVICES[0]}" bs=1 seek=$((16#474)) conv=notrunc count=8
+		    "mkfs.hfs" -b $BLKSIZE -v "`echo $FSLABEL |recode utf8..macroman`" -h "${MOUNTDEVICE}"
+		    dd if=/dev/urandom of="${MOUNTDEVICE}" bs=1 seek=$((16#474)) conv=notrunc count=8
 		    MOUNTOPTS="iocharset=utf8,codepage=macroman,"
 		    ;;
 		x"vfat"*|xmsdos*)
@@ -643,98 +682,98 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		    else
 			A=
 		    fi
-		    "mkfs.vfat" -a $A -S $SECSIZE -s $((BLKSIZE/SECSIZE)) -F "${BITS:0:2}" -n "$FSLABEL" "${FSIMAGES[0]}"
+		    "mkfs.vfat" -a $A -S $SECSIZE -s $((BLKSIZE/SECSIZE)) -F "${BITS:0:2}" -n "$FSLABEL" "${MOUNTDEVICE}"
 		    MOUNTOPTS="iocharset=utf8,codepage=437,"
 		    MOUNTFS="$(echo "$fs"|sed 's,[0-9]*a\?$,,')";;
 		x"minix2")
-		    "mkfs.minix" -v "${LODEVICES[0]}"
+		    "mkfs.minix" -v "${MOUNTDEVICE}"
 		    MOUNTFS="minix";;
 		x"minix3")
-		    "mkfs.minix" -B $BLKSIZE -3 "${LODEVICES[0]}"
+		    "mkfs.minix" -B $BLKSIZE -3 "${MOUNTDEVICE}"
 		    MOUNTFS="minix";;
 		x"ntfs"*)
-		    "mkfs.ntfs" -s "$SECSIZE" -c "$BLKSIZE" -L "$FSLABEL" -Q -q "${LODEVICES[0]}"
+		    "mkfs.ntfs" -s "$SECSIZE" -c "$BLKSIZE" -L "$FSLABEL" -Q -q "${MOUNTDEVICE}"
 		    MOUNTOPTS="iocharset=utf8,compression,"
 		    MOUNTFS="ntfs-3g";;
 		x"udf")
-		    "mkudffs" --utf8 -b $BLKSIZE --lvid="$FSLABEL" "${LODEVICES[0]}"
+		    "mkudffs" --utf8 -b $BLKSIZE --lvid="$FSLABEL" "${MOUNTDEVICE}"
 		    MOUNTOPTS="iocharset=utf8,bs=$BLKSIZE,";;
 		x"ufs2")
-		    "mkfs.ufs" -b $BLKSIZE -L "$FSLABEL" -O 2 "${LODEVICES[0]}"
+		    "mkfs.ufs" -b $BLKSIZE -L "$FSLABEL" -O 2 "${MOUNTDEVICE}"
 		    MOUNTOPTS="ufstype=ufs2,"
 		    MOUNTFS="ufs";;
 		x"ufs1")
-		    "mkfs.ufs" -b $BLKSIZE -L "$FSLABEL" -O 1 "${LODEVICES[0]}"
+		    "mkfs.ufs" -b $BLKSIZE -L "$FSLABEL" -O 1 "${MOUNTDEVICE}"
 		    MOUNTOPTS="ufstype=44bsd,"
 		    MOUNTFS="ufs";;
 		x"ufs1_sun")
-		    "mkfs.ufs" -b $BLKSIZE -L "$FSLABEL" -O 1 "${LODEVICES[0]}"
+		    "mkfs.ufs" -b $BLKSIZE -L "$FSLABEL" -O 1 "${MOUNTDEVICE}"
 		    MOUNTOPTS="ufstype=sun,"
 		    MOUNTFS="ufs";;
 		x"zfs")
-		    "zpool" create -R "$MNTPOINTRW" "$FSLABEL" "${LODEVICES[0]}"
+		    "zpool" create -R "$MNTPOINTRW" "$FSLABEL" "${MOUNTDEVICE}"
 		    sleep 1
 		    "zfs" create "$FSLABEL"/"grub fs"
 		    sleep 1;;
 		x"zfs_caseins")
-		    "zpool" create -R "$MNTPOINTRW" "$FSLABEL" "${LODEVICES[0]}"
+		    "zpool" create -R "$MNTPOINTRW" "$FSLABEL" "${MOUNTDEVICE}"
 		    sleep 1
 		    "zfs" create -o casesensitivity=insensitive "$FSLABEL"/"grub fs"
 		    sleep 1;;
 		x"zfs_lzjb" | xzfs_gzip | xzfs_zle)
-		    "zpool" create -O compression=${fs/zfs_/} -R "$MNTPOINTRW" "$FSLABEL" "${LODEVICES[0]}"
+		    "zpool" create -O compression=${fs/zfs_/} -R "$MNTPOINTRW" "$FSLABEL" "${MOUNTDEVICE}"
 		    sleep 1
 		    "zfs" create -o compression=${fs/zfs_/} "$FSLABEL"/"grub fs"
 		    sleep 1;;
 		x"zfs_raidz")
-		    "zpool" create -R "$MNTPOINTRW" "$FSLABEL" raidz1 "${LODEVICES[@]}"
+		    "zpool" create -R "$MNTPOINTRW" "$FSLABEL" raidz1 $LODEVICES
 		    sleep 1
 		    "zfs" create "$FSLABEL"/"grub fs"
 		    sleep 1;;
 		x"zfs_raidz2")
-		    "zpool" create -R "$MNTPOINTRW" "$FSLABEL" raidz2 "${LODEVICES[@]}"
+		    "zpool" create -R "$MNTPOINTRW" "$FSLABEL" raidz2 $LODEVICES
 		    sleep 1
 		    "zfs" create "$FSLABEL"/"grub fs"
 		    sleep 1;;
 		x"zfs_raidz3")
-		    "zpool" create -R "$MNTPOINTRW" "$FSLABEL" raidz3 "${LODEVICES[@]}"
+		    "zpool" create -R "$MNTPOINTRW" "$FSLABEL" raidz3 $LODEVICES
 		    sleep 1
 		    "zfs" create "$FSLABEL"/"grub fs"
 		    sleep 1;;
 		x"zfs_mirror")
-		    "zpool" create -R "$MNTPOINTRW" "$FSLABEL" mirror "${LODEVICES[@]}"
+		    "zpool" create -R "$MNTPOINTRW" "$FSLABEL" mirror $LODEVICES
 		    sleep 1
 		    "zfs" create "$FSLABEL"/"grub fs"
 		    sleep 1;;
 		x"zfs_stripe")
-		    "zpool" create -R "$MNTPOINTRW" "$FSLABEL" "${LODEVICES[@]}"
+		    "zpool" create -R "$MNTPOINTRW" "$FSLABEL" $LODEVICES
 		    sleep 1
 		    "zfs" create "$FSLABEL"/"grub fs"
 		    sleep 1;;
 		x"tarfs" | x"cpio_"* | x"iso9660" | xjoliet | xrockridge | xrockridge_joliet | x"iso9660_1999" | xjoliet_1999 | xrockridge_1999 | xrockridge_joliet_1999 | x"ziso9660" | x"romfs" | x"squash4_"*)
 		    INSTDEVICE=/dev/null;;
 		x"reiserfs")
-		    "mkfs.reiserfs" --format=3.6 -b $BLKSIZE -l "$FSLABEL" -q "${LODEVICES[0]}" ;;
+		    "mkfs.reiserfs" --format=3.6 -b $BLKSIZE -l "$FSLABEL" -q "${MOUNTDEVICE}" ;;
 		x"reiserfs_old")
-		    "mkfs.reiserfs" --format=3.5 -b $BLKSIZE -l "$FSLABEL" -q "${LODEVICES[0]}"
+		    "mkfs.reiserfs" --format=3.5 -b $BLKSIZE -l "$FSLABEL" -q "${MOUNTDEVICE}"
 		    MOUNTFS=reiserfs;;
 		x"jfs")
-		    "mkfs.jfs" -L "$FSLABEL" -q "${LODEVICES[0]}"
+		    "mkfs.jfs" -L "$FSLABEL" -q "${MOUNTDEVICE}"
 		    MOUNTOPTS="iocharset=utf8,";;
 		x"jfs_caseins")
-		    "mkfs.jfs" -O -L "$FSLABEL" -q "${LODEVICES[0]}"
+		    "mkfs.jfs" -O -L "$FSLABEL" -q "${MOUNTDEVICE}"
 		    MOUNTFS=jfs
 		    MOUNTOPTS="iocharset=utf8,";;
 		x"mdraid"*)
-		    mdadm -C --chunk=$((BLKSIZE/1024)) --force -e "${fs:6:1}.${fs:7:1}" "/dev/md/${fs}_${NDEVICES}" --level="${fs:13}" --raid-devices="$NDEVICES" "${LODEVICES[@]}"
+		    mdadm -C --chunk=$((BLKSIZE/1024)) --force -e "${fs:6:1}.${fs:7:1}" "/dev/md/${fs}_${NDEVICES}" --level="${fs:13}" --raid-devices="$NDEVICES" $LODEVICES
 		    MOUNTDEVICE="/dev/md/${fs}_${NDEVICES}"
 		    MOUNTFS=ext2
 		    "mkfs.ext2" -L "$FSLABEL" -q "${MOUNTDEVICE}" ;;
 		x"lvm"*)
-		    for ((i=0;i<NDEVICES;i++)); do
-			pvcreate "${LODEVICES[i]}"
+		    for lodev in $LODEVICES; do
+			pvcreate "$lodev"
 		    done
-		    vgcreate -s $((BLKSIZE/1024))K grub_test "${LODEVICES[@]}"
+		    vgcreate -s $((BLKSIZE/1024))K grub_test $LODEVICES
 		    if [ x$fs = xlvm ] ; then
 			lvcreate -l "$((NDEVICES*7*LVMBLKMUL))" -n testvol grub_test
 		    elif [ x$fs = xlvm_stripe ] ; then
@@ -756,23 +795,29 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		    MOUNTDEVICE="/dev/mapper/grub_test-testvol"
 		    MOUNTFS=ext2
 		    "mkfs.ext2" -L "$FSLABEL" -q "${MOUNTDEVICE}"  ;;
+		xf2fs)
+		    "mkfs.f2fs" -l "$FSLABEL" -q "${LODEVICES[0]}" ;;
 		xnilfs2)
-		    "mkfs.nilfs2" -L "$FSLABEL" -b $BLKSIZE  -q "${LODEVICES[0]}" ;;
+		    "mkfs.nilfs2" -L "$FSLABEL" -b $BLKSIZE  -q "${MOUNTDEVICE}" ;;
 		xext2_old)
-		    MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.ext2" -r 0 -b $BLKSIZE -L "$FSLABEL" -q "${LODEVICES[0]}"
+		    MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.ext2" -r 0 -b $BLKSIZE -L "$FSLABEL" -q "${MOUNTDEVICE}"
 		    MOUNTFS=ext2
 		    ;;
 		xext4_metabg)
-		    MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.ext4" -O meta_bg,^resize_inode -b $BLKSIZE -L "$FSLABEL" -q "${LODEVICES[0]}"
+		    MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.ext4" -O meta_bg,^resize_inode -b $BLKSIZE -L "$FSLABEL" -q "${MOUNTDEVICE}"
 		    MOUNTFS=ext4
 		    ;;
+               xext4_encrypt)
+                   MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.ext4" -O encrypt -b $BLKSIZE -L "$FSLABEL" -q "${MOUNTDEVICE}"
+                   MOUNTFS=ext4
+                   ;;
 		xext*)
-		    MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.$fs" -b $BLKSIZE -L "$FSLABEL" -q "${LODEVICES[0]}" ;;
+		    MKE2FS_DEVICE_SECTSIZE=$SECSIZE "mkfs.$fs" -b $BLKSIZE -L "$FSLABEL" -q "${MOUNTDEVICE}" ;;
 		xxfs)
-		    "mkfs.xfs" -m crc=0 -b size=$BLKSIZE -s size=$SECSIZE -L "$FSLABEL" -q "${LODEVICES[0]}" ;;
+		    "mkfs.xfs" -m crc=0 -b size=$BLKSIZE -s size=$SECSIZE -L "$FSLABEL" -q "${MOUNTDEVICE}" ;;
 		xxfs_crc)
 		    MOUNTFS="xfs"
-		    "mkfs.xfs" -m crc=1 -b size=$BLKSIZE -s size=$SECSIZE -L "$FSLABEL" -q "${LODEVICES[0]}" ;;
+		    "mkfs.xfs" -m crc=1 -b size=$BLKSIZE -s size=$SECSIZE -L "$FSLABEL" -q "${MOUNTDEVICE}" ;;
 		*)
 		    echo "Add appropriate mkfs command here"
 		    exit 1
@@ -873,11 +918,13 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		*)
 		    if ! mount -t "$MOUNTFS" "${MOUNTDEVICE}" "$MNTPOINTRW" -o ${MOUNTOPTS}${SELINUXOPTS}rw  ; then
 			echo "MOUNT FAILED."
-			for ((i=0; i < NDEVICES; i++)); do
-			    while ! losetup -d "${LODEVICES[i]}"; do
+			for lodev in $LODEVICES; do
+			    while ! losetup -d "$lodev"; do
 				sleep 1
 			    done
-			    rm "${FSIMAGES[i]}"
+			done
+			for i in $(range 0 $((NDEVICES-1)) 1); do
+			    rm "$FSIMAGEP${i}.img"
 			done
 			exit 1;
 		    fi
@@ -915,7 +962,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    esac
 	    # Make sure file is not exact multiple of block size. This helps to force
 	    # tail packing in case of squash4.
-	    : $((BLOCKCNT--))
+	    BLOCKCNT="$((BLOCKCNT-1))"
 	    case x"$fs" in
 		x"ntfscomp")
 		    setfattr -h -v 0x00000800 -n system.ntfs_attrib_be "$MNTPOINTRW/$OSDIR";;
@@ -939,11 +986,11 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    if (test x$fs = xvfat12a || test x$fs = xmsdos12a) && test x$BLKSIZE = x131072; then
 		    # With this config there isn't enough space for full copy.
 		    # Copy as much as we can
-		cp "${CFILESSRC[0]}" "$MNTPOINTRW/$OSDIR/${CFILES[0]}" &> /dev/null;
+		cp "${CFILESRC}" "$MNTPOINTRW/$OSDIR/${CFILE}" &> /dev/null;
 	    else
-		for ((i=0;i<$CFILESN;i++)); do
-		    cp "${CFILESSRC[i]}" "$MNTPOINTRW/$OSDIR/${CFILES[i]}";
-		done
+
+		cp "${CFILESRC}" "$MNTPOINTRW/$OSDIR/${CFILE}";
+
 	    fi
 
 	    if [ x$NOSYMLINK != xy ]; then
@@ -968,48 +1015,48 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		    sleep 2
 		    ;;
 		x"tarfs")
-		    (cd "$MASTER"; tar cf "${FSIMAGES[0]}" .) ;;
+		    (cd "$MASTER"; tar cf "${FSIMAGEP}0.img" .) ;;
 		x"cpio_"*)
-		    (cd "$MASTER"; find . | cpio -o -H "${fs/cpio_/}" > "${FSIMAGES[0]}" ) ;;
+		    (cd "$MASTER"; find . | cpio -o -H "$(echo ${fs} | sed 's@^cpio_@@')" > "${FSIMAGEP}0.img" ) ;;
 		x"ziso9660")
 		    FSUUID=$(date -u +%Y-%m-%d-%H-%M-%S-00);
-		    xorriso -compliance rec_mtime -set_filter_r --zisofs -- -zisofs default -as mkisofs -iso-level 3 -graft-points -R -J -joliet-long -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGES[0]}"  -- -set_filter_r --zisofs -- -zisofs default -add /="$MASTER" ;;
+		    xorriso -compliance rec_mtime -set_filter_r --zisofs -- -zisofs default -as mkisofs -iso-level 3 -graft-points -R -J -joliet-long -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGEP}0.img"  -- -set_filter_r --zisofs -- -zisofs default -add /="$MASTER" ;;
 		x"iso9660")
 		    FSUUID=$(date -u +%Y-%m-%d-%H-%M-%S-00);
-		    xorriso --rockridge off -compliance rec_mtime -as mkisofs -iso-level 3 -graft-points -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGES[0]}" /="$MASTER"  ;;
+		    xorriso --rockridge off -compliance rec_mtime -as mkisofs -iso-level 3 -graft-points -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGEP}0.img" /="$MASTER"  ;;
 		x"joliet")
 		    FSUUID=$(date -u +%Y-%m-%d-%H-%M-%S-00);
-		    xorriso --rockridge off  -compliance rec_mtime -as mkisofs -iso-level 3 -graft-points -J -joliet-long -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGES[0]}" /="$MASTER"  ;;
+		    xorriso --rockridge off  -compliance rec_mtime -as mkisofs -iso-level 3 -graft-points -J -joliet-long -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGEP}0.img" /="$MASTER"  ;;
 		x"rockridge")
 		    FSUUID=$(date -u +%Y-%m-%d-%H-%M-%S-00);
-		    xorriso --rockridge on -compliance rec_mtime -as mkisofs -iso-level 3 -graft-points -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGES[0]}" /="$MASTER"  ;;
+		    xorriso --rockridge on -compliance rec_mtime -as mkisofs -iso-level 3 -graft-points -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGEP}0.img" /="$MASTER"  ;;
 		x"rockridge_joliet")
 		    FSUUID=$(date -u +%Y-%m-%d-%H-%M-%S-00);
-		    xorriso --rockridge on -compliance rec_mtime -as mkisofs -iso-level 3 -graft-points -J -joliet-long -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGES[0]}" /="$MASTER"  ;;
+		    xorriso --rockridge on -compliance rec_mtime -as mkisofs -iso-level 3 -graft-points -J -joliet-long -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGEP}0.img" /="$MASTER"  ;;
 		x"iso9660_1999")
 		    FSUUID=$(date -u +%Y-%m-%d-%H-%M-%S-00);
-		    xorriso --rockridge off -compliance rec_mtime -as mkisofs -iso-level 4 -graft-points -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGES[0]}" /="$MASTER"  ;;
+		    xorriso --rockridge off -compliance rec_mtime -as mkisofs -iso-level 4 -graft-points -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGEP}0.img" /="$MASTER"  ;;
 		x"joliet_1999")
 		    FSUUID=$(date -u +%Y-%m-%d-%H-%M-%S-00);
-		    xorriso --rockridge off  -compliance rec_mtime -as mkisofs -iso-level 4 -graft-points -J -joliet-long -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGES[0]}" /="$MASTER"  ;;
+		    xorriso --rockridge off  -compliance rec_mtime -as mkisofs -iso-level 4 -graft-points -J -joliet-long -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGEP}0.img" /="$MASTER"  ;;
 		x"rockridge_1999")
 		    FSUUID=$(date -u +%Y-%m-%d-%H-%M-%S-00);
-		    xorriso --rockridge on -compliance rec_mtime -as mkisofs -iso-level 4 -graft-points -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGES[0]}" /="$MASTER"  ;;
+		    xorriso --rockridge on -compliance rec_mtime -as mkisofs -iso-level 4 -graft-points -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGEP}0.img" /="$MASTER"  ;;
 		x"rockridge_joliet_1999")
 		    FSUUID=$(date -u +%Y-%m-%d-%H-%M-%S-00);
-		    xorriso --rockridge on -compliance rec_mtime -as mkisofs -iso-level 4 -graft-points -J -joliet-long -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGES[0]}" /="$MASTER"  ;;
+		    xorriso --rockridge on -compliance rec_mtime -as mkisofs -iso-level 4 -graft-points -J -joliet-long -V "$FSLABEL" --modification-date=$(echo ${FSUUID} | sed 's/-//g;') -o "${FSIMAGEP}0.img" /="$MASTER"  ;;
 		x"romfs")
-		    genromfs -V "$FSLABEL" -f "${FSIMAGES[0]}" -d "$MASTER" ;;
+		    genromfs -V "$FSLABEL" -f "${FSIMAGEP}0.img" -d "$MASTER" ;;
 		xsquash4_*)
-		    echo mksquashfs "$MASTER" "${FSIMAGES[0]}" -always-use-fragments -comp "${fs/squash4_/}" -b $BLKSIZE
-		    mksquashfs "$MASTER" "${FSIMAGES[0]}" -always-use-fragments -comp "${fs/squash4_/}" -b $BLKSIZE ;;
+		    echo mksquashfs "$MASTER" "${FSIMAGEP}0.img" -always-use-fragments -comp "${fs/squash4_/}" -b $BLKSIZE
+		    mksquashfs "$MASTER" "${FSIMAGEP}0.img" -always-use-fragments -comp "${fs/squash4_/}" -b $BLKSIZE ;;
 		x"bfs")
 		    sleep 1
 		    fusermount -u "$MNTPOINTRW"
 		    ;;
 		xlvm*)
 		    sleep 1
-		    for ((try=0;try < 20; try++)); do
+		    for try in $(range 0 20 1); do
 			if umount "$MNTPOINTRW" ; then
 			    break;
 			fi
@@ -1021,7 +1068,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		    ;;
 		xmdraid*)
 		    sleep 1
-		    for ((try=0;try < 20; try++)); do
+		    for try in $(range 0 20 1); do
 			if umount "$MNTPOINTRW" ; then
 			    break;
 			fi
@@ -1033,7 +1080,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		    ;;
 		*)
 		    sleep 1
-		    for ((try=0;try < 20; try++)); do
+		    for try in $(range 0 20 1); do
 			if umount "$MNTPOINTRW" ; then
 			    break;
 			fi
@@ -1066,7 +1113,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		    sleep 1
 		    mount -t "$MOUNTFS" "${MOUNTDEVICE}" "$MNTPOINTRO" -o ${MOUNTOPTS}${SELINUXOPTS}ro ;;
 		xmdraid*)
-		    mdadm --assemble /dev/md/"${fs}_$NDEVICES" "${LODEVICES[@]}"
+		    mdadm --assemble /dev/md/"${fs}_$NDEVICES" $LODEVICES
 		    sleep 1
 		    mount -t "$MOUNTFS" "${MOUNTDEVICE}" "$MNTPOINTRO" -o ${MOUNTOPTS}${SELINUXOPTS}ro ;;
 		*)
@@ -1085,7 +1132,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    else
 		echo LIST FAIL
 		echo "$LSROUT"
-		TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO"
+		TZ=UTC ls -l "$MNTPOINTRO"
 		exit 1
 	    fi
 
@@ -1094,7 +1141,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    else
 		echo NLIST FAIL
 		echo "$LSROUT"
-		TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -lA "$MNTPOINTRO"
+		TZ=UTC ls -lA "$MNTPOINTRO"
 		exit 1
 	    fi
 
@@ -1103,7 +1150,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    else
 		echo ILIST FAIL
 		echo "$LSROUT"
-		TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO"
+		TZ=UTC ls -l "$MNTPOINTRO"
 		exit 1
 	    fi
 
@@ -1112,7 +1159,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    else
 		echo LONG LIST FAIL
 		echo "$LSROUT"
-		TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO"
+		TZ=UTC ls -l "$MNTPOINTRO"
 		exit 1
 	    fi
 
@@ -1123,7 +1170,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		else
 		    echo TIME FAIL
 		    echo "$LSROUT"
-		    TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO"
+		    TZ=UTC ls -l "$MNTPOINTRO"
 		    exit 1
 		fi
 
@@ -1133,7 +1180,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		else
 		    echo LONG TIME FAIL
 		    echo "$LSROUT"
-		    TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO"
+		    TZ=UTC ls -l "$MNTPOINTRO"
 		    exit 1
 		fi
 	    fi
@@ -1149,7 +1196,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    else
 		echo DOT IN ROOTDIR FAIL
 		echo "$LSROUT"
-		TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO"
+		TZ=UTC ls -l "$MNTPOINTRO"
 		exit 1
 	    fi
 
@@ -1163,7 +1210,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		    else
 			echo DOTDOT IN ROOTDIR FAIL
 			echo "$LSROUT"
-			TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO"
+			TZ=UTC ls -l "$MNTPOINTRO"
 			exit 1
 		    fi
 		    ;;
@@ -1180,7 +1227,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    else
 		echo SLIST FAIL
 		echo "$LSROUT"
-		TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO/sdir"
+		TZ=UTC ls -l "$MNTPOINTRO/sdir"
 		exit 1
 	    fi
 
@@ -1195,7 +1242,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    else
 		echo PLIST FAIL
 		echo "$LSROUT"
-		TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO/$PDIR"
+		TZ=UTC ls -l "$MNTPOINTRO/$PDIR"
 		exit 1
 	    fi
 
@@ -1210,7 +1257,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    else
 		echo DOT IN SUBDIR FAIL
 		echo "$LSROUT"
-		TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO/$OSDIR/sdir"
+		TZ=UTC ls -l "$MNTPOINTRO/$OSDIR/sdir"
 		exit 1
 	    fi
 
@@ -1225,7 +1272,7 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    else
 		echo DOTDOT IN SUBDIR FAIL
 		echo "$LSROUT"
-		TZ=UTC ls --time-style=+%Y%m%d%H%M%S.%N -l "$MNTPOINTRO/$OSDIR/ssdir"
+		TZ=UTC ls -l "$MNTPOINTRO/$OSDIR/ssdir"
 		exit 1
 	    fi
 
@@ -1245,8 +1292,8 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 	    case x"$fs" in
 		x"iso9660" | x"ziso9660" | xrockridge | xjoliet | xrockridge_joliet | x"iso9660_1999" | xrockridge_1999 | xjoliet_1999 | xrockridge_joliet_1999) ;;
 		x"zfs"*)
-		    for ((i=0;i<NDEVICES;i++)); do
-			FSUUID=$(printf "%016x\n" $(blkid -o export "${LODEVICES[i]}" |grep -F UUID=|sed s,UUID=,,g))
+		    for lodev in $LODEVICES; do
+			FSUUID=$(printf "%016x\n" $(blkid -o export "$lodev" |grep -F UUID=|sed s,UUID=,,g))
 			if [ "$FSUUID" != 0000000000000000 ]; then
 			    break;
 			fi
@@ -1264,8 +1311,8 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 			echo UUID FAIL
 			echo "$LSOUT"
 			echo "$GRUBUUID"
-			for ((i=0;i<NDEVICES;i++)); do
-			    blkid "${LODEVICES[i]}"
+			for lodev in $LODEVICES; do
+			    blkid "$lodev"
 			done
 			exit 1
 		    fi
@@ -1290,37 +1337,37 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 			echo UUID FAIL
 			echo "$FSUUID"
 			echo "$LSOUT"
-			blkid "${LODEVICES[0]}"
+			blkid "${MOUNTDEVICE}"
 			exit 1
 		    fi
 		    ;;
 	    esac
 
-	    case x$fs in
-		xiso9660 | xziso9660 | xrockridge | xjoliet | xrockridge_joliet | xiso9660_1999 | xrockridge_1999 | xjoliet_1999 | xrockridge_joliet_1999)
-		    FSTIME="$(date -d "$(echo ${FSUUID} | awk -F - '{ print $1"-"$2"-"$3" "$4":"$5":"$6 ;}')" '+%Y-%m-%d %H:%M:%S')";;
-		xlvm*|xmdraid*)
-		    # With some abstractions like mdraid flushing to disk
-		    # may be delayed for a long time.
-		    FSTIME="$UMOUNT_TIME";;
-		*)
-		    FSTIME="$(TZ=UTC ls --time-style="+%Y-%m-%d_%H:%M:%S" -l -d "${FSIMAGES[0]}"|awk '{print $6; }'|sed 's,_, ,g')";;
-	    esac
-	    # With some abstractions like mdraid computing of UMOUNT_TIME
-	    # is not precise. Account for small difference here.
-	    FSTIMEM1="$(date -d "$FSTIME UTC -1 second" -u "+%Y-%m-%d %H:%M:%S")"
-	    FSTIMEM2="$(date -d "$FSTIME UTC -2 second" -u "+%Y-%m-%d %H:%M:%S")"
-	    FSTIMEM3="$(date -d "$FSTIME UTC -3 second" -u "+%Y-%m-%d %H:%M:%S")"
+	    if [ x$NOFSTIME != xy ]; then
+		case x$fs in
+		    xiso9660 | xziso9660 | xrockridge | xjoliet | xrockridge_joliet | xiso9660_1999 | xrockridge_1999 | xjoliet_1999 | xrockridge_joliet_1999)
+			FSTIME="$(date -d "$(echo ${FSUUID} | awk -F - '{ print $1"-"$2"-"$3" "$4":"$5":"$6 ;}')" '+%Y-%m-%d %H:%M:%S')";;
+		    xlvm*|xmdraid*)
+			# With some abstractions like mdraid flushing to disk
+			# may be delayed for a long time.
+			FSTIME="$UMOUNT_TIME";;
+		    *)
+			FSTIME="$(TZ=UTC ls --time-style="+%Y-%m-%d_%H:%M:%S" -l -d "${FSIMAGEP}0.img"|awk '{print $6; }'|sed 's,_, ,g')";;
+		esac
+		# With some abstractions like mdraid computing of UMOUNT_TIME
+		# is not precise. Account for small difference here.
+		FSTIMEM1="$(date -d "$FSTIME UTC -1 second" -u "+%Y-%m-%d %H:%M:%S")"
+		FSTIMEM2="$(date -d "$FSTIME UTC -2 second" -u "+%Y-%m-%d %H:%M:%S")"
+		FSTIMEM3="$(date -d "$FSTIME UTC -3 second" -u "+%Y-%m-%d %H:%M:%S")"
 
-	    if [ x$NOFSTIME = xy ]; then
-		:
-	    elif echo "$LSOUT" | grep -F 'Last modification time '"$FSTIME" > /dev/null || echo "$LSOUT" | grep -F 'Last modification time '"$FSTIMEM1" > /dev/null || echo "$LSOUT" | grep -F 'Last modification time '"$FSTIMEM2" || echo "$LSOUT" | grep -F 'Last modification time '"$FSTIMEM3" > /dev/null; then
-		:
-	    else
-		echo FSTIME FAIL
-		echo "$FSTIME"
-		echo "$LSOUT"
-		exit 1
+		if echo "$LSOUT" | grep -F 'Last modification time '"$FSTIME" > /dev/null || echo "$LSOUT" | grep -F 'Last modification time '"$FSTIMEM1" > /dev/null || echo "$LSOUT" | grep -F 'Last modification time '"$FSTIMEM2" || echo "$LSOUT" | grep -F 'Last modification time '"$FSTIMEM3" > /dev/null; then
+		    :
+		else
+		    echo FSTIME FAIL
+		    echo "$FSTIME"
+		    echo "$LSOUT"
+		    exit 1
+		fi
 	    fi
 
 	    if [ x$NOHARDLINK != xy ]; then
@@ -1410,11 +1457,9 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		exit 1
 	    fi
 	    ok=true
-	    for ((i=0;i<$CFILESN;i++)); do
-		if ! run_grubfstest cmp "$GRUBDIR/${CFILES[i]}" "$MNTPOINTRO/$OSDIR/${CFILES[i]}"  ; then
-		    ok=false;
-		fi
-	    done
+	    if ! run_grubfstest cmp "$GRUBDIR/${CFILE}" "$MNTPOINTRO/$OSDIR/${CFILE}"  ; then
+		ok=false;
+	    fi
 	    if  test x$ok = xtrue; then
 		:
 	    else
@@ -1503,15 +1548,17 @@ for ((LOGSECSIZE=MINLOGSECSIZE;LOGSECSIZE<=MAXLOGSECSIZE;LOGSECSIZE=LOGSECSIZE +
 		    sleep 1
 		    ;;
 	    esac
-	    for ((i=0; i < NDEVICES; i++)); do
-		case x"$fs" in
-		    x"tarfs" | x"cpio_"* | x"iso9660" | xrockridge | xjoliet | xrockridge_joliet | x"ziso9660" | x"romfs" | x"squash4_"* | x"iso9660_1999" | xrockridge_1999 | xjoliet_1999 | xrockridge_joliet_1999) ;;
-		    *)
-			while ! losetup -d "${LODEVICES[i]}"; do
+	    case x"$fs" in
+		x"tarfs" | x"cpio_"* | x"iso9660" | xrockridge | xjoliet | xrockridge_joliet | x"ziso9660" | x"romfs" | x"squash4_"* | x"iso9660_1999" | xrockridge_1999 | xjoliet_1999 | xrockridge_joliet_1999) ;;
+		*)
+		    for lodev in $LODEVICES; do
+			while ! losetup -d "$lodev"; do
 			    sleep 1
-			done;;
-		esac
-		rm "${FSIMAGES[i]}"
+			done
+		    done;;
+	    esac
+	    for i in $(range 0 $((NDEVICES-1)) 1); do
+		rm "$FSIMAGEP${i}.img"
 	    done
 	    if [ x"$fs" = x"zfs" ]; then
 		rmdir "$MNTPOINTRW"/"grub fs"  || true
diff --git a/tests/util/grub-shell-tester.in b/tests/util/grub-shell-tester.in
index 5adce0a47fe3208e14bbbf4820685d67b43ef9bb..8a87109b15240de9d61f2ac02becfcb5300582f1 100644
--- a/tests/util/grub-shell-tester.in
+++ b/tests/util/grub-shell-tester.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 set -e
 
 # Compares GRUB script output with BASH output.
diff --git a/tests/util/grub-shell.in b/tests/util/grub-shell.in
index 814f36c6bd2438b7f9c59f5f4a9777e95b9e38db..d690d6734efb82109f7635c4688b6fc7417a5751 100644
--- a/tests/util/grub-shell.in
+++ b/tests/util/grub-shell.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 set -e
 
 # Run GRUB script in a Qemu instance
diff --git a/tests/xfs_test.in b/tests/xfs_test.in
index 3807e2e5c77e244f8b2f0d43ec28b86b3f2f9e9b..03a3513595dc719cd72b4d9b7198f22b338cb588 100644
--- a/tests/xfs_test.in
+++ b/tests/xfs_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/tests/xzcompress_test.in b/tests/xzcompress_test.in
index b2bd999ec071c24205533e50cf51f46ec59a2218..03bfb5e951dd8dfb7ccb15fb6a31dd4aea639df9 100644
--- a/tests/xzcompress_test.in
+++ b/tests/xzcompress_test.in
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! @BUILD_SHEBANG@
 # Copyright (C) 2013  Free Software Foundation, Inc.
 #
 # GRUB is free software: you can redistribute it and/or modify
diff --git a/tests/zfs_test.in b/tests/zfs_test.in
index 047120e47a0e042f0540d6762666edf4cb0b37fb..eee62c10d704ec42b090eba5ac16b4966ff760ad 100644
--- a/tests/zfs_test.in
+++ b/tests/zfs_test.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!@BUILD_SHEBANG@
 
 set -e
 
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index f8496d28bdf7f4bcbc2413888330834c1e252a64..33332360eecf954fc2952df944fe171006fc4143 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -134,6 +134,7 @@ 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_PARTUUID="`${grub_probe} --device ${GRUB_DEVICE} --target=partuuid 2> /dev/null`" || true
 
 # Device containing our /boot partition.  Usually the same as GRUB_DEVICE.
 GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`"
@@ -147,6 +148,12 @@ if [ x"$GRUB_FS" = xunknown ]; then
     GRUB_FS="$(stat -f --printf=%T / || echo unknown)"
 fi
 
+# Provide a default set of stock linux early initrd images.
+# Define here so the list can be modified in the sourced config file.
+if [ "x${GRUB_EARLY_INITRD_LINUX_STOCK}" = "x" ]; then
+	GRUB_EARLY_INITRD_LINUX_STOCK="intel-uc.img intel-ucode.img amd-uc.img amd-ucode.img early_ucode.cpio microcode.cpio"
+fi
+
 if test -f ${sysconfdir}/default/grub ; then
   . ${sysconfdir}/default/grub
 fi
@@ -182,6 +189,7 @@ if [ "x${GRUB_ACTUAL_DEFAULT}" = "xsaved" ] ; then GRUB_ACTUAL_DEFAULT="`"${grub
 # override them.
 export GRUB_DEVICE \
   GRUB_DEVICE_UUID \
+  GRUB_DEVICE_PARTUUID \
   GRUB_DEVICE_BOOT \
   GRUB_DEVICE_BOOT_UUID \
   GRUB_FS \
@@ -211,10 +219,13 @@ export GRUB_DEFAULT \
   GRUB_CMDLINE_NETBSD \
   GRUB_CMDLINE_NETBSD_DEFAULT \
   GRUB_CMDLINE_GNUMACH \
+  GRUB_EARLY_INITRD_LINUX_CUSTOM \
+  GRUB_EARLY_INITRD_LINUX_STOCK \
   GRUB_TERMINAL_INPUT \
   GRUB_TERMINAL_OUTPUT \
   GRUB_SERIAL_COMMAND \
   GRUB_DISABLE_LINUX_UUID \
+  GRUB_DISABLE_LINUX_PARTUUID \
   GRUB_DISABLE_RECOVERY \
   GRUB_VIDEO_BACKEND \
   GRUB_GFXMODE \
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
index 60b31caddeb42b5db338897dc18acdc156dd2c22..0f801cab3e4d05efface62c7fcb9b787c69995c3 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -188,6 +188,7 @@ grub_file_is_not_garbage ()
       *.dpkg-*) return 1 ;; # debian dpkg
       *.rpmsave|*.rpmnew) return 1 ;;
       README*|*/README*)  return 1 ;; # documentation
+      *.sig) return 1 ;; # signatures
     esac
   else
     return 1
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index de9044c7f28611d56358f581ac52ca2d2b7fc982..61ebd7dc714e87aedb167345729f574426d69b77 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -43,12 +43,22 @@ case ${GRUB_DEVICE} in
   ;;
 esac
 
+# Default to disabling partition uuid support to maintian compatibility with
+# older kernels.
+GRUB_DISABLE_LINUX_PARTUUID=${GRUB_DISABLE_LINUX_PARTUUID-true}
+
 # btrfs may reside on multiple devices. We cannot pass them as value of root= parameter
 # and mounting btrfs requires user space scanning, so force UUID in this case.
-if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
-    || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
+if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] && [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] ) \
+    || ( [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
+	&& [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ] ) \
+    || ( ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
+	&& ! test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ) \
     || ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then
   LINUX_ROOT_DEVICE=${GRUB_DEVICE}
+elif [ "x${GRUB_DEVICE_UUID}" = "x" ] \
+    || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ]; then
+  LINUX_ROOT_DEVICE=PARTUUID=${GRUB_DEVICE_PARTUUID}
 else
   LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
 fi
@@ -136,9 +146,13 @@ EOF
   if test -n "${initrd}" ; then
     # TRANSLATORS: ramdisk isn't identifier. Should be translated.
     message="$(gettext_printf "Loading initial ramdisk ...")"
+    initrd_path=
+    for i in ${initrd}; do
+      initrd_path="${initrd_path} ${rel_dirname}/${i}"
+    done
     sed "s/^/$submenu_indentation/" << EOF
 	echo	'$(echo "$message" | grub_quote)'
-	initrd	${rel_dirname}/${initrd}
+	initrd	$(echo $initrd_path)
 EOF
   fi
   sed "s/^/$submenu_indentation/" << EOF
@@ -188,7 +202,15 @@ while [ "x$list" != "x" ] ; do
   alt_version=`echo $version | sed -e "s,\.old$,,g"`
   linux_root_device_thisversion="${LINUX_ROOT_DEVICE}"
 
-  initrd=
+  initrd_early=
+  for i in ${GRUB_EARLY_INITRD_LINUX_STOCK} \
+	   ${GRUB_EARLY_INITRD_LINUX_CUSTOM}; do
+    if test -e "${dirname}/${i}" ; then
+      initrd_early="${initrd_early} ${i}"
+    fi
+  done
+
+  initrd_real=
   for i in "initrd.img-${version}" "initrd-${version}.img" "initrd-${version}.gz" \
 	   "initrd-${version}" "initramfs-${version}.img" \
 	   "initrd.img-${alt_version}" "initrd-${alt_version}.img" \
@@ -198,11 +220,22 @@ while [ "x$list" != "x" ] ; do
 	   "initramfs-genkernel-${GENKERNEL_ARCH}-${version}" \
 	   "initramfs-genkernel-${GENKERNEL_ARCH}-${alt_version}"; do
     if test -e "${dirname}/${i}" ; then
-      initrd="$i"
+      initrd_real="${i}"
       break
     fi
   done
 
+  initrd=
+  if test -n "${initrd_early}" || test -n "${initrd_real}"; then
+    initrd="${initrd_early} ${initrd_real}"
+
+    initrd_display=
+    for i in ${initrd}; do
+      initrd_display="${initrd_display} ${dirname}/${i}"
+    done
+    gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
+  fi
+
   config=
   for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
     if test -e "${i}" ; then
@@ -216,12 +249,16 @@ while [ "x$list" != "x" ] ; do
       initramfs=`grep CONFIG_INITRAMFS_SOURCE= "${config}" | cut -f2 -d= | tr -d \"`
   fi
 
-  if test -n "${initrd}" ; then
-    gettext_printf "Found initrd image: %s\n" "${dirname}/${initrd}" >&2
-  elif test -z "${initramfs}" ; then
+  if test -z "${initramfs}" && test -z "${initrd_real}" ; then
     # "UUID=" and "ZFS=" magic is parsed by initrd or initramfs.  Since there's
     # no initrd or builtin initramfs, it can't work here.
-    linux_root_device_thisversion=${GRUB_DEVICE}
+    if [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] \
+	|| [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ]; then
+
+	linux_root_device_thisversion=${GRUB_DEVICE}
+    else
+	linux_root_device_thisversion=PARTUUID=${GRUB_DEVICE_PARTUUID}
+    fi
   fi
 
   if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then
diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
index c48af948d6ecdf672aa341f713912ba15de8f27d..e8143b079dc8bcdf21ec8a763b19a356c863a5e3 100644
--- a/util/grub.d/20_linux_xen.in
+++ b/util/grub.d/20_linux_xen.in
@@ -43,12 +43,22 @@ case ${GRUB_DEVICE} in
   ;;
 esac
 
+# Default to disabling partition uuid support to maintian compatibility with
+# older kernels.
+GRUB_DISABLE_LINUX_PARTUUID=${GRUB_DISABLE_LINUX_PARTUUID-true}
+
 # btrfs may reside on multiple devices. We cannot pass them as value of root= parameter
 # and mounting btrfs requires user space scanning, so force UUID in this case.
-if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
-    || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
+if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] && [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] ) \
+    || ( [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
+	&& [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ] ) \
+    || ( ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
+	&& ! test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ) \
     || ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then
   LINUX_ROOT_DEVICE=${GRUB_DEVICE}
+elif [ "x${GRUB_DEVICE_UUID}" = "x" ] \
+    || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ]; then
+  LINUX_ROOT_DEVICE=PARTUUID=${GRUB_DEVICE_PARTUUID}
 else
   LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
 fi
@@ -122,16 +132,16 @@ linux_entry ()
         else
             xen_rm_opts="no-real-mode edd=off"
         fi
-	multiboot	${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
+	${xen_loader}	${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
 	echo	'$(echo "$lmessage" | grub_quote)'
-	module	${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
+	${module_loader}	${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
 EOF
   if test -n "${initrd}" ; then
     # TRANSLATORS: ramdisk isn't identifier. Should be translated.
     message="$(gettext_printf "Loading initial ramdisk ...")"
     sed "s/^/$submenu_indentation/" << EOF
 	echo	'$(echo "$message" | grub_quote)'
-	module	--nounzip   ${rel_dirname}/${initrd}
+	${module_loader}	--nounzip   ${rel_dirname}/${initrd}
 EOF
   fi
   sed "s/^/$submenu_indentation/" << EOF
@@ -206,6 +216,18 @@ while [ "x${xen_list}" != "x" ] ; do
     if [ "x$is_top_level" != xtrue ]; then
 	echo "	submenu '$(gettext_printf "Xen hypervisor, version %s" "${xen_version}" | grub_quote)' \$menuentry_id_option 'xen-hypervisor-$xen_version-$boot_device_id' {"
     fi
+    if ($grub_file --is-arm64-efi $current_xen); then
+	xen_loader="xen_hypervisor"
+	module_loader="xen_module"
+    else
+	if ($grub_file --is-x86-multiboot2 $current_xen); then
+	    xen_loader="multiboot2"
+	    module_loader="module2"
+	else
+	    xen_loader="multiboot"
+	    module_loader="module"
+        fi
+    fi
     while [ "x$list" != "x" ] ; do
 	linux=`version_find_latest $list`
 	gettext_printf "Found linux image: %s\n" "$linux" >&2
@@ -234,7 +256,13 @@ while [ "x${xen_list}" != "x" ] ; do
 	    gettext_printf "Found initrd image: %s\n" "${dirname}/${initrd}" >&2
 	else
     # "UUID=" magic is parsed by initrds.  Since there's no initrd, it can't work here.
-	    linux_root_device_thisversion=${GRUB_DEVICE}
+	    if [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] \
+		|| [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ]; then
+
+		linux_root_device_thisversion=${GRUB_DEVICE}
+	    else
+		linux_root_device_thisversion=PARTUUID=${GRUB_DEVICE_PARTUUID}
+	    fi
 	fi
 
 	if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then