diff --git a/INSTALL b/INSTALL
index 342c158..991479b 100644
--- a/INSTALL
+++ b/INSTALL
@@ -11,27 +11,9 @@ GRUB depends on some software packages installed into your system. If
 you don't have any of them, please obtain and install them before
 configuring the GRUB.
 
-* GCC 4.1.3 or later
-  Note: older versions may work but support is limited
-
-  Experimental support for clang 3.3 or later (results in much bigger binaries)
+* GCC 5.1.0 or later
+  Experimental support for clang 3.8.0 or later (results in much bigger binaries)
   for i386, x86_64, arm (including thumb), arm64, mips(el), powerpc, sparc64
-  Note: clang 3.2 or later works for i386 and x86_64 targets but results in
-        much bigger binaries.
-	earlier versions not tested
-  Note: clang 3.2 or later works for arm
-	earlier versions not tested
-  Note: clang on arm64 is not supported due to
-	https://llvm.org/bugs/show_bug.cgi?id=26030
-  Note: clang 3.3 or later works for mips(el)
-	earlier versions fail to generate .reginfo and hence gprel relocations
-	fail.
-  Note: clang 3.2 or later works for powerpc
-	earlier versions not tested
-  Note: clang 3.5 or later works for sparc64
-        earlier versions return "error: unable to interface with target machine"
-  Note: clang has no support for ia64 and hence you can't compile GRUB
-	for ia64 with clang
 * GNU Make
 * GNU Bison 2.3 or later
 * GNU gettext 0.17 or later
diff --git a/Makefile.am b/Makefile.am
index 1f4bb9b..e6a2207 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -473,6 +473,9 @@ ChangeLog: FORCE
 		touch $@; \
 	fi
 
+systemdsystemunit_DATA = \
+	grub-initrd-fallback.service
+
 EXTRA_DIST += ChangeLog ChangeLog-2015
 
 syslinux_test: $(top_builddir)/config.status tests/syslinux/ubuntu10.04_grub.cfg
diff --git a/Makefile.util.def b/Makefile.util.def
index 59e4142..504d1c0 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -500,6 +500,13 @@ script = {
 };
 
 script = {
+  name = '10_linux_zfs';
+  common = util/grub.d/10_linux_zfs.in;
+  installdir = grubconf;
+  condition = COND_HOST_LINUX;
+};
+
+script = {
   name = '10_xnu';
   common = util/grub.d/10_xnu.in;
   installdir = grubconf;
diff --git a/configure.ac b/configure.ac
index 8832455..fae9171 100644
--- a/configure.ac
+++ b/configure.ac
@@ -305,6 +305,16 @@ AC_SUBST(grubdirname)
 AC_DEFINE_UNQUOTED(GRUB_DIR_NAME, "$grubdirname",
     [Default grub directory name])
 
+##### systemd unit files
+AC_ARG_WITH([systemdsystemunitdir],
+            AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
+            [],
+            [with_systemdsystemunitdir=/usr/lib/systemd/system],
+            [with_systemdsystemunitdir=no])
+if test "x$with_systemdsystemunitdir" != xno; then
+   AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
+fi
+
 #
 # Checks for build programs.
 #
@@ -410,7 +420,7 @@ else
 fi
 
 # Check for functions and headers.
-AC_CHECK_FUNCS(posix_memalign memalign getextmntent)
+AC_CHECK_FUNCS(posix_memalign memalign getextmntent on_exit)
 AC_CHECK_HEADERS(sys/param.h sys/mount.h sys/mnttab.h limits.h)
 
 # glibc 2.25 still includes sys/sysmacros.h in sys/types.h but emits deprecation
@@ -1661,7 +1671,7 @@ fi
 
 if test x"$starfield_excuse" = x; then
    for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do
-     for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype; do
+     for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype /usr/share/fonts/truetype/dejavu; do
         if test -f "$dir/DejaVuSans.$ext"; then
           DJVU_FONT_SOURCE="$dir/DejaVuSans.$ext"
           break 2
diff --git a/debian/.git-dpm b/debian/.git-dpm
index a87b37e..b8d04a8 100644
--- a/debian/.git-dpm
+++ b/debian/.git-dpm
@@ -1,6 +1,6 @@
 # see git-dpm(1) from git-dpm package
-3d51b212987d47da2b8c65a911140bbbc2fd3153
-3d51b212987d47da2b8c65a911140bbbc2fd3153
+50b137848fd25a580fcd76760802af16e4e961fa
+50b137848fd25a580fcd76760802af16e4e961fa
 578bb115fbd47e1c464696f1f8d6183e5443975d
 578bb115fbd47e1c464696f1f8d6183e5443975d
 grub2_2.04.orig.tar.xz
diff --git a/debian/build-efi-images b/debian/build-efi-images
index dbff3e7..f789cf6 100755
--- a/debian/build-efi-images
+++ b/debian/build-efi-images
@@ -129,6 +129,7 @@ CD_MODULES="
 	search_fs_file
 	search_label
 	sleep
+	smbios
 	squash4
 	test
 	true
@@ -189,6 +190,7 @@ GRUB_MODULES="$CD_MODULES
 	raid6rec
 	"
 NET_MODULES="$CD_MODULES
+	http
 	tftp
 	"
 
@@ -212,9 +214,12 @@ NET_MODULES="$CD_MODULES
 # Special network boot image for d-i to use. Just the same as the
 # normal network boot image, but with a different value baked in for
 # the prefix setting
-"$grub_mkimage" -O "$platform" -o "$outdir/grubnet$efi_name-installer.efi" \
-	-d "$grub_core" -c "$workdir/grub-bootstrap.cfg" \
-	-m "$workdir/memdisk-netboot.fat" \
-	-p "${efi_vendor}-installer/$deb_arch/grub" $NET_MODULES
+#
+# but not on Ubuntu LP: #1863994
+#
+#"$grub_mkimage" -O "$platform" -o "$outdir/grubnet$efi_name-installer.efi" \
+#	-d "$grub_core" -c "$workdir/grub-bootstrap.cfg" \
+#	-m "$workdir/memdisk-netboot.fat" \
+#	-p "${efi_vendor}-installer/$deb_arch/grub" $NET_MODULES
 
 exit 0
diff --git a/debian/canonical-uefi-ca.crt b/debian/canonical-uefi-ca.crt
new file mode 100644
index 0000000..55c06d5
--- /dev/null
+++ b/debian/canonical-uefi-ca.crt
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIENDCCAxygAwIBAgIJALlBJKAYLJJnMA0GCSqGSIb3DQEBCwUAMIGEMQswCQYD
+VQQGEwJHQjEUMBIGA1UECAwLSXNsZSBvZiBNYW4xEDAOBgNVBAcMB0RvdWdsYXMx
+FzAVBgNVBAoMDkNhbm9uaWNhbCBMdGQuMTQwMgYDVQQDDCtDYW5vbmljYWwgTHRk
+LiBNYXN0ZXIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEyMDQxMjExMTI1MVoX
+DTQyMDQxMTExMTI1MVowgYQxCzAJBgNVBAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9m
+IE1hbjEQMA4GA1UEBwwHRG91Z2xhczEXMBUGA1UECgwOQ2Fub25pY2FsIEx0ZC4x
+NDAyBgNVBAMMK0Nhbm9uaWNhbCBMdGQuIE1hc3RlciBDZXJ0aWZpY2F0ZSBBdXRo
+b3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/WzoWdO4hXa5h
+7Z1WrL3e3nLz3X4tTGIPrMBtSAgRz42L+2EfJ8wRbtlVPTlU60A7sbvihTR5yvd7
+v7p6yBAtGX2tWc+m1OlOD9quUupMnpDOxpkNTmdleF350dU4Skp6j5OcfxqjhdvO
++ov3wqIhLZtUQTUQVxONbLwpBlBKfuqZqWinO8cHGzKeoBmHDnm7aJktfpNS5fbr
+yZv5K+24aEm82ZVQQFvFsnGq61xX3nH5QArdW6wehC1QGlLW4fNrbpBkT1u06yDk
+YRDaWvDq5ELXAcT+IR/ZucBUlUKBUnIfSWR6yGwk8QhwC02loDLRoBxXqE3jr6WO
+BQU+EEOhAgMBAAGjgaYwgaMwHQYDVR0OBBYEFK2RmQvCKrH1FwSMI7ZlWiaONFpj
+MB8GA1UdIwQYMBaAFK2RmQvCKrH1FwSMI7ZlWiaONFpjMA8GA1UdEwEB/wQFMAMB
+Af8wCwYDVR0PBAQDAgGGMEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly93d3cuY2Fu
+b25pY2FsLmNvbS9zZWN1cmUtYm9vdC1tYXN0ZXItY2EuY3JsMA0GCSqGSIb3DQEB
+CwUAA4IBAQA/ffZ2pbODtCt60G1SGgODxBKnUJxHkszAlHeC0q5Xs5kE9TI6xlUd
+B9sSqVb62NR2IOvkw1Hbmlyckj8Yc9qUaqGZOIykiG3B/Dlx0HR2FgM+ViM11VVH
+WxodQcLTEkzc/64KkpxiChcBnHPgXrH9vNa1GRF6fs0+A35m21uoyTlIUf9T4Zwx
+U5EbOxB1Axe65oECgJRwTEa3lLA9Fc0fjgLgaAKP+/lHHX2iAcYHUcSazO3dz6Nd
+7ZK7vtH95uwfM1FzBL48crB9CPgB/5h9y5zgaTl3JUdxiLGNJ6UuqPc/X4Bplz6p
+9JkU284DDgtmxBxtvbgnd8FClL38agq8
+-----END CERTIFICATE-----
diff --git a/debian/changelog b/debian/changelog
index 79734b2..a9de8cc 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,506 @@
+grub2 (2.04-1ubuntu36) UNRELEASED; urgency=medium
+
+  * 10_linux: emit messages when initrdless boot is configured, attempted
+    and fails triggering fallback. LP: #1901553
+  * grub-common.service: port init.d script to systemd unit. Add warning
+    message, when initrdless boot fails triggering fallback. LP: #1901553
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Tue, 27 Oct 2020 13:07:20 +0000
+
+grub2 (2.04-1ubuntu35) groovy; urgency=medium
+
+  * postinst.in, grub-multi-install: fix logic of skipping installing onto
+    any device, if one chose to not install bootloader on any device. LP:
+    #1896608
+  * Do not finalize params twice on arm64. LP: #1897819
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Thu, 01 Oct 2020 22:59:51 +0800
+
+grub2 (2.04-1ubuntu34) groovy; urgency=medium
+
+  * configure.ac: one more dejavu font search path
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Mon, 14 Sep 2020 10:53:07 +0100
+
+grub2 (2.04-1ubuntu33) groovy; urgency=medium
+
+  * Build-depend on fonts-dejavu-core, not obsolete ttf-dejavu-core.
+
+ -- Steve Langasek <steve.langasek@ubuntu.com>  Sun, 13 Sep 2020 23:49:08 -0700
+
+grub2 (2.04-1ubuntu32) groovy; urgency=medium
+
+  * ubuntu-linuxefi-arm64.patch: Fix build on armhf
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Fri, 11 Sep 2020 20:33:34 +0200
+
+grub2 (2.04-1ubuntu31) groovy; urgency=medium
+
+  * ubuntu-linuxefi-arm64.patch: Restore arm64 parts of ubuntu-linuxefi.patch
+    that got lost in the 2.04 rebase (LP: #1862279)
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Fri, 11 Sep 2020 17:49:50 +0200
+
+grub2 (2.04-1ubuntu30) groovy; urgency=medium
+
+  * postinst.in: do not attempt to call grub-install upon fresh install of
+    grub-pc because it it a job of installers to do that after fresh
+    install.
+  * grub-multi-install: fix non-interactive failures for grub-efi like it
+    was fixed in postinst for grub-pc.
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Thu, 03 Sep 2020 14:54:23 +0100
+
+grub2 (2.04-1ubuntu29) groovy; urgency=medium
+
+  * grub-install: cherry-pick patch from grub-devel to make grub-install
+    fault tolerant. Create backup of files in /boot/grub, and restore them
+    on failure to complete grub-install. LP: #1891680
+  * postinst.in: do not exit successfully when failing to show critical
+    grub-pc/install_devices_failed and grub-pc/install_devices_empty
+    prompts in non-interactive mode. This enables surfacing upgrade errors
+    to the users and/or automation. LP: #1891680
+  * postinst.in: Fixup postinst.in, to attempt grub-install upon explicit
+    dpkg-reconfigure grub-pc. LP: #1892526
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Tue, 01 Sep 2020 20:04:44 +0100
+
+grub2 (2.04-1ubuntu28) groovy; urgency=medium
+
+  * Ensure that grub-multi-install can always find templates (LP: #1879948)
+  * Fix changelog entries for security update
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Mon, 10 Aug 2020 15:07:29 +0200
+
+grub2 (2.04-1ubuntu27) groovy; urgency=medium
+
+  * debian/patches/ubuntu-flavour-order.patch:
+    - Add a (hidden) GRUB_FLAVOUR_ORDER setting that can mark certain kernel
+      flavours as preferred, and specify an order between those preferred
+      flavours (LP: #1882663)
+  * debian/patches/ubuntu-zfs-enhance-support.patch:
+    - Use version_find_latest for ordering kernels, so it also supports
+      the GRUB_FLAVOUR_ORDER setting.
+  * debian/patches/ubuntu-dont-verify-loopback-images.patch:
+    - disk/loopback: Don't verify loopback images (LP: #1878541),
+      Thanks to Chris Coulson for the patch
+  * debian/patches/ubuntu-recovery-dis_ucode_ldr.patch
+    - Pass dis_ucode_ldr to kernel for recovery mode (LP: #1831789)
+  * debian/patches/ubuntu-add-initrd-less-boot-fallback.patch:
+    - Merge changes from xnox to fix multiple initrds support (LP: #1878705)
+  * debian/patches/ubuntu-clear-invalid-initrd-spacing.patch:
+    - Remove, no longer needed thanks to xnox's patch
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Thu, 06 Aug 2020 14:47:52 +0200
+
+grub2 (2.04-1ubuntu26.2) focal; urgency=medium
+
+  * debian/postinst.in: Avoid calling grub-install on upgrade of the grub-pc
+    package, since we cannot be certain that it will install to the correct
+    disk and a grub-install failure will render the system unbootable.
+    LP: #1889556.
+
+ -- Steve Langasek <steve.langasek@ubuntu.com>  Thu, 30 Jul 2020 17:34:25 -0700
+
+grub2 (2.04-1ubuntu26.1) focal; urgency=medium
+
+  [ Julian Andres Klode ]
+  * Move gettext patches out of git-dpm's way, so it does not delete them
+
+  [ Chris Coulson ]
+  * SECURITY UPDATE: Heap buffer overflow when encountering commands that
+    cannot be tokenized to less than 8192 characters.
+    - 0082-yylex-Make-lexer-fatal-errors-actually-be-fatal.patch: Make
+      fatal lexer errors actually be fatal
+    - CVE-2020-10713
+  * SECURITY UPDATE: Multiple integer overflow bugs that could result in
+    heap buffer allocations that were too small and subsequent heap buffer
+    overflows when handling certain filesystems, font files or PNG images.
+    - 0083-safemath-Add-some-arithmetic-primitives-that-check-f.patch: Add
+      arithmetic primitives that allow for overflows to be detected
+    - 0084-calloc-Make-sure-we-always-have-an-overflow-checking.patch:
+      Make sure that there is always an overflow checking implementation
+      of calloc() available
+    - 0085-calloc-Use-calloc-at-most-places.patch: Use calloc where
+      appropriate
+    - 0086-malloc-Use-overflow-checking-primitives-where-we-do-.patch: Use
+      overflow-safe arithmetic primitives when performing allocations
+      based on the results of operations that might overflow
+    - 0094-hfsplus-fix-two-more-overflows.patch: Fix integer overflows in
+      hfsplus
+    - 0095-lvm-fix-two-more-potential-data-dependent-alloc-over.patch: Fix
+      more potential integer overflows in lvm
+    - CVE-2020-14308, CVE-2020-14309, CVE-2020-14310, CVE-2020-14311
+  * SECURITY UPDATE: Use-after-free when executing a command that causes
+    a currently executing function to be redefined.
+    - 0092-script-Remove-unused-fields-from-grub_script_functio.patch:
+      Remove unused fields from grub_script_function
+    - 0093-script-Avoid-a-use-after-free-when-redefining-a-func.patch:
+      Avoid a use-after-free when redefining a function during execution
+    - CVE-2020-15706
+  * SECURITY UPDATE: Integer overflows that could result in heap buffer
+    allocations that were too small and subsequent heap buffer overflows
+    during initrd loading.
+    - 0105-linux-Fix-integer-overflows-in-initrd-size-handling.patch: Fix
+      integer overflows in initrd size handling
+    - 0106-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch: Fix
+      integer overflows in linuxefi grub_cmd_initrd
+    - CVE-2020-15707
+  * Various fixes as a result of code review and static analysis:
+    - 0087-iso9660-Don-t-leak-memory-on-realloc-failures.patch: Fix a
+     memory leak on realloc failures when processing symbolic links
+    - 0088-font-Do-not-load-more-than-one-NAME-section.patch: Fix a
+      memory leak when processing font files with more than one NAME
+      section
+    - 0089-gfxmenu-Fix-double-free-in-load_image.patch: Zero self->bitmap
+      after it is freed in order to avoid a potential double free later on
+    - 0090-lzma-Make-sure-we-don-t-dereference-past-array.patch: Fix an
+      out-of-bounds read in LzmaEncode
+    - 0091-tftp-Do-not-use-priority-queue.patch: Refactor tftp to not use
+      priority queues and fix a double free
+    - 0096-efi-fix-some-malformed-device-path-arithmetic-errors.patch: Fix
+      various arithmetic errors with malformed device paths
+    - 0098-Fix-a-regression-caused-by-efi-fix-some-malformed-de.patch: Fix
+      a NULL deref in the chainloader command introduced by a previous
+      patch
+    - 0099-efi-Fix-use-after-free-in-halt-reboot-path.patch: Fix a
+      use-after-free in the halt and reboot commands by not freeing
+      allocated memory in these paths
+    - 0100-chainloader-Avoid-a-double-free-when-validation-fail.patch:
+      Avoid a double free in the chainloader command when validation fails
+    - 0101-relocator-Protect-grub_relocator_alloc_chunk_addr-in.patch:
+      Protect grub_relocator_alloc_chunk_addr input arguments against
+      integer overflow / underflow
+    - 0102-relocator-Protect-grub_relocator_alloc_chunk_align-m.patch:
+      Protect grub_relocator_alloc_chunk_align max_addr argument against
+      integer underflow
+    - 0103-relocator-Fix-grub_relocator_alloc_chunk_align-top-m.patch: Fix
+      grub_relocator_alloc_chunk_align top memory allocation
+    - 0104-linux-loader-avoid-overflow-on-initrd-size-calculati.patch:
+      Avoid overflow on initrd size calculation
+
+  [ Dimitri John Ledkov ]
+  * SECURITY UPDATE: Grub does not enforce kernel signature validation
+    when the shim protocol isn't present.
+    - 0097-linuxefi-fail-kernel-validation-without-shim-protoco.patch:
+      Fail kernel validation if the shim protocol isn't available
+    - CVE-2020-15705
+
+ -- Chris Coulson <chris.coulson@canonical.com>  Mon, 20 Jul 2020 19:19:08 +0100
+
+grub2 (2.04-1ubuntu26) focal; urgency=medium
+
+  [ Julian Andres Klode ]
+  * Move /boot/efi -> debconf migration into wrapper, so it runs everywhere
+    (LP: #1872077)
+  * Display disk name and size in the ESP selection dialog, instead of ???
+
+  [ Sebastien Bacher ]
+  * debian/patches/gettext,
+    debian/patches/rules:
+    - backport upstream patches to fix the list of translated strings,
+      reported on the ubuntu-translators mailing list. The changes would
+      be overwritten by autoreconf so applying from a rules override.
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Wed, 15 Apr 2020 13:31:27 +0200
+
+grub2 (2.04-1ubuntu25) focal; urgency=medium
+
+  [ Jean-Baptiste Lallement ]
+  [ Didier Roche ]
+  * debian/patches/ubuntu-zfs-enhance-support.patch:
+    - fix trailing } when no advanced menu is printed
+    - ensure we unmount all temporary snapshots path before zfs collect them
+      out.
+  * debian/patches/ubuntu-speed-zsys-history.patch:
+    - Speed up navigating zsys history by reducing greatly grub.cfg file size.
+      It used to take eg 80 seconds when loading 100 system snapshots. This is
+      now instantaneous by using a function with parameters that the users can
+      still easily edit.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Mon, 13 Apr 2020 15:17:42 +0200
+
+grub2 (2.04-1ubuntu24) focal; urgency=medium
+
+  * Support installing to multiple ESPs (LP: #1871821)
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Thu, 09 Apr 2020 12:51:07 +0200
+
+grub2 (2.04-1ubuntu23) focal; urgency=medium
+
+  [ Jean-Baptiste Lallement ]
+  [ Didier Roche ]
+  * Performance improvements for update-grub on ZFS systems (LP: #1869885)
+
+ -- Didier Roche <didrocks@ubuntu.com>  Tue, 31 Mar 2020 15:30:36 +0200
+
+grub2 (2.04-1ubuntu22) focal; urgency=medium
+
+  * smbios: Add a --linux argument to apply linux modalias-like filtering
+  * Make the linux command in EFI grub always try EFI handover; thanks
+    to Chris Coulson for the patches (LP: #1864533)
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Wed, 11 Mar 2020 17:46:35 +0100
+
+grub2 (2.04-1ubuntu21) focal; urgency=medium
+
+  * Make ZFS menu generation depending on new zsysd binary instead of eoan
+    zsys compatibility symlink.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Wed, 26 Feb 2020 09:59:49 +0100
+
+grub2 (2.04-1ubuntu20) focal; urgency=medium
+
+  * build-efi-images: do not produce -installer.efi.signed. LP: #1863994
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Tue, 25 Feb 2020 01:11:31 +0000
+
+grub2 (2.04-1ubuntu19) focal; urgency=medium
+
+  * uefi-firmware: rename fwsetup menuentry to UEFI Firmware Settings
+    (LP: #1864547)
+  * build-efi-images: add smbios module to the prebuilt signed EFI images
+    (LP: #1856424)
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Mon, 24 Feb 2020 20:34:13 +0000
+
+grub2 (2.04-1ubuntu18) focal; urgency=medium
+
+  * Cherry-pick fix from Colin W. in debian to build with python3.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Thu, 06 Feb 2020 18:37:44 +0100
+
+grub2 (2.04-1ubuntu17) focal; urgency=medium
+
+  * Fix ZFS menu generation with ZFS 0.8.x where mounted datasets can’t list
+    snapshots due to an upstream change.
+    https://github.com/zfsonlinux/zfs/issues/9958
+
+ -- Didier Roche <didrocks@ubuntu.com>  Thu, 06 Feb 2020 18:20:16 +0100
+
+grub2 (2.04-1ubuntu16) focal; urgency=medium
+
+  * Revert "Add smbios module to build-efi-images script" from previous
+    upload, pending review see https://bugs.launchpad.net/bugs/1856424
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Sun, 15 Dec 2019 01:28:49 +0000
+
+grub2 (2.04-1ubuntu15) focal; urgency=medium
+
+  * ubuntu-efi-allow-loopmount-chainload.patch:
+    - Enable chainloading EFI apps from loopmounts
+  * cherrypick-lsefisystab-define-smbios3.patch:
+  * cherrypick-smbios-modules.patch:
+    - Cherrypick from 2.05 module for retrieving SMBIOS information
+  * cherrypick-lsefisystab-show-dtb.patch:
+    - If dtb is provided by the firmware / DtbLoader driver, display it in
+    human form, rather than just UUID
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Fri, 13 Dec 2019 11:24:21 +0000
+
+grub2 (2.04-1ubuntu14) focal; urgency=medium
+
+  * debian/patches/ubuntu-zfs-enhance-support.patch:
+    - Handle the case where grub-probe returns several devices for a single
+      pool (LP: #1848856). Thanks jpb for the report and the proposed patch.
+    - Add savedefault to non-recovery entries (LP: #1850202). Thanks Deltik
+      for the patch.
+    - Do not crash on invalid fstab and report the invalid entry.
+      (LP: #1849347) Thanks Deltik for the patch.
+    - When a pool fails to import, catch and display the error message and
+      continue with other pools. Import all the pools in readonly mode so we
+      can import other pools with unsupported features (LP: #1848399) Thanks
+      satmandu for the investigation and the proposed patch
+
+ -- Jean-Baptiste Lallement <jean-baptiste.lallement@ubuntu.com>  Mon, 18 Nov 2019 11:22:43 +0100
+
+grub2 (2.04-1ubuntu13) focal; urgency=medium
+
+  * debian/patches/ubuntu-tpm-unknown-error-non-fatal.patch: treat "unknown"
+    TPM errors as non-fatal, but still write up the details as debug messages
+    so we can further track what happens with the systems throwing those up.
+    (LP: #1848892)
+  * debian/patches/ubuntu-linuxefi.patch: Drop extra check for Secure Boot
+    status in linuxefi_secure_validate(); it's unnecessary and blocking boot
+    in chainload (like chainloading Windows) when SB is disabled.
+    (LP: #1845289)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Thu, 31 Oct 2019 17:58:47 -0400
+
+grub2 (2.04-1ubuntu12) eoan; urgency=medium
+
+  * Move our identifier to com.ubuntu
+    As we are not going to own org.zsys, move our identifier under
+    com.ubuntu.zsys (LP: #1847711)
+
+ -- Didier Roche <didrocks@ubuntu.com>  Fri, 11 Oct 2019 15:57:47 +0200
+
+grub2 (2.04-1ubuntu11) eoan; urgency=medium
+
+  * Load all kernels (even those without .efi.signed) for secure boot mode
+    as those are signed kernels on ubuntu, loaded by the shim. (LP: #1847581)
+
+ -- Didier Roche <didrocks@ubuntu.com>  Thu, 10 Oct 2019 11:40:44 +0200
+
+grub2 (2.04-1ubuntu10) eoan; urgency=medium
+
+  * debian/patches/ubuntu-skip-disk-by-id-lvm-pvm-uuid-entries.patch:
+    skip /dev/disk/by-id/lvm-pvm-uuid entries from device iteration.
+    (LP: #1838525)
+
+ -- Rafael David Tinoco <rafaeldtinoco@ubuntu.com>  Mon, 07 Oct 2019 23:23:54 -0300
+
+grub2 (2.04-1ubuntu9) eoan; urgency=medium
+
+  * debian/patches/ubuntu-zfs-enhance-support.patch:
+    - Handle case of pure zfs only snapshots giving additional "}", and as
+      such, creating invalid grub menu.
+      Spotted by grubzfs-testsuite autopkgtests.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Wed, 02 Oct 2019 09:59:19 +0200
+
+grub2 (2.04-1ubuntu8) eoan; urgency=medium
+
+  * debian/patches/install-signed.patch -> ubuntu-install-signed.patch:
+    Really fix the installation of UEFI artefacts to the distributor path (we
+    only want shim, grub, and MokManager, and shim's boot.csv there), and to
+    the removable /EFI/BOOT path (where we want shim and fallback only).
+    Rename the patch to ubuntu- like others that are Ubuntu-specific or
+    otherwise modified to avoid such confusion at merge time in the future.
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Tue, 01 Oct 2019 11:29:24 -0400
+
+grub2 (2.04-1ubuntu7) eoan; urgency=medium
+
+  * debian/patches/ubuntu-zfs-enhance-support.patch:
+    Disable history entry under some conditions:
+    - Don't show up if the system is a zsys one and zsys isn't installed
+      (LP: #1845333)
+    - Don't show for pure zfs systems: we identified multiple issues due
+      to the mount generator in upstream zfs which makes it incompatible.
+      Disable for now (LP: #1845913)
+
+ -- Didier Roche <didrocks@ubuntu.com>  Mon, 30 Sep 2019 09:35:03 +0200
+
+grub2 (2.04-1ubuntu6) eoan; urgency=medium
+
+  * debian/patches/install-signed.patch: fix paths for MokManager/fallback;
+    shim no longer ships these with a .signed suffix. (LP: #1845466)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Thu, 26 Sep 2019 09:48:07 -0400
+
+grub2 (2.04-1ubuntu5) eoan; urgency=medium
+
+  * d/patches/ubuntu-boot-from-multipath-dependent-symlink.patch: fix
+    mis-spelling of helper function in final computation of GRUB_DEVICE in
+    multipath case.
+
+ -- Michael Hudson-Doyle <michael.hudson@ubuntu.com>  Tue, 13 Aug 2019 08:56:16 +1200
+
+grub2 (2.04-1ubuntu4) eoan; urgency=medium
+
+  * d/patches/ubuntu-boot-from-multipath-dependent-symlink.patch: when / is
+    multipathed there will be multiple paths to the partition, so using
+    root=UUID= exposes the boot process to udev races.  In addition
+    grub-probe --target device / in this case reports /dev/dm-1 or similar --
+    better to use a symlink that depends on the multipath name. (LP: #1429327)
+
+ -- Michael Hudson-Doyle <michael.hudson@ubuntu.com>  Tue, 06 Aug 2019 12:37:18 +1200
+
+grub2 (2.04-1ubuntu3) eoan; urgency=medium
+
+  [ Mathieu Trudel-Lapierre ]
+  * debian/patches/ubuntu-add-devicetree-command-support.patch: import patch
+    into git-dpm: drop [PATCH] tag and add Patch-Name.
+
+  [ Didier Roche ]
+  * debian/patches/ubuntu-zfs-enhance-support.patch
+    - Don't patch autoregenerated files.
+    - rewrite generate MenuMeta implementation in shell (LP: #1834095)
+      mawk doesn't support \s and other array features.
+      + Change \s by their space or tab equivalent.
+      + Rewrite the menumeta generation in pure shell, which is easier to
+        debug, keeping globally the same algorithm
+      + Support i18n in entry name generation.
+      Co-authored with Jean-Baptiste.
+    - Resplit all patches in debian/patches/*, so that we have upstreamable
+      and non upstreamable parts separate. Also, any change in 10_linux patch
+      will be reflected in 10_linux_zfs.
+    - Always import pools (using force), as we don't mount them. Ensure also
+      that we don't update the host cache, as we import all pools, and not
+      only those attached to that system.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Mon, 29 Jul 2019 08:08:48 +0200
+
+grub2 (2.04-1ubuntu2) eoan; urgency=medium
+
+  * Add device-tree command support as installed by flash-kernel.
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Wed, 17 Jul 2019 23:47:27 +0100
+
+grub2 (2.04-1ubuntu1) eoan; urgency=medium
+
+  * Merge against Debian; remaining changes:
+    - debian/control: Update Vcs fields for code location on Ubuntu.
+    - debian/control: Breaks shim (<< 13).
+    - debian/patches/linuxefi.patch: Secure Boot support: use newer patchset
+      from rhboot repo, flattened to a single patch.
+    - debian/patches/install_signed.patch, grub-install-extra-removable.patch:
+      - Make sure if we install shim; it should also be exported as the default
+        bootloader to install later to a removable path, if we do.
+      - Rework grub-install-extra-removable.patch to reverse its logic: in the
+        default case, install the bootloader to /EFI/BOOT, unless we're trying
+        to install on a removable device, or explicitly telling grub *not* to
+        do it.
+      - Install a BOOT.CSV for fallback to use.
+      - Make sure postinst and templates know about the replacement of
+        --force-extra-removable with --no-extra-removable.
+    - debian/patches/ubuntu-support-initrd-less-boot.patch: allow non-initrd
+      boot config.
+    - debian/patches/ubuntu-add-initrd-less-boot-fallback.patch: If a kernel
+      fails to boot without initrd, we will fallback to trying to boot the
+      kernel with an initrd.
+    - debian/patches/ubuntu-mkconfig-leave-breadcrumbs.patch: make sure
+      grub-mkconfig leaves a trace of what files were sourced to help generate
+      the config we're building.
+    - debian/patches/ubuntu-efi-console-set-text-mode-as-needed.patch: in EFI
+      console, only set text-mode when we're actually going to need it.
+    - debian/patches/ubuntu-zfs-enhance-support.patch: Better ZFS grub support.
+    - Disable os-prober for ppc64el on the PowerNV platform, to reduce the
+      number of entries/clutter from other OSes in Petitboot
+    - debian/patches/ubuntu-shorter-version-info.patch: Only show the upstream
+      version in menu and console, and hide the package one in a
+      package_version variable.
+    - Verify that the current and newer kernels are signed when grub is
+      updated, to make sure people do not accidentally shutdown without a
+      signed kernel.
+    - debian/default/grub: replace GRUB_HIDDEN_* variables with the less
+      confusing GRUB_TIMEOUT_STYLE=hidden.
+    - debian/rules: shuffle files around for now to keep build artefacts
+      for signing at the same location as they were expected by Launchpad.
+    - debian/rules, debian/control: enable dh-systemd.
+    - debian/grub-common.install.in: install the systemd unit that's part of
+      initrd fallback handling, missed when the feature landed.
+    - debian/build-efi-images: add http module to NET_MODULES.
+  * debian/patches/linuxefi*.patch: Flatten linuxefi patches into one.
+  * debian/patches: rename patches to use "-" as a separator rather than "_".
+  * debian/patches: rename Ubuntu-specific patches and commits to add "ubuntu"
+    so it's clearer which are new or changed when doing a merge.
+  * debian/patches/ubuntu-fix-lzma-decompressor-objcopy.patch: fix FTBFS due
+    to objcopy building an invalid binary padded with zeroes (LP: #1833234)
+  * debian/patches/ubuntu-clear-invalid-initrd-spacing.patch: clear up invalid
+    spacing for the initrd command when not using early initrds.
+  * debian/patches/ubuntu-add-initrd-less-boot-fallback.patch: move the initrd
+    boot success/failure service to start later at boot time. (LP: #1823391)
+  * debian/patches/fix-lockdown.patch: Drop lockdown patch from Debian, which
+    breaks with new linuxefi patchset.
+  * debian/patches/ubuntu-temp-keep-auto-nvram.patch: Temporarily keep the
+    --auto-nvram option we previously had as a supported option in grub-install
+    (with no effect now), to avoid breaking upgrades. "auto-nvram" is default
+    behavior now that we use libefivar instead of calling efibootmgr.
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Tue, 16 Jul 2019 11:31:29 -0400
+
 grub2 (2.04-2) UNRELEASED; urgency=medium
 
   [ James Clarke ]
@@ -139,6 +642,112 @@ grub2 (2.02+dfsg1-13) unstable; urgency=medium
 
  -- Colin Watson <cjwatson@debian.org>  Thu, 14 Mar 2019 10:33:24 +0000
 
+grub2 (2.02+dfsg1-12ubuntu3) eoan; urgency=medium
+
+  * debian/patches/zfs_enhance_support.patch:
+    Enhance ZFS grub support:
+    - Support multiple zfs systems (grouped by machine-id)
+    - Group zfs snapshots and clones with latest dataset for a given
+      installation.
+    - Support "history" entry with one time boot, recovery mode and
+      consecutive reboots.
+    - Pin kernel to particular snapshot, trying to reboot with the exact
+      same kernel and initrd.
+    - Disable in 10_linux zfs support if 10_linux_zfs is installed so that
+      we don't end up with the same installation multiple times.
+  * debian/patches/*:
+    - Apply ubuntu/debian specific changes of 10_linux to 10_linux_zfs.
+
+  Work done with Jean-Baptiste.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Mon, 17 Jun 2019 11:28:48 +0200
+
+grub2 (2.02+dfsg1-12ubuntu2) disco; urgency=medium
+
+  * debian/patches/efi-console-set-text-mode-as-needed.patch: in EFI console,
+    only set text-mode when we're actually going to need it.
+  * debian/build-efi-images: add http module to NET_MODULES. (LP: #1787630)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Mon, 11 Mar 2019 17:48:49 -0400
+
+grub2 (2.02+dfsg1-12ubuntu1) disco; urgency=medium
+
+  * Merge against Debian unstable; remaining changes (LP: #564853):
+    - debian/control: Update Vcs fields for code location on Ubuntu.
+    - debian/control: Breaks shim (<< 13).
+    - Secure Boot support: use newer patchset from rhboot repo:
+      - many linuxefi_* patches added and modified
+      - dropped debian/patches/linuxefi_require_shim.patch
+      - renamed: debian/patches/no_insmod_on_sb.patch ->
+        debian/patches/linuxefi_no_insmod_on_sb.patch
+    - debian/patches/install_signed.patch, grub-install-extra-removable.patch:
+      - Make sure if we install shim; it should also be exported as the default
+        bootloader to install later to a removable path, if we do.
+      - Rework grub-install-extra-removable.patch to reverse its logic: in the
+        default case, install the bootloader to /EFI/BOOT, unless we're trying
+        to install on a removable device, or explicitly telling grub *not* to
+        do it.
+      - Install a BOOT.CSV for fallback to use.
+      - Make sure postinst and templates know about the replacement of
+        --force-extra-removable with --no-extra-removable.
+    - debian/patches/add-an-auto-nvram-option-to-grub-install.patch: Add the
+      --auto-nvram option to grub-install for auto-detecting NVRAM availability
+      before attempting NVRAM updates.
+    - debian/build-efi-images: provide a new grub EFI image which enforces that
+      loaded kernels are signed for Secure Boot: build gsb$arch.efi; which is
+      the same as grub$arch.efi minus the 'linux' module. Without fallback to
+      'linux' for unsigned loading, this makes it effectively enforce having a
+      signed kernel.
+    - Verify that the current and newer kernels are signed when grub is
+      updated, to make sure people do not accidentally shutdown without a
+      signed kernel.
+    - debian/default/grub: replace GRUB_HIDDEN_* variables with the less
+      confusing GRUB_TIMEOUT_STYLE=hidden.
+    - debian/patches/support_initrd-less_boot.patch: Added knobs to allow
+      non-initrd boot config.
+    - Disable os-prober for ppc64el on the PowerNV platform, to reduce the
+      number of entries/clutter from other OSes in Petitboot
+    - debian/patches/shorter_version_info.patch: Only show the upstream version
+      in menu and console, and hide the package one in a package_version
+      variable.
+    - debian/patches/skip_text_gfxpayload_where_not_supported.patch: Skip the
+      'text' payload if it's not supported but present in gfxpayload, such as
+      on EFI systems.
+    - debian/patches/bufio_sensible_block_sizes.patch: Don't use arbitrary file
+      fizes as block sizes in bufio: this avoids potentially seeking back in
+      the files unnecessarily, which may require re-open files that cannot be
+      seeked into, such as via TFTP.
+    - debian/patches/ofnet-init-structs-in-bootpath-parser.patch: initialize
+      structs in bootpath parser.
+    - debian/rules: shuffle files around for now to keep build artefacts
+      for signing at the same location as they were expected by Launchpad.
+    - debian/rules, debian/control: enable dh-systemd.
+    - debian/grub-common.install.in: install the systemd unit that's part of
+      initrd fallback handling, missed when the feature landed.
+    - debian/patches/quick-boot-lvm.patch: If we don't have writable
+      grubenv and we're on EFI, always show the menu.
+    - debian/patches/mkconfig_leave_breadcrumbs.patch: make sure grub-mkconfig
+      leaves a trace of what files were sourced to help generate the config
+      we're building.
+    - debian/patches/linuxefi_truncate_overlong_reloc_section.patch: Windows
+      7 bootloader has inconsistent headers; truncate to the smaller, correct
+      size to fix chainloading Windows 7.
+    - debian/patches/linuxefi_fix_relocate_coff.patch: fix typo in
+      relocate_coff() causing issues with relocation of code in chainload.
+    - debian/patches/add-initrd-less-boot-fallback.patch: add initrd-less
+      capabilities. If a kernel fails to boot without initrd, we will fallback
+      to trying to boot the kernel with an initrd. Patch by Chris Glass.
+    - debian/patches/grub-reboot-warn.patch: Warn when "for the next
+      boot only" promise cannot be kept.
+  * Refreshed patches and fixed up attribution to the right authors after
+    merge with Debian.
+  * debian/patches/linuxefi_missing_include.patch,
+    debian/patches/linuxefi_fixing_more_errors.patch: Apply some additional
+    small fixes to casts, format strings, includes and Makefile to make sure
+    the newer linuxefi patches apply and build properly.
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Tue, 05 Mar 2019 17:05:09 -0500
+
 grub2 (2.02+dfsg1-12) unstable; urgency=medium
 
   [ Colin Watson ]
@@ -283,6 +892,175 @@ grub2 (2.02+dfsg1-6) unstable; urgency=medium
 
  -- Colin Watson <cjwatson@debian.org>  Tue, 28 Aug 2018 16:17:21 +0100
 
+grub2 (2.02+dfsg1-5ubuntu11) disco; urgency=medium
+
+  [ Mathieu Trudel-Lapierre ]
+  * debian/grub-check-signatures: properly account for DB showing as empty on
+    some broken firmwares: Guard against mokutil --export --db failing, and do
+    a better job at finding the DER certs for conversion to PEM format.
+    (LP: #1814575)
+
+  [ Steve Langasek ]
+  * debian/patches/quick-boot-lvm.patch: checking the return value of
+    'lsefi' when the command doesn't exist does not do what's expected, so
+    instead check the value of $grub_platform which is simpler anyway.
+    LP: #1814403.
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Mon, 04 Feb 2019 17:51:15 -0500
+
+grub2 (2.02+dfsg1-5ubuntu10) disco; urgency=medium
+
+  * debian/grub-check-signatures: check kernel signatures against keys known
+    in firmware, in case a kernel is signed but not using a key that will pass
+    validation, such as when using kernels coming from a PPA. (LP: #1789918)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Mon, 21 Jan 2019 09:34:36 -0500
+
+grub2 (2.02+dfsg1-5ubuntu9) disco; urgency=medium
+
+  [ Steve Langasek ]
+  * debian/patches/quick-boot-lvm.patch: If we don't have writable
+    grubenv and we're on EFI, always show the menu.  Closes LP: #1800722.
+
+  [ Mathieu Trudel-Lapierre ]
+  * debian/patches/mkconfig_leave_breadcrumbs.patch: make sure grub-mkconfig
+    leaves a trace of what files were sourced to help generate the config
+    we're building.
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Mon, 07 Jan 2019 17:32:01 -0500
+
+grub2 (2.02+dfsg1-5ubuntu8) cosmic; urgency=medium
+
+  * debian/patches/grub-install-extra-removable.patch: install mmx64.efi to
+    the EFI removable path to avoid boot failures after install when certs
+    need to be enrolled and the system's firmware is confused. (LP: #1798171)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Wed, 17 Oct 2018 14:44:49 -0400
+
+grub2 (2.02+dfsg1-5ubuntu7) cosmic; urgency=medium
+
+  [ Steve Langasek ]
+  * debian/grub-common.install.in: install the systemd unit that's part of
+    initrd fallback handling, missed when the feature landed.
+
+  [ Mathieu Trudel-Lapierre ]
+  * debian/rules: set DEFAULT_TIMEOUT to 0 if we've enabled FLICKER_FREE_BOOT,
+    to avoid unnecessary delay at boot time. (LP: #1784363)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Fri, 12 Oct 2018 11:10:10 -0400
+
+grub2 (2.02+dfsg1-5ubuntu6) cosmic; urgency=medium
+
+  [ Steve Langasek ]
+  * debian/grub-check-signatures: Handle the case where we have unsigned
+    vmlinuz and signed vmlinuz.efi.signed. (LP: #1788727)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Wed, 03 Oct 2018 14:59:05 -0400
+
+grub2 (2.02+dfsg1-5ubuntu5) cosmic; urgency=medium
+
+  [ Mathieu Trudel-Lapierre ]
+  * debian/patches/linuxefi_truncate_overlong_reloc_section.patch: The Windows
+    7 bootloader has inconsistent headers; truncate to the smaller, correct
+    size to fix chainloading Windows 7.
+
+  [ Steve Langasek ]
+  * debian/rules, debian/control: enable dh-systemd.
+  * debian/patches/add-initrd-less-boot-fallback.patch: add initrd-less
+    capabilities. If a kernel fails to boot without initrd, grub will fallback
+    to trying to boot the kernel with an initrd. Patch by Chris Glass.
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Tue, 25 Sep 2018 16:05:13 -0400
+
+grub2 (2.02+dfsg1-5ubuntu4) cosmic; urgency=medium
+
+  * debian/patches/linuxefi_fix_relocate_coff.patch: fix typo in
+    relocate_coff() causing issues with relocation of code in chainload.
+    (LP: #1792575)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Mon, 17 Sep 2018 07:45:49 -0400
+
+grub2 (2.02+dfsg1-5ubuntu3) cosmic; urgency=medium
+
+  * debian/patches/grub-reboot-warn.patch: Warn when "for the next
+    boot only" promise cannot be kept. (LP: #788298)
+
+ -- dann frazier <dannf@ubuntu.com>  Thu, 13 Sep 2018 15:28:50 -0600
+
+grub2 (2.02+dfsg1-5ubuntu2) cosmic; urgency=medium
+
+  * debian/patches/add_ext_lfb_base_support.patch: i386/linux: Add support for
+    ext_lfb_base. (LP: #1785033)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Wed, 05 Sep 2018 14:29:04 -0400
+
+grub2 (2.02+dfsg1-5ubuntu1) cosmic; urgency=medium
+
+  [ Mathieu Trudel-Lapierre]
+  * Merge against Debian unstable; remaining changes:
+    - debian/control: Update Vcs fields for code location on Ubuntu.
+    - debian/control: Breaks shim (<< 13).
+    - Secure Boot support: use newer patchset from rhboot repo:
+      - many linuxefi_* patches added and modified
+      - dropped debian/patches/linuxefi_require_shim.patch
+      - renamed: debian/patches/no_insmod_on_sb.patch ->
+        debian/patches/linuxefi_no_insmod_on_sb.patch
+    - debian/patches/install_signed.patch, grub-install-extra-removable.patch:
+      - Make sure if we install shim; it should also be exported as the default
+        bootloader to install later to a removable path, if we do.
+      - Rework grub-install-extra-removable.patch to reverse its logic: in the
+        default case, install the bootloader to /EFI/BOOT, unless we're trying
+        to install on a removable device, or explicitly telling grub *not* to
+        do it.
+      - Move installing fb$arch.efi to --no-extra-removable; as we don't want
+        fallback to be installed unless we're also installing to /EFI/BOOT.
+        (LP: #1684341)
+      - Install a BOOT.CSV for fallback to use.
+      - Make sure postinst and templates know about the replacement of
+        --force-extra-removable with --no-extra-removable.
+    - debian/patches/add-an-auto-nvram-option-to-grub-install.patch: Add the
+      --auto-nvram option to grub-install for auto-detecting NVRAM availability
+      before attempting NVRAM updates.
+    - debian/build-efi-images: provide a new grub EFI image which enforces that
+      loaded kernels are signed for Secure Boot: build gsb$arch.efi; which is
+      the same as grub$arch.efi minus the 'linux' module. Without fallback to
+      'linux' for unsigned loading, this makes it effectively enforce having a
+      signed kernel. (LP: #1401532)
+    - Verify that the current and newer kernels are signed when grub is
+      updated, to make sure people do not accidentally shutdown without a
+      signed kernel.
+    - debian/default/grub: replace GRUB_HIDDEN_* variables with the less
+      confusing GRUB_TIMEOUT_STYLE=hidden. (LP: #1258597)
+    - debian/patches/support_initrd-less_boot.patch: Added knobs to allow
+      non-initrd boot config. (LP: #1640878)
+    - Disable os-prober for ppc64el on the PowerNV platform, to reduce the
+      number of entries/clutter from other OSes in Petitboot (LP: #1447500)
+    - debian/patches/shorter_version_info.patch: Only show the upstream version
+      in menu and console, and hide the package one in a package_version
+      variable. (LP: #1723434)
+    - debian/patches/skip_text_gfxpayload_where_not_supported.patch: Skip the
+      'text' payload if it's not supported but present in gfxpayload, such as
+      on EFI systems. (LP: #1711452)
+    - debian/patches/bufio_sensible_block_sizes.patch: Don't use arbitrary file
+      fizes as block sizes in bufio: this avoids potentially seeking back in
+      the files unnecessarily, which may require re-open files that cannot be
+      seeked into, such as via TFTP. (LP: #1743249)
+    * util/grub-install.c: Drop extra handling for x.efi.signed files for mok
+      and fallback binaries: shim now installs them without the .signed
+      extension. (LP: #1708245)
+    - debian/patches/dont-fail-efi-warnings.patch: handle linuxefi patches and
+      the casting they do on some architectures: we don't want to fail build
+      because of some of the warnings that can show up since we otherwise build
+      with -Werror.
+  * debian/rules: shuffle files around for now to keep putting build artefacts
+    for signing at the same location as they were expected by Launchpad.
+
+  [ Julian Andres Klode ]
+  * debian/patches/ofnet-init-structs-in-bootpath-parser.patch: initialize
+    structs in bootpath parser. Fixes netboot issues on ppc64el. (LP: #1785859)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Thu, 23 Aug 2018 15:00:14 -0400
+
 grub2 (2.02+dfsg1-5) unstable; urgency=medium
 
   [ Colin Watson ]
@@ -379,6 +1157,171 @@ grub2 (2.02-3) unstable; urgency=medium
 
  -- Colin Watson <cjwatson@debian.org>  Sat, 10 Feb 2018 03:00:30 +0000
 
+grub2 (2.02-2ubuntu13) cosmic; urgency=medium
+
+  * debian/patches/tests_update_for_new_qemu.patch: update qemu options to
+    remove deprecated options that fail tests.
+  * debian/patches: fix up busted patches due to git-dpm:
+    - debian/patches/add-an-auto-nvram-option-to-grub-install.patch
+    - debian/patches/grub-shell-test-helper-disable-seabios-sercon.patch
+  * debian/patches/r_x86_64_plt32-is-like-r_x86_64_pc32.patch: For the purpose
+    of grub-mkimage, the R_X86_64_PLT32 relocation is basically the same as
+    R_X86_64_PC32. Make R_X86_64_PLT32 supported.
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Thu, 19 Jul 2018 09:46:53 -0400
+
+grub2 (2.02-2ubuntu12) cosmic; urgency=medium
+
+  * debian/default/grub: replace GRUB_HIDDEN_* variables with the more concise
+    and less confusing GRUB_TIMEOUT_STYLE=hidden. (LP: #1258597)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Mon, 16 Jul 2018 14:18:46 -0400
+
+grub2 (2.02-2ubuntu11) cosmic; urgency=medium
+
+  * Verify that the current and newer kernels are signed when grub is updated, to
+    make sure people do not accidentally shutdown without a signed kernel.
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Fri, 13 Jul 2018 15:21:48 +0200
+
+grub2 (2.02-2ubuntu10) cosmic; urgency=medium
+
+  * debian/patches/grub-shell-test-helper-disable-seabios-sercon.patch: In the
+    grub-shell test helper, disable seabios's serial console through fw_cfg
+    runtime configuration as its boot output interferes with testing.
+    (LP: #1775249)
+
+ -- Łukasz 'sil2100' Zemczak <lukasz.zemczak@ubuntu.com>  Wed, 06 Jun 2018 01:03:26 +0200
+
+grub2 (2.02-2ubuntu9) cosmic; urgency=medium
+
+  * debian/patches/add-an-auto-nvram-option-to-grub-install.patch: Add the
+    --auto-nvram option to grub-install for auto-detecting NVRAM availability
+    before attempting NVRAM updates.
+
+ -- Łukasz 'sil2100' Zemczak <lukasz.zemczak@ubuntu.com>  Tue, 05 Jun 2018 00:34:38 +0200
+
+grub2 (2.02-2ubuntu8) bionic; urgency=medium
+
+  * Drop debian/patches/mkconfig_keep_native_term_active.patch, which can
+    lead to flickering between graphical and text mode when traversing the
+    menu. (LP: #1752767)
+  * debian/patches/yylex-explicitly_cast_fprintf_to_void.patch: Fix FTBFS
+    with flex 2.6.4.
+
+ -- dann frazier <dannf@ubuntu.com>  Sun, 04 Mar 2018 06:11:35 -0700
+
+grub2 (2.02-2ubuntu7) bionic; urgency=medium
+
+  [ Julian Andres Klode ]
+  * debian/patches/shorter_version_info.patch: Only show the upstream version
+    in menu and console, and hide the package one in a package_version
+    variable. (LP: #1723434)
+
+  [ Mathieu Trudel-Lapierre ]
+  * debian/patches/skip_text_gfxpayload_where_not_supported.patch: Skip the
+    'text' payload if it's not supported but present in gfxpayload, such as
+    on EFI systems. (LP: #1711452)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Fri, 09 Feb 2018 16:30:45 -0500
+
+grub2 (2.02-2ubuntu6) bionic; urgency=medium
+
+  [ Steve Langasek ]
+  * debian/patches/bufio_sensible_block_sizes.patch: Don't use arbitrary file
+    fizes as block sizes in bufio: this avoids potentially seeking back in
+    the files unnecessarily, which may require re-open files that cannot be
+    seeked into, such as via TFTP. (LP: #1743249)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Mon, 05 Feb 2018 11:58:09 -0500
+
+grub2 (2.02-2ubuntu5) bionic; urgency=medium
+
+  * debian/patches/mkconfig_keep_native_term_active.patch: Keep the
+    default EFI console active while enabling gfxterm. (LP: #1743884)
+
+ -- dann frazier <dannf@ubuntu.com>  Wed, 31 Jan 2018 10:51:11 -0700
+
+grub2 (2.02-2ubuntu4) bionic; urgency=medium
+
+  * debian/patches/vt_handoff.patch: modify the existing patch to set
+    vt.handoff=1 instead of vt.handoff=7 as we now start display managers on
+    vt1 anyway. This also fixes issues with netboot installed server systems
+    not displaying the login prompt on boot. (LP: #1675453)
+
+ -- Łukasz 'sil2100' Zemczak <lukasz.zemczak@ubuntu.com>  Thu, 18 Jan 2018 18:32:31 +0100
+
+grub2 (2.02-2ubuntu3) bionic; urgency=medium
+
+  * util/grub-install.c: Drop extra handling for x.efi.signed files for mok
+    and fallback binaries: shim now installs them without the .signed
+    extension. (LP: #1708245)
+  * debian/control: Breaks shim (<< 13).
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Wed, 17 Jan 2018 09:25:09 -0500
+
+grub2 (2.02-2ubuntu2) bionic; urgency=medium
+
+  * Cherry-pick upstream patch to change the default TSC calibration method
+    to pmtimer on EFI systems (LP: #1734278)
+  * debian/control: Update Vcs fields for code location on Ubuntu.
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Tue, 05 Dec 2017 11:47:31 -0500
+
+grub2 (2.02-2ubuntu1) bionic; urgency=medium
+
+  * Merge with Debian; remaining changes:
+    - debian/patches/support_initrd-less_boot.patch: Added knobs to allow
+      non-initrd boot config. (LP: #1640878)
+    - Disable os-prober for ppc64el on the PowerNV platform, to reduce the
+      number of entries/clutter from other OSes in Petitboot (LP: #1447500)
+    - debian/build-efi-images: provide a new grub EFI image which enforces that
+      loaded kernels are signed for Secure Boot: build gsb$arch.efi; which is
+      the same as grub$arch.efi minus the 'linux' module. Without fallback to
+      'linux' for unsigned loading, this makes it effectively enforce having a
+      signed kernel. (LP: #1401532)
+    - debian/patches/install_signed.patch, grub-install-extra-removable.patch:
+      - Make sure if we install shim; it should also be exported as the default
+        bootloader to install later to a removable path, if we do.
+      - Rework grub-install-extra-removable.patch to reverse its logic: in the
+        default case, install the bootloader to /EFI/BOOT, unless we're trying
+        to install on a removable device, or explicitly telling grub *not* to
+        do it.
+      - Move installing fb$arch.efi to --no-extra-removable; as we don't want
+        fallback to be installed unless we're also installing to /EFI/BOOT.
+        (LP: #1684341)
+      - Make sure postinst and templates know about the replacement of
+        --force-extra-removable with --no-extra-removable.
+  * Sync Secure Boot support patches with the upstream patch set from
+    rhboot/grub2:master-sb. Renamed some patches and updated descriptions for
+    the whole thing to make more sense, too:
+    - dropped debian/patches/linuxefi_require_shim.patch
+    - renamed: debian/patches/no_insmod_on_sb.patch ->
+      debian/patches/linuxefi_no_insmod_on_sb.patch
+    - debian/patches/linuxefi.patch
+    - debian/patches/linuxefi_debug.patch
+    - debian/patches/linuxefi_non_sb_fallback.patch
+    - debian/patches/linuxefi_add_sb_to_efi_chainload.patch
+    - debian/patches/linuxefi_cleanup_errors_in_loader.patch
+    - debian/patches/linuxefi_fix_efi_validation_race.patch
+    - debian/patches/linuxefi_handle_multiarch_boot.patch
+    - debian/patches/linuxefi_honor_sb_mode.patch
+    - debian/patches/linuxefi_move_fdt_helper.patch
+    - debian/patches/linuxefi_load_arm_with_sb.patch
+    - debian/patches/linuxefi_minor_cleanups.patch
+    - debian/patches/linuxefi_re-enable_linux_cmd.patch
+    - debian/patches/linuxefi_rework_linux16_cmd.patch
+    - debian/patches/linuxefi_rework_linux_cmd.patch
+    - debian/patches/linuxefi_rework_non-sb_efi_chainload.patch
+    - debian/patches/linuxefi_rework_pe_loading.patch
+    - debian/patches/linuxefi_use_dev_chainloader_target.patch
+  * debian/patches/dont-fail-efi-warnings.patch: handle linuxefi patches and
+    the casting they do on some architectures: we don't want to fail build
+    because of some of the warnings that can show up since we otherwise build
+    with -Werror.
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Mon, 06 Nov 2017 15:37:12 -0500
+
 grub2 (2.02-2) unstable; urgency=medium
 
   * Comment out debian/watch lines for betas and pre-releases for now.
@@ -415,6 +1358,92 @@ grub2 (2.02~beta3-5) unstable; urgency=medium
 
  -- Colin Watson <cjwatson@debian.org>  Sat, 11 Feb 2017 15:09:19 +0000
 
+grub2 (2.02~beta3-4ubuntu7) artful; urgency=medium
+
+  * debian/patches/headers_for_device_macros.patch,
+    debian/patches/fix_check_for_sys_macros.patch: make sure the right
+    device macro header is included and that the deprecation warning
+    is dealt with. LP: #1722955.
+
+ -- Tiago Stürmer Daitx <tiago.daitx@ubuntu.com>  Thu, 12 Oct 2017 09:41:17 -0400
+
+grub2 (2.02~beta3-4ubuntu6) artful; urgency=medium
+
+  * debian/patches/mount-ext4-fs-with-crypto-enabled.patch: Allow grub to
+    mount an EXT4 partition that has the 'encrypt' feature enabled
+    (closes: 840204)
+
+ -- Tyler Hicks <tyhicks@canonical.com>  Wed, 05 Jul 2017 22:23:03 +0000
+
+grub2 (2.02~beta3-4ubuntu5) artful; urgency=medium
+
+  * debian/patches/linuxefi.patch: fix double-free caused by an extra
+    grub_free() call in this patch (which the previous upload didn't change).
+  * debian/patches/linuxefi_rework_non-sb_cases.patch,
+    debian/patches/linuxefi_non_sb_fallback.patch: refreshed.
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Mon, 29 May 2017 16:28:41 -0400
+
+grub2 (2.02~beta3-4ubuntu4) artful; urgency=medium
+
+  * debian/patches: Rework linuxefi/SecureBoot support and sync with upstream
+    SB patch set:
+    - linuxefi_arm_sb_support.patch: add Secure Boot support for arm for its
+      chainloader.
+    - linuxefi_fix_validation_race.patch: Fix a race in validating images.
+    - linuxefi_chainloader_path.patch: honor the starting path for grub, so
+      images do not need to be started from $root.
+    - linuxefi_chainloader_sb.patch: Fix some more issues in chainloader use
+      when Secure Boot is enabled.
+    - linuxefi_loaders_enforce_sb.patch: Enforce Secure Boot policy for all
+      loaders: don't load the commands when Secure Boot is enabled.
+    - linuxefi_re-enable_linux_cmd.patch: Since we rely on the linux and
+      initrd commands to automatically hand-off to linuxefi/initrdefi; re-
+      enable the linux loader.
+    - linuxefi_chainloader_pe_fixes.patch: PE parsing fixes for chainloading
+      "special" PE images, such as Windows'.
+    - linuxefi_rework_non-sb_cases.patch: rework cases where Secure Boot is
+      disabled or shim validation is disabled so loading works as EFI binaries
+      when it is supposed to.
+    - Removed linuxefi_require_shim.patch; superseded by the above.
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Thu, 11 May 2017 17:05:04 -0400
+
+grub2 (2.02~beta3-4ubuntu3) artful; urgency=medium
+
+  * debian/patches/install_signed.patch, grub-install-extra-removable.patch:
+    - Make sure if we install shim; it should also be exported as the default
+      bootloader to install later to a removable path, if we do.
+    - Rework grub-install-extra-removable.patch to reverse its logic: in the
+      default case, install the bootloader to /EFI/BOOT, unless we're trying
+      to install on a removable device, or explicitly telling grub *not* to
+      do it.
+    - Move installing fb$arch.efi to --no-extra-removable; as we don't want
+      fallback to be installed unless we're also installing to /EFI/BOOT.
+      (LP: #1684341)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Wed, 26 Apr 2017 21:08:22 -0400
+
+grub2 (2.02~beta3-4ubuntu2) zesty; urgency=medium
+
+  * debian/build-efi-images: provide a new grub EFI image which enforces that
+    loaded kernels are signed for Secure Boot: build gsb$arch.efi; which is
+    the same as grub$arch.efi minus the 'linux' module. Without fallback to
+    'linux' for unsigned loading, this makes it effectively enforce having a
+    signed kernel. (LP: #1401532)
+
+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>  Thu, 30 Mar 2017 17:45:23 -0400
+
+grub2 (2.02~beta3-4ubuntu1) zesty; urgency=medium
+
+  * Merge with Debian; remaining changes:
+    - debian/patches/support_initrd-less_boot.patch: Added knobs to allow
+      non-initrd boot config. (LP: #1640878)
+    - Disable os-prober for ppc64el on the PowerNV platform, to reduce the
+      number of entries/clutter from other OSes in Petitboot (LP: #1447500)
+
+ -- dann frazier <dannf@ubuntu.com>  Thu, 09 Feb 2017 10:06:57 -0700
+
 grub2 (2.02~beta3-4) unstable; urgency=medium
 
   [ Colin Watson ]
diff --git a/debian/control b/debian/control
index bed7c77..f9fd5b0 100644
--- a/debian/control
+++ b/debian/control
@@ -1,11 +1,15 @@
 Source: grub2
 Section: admin
 Priority: optional
-Maintainer: GRUB Maintainers <pkg-grub-devel@alioth-lists.debian.net>
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+XSBC-Original-Maintainer: GRUB Maintainers <pkg-grub-devel@alioth-lists.debian.net>
 Uploaders: Felix Zielcke <fzielcke@z-51.de>, Jordi Mallach <jordi@debian.org>, Colin Watson <cjwatson@debian.org>, Ian Campbell <ijc@debian.org>, Steve McIntyre <93sam@debian.org>
 Build-Depends: debhelper (>= 10~),
  patchutils,
- python,
+ dh-autoreconf,
+ dh-systemd,
+ automake,
+ python3,
  flex,
  bison,
  po-debconf,
@@ -24,7 +28,7 @@ Build-Depends: debhelper (>= 10~),
  cpio [i386 kopensolaris-i386 amd64 x32],
  parted [!hurd-any],
  libfuse-dev (>= 2.8.4-1.4) [linux-any kfreebsd-any],
- ttf-dejavu-core,
+ fonts-dejavu-core,
  liblzma-dev,
  dosfstools [any-i386 any-amd64 any-arm64],
  mtools [any-i386 any-amd64 any-arm64],
@@ -37,8 +41,8 @@ Build-Depends: debhelper (>= 10~),
 Build-Conflicts: autoconf2.13, libzfs-dev, libnvpair-dev
 Standards-Version: 3.9.6
 Homepage: https://www.gnu.org/software/grub/
-Vcs-Git: https://salsa.debian.org/grub-team/grub.git
-Vcs-Browser: https://salsa.debian.org/grub-team/grub
+Vcs-Git: https://git.launchpad.net/~ubuntu-core-dev/grub/+git/ubuntu
+Vcs-Browser: https://git.launchpad.net/~ubuntu-core-dev/grub/+git/ubuntu
 Rules-Requires-Root: no
 
 Package: grub2
@@ -94,7 +98,7 @@ Architecture: any-i386 any-amd64 any-powerpc any-ppc64 any-ppc64el any-sparc any
 Depends: grub-common (= ${binary:Version}), dpkg (>= 1.15.4) | install-info, ${shlibs:Depends}, ${misc:Depends}
 Replaces: grub, grub-legacy, ${legacy-doc-br}, grub-common (<< 1.99-1), grub-pc (<< 2.02+dfsg1-7), grub-coreboot (<< 2.02+dfsg1-7), grub-efi-ia32 (<< 2.02+dfsg1-7), grub-efi-amd64 (<< 2.02+dfsg1-7), grub-efi-ia64 (<< 2.02+dfsg1-7), grub-efi-arm (<< 2.02+dfsg1-7), grub-efi-arm64 (<< 2.02+dfsg1-7), grub-ieee1275 (<< 2.02+dfsg1-7), grub-uboot (<< 2.02+dfsg1-7), grub-xen (<< 2.02+dfsg1-7), grub-yeeloong (<< 2.02+dfsg1-7), grub-cloud-amd64 (<< 0.0.4)
 Conflicts: grub-legacy
-Breaks: grub (<< 0.97-54), ${legacy-doc-br}, shim (<< 0.9+1474479173.6c180c6-0ubuntu1~), grub-pc (<< 2.02+dfsg1-7), grub-coreboot (<< 2.02+dfsg1-7), grub-efi-ia32 (<< 2.02+dfsg1-7), grub-efi-amd64 (<< 2.02+dfsg1-7), grub-efi-ia64 (<< 2.02+dfsg1-7), grub-efi-arm (<< 2.02+dfsg1-7), grub-efi-arm64 (<< 2.02+dfsg1-7), grub-ieee1275 (<< 2.02+dfsg1-7), grub-uboot (<< 2.02+dfsg1-7), grub-xen (<< 2.02+dfsg1-7), grub-yeeloong (<< 2.02+dfsg1-7), grub-cloud-amd64 (<< 0.0.4)
+Breaks: grub (<< 0.97-54), ${legacy-doc-br}, shim (<< 13), grub-pc (<< 2.02+dfsg1-7), grub-coreboot (<< 2.02+dfsg1-7), grub-efi-ia32 (<< 2.02+dfsg1-7), grub-efi-amd64 (<< 2.02+dfsg1-7), grub-efi-ia64 (<< 2.02+dfsg1-7), grub-efi-arm (<< 2.02+dfsg1-7), grub-efi-arm64 (<< 2.02+dfsg1-7), grub-ieee1275 (<< 2.02+dfsg1-7), grub-uboot (<< 2.02+dfsg1-7), grub-xen (<< 2.02+dfsg1-7), grub-yeeloong (<< 2.02+dfsg1-7), grub-cloud-amd64 (<< 0.0.4)
 Multi-Arch: foreign
 Description: GRand Unified Bootloader (common files for version 2)
  This package contains common files shared by the distinct flavours of GRUB.
diff --git a/debian/gettext-patches/0001-Support-POTFILES-shell.patch b/debian/gettext-patches/0001-Support-POTFILES-shell.patch
new file mode 100644
index 0000000..5a5d1ec
--- /dev/null
+++ b/debian/gettext-patches/0001-Support-POTFILES-shell.patch
@@ -0,0 +1,54 @@
+From d5bbd8f60aacb0f73ea5a0bde999152c467d0e78 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Sun, 1 Mar 2020 11:57:58 +0000
+Subject: [PATCH 1/4] Support POTFILES-shell
+
+---
+ gettext-runtime/po/Makefile.in.in | 24 ++++++++++++++++++++++--
+ 1 file changed, 22 insertions(+), 2 deletions(-)
+
+diff --git a/gettext-runtime/po/Makefile.in.in b/gettext-runtime/po/Makefile.in.in
+index fabdc76c9..32e9323d3 100644
+--- a/gettext-runtime/po/Makefile.in.in
++++ b/gettext-runtime/po/Makefile.in.in
+@@ -142,7 +142,7 @@ stamp-po: $(srcdir)/$(DOMAIN).pot
+ # The determination of whether the package xyz is a GNU one is based on the
+ # heuristic whether some file in the top level directory mentions "GNU xyz".
+ # If GNU 'find' is available, we avoid grepping through monster files.
+-$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed
++$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in $(srcdir)/POTFILES-shell.in remove-potcdate.sed
+ 	if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \
+ 	       LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f -size -10000000c -exec grep 'GNU @PACKAGE@' /dev/null '{}' ';' 2>/dev/null; \
+ 	     else \
+@@ -175,7 +175,27 @@ $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed
+ 	      --package-version='@VERSION@' \
+ 	      --msgid-bugs-address="$$msgid_bugs_address" \
+ 	    ;; \
+-	esac
++	esac; \
++	case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
++	  '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \
++	    $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
++	      --add-comments=TRANSLATORS: @XGETTEXT_EXTRA_OPTIONS@ \
++	      --files-from=$(srcdir)/POTFILES-shell.in \
++	      --copyright-holder='$(COPYRIGHT_HOLDER)' \
++	      --msgid-bugs-address="$$msgid_bugs_address" \
++	      --join-existing --language=Shell --keyword=gettext_quoted \
++	    ;; \
++	  *) \
++	    $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
++	      --add-comments=TRANSLATORS: @XGETTEXT_EXTRA_OPTIONS@ \
++	      --files-from=$(srcdir)/POTFILES-shell.in \
++	      --copyright-holder='$(COPYRIGHT_HOLDER)' \
++	      --package-name="$${package_gnu}@PACKAGE@" \
++	      --package-version='@VERSION@' \
++	      --msgid-bugs-address="$$msgid_bugs_address" \
++	      --join-existing --language=Shell --keyword=gettext_quoted \
++	    ;; \
++	esac; \
+ 	test ! -f $(DOMAIN).po || { \
+ 	  if test -f $(srcdir)/$(DOMAIN).pot; then \
+ 	    sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \
+-- 
+2.17.1
+
diff --git a/debian/gettext-patches/0002-Handle-gettext_printf-shell-function.patch b/debian/gettext-patches/0002-Handle-gettext_printf-shell-function.patch
new file mode 100644
index 0000000..2767ed6
--- /dev/null
+++ b/debian/gettext-patches/0002-Handle-gettext_printf-shell-function.patch
@@ -0,0 +1,46 @@
+From fd17c51f2e6c87427679fbdfb5f6224ff48795db Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Sun, 1 Mar 2020 12:00:41 +0000
+Subject: [PATCH 2/4] Handle gettext_printf shell function
+
+Extract gettext_printf arguments.
+
+Run grub.d.sed over strings extracted from util/grub.d/, in order to set
+c-format flags (xgettext refuses to include these itself for strings it
+extracted from a shell file, but these really are c-format).
+---
+ gettext-runtime/po/Makefile.in.in | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/gettext-runtime/po/Makefile.in.in b/gettext-runtime/po/Makefile.in.in
+index 32e9323d3..32e0c99a2 100644
+--- a/gettext-runtime/po/Makefile.in.in
++++ b/gettext-runtime/po/Makefile.in.in
+@@ -183,7 +183,8 @@ $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in $(srcdir)/POTFILES-shell
+ 	      --files-from=$(srcdir)/POTFILES-shell.in \
+ 	      --copyright-holder='$(COPYRIGHT_HOLDER)' \
+ 	      --msgid-bugs-address="$$msgid_bugs_address" \
+-	      --join-existing --language=Shell --keyword=gettext_quoted \
++	      --join-existing --language=Shell \
++	      --keyword=gettext_quoted --keyword=gettext_printf \
+ 	    ;; \
+ 	  *) \
+ 	    $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
+@@ -193,10 +194,13 @@ $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in $(srcdir)/POTFILES-shell
+ 	      --package-name="$${package_gnu}@PACKAGE@" \
+ 	      --package-version='@VERSION@' \
+ 	      --msgid-bugs-address="$$msgid_bugs_address" \
+-	      --join-existing --language=Shell --keyword=gettext_quoted \
++	      --join-existing --language=Shell \
++	      --keyword=gettext_quoted --keyword=gettext_printf \
+ 	    ;; \
+ 	esac; \
+ 	test ! -f $(DOMAIN).po || { \
++	  sed -f grub.d.sed < $(DOMAIN).po > $(DOMAIN).1po && \
++	  mv $(DOMAIN).1po $(DOMAIN).po; \
+ 	  if test -f $(srcdir)/$(DOMAIN).pot; then \
+ 	    sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \
+ 	    sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \
+-- 
+2.17.1
+
diff --git a/debian/gettext-patches/0003-Make-msgfmt-output-in-little-endian.patch b/debian/gettext-patches/0003-Make-msgfmt-output-in-little-endian.patch
new file mode 100644
index 0000000..4141611
--- /dev/null
+++ b/debian/gettext-patches/0003-Make-msgfmt-output-in-little-endian.patch
@@ -0,0 +1,34 @@
+From 156c523e2945c9b43c5500fb93988b0dd2f08d75 Mon Sep 17 00:00:00 2001
+From: Vladimir Serbinenko <phcoder@gmail.com>
+Date: Sun, 1 Mar 2020 12:09:25 +0000
+Subject: [PATCH 3/4] Make msgfmt output in little-endian
+
+GRUB expects this.
+---
+ gettext-runtime/po/Makefile.in.in | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/gettext-runtime/po/Makefile.in.in b/gettext-runtime/po/Makefile.in.in
+index 32e0c99a2..f3ef54c39 100644
+--- a/gettext-runtime/po/Makefile.in.in
++++ b/gettext-runtime/po/Makefile.in.in
+@@ -84,13 +84,13 @@ CATALOGS = @CATALOGS@
+ 
+ .po.mo:
+ 	@echo "$(MSGFMT) -c -o $@ $<"; \
+-	$(MSGFMT) -c -o t-$@ $< && mv t-$@ $@
++	$(MSGFMT) --endianness=little -c -o t-$@ $< && mv t-$@ $@
+ 
+ .po.gmo:
+ 	@lang=`echo $* | sed -e 's,.*/,,'`; \
+ 	test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
+-	echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \
+-	cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo
++	echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) --endianness=little -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \
++	cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) --endianness=little -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo
+ 
+ .sin.sed:
+ 	sed -e '/^#/d' $< > t-$@
+-- 
+2.17.1
+
diff --git a/debian/gettext-patches/0004-Use-SHELL-rather-than-bin-sh.patch b/debian/gettext-patches/0004-Use-SHELL-rather-than-bin-sh.patch
new file mode 100644
index 0000000..790521d
--- /dev/null
+++ b/debian/gettext-patches/0004-Use-SHELL-rather-than-bin-sh.patch
@@ -0,0 +1,26 @@
+From f36f12e77798223ee7ee882c0d09e0e63db11454 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Sun, 1 Mar 2020 12:14:07 +0000
+Subject: [PATCH 4/4] Use @SHELL rather than /bin/sh
+
+/bin/sh might not exist.
+---
+ gettext-runtime/po/Makefile.in.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gettext-runtime/po/Makefile.in.in b/gettext-runtime/po/Makefile.in.in
+index f3ef54c39..285a55a9d 100644
+--- a/gettext-runtime/po/Makefile.in.in
++++ b/gettext-runtime/po/Makefile.in.in
+@@ -16,7 +16,7 @@ VERSION = @VERSION@
+ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+ 
+ SED = @SED@
+-SHELL = /bin/sh
++SHELL = @SHELL@
+ @SET_MAKE@
+ 
+ srcdir = @srcdir@
+-- 
+2.17.1
+
diff --git a/debian/grub-check-signatures b/debian/grub-check-signatures
new file mode 100755
index 0000000..3d41c3c
--- /dev/null
+++ b/debian/grub-check-signatures
@@ -0,0 +1,129 @@
+#!/bin/sh
+
+set -e
+
+. /usr/share/debconf/confmodule
+
+# Check if we are on an EFI system
+efivars=/sys/firmware/efi/efivars
+secureboot_var=SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c
+moksbstatert_var=MokSBStateRT-605dab50-e046-4300-abb6-3dd810dd8b23
+tmpdir=$(mktemp -d)
+
+on_secure_boot() {
+	# Validate any queued actions before we go try to do them.
+	local moksbstatert=0
+
+	if ! [ -d $efivars ]; then
+		return 1
+	fi
+
+	if ! [ -f $efivars/$secureboot_var ] \
+		|| [ "$(od -An -t u1 $efivars/$secureboot_var | awk '{ print $NF }')" -ne 1 ]
+	then
+		return 1
+	fi
+
+	if [ -f /proc/sys/kernel/moksbstate_disabled ]; then
+		moksbstatert=$(cat /proc/sys/kernel/moksbstate_disabled 2>/dev/null || echo 0)
+	elif [ -f $efivars/$moksbstatert_var ]; then
+		# MokSBStateRT set to 1 means validation is disabled
+		moksbstatert=$(od -An -t u1 $efivars/$moksbstatert_var | \
+					   awk '{ print $NF; }')
+	fi
+
+	if [ $moksbstatert -eq 1 ]; then
+		return 1
+	fi
+
+	return 0
+}
+
+# Retrieve the keys we do trust from PK, DB, KEK, and MokList.
+extract_known_keys() {
+	# Make the Canonical CA cert available for validation too; in case
+	# MokListRT is empty due to a bug.
+	cp /usr/share/grub/canonical-uefi-ca.crt $tmpdir
+
+	# Extract known UEFI certs from firmware variables
+	( cd $tmpdir; \
+		mokutil --export --db >/dev/null 2>/dev/null; \
+		mokutil --export --mok >/dev/null 2>/dev/null; )
+	find $tmpdir -name "*.der" -exec openssl x509 -inform der -in {} -outform pem -out {}.crt  \;
+}
+
+# Check if a given kernel image is signed
+is_signed() {
+	tmp=$(mktemp)
+	sbattach --detach $tmp $1 >/dev/null 2>/dev/null 	# that's ugly...
+	test "$(wc -c < $tmp)" -ge 16	# Just _some_ minimum size
+	result=$?
+	if [ $result -eq 0 ]; then
+		sig_subject=$(openssl pkcs7 -inform der -in $tmp -print_certs | openssl x509 -noout -text | grep Subject: )
+	fi
+	rm $tmp
+	if [ $result -eq 0 ]; then
+		for crtfile in $tmpdir/*.crt; do
+			sbverify --cert $crtfile $1 >/dev/null 2>/dev/null
+			result=$?
+			if [ $result -eq 0 ]; then
+				return $result;
+			fi
+		done
+		echo "$1 is signed, but using an unknown key:" >&2
+		echo "$sig_subject" >&2
+	else
+		echo "$1 is unsigned." >&2
+	fi
+	return $result
+}
+
+# Check that our current kernel and every newer one is signed
+find_unsigned() {
+	uname_r="$(uname -r)"
+	for kernel in $(ls -1 /boot/vmlinuz-* | sort -V -r); do
+		# no kernels :(
+		if [ "$kernel" = "/boot/vmlinuz-*" ]; then
+			break
+		fi
+		this_uname_r="$(echo "$kernel" | sed -r 's#^/boot/vmlinuz-(.*)#\1#; s#\.efi\.signed$##')"
+		if dpkg --compare-versions "$this_uname_r" lt "$uname_r"; then
+			continue
+		fi
+		if [ -e "$kernel.efi.signed" ]; then
+			continue
+		fi
+		if ! is_signed $kernel; then
+			echo "$this_uname_r"
+		fi
+	done
+}
+
+# Only reached from show_warning
+error() {
+	echo "E: Your kernels are not signed with a key known to your firmware. This system will fail to boot in a Secure Boot environment." >&2
+	exit 1
+}
+
+# Either shows a debconf note or prints an error with error() above if
+# that fails
+show_warning() {
+	# kernels should be an indented list of one version per line
+	escaped="$(printf "%s" "$unsigned" | sed "s#^#     #" | debconf-escape -e )"
+	db_capb escape
+	db_settitle grub2/unsigned_kernels_title || error
+	db_fset grub2/unsigned_kernels seen 0 || error
+	db_subst grub2/unsigned_kernels unsigned_versions "$escaped" || error
+	db_input critical grub2/unsigned_kernels || error
+	db_go || error
+	error
+}
+
+if on_secure_boot; then
+	extract_known_keys
+	unsigned="$(find_unsigned)"
+	if [ -n "$unsigned" ]; then
+		show_warning "$unsigned"
+	fi
+	rm -rf "$tmpdir"
+fi
diff --git a/debian/grub-common.dirs b/debian/grub-common.dirs
index 3d70df4..832239c 100644
--- a/debian/grub-common.dirs
+++ b/debian/grub-common.dirs
@@ -1,2 +1,3 @@
 usr/sbin
 var/lib/grub/ucf
+var/lib/grub/esp
diff --git a/debian/grub-common.install.in b/debian/grub-common.install.in
index 420a61e..6c5c9f0 100644
--- a/debian/grub-common.install.in
+++ b/debian/grub-common.install.in
@@ -1,6 +1,9 @@
 ../../debian/apport/source_grub2.py	usr/share/apport/package-hooks/
 ../../debian/grub.d			etc
 ../../debian/init-select.cfg		etc/default/grub.d
+../../debian/grub-check-signatures usr/share/grub/
+../../debian/grub-multi-install usr/lib/grub/
+../../debian/canonical-uefi-ca.crt usr/share/grub/
 
 etc/grub.d
 usr/bin/grub-editenv
@@ -20,6 +23,7 @@ usr/bin/grub-mkstandalone
 usr/bin/grub-render-label
 usr/bin/grub-script-check
 usr/bin/grub-syslinux2cfg
+usr/lib/systemd/system/grub-initrd-fallback.service lib/systemd/system
 usr/sbin/grub-macbless
 usr/sbin/grub-mkconfig
 usr/sbin/grub-mkdevicemap
diff --git a/debian/grub-common.service b/debian/grub-common.service
new file mode 100644
index 0000000..1395ad9
--- /dev/null
+++ b/debian/grub-common.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Record successful boot for GRUB
+
+[Service]
+Type=simple
+Restart=no
+RemainAfterExit=yes
+ExecStartPre=/bin/sh -c '[ -s /boot/grub/grubenv ] || rm -f /boot/grub/grubenv; mkdir -p /boot/grub'
+ExecStart=grub-editenv /boot/grub/grubenv unset recordfail
+ExecStartPost=/bin/sh -c 'if grub-editenv /boot/grub/grubenv list | grep -q initrdless_boot_fallback_triggered=1; then echo "<3>grub: GRUB_FORCE_PARTUUID set, initrdless boot paniced, fallback triggered."; fi'
+StandardOutput=kmsg
+
+[Install]
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/debian/grub-common.templates b/debian/grub-common.templates
new file mode 100644
index 0000000..c75e5d3
--- /dev/null
+++ b/debian/grub-common.templates
@@ -0,0 +1,53 @@
+Template: grub-efi/install_devices
+Type: multiselect
+Choices-C: ${RAW_CHOICES}
+Choices: ${CHOICES}
+_Description: GRUB EFI system partitions:
+ The grub-efi package is being upgraded. This menu allows you to select which
+ EFI system partions you'd like grub-install to be automatically run for, if any.
+ .
+ Running grub-install automatically is recommended in most situations, to
+ prevent the installed GRUB core image from getting out of sync with GRUB
+ modules or grub.cfg.
+
+Template: grub-efi/install_devices_disks_changed
+Type: multiselect
+Choices-C: ${RAW_CHOICES}
+Choices: ${CHOICES}
+_Description: GRUB install devices:
+ The GRUB boot loader was previously installed to a disk that is no longer
+ present, or whose unique identifier has changed for some reason. It is
+ important to make sure that the installed GRUB core image stays in sync
+ with GRUB modules and grub.cfg. Please check again to make sure that GRUB
+ is written to the appropriate boot devices.
+
+Template: grub-efi/partition_description
+Type: text
+_Description: ${DEVICE} (${SIZE} MB; ${PATH}) on ${DISK_SIZE} MB ${DISK_MODEL}
+
+Template: grub-efi/install_devices_failed
+Type: boolean
+Default: false
+#flag:translate!:3
+_Description: Writing GRUB to boot device failed - continue?
+ GRUB failed to install to the following devices:
+ .
+ ${FAILED_DEVICES}
+ .
+ Do you want to continue anyway? If you do, your computer may not start up
+ properly.
+
+Template: grub-efi/install_devices_empty
+Type: boolean
+Default: false
+_Description: Continue without installing GRUB?
+ You chose not to install GRUB to any devices. If you continue, the boot
+ loader may not be properly configured, and when this computer next starts
+ up it will use whatever was previously configured. If there is an
+ earlier version of GRUB 2 in the EFI system partition, it may be unable to load
+ modules or handle the current configuration file.
+ .
+ If you are already using a different boot loader and want to carry on
+ doing so, or if this is a special environment where you do not need a boot
+ loader, then you should continue anyway. Otherwise, you should install
+ GRUB somewhere.
diff --git a/debian/grub-multi-install b/debian/grub-multi-install
new file mode 100755
index 0000000..bedc700
--- /dev/null
+++ b/debian/grub-multi-install
@@ -0,0 +1,417 @@
+#!/bin/bash
+#
+# Install to multiple ESPs
+
+set -e
+
+# Most of this is copy-paste from grub postinst, sigh.
+
+. /usr/share/debconf/confmodule
+
+# shamelessly stolen from ucf:
+#
+# Load our templates, just in case our template has
+# not been loaded or the Debconf DB lost or corrupted
+# since then.
+db_x_loadtemplatefile "$(dpkg-query --control-path grub-common templates)" grub-common
+
+###############################################################################
+#                       COPY FROM POSTINST
+###############################################################################
+# This only works on a Linux system with udev running.  This is probably the
+# vast majority of systems where we need any of this, though, and we fall
+# back reasonably gracefully if we don't have it.
+cached_available_ids=
+available_ids()
+{
+  local id path
+
+  if [ "$cached_available_ids" ]; then
+    echo "$cached_available_ids"
+    return
+  fi
+
+  [ -d /dev/disk/by-id ] || return
+  cached_available_ids="$(
+    for path in /dev/disk/by-id/*; do
+      [ -e "$path" ] || continue
+      printf '%s %s\n' "$path" "$(readlink -f "$path")"
+    done | sort -k2 -s -u | cut -d' ' -f1
+  )"
+  echo "$cached_available_ids"
+}
+
+# Returns non-zero and no output if no mapping can be found.
+device_to_id()
+{
+  local id
+  for id in $(available_ids); do
+    if [ "$(readlink -f "$id")" = "$(readlink -f "$1")" ]; then
+      echo "$id"
+      return 0
+    fi
+  done
+  # Fall back to the plain device name if there's no by-id link for it.
+  if [ -e "$1" ]; then
+    echo "$1"
+    return 0
+  fi
+  return 1
+}
+
+# for Linux
+sysfs_size()
+{
+  local num_sectors sector_size size
+  # Try to find out the size without relying on a partitioning tool being
+  # installed. This isn't too hard on Linux 2.6 with sysfs, but we have to
+  # try a couple of variants on detection of the sector size.
+  if [ -e "$1/size" ]; then
+    num_sectors="$(cat "$1/size")"
+    sector_size=512
+    if [ -e "$1/queue/logical_block_size" ]; then
+      sector_size="$(cat "$1/queue/logical_block_size")"
+    elif [ -e "$1/queue/hw_sector_size" ]; then
+      sector_size="$(cat "$1/queue/hw_sector_size")"
+    fi
+    size="$(expr "$num_sectors" \* "$sector_size" / 1000 / 1000)"
+  fi
+  [ "$size" ] || size='???'
+  echo "$size"
+}
+
+# for kFreeBSD
+camcontrol_size()
+{
+  local num_sectors sector_size size=
+
+  if num_sectors="$(camcontrol readcap "$1" -q -s -N)"; then
+    sector_size="$(camcontrol readcap "$1" -q -b)"
+    size="$(expr "$num_sectors" \* "$sector_size" / 1000 / 1000)"
+  fi
+
+  [ "$size" ] || size='???'
+  echo "$size"
+}
+
+maybe_udevadm()
+{
+  if which udevadm >/dev/null 2>&1; then
+    udevadm "$@" || true
+  fi
+}
+
+# Parse /proc/mounts and find out the mount for the given device.
+# The device must be a real device in /dev, not a symlink to one.
+get_mounted_device()
+{
+  mountpoint="$1"
+  cat /proc/mounts | while read -r line; do
+    set -f
+    set -- $line
+    set +f
+    if [ "$2" = "$mountpoint" ]; then
+      echo "$1"
+      break
+    fi
+  done
+}
+
+###############################################################################
+#                            New or modified helpers
+###############################################################################
+
+# Fixed: Return nothing if the argument is empty
+get_mountpoint()
+{
+  local relpath boot_mountpoint
+
+  if [ -z "$1" ]; then
+    return
+  fi
+
+  relpath="$(grub-mkrelpath "$1")"
+  boot_mountpoint="${1#$relpath}"
+  echo "${boot_mountpoint:-/}"
+}
+
+
+# Returns value in $RET, like a debconf command.
+#
+# Merged version of describe_disk and describe_partition, as disks can't be
+# valid ESPs on their own, so we can't render them as an entry.
+describe_efi_system_partition()
+{
+  local disk part id path sysfs_path diskbase partbase size
+  local disk_basename disk_size model
+  disk="$1"
+  part="$2"
+  id="$3"
+  path="$4"
+
+  # BEGIN: Stolen from describe_disk
+  model=
+  case $(uname -s) in
+    Linux)
+      sysfs_path="$(maybe_udevadm info -n "$disk" -q path)"
+      if [ -z "$sysfs_path" ]; then
+        sysfs_path="/block/$(printf %s "${disk#/dev/}" | sed 's,/,!,g')"
+      fi
+      disk_size="$(sysfs_size "/sys$sysfs_path")"
+
+      model="$(maybe_udevadm info -n "$disk" -q property | sed -n 's/^ID_MODEL=//p')"
+      if [ -z "$model" ]; then
+        model="$(maybe_udevadm info -n "$disk" -q property | sed -n 's/^DM_NAME=//p')"
+        if [ -z "$model" ]; then
+          model="$(maybe_udevadm info -n "$disk" -q property | sed -n 's/^MD_NAME=//p')"
+          if [ -z "$model" ] && which dmsetup >/dev/null 2>&1; then
+            model="$(dmsetup info -c --noheadings -o name "$disk" 2>/dev/null || true)"
+          fi
+        fi
+      fi
+    ;;
+    GNU/kFreeBSD)
+      disk_basename=$(basename "$disk")
+      disk_size="$(camcontrol_size "$disk_basename")"
+      model="$(camcontrol inquiry "$disk_basename" | sed -ne "s/^pass0: <\([^>]*\)>.*/\1/p")"
+    ;;
+  esac
+
+  [ "$model" ] || model='???'
+
+  # END: Stolen from describe_disk
+
+  sysfs_path="$(maybe_udevadm info -n "$part" -q path)"
+  if [ -z "$sysfs_path" ]; then
+    diskbase="${disk#/dev/}"
+    diskbase="$(printf %s "$diskbase" | sed 's,/,!,g')"
+    partbase="${part#/dev/}"
+    partbase="$(printf %s "$partbase" | sed 's,/,!,g')"
+    sysfs_path="/block/$diskbase/$partbase"
+  fi
+  size="$(sysfs_size "/sys$sysfs_path")"
+
+  db_subst grub-efi/partition_description DEVICE "$part"
+  db_subst grub-efi/partition_description SIZE "$size"
+  db_subst grub-efi/partition_description PATH "$path"
+  db_subst grub-efi/partition_description DISK_MODEL "$model"
+  db_subst grub-efi/partition_description DISK_SIZE "$disk_size"
+  db_metaget grub-efi/partition_description description
+}
+
+
+# Parse /proc/mounts and find out the mount for the given device.
+# The device must be a real device in /dev, not a symlink to one.
+find_mount_point()
+{
+  real_device="$1"
+  cat /proc/mounts | while read -r line; do
+    set -f
+    set -- $line
+    set +f
+    if [ "$1" = "$real_device" -a "$3" = "vfat" ]; then
+      echo "$2"
+      break
+    fi
+  done
+}
+
+# Return all devices that are a valid ESP
+usable_efi_system_partitions()
+{
+  local last_partition path partition partition_id
+  local ID_PART_ENTRY_TYPE ID_PART_ENTRY_SCHEME
+
+  last_partition=
+  (
+  for partition in /dev/disk/by-id/*; do
+    eval "$(udevadm info -q property -n "$partition" | grep -E '^ID_PART_ENTRY_(TYPE|SCHEME)=')"
+    if [ -z "$ID_PART_ENTRY_TYPE" -o -z "$ID_PART_ENTRY_SCHEME" -o \
+    \( "$ID_PART_ENTRY_SCHEME" != gpt -a "$ID_PART_ENTRY_SCHEME" != dos \) -o \
+    \( "$ID_PART_ENTRY_SCHEME" = gpt -a "$ID_PART_ENTRY_TYPE" != c12a7328-f81f-11d2-ba4b-00a0c93ec93b \) -o \
+    \( "$ID_PART_ENTRY_SCHEME" = dos -a "$ID_PART_ENTRY_TYPE" != 0xef \) ]; then
+      continue
+    fi
+    # unify the partition id
+    partition_id="$(device_to_id "$partition" || true)"
+    real_device="$(readlink -f "$partition")"
+    path="$(find_mount_point $real_device)"
+    echo "$path:$partition_id"
+  done
+  ) | sort -t: -k2 -u
+}
+
+###############################################################################
+#                            MAGIC SCRIPT
+###############################################################################
+FALLBACK_MOUNTPOINT=/var/lib/grub/esp
+
+# Initial install/upgrade from /boot/efi?
+db_fget grub-efi/install_devices seen
+seen="$RET"
+
+# Get configured value
+question=grub-efi/install_devices
+priority=high
+db_get grub-efi/install_devices
+valid=1
+
+# We either migrate /boot/efi over, or we check if we have invalid devices
+if [ -z "$RET" ] && [ "$seen" != "true" ]; then
+  echo "Trying to migrate /boot/efi into esp config"
+  esp="$(get_mounted_device /boot/efi)"
+  if [ "$esp" ]; then
+    esp="$(device_to_id "$esp")"
+  fi
+  if [ "$esp" ]; then
+    db_set grub-efi/install_devices "$esp"
+    db_fset grub-efi/install_devices seen true
+    RET="$esp"
+  fi
+else
+  for device in $RET; do
+    if [ ! -e "${device%,}" ]; then
+      valid=0
+      break
+    fi
+  done
+fi
+
+# If /boot/efi points to a device that's not in the list, trigger the
+# install_devices_disks_changed prompt below, but add the device behind
+# /boot/efi to the defaults.
+boot_efi_device=$(get_mounted_device /boot/efi || true)
+if [ "$boot_efi_device" ]; then
+  for device in $RET; do
+    device="${device%,}"
+    real_device="$(readlink -f "$device" || true)"
+    if [ "$real_device" = "$boot_efi_device" ]; then
+      boot_efi_device=""
+      break
+    fi
+  done
+
+  if [ "$boot_efi_device" ]; then
+    boot_efi_device="$(device_to_id "$boot_efi_device" || true)"
+    if [ "$RET" ]; then
+      RET="$RET, $boot_efi_device"
+    else
+      RET="$boot_efi_device"
+    fi
+    valid=0
+  fi
+fi
+
+
+if [ "$valid" = 0 ]; then
+  question=grub-efi/install_devices_disks_changed
+  priority=critical
+  db_set "$question" "$RET"
+  db_fset "$question" seen false
+  db_fset grub-efi/install_devices_empty seen false
+fi
+
+while :; do
+  ids=
+  descriptions=
+  partitions="$(usable_efi_system_partitions)"
+
+  for partition_pair in $partitions; do
+    partition_id="${partition_pair#*:}"
+    device="${partition_id%%-part*}"
+    ids="${ids:+$ids, }$partition_id"
+    describe_efi_system_partition "$(readlink -f "$device")" "$(readlink -f "$partition_id")" "$partition_id" "$(get_mountpoint "${partition_pair%%:*}")"
+    RET="$(printf %s "$RET" | sed 's/,/\\,/g')"
+    descriptions="${descriptions:+$descriptions, }$RET"
+  done
+
+  db_subst "$question" RAW_CHOICES "$ids"
+  db_subst "$question" CHOICES "$descriptions"
+  db_input "$priority" "$question" || true
+  db_go
+  db_get "$question"
+
+
+  # Run the installer
+  failed_devices=
+  for i in `echo $RET | sed -e 's/, / /g'` ; do
+    real_device="$(readlink -f "$i")"
+    mntpoint=$(find_mount_point $real_device)
+    if [ -z "$mntpoint" ]; then
+      mntpoint=$FALLBACK_MOUNTPOINT
+      mount $real_device $mntpoint
+    fi
+    echo "Installing grub to $mntpoint." >&2
+    if _UBUNTU_ALTERNATIVE_ESPS="$RET" grub-install --efi-directory=$mntpoint "$@" ; then
+      # We just installed GRUB 2; then also generate grub.cfg.
+      touch /boot/grub/grub.cfg
+    else
+      failed_devices="$failed_devices $real_device"
+    fi
+
+    if [ "$mntpoint" = "$FALLBACK_MOUNTPOINT" ]; then
+      umount $mntpoint
+    fi
+  done
+
+  if [ "$question" != grub-efi/install_devices ] && [ "$RET" ]; then
+    # XXX cjwatson 2019-02-26: The description of
+    # grub-efi/install_devices_disks_changed ought to explain that
+    # selecting no devices will leave the configuration unchanged
+    # so that you'll be prompted again next time, but it's a bit
+    # close to the Debian 10 release to be introducing new
+    # translatable text.  For now, it should be sufficient to
+    # avoid losing configuration data.
+    db_set grub-efi/install_devices "$RET"
+    db_fset grub-efi/install_devices seen true
+  fi
+
+  if [ "$failed_devices" ]; then
+    db_subst grub-efi/install_devices_failed FAILED_DEVICES "$failed_devices"
+    db_fset grub-efi/install_devices_failed seen false
+    if db_input critical grub-efi/install_devices_failed; then
+      db_go
+      db_get grub-efi/install_devices_failed
+      if [ "$RET" = true ]; then
+        break
+      else
+        db_fset "$question" seen false
+        db_fset grub-efi/install_devices_failed seen false
+        continue
+      fi
+    else
+      exit 1 # noninteractive
+    fi
+  fi
+
+  db_get "$question"
+  if [ -z "$RET" ]; then
+    # Reset the seen flag if the current answer is false, since
+    # otherwise we'll loop with no indication of why.
+    db_get grub-efi/install_devices_empty
+    if [ "$RET" = false ]; then
+      db_fset grub-efi/install_devices_empty seen false
+    fi
+    if db_input critical grub-efi/install_devices_empty; then
+      db_go
+      db_get grub-efi/install_devices_empty
+      if [ "$RET" = true ]; then
+        break
+      else
+        db_fset "$question" seen false
+        db_fset grub-efi/install_devices_empty seen false
+      fi
+    else
+      # if question was seen we are done
+      # Otherwise, abort
+      db_fget grub-efi/install_devices_empty seen
+      if [ "$RET" = true ]; then
+        break
+      else
+        exit 1
+      fi
+    fi
+  else
+    break
+  fi
+done
diff --git a/debian/patches/0074-uefi-firmware-rename-fwsetup-menuentry-to-UEFI-Firmw.patch b/debian/patches/0074-uefi-firmware-rename-fwsetup-menuentry-to-UEFI-Firmw.patch
new file mode 100644
index 0000000..20dbfb4
--- /dev/null
+++ b/debian/patches/0074-uefi-firmware-rename-fwsetup-menuentry-to-UEFI-Firmw.patch
@@ -0,0 +1,26 @@
+From 7bae32b384bf0129a980b77447e21abb4024f693 Mon Sep 17 00:00:00 2001
+From: Dimitri John Ledkov <xnox@ubuntu.com>
+Date: Mon, 24 Feb 2020 20:29:53 +0000
+Subject: uefi-firmware: rename fwsetup menuentry to UEFI Firmware Settings
+
+LP: #1864547
+---
+ util/grub.d/30_uefi-firmware.in | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/util/grub.d/30_uefi-firmware.in b/util/grub.d/30_uefi-firmware.in
+index 3c9f533d8c..b072d219f6 100644
+--- a/util/grub.d/30_uefi-firmware.in
++++ b/util/grub.d/30_uefi-firmware.in
+@@ -32,9 +32,9 @@ OsIndications="$efi_vars_dir/OsIndicationsSupported-$EFI_GLOBAL_VARIABLE/data"
+ 
+ if [ -e "$OsIndications" ] && \
+    [ "$(( $(printf 0x%x \'"$(cat $OsIndications | cut -b1)") & 1 ))" = 1 ]; then
+-  LABEL="System setup"
++  LABEL="UEFI Firmware Settings"
+ 
+-  gettext_printf "Adding boot menu entry for EFI firmware configuration\n" >&2
++  gettext_printf "Adding boot menu entry for UEFI Firmware Settings\n" >&2
+ 
+   onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
+ 
diff --git a/debian/patches/0075-smbios-Add-a-linux-argument-to-apply-linux-modalias-.patch b/debian/patches/0075-smbios-Add-a-linux-argument-to-apply-linux-modalias-.patch
new file mode 100644
index 0000000..3f8f67c
--- /dev/null
+++ b/debian/patches/0075-smbios-Add-a-linux-argument-to-apply-linux-modalias-.patch
@@ -0,0 +1,86 @@
+From 484c805e1361fd010e0c3e2c44585f5f7e3899c1 Mon Sep 17 00:00:00 2001
+From: Julian Andres Klode <julian.klode@canonical.com>
+Date: Tue, 3 Mar 2020 16:06:34 +0100
+Subject: smbios: Add a --linux argument to apply linux modalias-like filtering
+
+Linux creates modalias strings by filtering out non-ASCII, space,
+and colon characters. Provide an option that does the same filtering
+so people can create a modalias string in GRUB, and then match their
+modalias patterns against it.
+
+Signed-off-by: Julian Andres Klode <julian.klode@canonical.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Origin: upstream, https://git.savannah.gnu.org/cgit/grub.git/commit/?id=87049f9716fb095aecb595fb8f45497bbbb1b4a2
+---
+ grub-core/commands/smbios.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/grub-core/commands/smbios.c b/grub-core/commands/smbios.c
+index 7a6a391fc1..1a9086ddd4 100644
+--- a/grub-core/commands/smbios.c
++++ b/grub-core/commands/smbios.c
+@@ -64,6 +64,21 @@ grub_smbios_get_eps3 (void)
+   return eps;
+ }
+ 
++static char *
++linux_string (const char *value)
++{
++  char *out = grub_malloc( grub_strlen (value) + 1);
++  const char *src = value;
++  char *dst = out;
++
++  for (; *src; src++)
++    if (*src > ' ' && *src < 127 && *src != ':')
++      *dst++ = *src;
++
++  *dst = 0;
++  return out;
++}
++
+ /*
+  * These functions convert values from the various SMBIOS structure field types
+  * into a string formatted to be returned to the user.  They expect that the
+@@ -176,6 +191,7 @@ static const struct {
+ /* List command options, with structure field getters ordered as above. */
+ #define FIRST_GETTER_OPT (3)
+ #define SETTER_OPT (FIRST_GETTER_OPT + ARRAY_SIZE(field_extractors))
++#define LINUX_OPT (FIRST_GETTER_OPT + ARRAY_SIZE(field_extractors) + 1)
+ 
+ static const struct grub_arg_option options[] = {
+   {"type",       't', 0, N_("Match structures with the given type."),
+@@ -198,6 +214,8 @@ static const struct grub_arg_option options[] = {
+                          N_("offset"), ARG_TYPE_INT},
+   {"set",       '\0', 0, N_("Store the value in the given variable name."),
+                          N_("variable"), ARG_TYPE_STRING},
++  {"linux",     '\0', 0, N_("Filter the result like linux does."),
++                         N_("variable"), ARG_TYPE_NONE},
+   {0, 0, 0, 0, 0, 0}
+ };
+ 
+@@ -261,6 +279,7 @@ grub_cmd_smbios (grub_extcmd_context_t ctxt,
+ 
+   const grub_uint8_t *structure;
+   const char *value;
++  char *modified_value = NULL;
+   grub_int32_t option;
+   grub_int8_t field_type = -1;
+   grub_uint8_t i;
+@@ -334,12 +353,17 @@ grub_cmd_smbios (grub_extcmd_context_t ctxt,
+     return grub_error (GRUB_ERR_IO,
+                        N_("failed to retrieve the structure field"));
+ 
++  if (state[LINUX_OPT].set)
++    value = modified_value = linux_string (value);
++
+   /* Store or print the formatted value. */
+   if (state[SETTER_OPT].set)
+     grub_env_set (state[SETTER_OPT].arg, value);
+   else
+     grub_printf ("%s\n", value);
+ 
++  grub_free(modified_value);
++
+   return GRUB_ERR_NONE;
+ }
+ 
diff --git a/debian/patches/0076-ubuntu-Make-the-linux-command-in-EFI-grub-always-try.patch b/debian/patches/0076-ubuntu-Make-the-linux-command-in-EFI-grub-always-try.patch
new file mode 100644
index 0000000..8460c3c
--- /dev/null
+++ b/debian/patches/0076-ubuntu-Make-the-linux-command-in-EFI-grub-always-try.patch
@@ -0,0 +1,118 @@
+From 80b0e6a9375628f209b96173ce0a3af70060131c Mon Sep 17 00:00:00 2001
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Wed, 11 Mar 2020 16:46:00 +0100
+Subject: ubuntu: Make the linux command in EFI grub always try EFI handover
+
+The previous implementation only boots via the EFI handover protocol when
+secure boot is enabled. This means that disabling secure boot breaks some
+features that depend on the kernel being booted via the EFI handover entry
+point, such as retrieval of the TCG event log.
+
+Update the linux command to always attempt to defer to linuxefi in EFI grub
+builds, regardless of whether secure boot is enabled or not. This also allows
+a fallback to the non-EFI handover path on kernels that don't support it, but
+only if secure boot is disabled.
+---
+ grub-core/loader/i386/efi/linux.c | 14 +++++----
+ grub-core/loader/i386/linux.c     | 47 +++++++++++++++++--------------
+ 2 files changed, 35 insertions(+), 26 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 6b6aef87f7..fe3ca2c596 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -27,6 +27,7 @@
+ #include <grub/lib/cmdline.h>
+ #include <grub/efi/efi.h>
+ #include <grub/efi/linux.h>
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -195,12 +196,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-  rc = grub_linuxefi_secure_validate (kernel, filelen);
+-  if (rc < 0)
++  if (grub_efi_secure_boot ())
+     {
+-      grub_error (GRUB_ERR_ACCESS_DENIED, N_("%s has invalid signature"),
+-		  argv[0]);
+-      goto fail;
++      rc = grub_linuxefi_secure_validate (kernel, filelen);
++      if (rc < 0)
++	{
++	  grub_error (GRUB_ERR_ACCESS_DENIED, N_("%s has invalid signature"),
++		      argv[0]);
++	  goto fail;
++	}
+     }
+ 
+   params = grub_efi_allocate_pages_max (0x3fffffff,
+diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
+index 4328bcbdb0..991eb29db9 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -658,35 +658,40 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+ #ifdef GRUB_MACHINE_EFI
+   using_linuxefi = 0;
+-  if (grub_efi_secure_boot ())
+-    {
+-      /* linuxefi requires a successful signature check and then hand over
+-	 to the kernel without calling ExitBootServices. */
+-      grub_dl_t mod;
+-      grub_command_t linuxefi_cmd;
+ 
+-      grub_dprintf ("linux", "Secure Boot enabled: trying linuxefi\n");
++  grub_dl_t mod;
++  grub_command_t linuxefi_cmd;
++
++  grub_dprintf ("linux", "Trying linuxefi\n");
+ 
+-      mod = grub_dl_load ("linuxefi");
+-      if (mod)
++  mod = grub_dl_load ("linuxefi");
++  if (mod)
++    {
++      grub_dl_ref (mod);
++      linuxefi_cmd = grub_command_find ("linuxefi");
++      initrdefi_cmd = grub_command_find ("initrdefi");
++      if (linuxefi_cmd && initrdefi_cmd)
+ 	{
+-	  grub_dl_ref (mod);
+-	  linuxefi_cmd = grub_command_find ("linuxefi");
+-	  initrdefi_cmd = grub_command_find ("initrdefi");
+-	  if (linuxefi_cmd && initrdefi_cmd)
++	  (linuxefi_cmd->func) (linuxefi_cmd, argc, argv);
++	  if (grub_errno == GRUB_ERR_NONE)
++	    {
++	      grub_dprintf ("linux", "Handing off to linuxefi\n");
++	      using_linuxefi = 1;
++	      return GRUB_ERR_NONE;
++	    }
++	  else if (grub_efi_secure_boot ())
+ 	    {
+-	      (linuxefi_cmd->func) (linuxefi_cmd, argc, argv);
+-	      if (grub_errno == GRUB_ERR_NONE)
+-		{
+-		  grub_dprintf ("linux", "Handing off to linuxefi\n");
+-		  using_linuxefi = 1;
+-		  return GRUB_ERR_NONE;
+-		}
+-	      grub_dprintf ("linux", "linuxefi failed (%d)\n", grub_errno);
++	      grub_dprintf ("linux", "linuxefi failed and secure boot is enabled (%d)\n", grub_errno);
+ 	      goto fail;
+ 	    }
+ 	}
+     }
++
++  if (grub_efi_secure_boot ())
++    {
++      grub_dprintf("linux", "Unable to hand off to linuxefi and secure boot is enabled\n");
++      goto fail;
++    }
+ #endif
+ 
+   if (argc == 0)
diff --git a/debian/patches/0077-ubuntu-Update-the-linux-boot-protocol-version-check.patch b/debian/patches/0077-ubuntu-Update-the-linux-boot-protocol-version-check.patch
new file mode 100644
index 0000000..dfd3ee8
--- /dev/null
+++ b/debian/patches/0077-ubuntu-Update-the-linux-boot-protocol-version-check.patch
@@ -0,0 +1,25 @@
+From f59fbf2d6ae70d8872d8b680cfccb6e139410944 Mon Sep 17 00:00:00 2001
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Wed, 11 Mar 2020 16:46:41 +0100
+Subject: ubuntu: Update the linux boot protocol version check.
+
+The EFI implementation of grub_cmd_linux makes use of xloadflags which was
+introduced in to version 2.12 of the kernel's boot protocol, so update the
+check accordingly.
+---
+ grub-core/loader/i386/efi/linux.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index fe3ca2c596..2929da7a29 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -245,7 +245,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+     }
+ 
+   grub_dprintf ("linuxefi", "checking lh->version\n");
+-  if (lh->version < grub_cpu_to_le16 (0x020b))
++  if (lh->version < grub_cpu_to_le16 (0x020c))
+     {
+       grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
+       goto fail;
diff --git a/debian/patches/0081-yylex-Make-lexer-fatal-errors-actually-be-fatal.patch b/debian/patches/0081-yylex-Make-lexer-fatal-errors-actually-be-fatal.patch
new file mode 100644
index 0000000..5ce30a2
--- /dev/null
+++ b/debian/patches/0081-yylex-Make-lexer-fatal-errors-actually-be-fatal.patch
@@ -0,0 +1,66 @@
+From e25ff4f02fae2c006408a8fa1283320cd81ff87d Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 15 Apr 2020 15:45:02 -0400
+Subject: yylex: Make lexer fatal errors actually be fatal
+
+When presented with a command that can't be tokenized to anything
+smaller than YYLMAX characters, the parser calls YY_FATAL_ERROR(errmsg),
+expecting that will stop further processing, as such:
+
+  #define YY_DO_BEFORE_ACTION \
+        yyg->yytext_ptr = yy_bp; \
+        yyleng = (int) (yy_cp - yy_bp); \
+        yyg->yy_hold_char = *yy_cp; \
+        *yy_cp = '\0'; \
+        if ( yyleng >= YYLMAX ) \
+                YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \
+        yy_flex_strncpy( yytext, yyg->yytext_ptr, yyleng + 1 , yyscanner); \
+        yyg->yy_c_buf_p = yy_cp;
+
+The code flex generates expects that YY_FATAL_ERROR() will either return
+for it or do some form of longjmp(), or handle the error in some way at
+least, and so the strncpy() call isn't in an "else" clause, and thus if
+YY_FATAL_ERROR() is *not* actually fatal, it does the call with the
+questionable limit, and predictable results ensue.
+
+Unfortunately, our implementation of YY_FATAL_ERROR() is:
+
+   #define YY_FATAL_ERROR(msg)                     \
+     do {                                          \
+       grub_printf (_("fatal error: %s\n"), _(msg));     \
+     } while (0)
+
+The same pattern exists in yyless(), and similar problems exist in users
+of YY_INPUT(), several places in the main parsing loop,
+yy_get_next_buffer(), yy_load_buffer_state(), yyensure_buffer_stack,
+yy_scan_buffer(), etc.
+
+All of these callers expect YY_FATAL_ERROR() to actually be fatal, and
+the things they do if it returns after calling it are wildly unsafe.
+
+Fixes: CVE-2020-10713
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/script/yylex.l | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l
+index 7b44c37b76..b7203c8230 100644
+--- a/grub-core/script/yylex.l
++++ b/grub-core/script/yylex.l
+@@ -37,11 +37,11 @@
+ 
+ /* 
+  * As we don't have access to yyscanner, we cannot do much except to
+- * print the fatal error.
++ * print the fatal error and exit.
+  */
+ #define YY_FATAL_ERROR(msg)                     \
+   do {                                          \
+-    grub_printf (_("fatal error: %s\n"), _(msg));     \
++    grub_fatal (_("fatal error: %s\n"), _(msg));\
+   } while (0)
+ 
+ #define COPY(str, hint)                         \
diff --git a/debian/patches/0082-safemath-Add-some-arithmetic-primitives-that-check-f.patch b/debian/patches/0082-safemath-Add-some-arithmetic-primitives-that-check-f.patch
new file mode 100644
index 0000000..b87a7fb
--- /dev/null
+++ b/debian/patches/0082-safemath-Add-some-arithmetic-primitives-that-check-f.patch
@@ -0,0 +1,120 @@
+From daa399d191529cbbe465cfe3ecf5e90cada76786 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 15 Jun 2020 10:58:42 -0400
+Subject: safemath: Add some arithmetic primitives that check for overflow
+
+This adds a new header, include/grub/safemath.h, that includes easy to
+use wrappers for __builtin_{add,sub,mul}_overflow() declared like:
+
+  bool OP(a, b, res)
+
+where OP is grub_add, grub_sub or grub_mul. OP() returns true in the
+case where the operation would overflow and res is not modified.
+Otherwise, false is returned and the operation is executed.
+
+These arithmetic primitives require newer compiler versions. So, bump
+these requirements in the INSTALL file too.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ INSTALL                 | 22 ++--------------------
+ include/grub/compiler.h |  8 ++++++++
+ include/grub/safemath.h | 37 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 47 insertions(+), 20 deletions(-)
+ create mode 100644 include/grub/safemath.h
+
+diff --git a/INSTALL b/INSTALL
+index 342c158e91..991479b521 100644
+--- a/INSTALL
++++ b/INSTALL
+@@ -11,27 +11,9 @@ GRUB depends on some software packages installed into your system. If
+ you don't have any of them, please obtain and install them before
+ configuring the GRUB.
+ 
+-* GCC 4.1.3 or later
+-  Note: older versions may work but support is limited
+-
+-  Experimental support for clang 3.3 or later (results in much bigger binaries)
++* GCC 5.1.0 or later
++  Experimental support for clang 3.8.0 or later (results in much bigger binaries)
+   for i386, x86_64, arm (including thumb), arm64, mips(el), powerpc, sparc64
+-  Note: clang 3.2 or later works for i386 and x86_64 targets but results in
+-        much bigger binaries.
+-	earlier versions not tested
+-  Note: clang 3.2 or later works for arm
+-	earlier versions not tested
+-  Note: clang on arm64 is not supported due to
+-	https://llvm.org/bugs/show_bug.cgi?id=26030
+-  Note: clang 3.3 or later works for mips(el)
+-	earlier versions fail to generate .reginfo and hence gprel relocations
+-	fail.
+-  Note: clang 3.2 or later works for powerpc
+-	earlier versions not tested
+-  Note: clang 3.5 or later works for sparc64
+-        earlier versions return "error: unable to interface with target machine"
+-  Note: clang has no support for ia64 and hence you can't compile GRUB
+-	for ia64 with clang
+ * GNU Make
+ * GNU Bison 2.3 or later
+ * GNU gettext 0.17 or later
+diff --git a/include/grub/compiler.h b/include/grub/compiler.h
+index c9e1d7a73d..8f3be3ae70 100644
+--- a/include/grub/compiler.h
++++ b/include/grub/compiler.h
+@@ -48,4 +48,12 @@
+ #  define WARN_UNUSED_RESULT
+ #endif
+ 
++#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__)
++#  define CLANG_PREREQ(maj,min) \
++          ((__clang_major__ > (maj)) || \
++	   (__clang_major__ == (maj) && __clang_minor__ >= (min)))
++#else
++#  define CLANG_PREREQ(maj,min) 0
++#endif
++
+ #endif /* ! GRUB_COMPILER_HEADER */
+diff --git a/include/grub/safemath.h b/include/grub/safemath.h
+new file mode 100644
+index 0000000000..c17b89bba1
+--- /dev/null
++++ b/include/grub/safemath.h
+@@ -0,0 +1,37 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2020  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/>.
++ *
++ *  Arithmetic operations that protect against overflow.
++ */
++
++#ifndef GRUB_SAFEMATH_H
++#define GRUB_SAFEMATH_H 1
++
++#include <grub/compiler.h>
++
++/* These appear in gcc 5.1 and clang 3.8. */
++#if GNUC_PREREQ(5, 1) || CLANG_PREREQ(3, 8)
++
++#define grub_add(a, b, res)	__builtin_add_overflow(a, b, res)
++#define grub_sub(a, b, res)	__builtin_sub_overflow(a, b, res)
++#define grub_mul(a, b, res)	__builtin_mul_overflow(a, b, res)
++
++#else
++#error gcc 5.1 or newer or clang 3.8 or newer is required
++#endif
++
++#endif /* GRUB_SAFEMATH_H */
diff --git a/debian/patches/0083-calloc-Make-sure-we-always-have-an-overflow-checking.patch b/debian/patches/0083-calloc-Make-sure-we-always-have-an-overflow-checking.patch
new file mode 100644
index 0000000..6238eee
--- /dev/null
+++ b/debian/patches/0083-calloc-Make-sure-we-always-have-an-overflow-checking.patch
@@ -0,0 +1,239 @@
+From 5cffb625b814199eff98b73c34a92879b17fd5ac Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 15 Jun 2020 12:15:29 -0400
+Subject: calloc: Make sure we always have an overflow-checking calloc()
+ available
+
+This tries to make sure that everywhere in this source tree, we always have
+an appropriate version of calloc() (i.e. grub_calloc(), xcalloc(), etc.)
+available, and that they all safely check for overflow and return NULL when
+it would occur.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/kern/emu/misc.c          | 12 +++++++++
+ grub-core/kern/emu/mm.c            | 10 ++++++++
+ grub-core/kern/mm.c                | 40 ++++++++++++++++++++++++++++++
+ grub-core/lib/libgcrypt_wrap/mem.c | 11 ++++++--
+ grub-core/lib/posix_wrap/stdlib.h  |  8 +++++-
+ include/grub/emu/misc.h            |  1 +
+ include/grub/mm.h                  |  6 +++++
+ 7 files changed, 85 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c
+index 65db79baa1..dfd8a8ec48 100644
+--- a/grub-core/kern/emu/misc.c
++++ b/grub-core/kern/emu/misc.c
+@@ -85,6 +85,18 @@ grub_util_error (const char *fmt, ...)
+   exit (1);
+ }
+ 
++void *
++xcalloc (grub_size_t nmemb, grub_size_t size)
++{
++  void *p;
++
++  p = calloc (nmemb, size);
++  if (!p)
++    grub_util_error ("%s", _("out of memory"));
++
++  return p;
++}
++
+ void *
+ xmalloc (grub_size_t size)
+ {
+diff --git a/grub-core/kern/emu/mm.c b/grub-core/kern/emu/mm.c
+index f262e95e38..145b01d371 100644
+--- a/grub-core/kern/emu/mm.c
++++ b/grub-core/kern/emu/mm.c
+@@ -25,6 +25,16 @@
+ #include <string.h>
+ #include <grub/i18n.h>
+ 
++void *
++grub_calloc (grub_size_t nmemb, grub_size_t size)
++{
++  void *ret;
++  ret = calloc (nmemb, size);
++  if (!ret)
++    grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++  return ret;
++}
++
+ void *
+ grub_malloc (grub_size_t size)
+ {
+diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
+index ee88ff6118..f2822a8364 100644
+--- a/grub-core/kern/mm.c
++++ b/grub-core/kern/mm.c
+@@ -67,8 +67,10 @@
+ #include <grub/dl.h>
+ #include <grub/i18n.h>
+ #include <grub/mm_private.h>
++#include <grub/safemath.h>
+ 
+ #ifdef MM_DEBUG
++# undef grub_calloc
+ # undef grub_malloc
+ # undef grub_zalloc
+ # undef grub_realloc
+@@ -375,6 +377,30 @@ grub_memalign (grub_size_t align, grub_size_t size)
+   return 0;
+ }
+ 
++/*
++ * Allocate NMEMB instances of SIZE bytes and return the pointer, or error on
++ * integer overflow.
++ */
++void *
++grub_calloc (grub_size_t nmemb, grub_size_t size)
++{
++  void *ret;
++  grub_size_t sz = 0;
++
++  if (grub_mul (nmemb, size, &sz))
++    {
++      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
++      return NULL;
++    }
++
++  ret = grub_memalign (0, sz);
++  if (!ret)
++    return NULL;
++
++  grub_memset (ret, 0, sz);
++  return ret;
++}
++
+ /* Allocate SIZE bytes and return the pointer.  */
+ void *
+ grub_malloc (grub_size_t size)
+@@ -561,6 +587,20 @@ grub_mm_dump (unsigned lineno)
+   grub_printf ("\n");
+ }
+ 
++void *
++grub_debug_calloc (const char *file, int line, grub_size_t nmemb, grub_size_t size)
++{
++  void *ptr;
++
++  if (grub_mm_debug)
++    grub_printf ("%s:%d: calloc (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE ") = ",
++		 file, line, size);
++  ptr = grub_calloc (nmemb, size);
++  if (grub_mm_debug)
++    grub_printf ("%p\n", ptr);
++  return ptr;
++}
++
+ void *
+ grub_debug_malloc (const char *file, int line, grub_size_t size)
+ {
+diff --git a/grub-core/lib/libgcrypt_wrap/mem.c b/grub-core/lib/libgcrypt_wrap/mem.c
+index beeb661a3c..74c6eafe52 100644
+--- a/grub-core/lib/libgcrypt_wrap/mem.c
++++ b/grub-core/lib/libgcrypt_wrap/mem.c
+@@ -4,6 +4,7 @@
+ #include <grub/crypto.h>
+ #include <grub/dl.h>
+ #include <grub/env.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -36,7 +37,10 @@ void *
+ gcry_xcalloc (size_t n, size_t m)
+ {
+   void *ret;
+-  ret = grub_zalloc (n * m);
++  size_t sz;
++  if (grub_mul (n, m, &sz))
++    grub_fatal ("gcry_xcalloc would overflow");
++  ret = grub_zalloc (sz);
+   if (!ret)
+     grub_fatal ("gcry_xcalloc failed");
+   return ret;
+@@ -56,7 +60,10 @@ void *
+ gcry_xcalloc_secure (size_t n, size_t m)
+ {
+   void *ret;
+-  ret = grub_zalloc (n * m);
++  size_t sz;
++  if (grub_mul (n, m, &sz))
++    grub_fatal ("gcry_xcalloc would overflow");
++  ret = grub_zalloc (sz);
+   if (!ret)
+     grub_fatal ("gcry_xcalloc failed");
+   return ret;
+diff --git a/grub-core/lib/posix_wrap/stdlib.h b/grub-core/lib/posix_wrap/stdlib.h
+index 3b46f47ff5..7a8d385e97 100644
+--- a/grub-core/lib/posix_wrap/stdlib.h
++++ b/grub-core/lib/posix_wrap/stdlib.h
+@@ -21,6 +21,7 @@
+ 
+ #include <grub/mm.h>
+ #include <grub/misc.h>
++#include <grub/safemath.h>
+ 
+ static inline void 
+ free (void *ptr)
+@@ -37,7 +38,12 @@ malloc (grub_size_t size)
+ static inline void *
+ calloc (grub_size_t size, grub_size_t nelem)
+ {
+-  return grub_zalloc (size * nelem);
++  grub_size_t sz;
++
++  if (grub_mul (size, nelem, &sz))
++    return NULL;
++
++  return grub_zalloc (sz);
+ }
+ 
+ static inline void *
+diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h
+index ce464cfd00..ff9c48a649 100644
+--- a/include/grub/emu/misc.h
++++ b/include/grub/emu/misc.h
+@@ -47,6 +47,7 @@ grub_util_device_is_mapped (const char *dev);
+ #define GRUB_HOST_PRIuLONG_LONG "llu"
+ #define GRUB_HOST_PRIxLONG_LONG "llx"
+ 
++void * EXPORT_FUNC(xcalloc) (grub_size_t nmemb, grub_size_t size) WARN_UNUSED_RESULT;
+ void * EXPORT_FUNC(xmalloc) (grub_size_t size) WARN_UNUSED_RESULT;
+ void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) WARN_UNUSED_RESULT;
+ char * EXPORT_FUNC(xstrdup) (const char *str) WARN_UNUSED_RESULT;
+diff --git a/include/grub/mm.h b/include/grub/mm.h
+index 28e2e53eb3..9c38dd3ca5 100644
+--- a/include/grub/mm.h
++++ b/include/grub/mm.h
+@@ -29,6 +29,7 @@
+ #endif
+ 
+ void grub_mm_init_region (void *addr, grub_size_t size);
++void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size);
+ void *EXPORT_FUNC(grub_malloc) (grub_size_t size);
+ void *EXPORT_FUNC(grub_zalloc) (grub_size_t size);
+ void EXPORT_FUNC(grub_free) (void *ptr);
+@@ -48,6 +49,9 @@ extern int EXPORT_VAR(grub_mm_debug);
+ void grub_mm_dump_free (void);
+ void grub_mm_dump (unsigned lineno);
+ 
++#define grub_calloc(nmemb, size)	\
++  grub_debug_calloc (GRUB_FILE, __LINE__, nmemb, size)
++
+ #define grub_malloc(size)	\
+   grub_debug_malloc (GRUB_FILE, __LINE__, size)
+ 
+@@ -63,6 +67,8 @@ void grub_mm_dump (unsigned lineno);
+ #define grub_free(ptr)	\
+   grub_debug_free (GRUB_FILE, __LINE__, ptr)
+ 
++void *EXPORT_FUNC(grub_debug_calloc) (const char *file, int line,
++				      grub_size_t nmemb, grub_size_t size);
+ void *EXPORT_FUNC(grub_debug_malloc) (const char *file, int line,
+ 				      grub_size_t size);
+ void *EXPORT_FUNC(grub_debug_zalloc) (const char *file, int line,
diff --git a/debian/patches/0084-calloc-Use-calloc-at-most-places.patch b/debian/patches/0084-calloc-Use-calloc-at-most-places.patch
new file mode 100644
index 0000000..ac5217f
--- /dev/null
+++ b/debian/patches/0084-calloc-Use-calloc-at-most-places.patch
@@ -0,0 +1,1833 @@
+From 855173c18eab34ad93f21f5c509fe0e91bfd1c44 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 15 Jun 2020 12:26:01 -0400
+Subject: calloc: Use calloc() at most places
+
+This modifies most of the places we do some form of:
+
+  X = malloc(Y * Z);
+
+to use calloc(Y, Z) instead.
+
+Among other issues, this fixes:
+  - allocation of integer overflow in grub_png_decode_image_header()
+    reported by Chris Coulson,
+  - allocation of integer overflow in luks_recover_key()
+    reported by Chris Coulson,
+  - allocation of integer overflow in grub_lvm_detect()
+    reported by Chris Coulson.
+
+Fixes: CVE-2020-14308
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/bus/usb/usbhub.c                |  8 ++++----
+ grub-core/commands/efi/lsefisystab.c      |  3 ++-
+ grub-core/commands/legacycfg.c            |  6 +++---
+ grub-core/commands/menuentry.c            |  2 +-
+ grub-core/commands/nativedisk.c           |  2 +-
+ grub-core/commands/parttool.c             | 12 +++++++++---
+ grub-core/commands/regexp.c               |  2 +-
+ grub-core/commands/search_wrap.c          |  2 +-
+ grub-core/disk/diskfilter.c               |  4 ++--
+ grub-core/disk/ieee1275/ofdisk.c          |  2 +-
+ grub-core/disk/ldm.c                      | 14 +++++++-------
+ grub-core/disk/luks.c                     |  2 +-
+ grub-core/disk/lvm.c                      |  8 ++++----
+ grub-core/disk/xen/xendisk.c              |  2 +-
+ grub-core/efiemu/loadcore.c               |  2 +-
+ grub-core/efiemu/mm.c                     |  6 +++---
+ grub-core/font/font.c                     |  3 +--
+ grub-core/fs/affs.c                       |  6 +++---
+ grub-core/fs/btrfs.c                      |  6 +++---
+ grub-core/fs/hfs.c                        |  2 +-
+ grub-core/fs/hfsplus.c                    |  6 +++---
+ grub-core/fs/iso9660.c                    |  2 +-
+ grub-core/fs/ntfs.c                       |  4 ++--
+ grub-core/fs/sfs.c                        |  2 +-
+ grub-core/fs/tar.c                        |  2 +-
+ grub-core/fs/udf.c                        |  4 ++--
+ grub-core/fs/zfs/zfs.c                    |  4 ++--
+ grub-core/gfxmenu/gui_string_util.c       |  2 +-
+ grub-core/gfxmenu/widget-box.c            |  4 ++--
+ grub-core/io/gzio.c                       |  2 +-
+ grub-core/kern/efi/efi.c                  |  6 +++---
+ grub-core/kern/emu/hostdisk.c             |  2 +-
+ grub-core/kern/fs.c                       |  2 +-
+ grub-core/kern/misc.c                     |  2 +-
+ grub-core/kern/parser.c                   |  2 +-
+ grub-core/kern/uboot/uboot.c              |  2 +-
+ grub-core/lib/libgcrypt/cipher/ac.c       |  8 ++++----
+ grub-core/lib/libgcrypt/cipher/primegen.c |  4 ++--
+ grub-core/lib/libgcrypt/cipher/pubkey.c   |  4 ++--
+ grub-core/lib/priority_queue.c            |  2 +-
+ grub-core/lib/reed_solomon.c              |  7 +++----
+ grub-core/lib/relocator.c                 | 10 +++++-----
+ grub-core/lib/zstd/fse_decompress.c       |  2 +-
+ grub-core/loader/arm/linux.c              |  2 +-
+ grub-core/loader/efi/chainloader.c        |  2 +-
+ grub-core/loader/i386/bsdXX.c             |  2 +-
+ grub-core/loader/i386/xnu.c               |  4 ++--
+ grub-core/loader/macho.c                  |  2 +-
+ grub-core/loader/multiboot_elfxx.c        |  2 +-
+ grub-core/loader/xnu.c                    |  2 +-
+ grub-core/mmap/mmap.c                     |  4 ++--
+ grub-core/net/bootp.c                     |  2 +-
+ grub-core/net/dns.c                       | 10 +++++-----
+ grub-core/net/net.c                       |  4 ++--
+ grub-core/normal/charset.c                | 10 +++++-----
+ grub-core/normal/cmdline.c                | 14 +++++++-------
+ grub-core/normal/menu_entry.c             | 14 +++++++-------
+ grub-core/normal/menu_text.c              |  4 ++--
+ grub-core/normal/term.c                   |  4 ++--
+ grub-core/osdep/linux/getroot.c           |  6 +++---
+ grub-core/osdep/unix/config.c             |  2 +-
+ grub-core/osdep/windows/getroot.c         |  2 +-
+ grub-core/osdep/windows/hostdisk.c        |  4 ++--
+ grub-core/osdep/windows/init.c            |  2 +-
+ grub-core/osdep/windows/platform.c        |  4 ++--
+ grub-core/osdep/windows/relpath.c         |  2 +-
+ grub-core/partmap/gpt.c                   |  2 +-
+ grub-core/partmap/msdos.c                 |  2 +-
+ grub-core/script/execute.c                |  2 +-
+ grub-core/tests/fake_input.c              |  2 +-
+ grub-core/tests/video_checksum.c          |  6 +++---
+ grub-core/video/capture.c                 |  2 +-
+ grub-core/video/emu/sdl.c                 |  2 +-
+ grub-core/video/i386/pc/vga.c             |  2 +-
+ grub-core/video/readers/png.c             |  2 +-
+ include/grub/unicode.h                    |  4 ++--
+ util/getroot.c                            |  2 +-
+ util/grub-file.c                          |  2 +-
+ util/grub-fstest.c                        |  4 ++--
+ util/grub-install-common.c                |  2 +-
+ util/grub-install.c                       |  4 ++--
+ util/grub-mkimagexx.c                     |  6 ++----
+ util/grub-mkrescue.c                      |  4 ++--
+ util/grub-mkstandalone.c                  |  2 +-
+ util/grub-pe2elf.c                        | 12 +++++-------
+ util/grub-probe.c                         |  4 ++--
+ 86 files changed, 176 insertions(+), 175 deletions(-)
+
+diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c
+index 34a7ff1b5f..a06cce302d 100644
+--- a/grub-core/bus/usb/usbhub.c
++++ b/grub-core/bus/usb/usbhub.c
+@@ -149,8 +149,8 @@ grub_usb_add_hub (grub_usb_device_t dev)
+   grub_usb_set_configuration (dev, 1);
+ 
+   dev->nports = hubdesc.portcnt;
+-  dev->children = grub_zalloc (hubdesc.portcnt * sizeof (dev->children[0]));
+-  dev->ports = grub_zalloc (dev->nports * sizeof (dev->ports[0]));
++  dev->children = grub_calloc (hubdesc.portcnt, sizeof (dev->children[0]));
++  dev->ports = grub_calloc (dev->nports, sizeof (dev->ports[0]));
+   if (!dev->children || !dev->ports)
+     {
+       grub_free (dev->children);
+@@ -268,8 +268,8 @@ grub_usb_controller_dev_register_iter (grub_usb_controller_t controller, void *d
+ 
+   /* Query the number of ports the root Hub has.  */
+   hub->nports = controller->dev->hubports (controller);
+-  hub->devices = grub_zalloc (sizeof (hub->devices[0]) * hub->nports);
+-  hub->ports = grub_zalloc (sizeof (hub->ports[0]) * hub->nports);
++  hub->devices = grub_calloc (hub->nports, sizeof (hub->devices[0]));
++  hub->ports = grub_calloc (hub->nports, sizeof (hub->ports[0]));
+   if (!hub->devices || !hub->ports)
+     {
+       grub_free (hub->devices);
+diff --git a/grub-core/commands/efi/lsefisystab.c b/grub-core/commands/efi/lsefisystab.c
+index 902788250e..d29188efaf 100644
+--- a/grub-core/commands/efi/lsefisystab.c
++++ b/grub-core/commands/efi/lsefisystab.c
+@@ -73,7 +73,8 @@ grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)),
+     grub_printf ("Vendor: ");
+     
+     for (vendor_utf16 = st->firmware_vendor; *vendor_utf16; vendor_utf16++);
+-    vendor = grub_malloc (4 * (vendor_utf16 - st->firmware_vendor) + 1);
++    /* Allocate extra 3 bytes to simplify math. */
++    vendor = grub_calloc (4, vendor_utf16 - st->firmware_vendor + 1);
+     if (!vendor)
+       return grub_errno;
+     *grub_utf16_to_utf8 ((grub_uint8_t *) vendor, st->firmware_vendor,
+diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c
+index db7a8f0027..5e3ec0d5e4 100644
+--- a/grub-core/commands/legacycfg.c
++++ b/grub-core/commands/legacycfg.c
+@@ -314,7 +314,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
+   if (argc < 2)
+     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+ 
+-  cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1));
++  cutargs = grub_calloc (argc - 1, sizeof (cutargs[0]));
+   if (!cutargs)
+     return grub_errno;
+   cutargc = argc - 1;
+@@ -436,7 +436,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
+ 	    {
+ 	      char rbuf[3] = "-r";
+ 	      bsdargc = cutargc + 2;
+-	      bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc);
++	      bsdargs = grub_calloc (bsdargc, sizeof (bsdargs[0]));
+ 	      if (!bsdargs)
+ 		{
+ 		  err = grub_errno;
+@@ -559,7 +559,7 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused
+ 	return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
+ 			   "module");
+ 
+-      newargs = grub_malloc ((argc + 1) * sizeof (newargs[0]));
++      newargs = grub_calloc (argc + 1, sizeof (newargs[0]));
+       if (!newargs)
+ 	return grub_errno;
+       grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0]));
+diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c
+index 2c5363da7f..9164df744a 100644
+--- a/grub-core/commands/menuentry.c
++++ b/grub-core/commands/menuentry.c
+@@ -154,7 +154,7 @@ grub_normal_add_menu_entry (int argc, const char **args,
+     goto fail;
+ 
+   /* Save argc, args to pass as parameters to block arg later. */
+-  menu_args = grub_malloc (sizeof (char*) * (argc + 1));
++  menu_args = grub_calloc (argc + 1, sizeof (char *));
+   if (! menu_args)
+     goto fail;
+ 
+diff --git a/grub-core/commands/nativedisk.c b/grub-core/commands/nativedisk.c
+index 699447d11e..7c8f97f6ad 100644
+--- a/grub-core/commands/nativedisk.c
++++ b/grub-core/commands/nativedisk.c
+@@ -195,7 +195,7 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
+   else
+     path_prefix = prefix;
+ 
+-  mods = grub_malloc (argc * sizeof (mods[0]));
++  mods = grub_calloc (argc, sizeof (mods[0]));
+   if (!mods)
+     return grub_errno;
+ 
+diff --git a/grub-core/commands/parttool.c b/grub-core/commands/parttool.c
+index 22b46b1874..051e31320e 100644
+--- a/grub-core/commands/parttool.c
++++ b/grub-core/commands/parttool.c
+@@ -59,7 +59,13 @@ grub_parttool_register(const char *part_name,
+   for (nargs = 0; args[nargs].name != 0; nargs++);
+   cur->nargs = nargs;
+   cur->args = (struct grub_parttool_argdesc *)
+-    grub_malloc ((nargs + 1) * sizeof (struct grub_parttool_argdesc));
++    grub_calloc (nargs + 1, sizeof (struct grub_parttool_argdesc));
++  if (!cur->args)
++    {
++      grub_free (cur);
++      curhandle--;
++      return -1;
++    }
+   grub_memcpy (cur->args, args,
+ 	       (nargs + 1) * sizeof (struct grub_parttool_argdesc));
+ 
+@@ -257,7 +263,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
+ 	return err;
+       }
+ 
+-  parsed = (int *) grub_zalloc (argc * sizeof (int));
++  parsed = (int *) grub_calloc (argc, sizeof (int));
+ 
+   for (i = 1; i < argc; i++)
+     if (! parsed[i])
+@@ -290,7 +296,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
+ 	  }
+ 	ptool = cur;
+ 	pargs = (struct grub_parttool_args *)
+-	  grub_zalloc (ptool->nargs * sizeof (struct grub_parttool_args));
++	  grub_calloc (ptool->nargs, sizeof (struct grub_parttool_args));
+ 	for (j = i; j < argc; j++)
+ 	  if (! parsed[j])
+ 	    {
+diff --git a/grub-core/commands/regexp.c b/grub-core/commands/regexp.c
+index f00b184c81..4019164f36 100644
+--- a/grub-core/commands/regexp.c
++++ b/grub-core/commands/regexp.c
+@@ -116,7 +116,7 @@ grub_cmd_regexp (grub_extcmd_context_t ctxt, int argc, char **args)
+   if (ret)
+     goto fail;
+ 
+-  matches = grub_zalloc (sizeof (*matches) * (regex.re_nsub + 1));
++  matches = grub_calloc (regex.re_nsub + 1, sizeof (*matches));
+   if (! matches)
+     goto fail;
+ 
+diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c
+index d7fd26b940..47fc8eb996 100644
+--- a/grub-core/commands/search_wrap.c
++++ b/grub-core/commands/search_wrap.c
+@@ -122,7 +122,7 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
+     for (i = 0; state[SEARCH_HINT_BAREMETAL].args[i]; i++)
+       nhints++;
+ 
+-  hints = grub_malloc (sizeof (hints[0]) * nhints);
++  hints = grub_calloc (nhints, sizeof (hints[0]));
+   if (!hints)
+     return grub_errno;
+   j = 0;
+diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
+index c3b578acf2..68ca9e0be9 100644
+--- a/grub-core/disk/diskfilter.c
++++ b/grub-core/disk/diskfilter.c
+@@ -1134,7 +1134,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
+   array->lvs->segments->node_count = nmemb;
+   array->lvs->segments->raid_member_size = disk_size;
+   array->lvs->segments->nodes
+-    = grub_zalloc (nmemb * sizeof (array->lvs->segments->nodes[0]));
++    = grub_calloc (nmemb, sizeof (array->lvs->segments->nodes[0]));
+   array->lvs->segments->stripe_size = stripe_size;
+   for (i = 0; i < nmemb; i++)
+     {
+@@ -1226,7 +1226,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id,
+ 	  grub_partition_t p;
+ 	  for (p = disk->partition; p; p = p->parent)
+ 	    s++;
+-	  pv->partmaps = xmalloc (s * sizeof (pv->partmaps[0]));
++	  pv->partmaps = xcalloc (s, sizeof (pv->partmaps[0]));
+ 	  s = 0;
+ 	  for (p = disk->partition; p; p = p->parent)
+ 	    pv->partmaps[s++] = xstrdup (p->partmap->name);
+diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
+index f73257e66d..03674cb477 100644
+--- a/grub-core/disk/ieee1275/ofdisk.c
++++ b/grub-core/disk/ieee1275/ofdisk.c
+@@ -297,7 +297,7 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
+       /* Power machines documentation specify 672 as maximum SAS disks in
+          one system. Using a slightly larger value to be safe. */
+       table_size = 768;
+-      table = grub_malloc (table_size * sizeof (grub_uint64_t));
++      table = grub_calloc (table_size, sizeof (grub_uint64_t));
+ 
+       if (!table)
+         {
+diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
+index 2a22d2d6c1..e6323701ab 100644
+--- a/grub-core/disk/ldm.c
++++ b/grub-core/disk/ldm.c
+@@ -323,8 +323,8 @@ make_vg (grub_disk_t disk,
+ 	  lv->segments->type = GRUB_DISKFILTER_MIRROR;
+ 	  lv->segments->node_count = 0;
+ 	  lv->segments->node_alloc = 8;
+-	  lv->segments->nodes = grub_zalloc (sizeof (*lv->segments->nodes)
+-					     * lv->segments->node_alloc);
++	  lv->segments->nodes = grub_calloc (lv->segments->node_alloc,
++					     sizeof (*lv->segments->nodes));
+ 	  if (!lv->segments->nodes)
+ 	    goto fail2;
+ 	  ptr = vblk[i].dynamic;
+@@ -543,8 +543,8 @@ make_vg (grub_disk_t disk,
+ 	    {
+ 	      comp->segment_alloc = 8;
+ 	      comp->segment_count = 0;
+-	      comp->segments = grub_malloc (sizeof (*comp->segments)
+-					    * comp->segment_alloc);
++	      comp->segments = grub_calloc (comp->segment_alloc,
++					    sizeof (*comp->segments));
+ 	      if (!comp->segments)
+ 		goto fail2;
+ 	    }
+@@ -590,8 +590,8 @@ make_vg (grub_disk_t disk,
+ 		}
+ 	      comp->segments->node_count = read_int (ptr + 1, *ptr);
+ 	      comp->segments->node_alloc = comp->segments->node_count;
+-	      comp->segments->nodes = grub_zalloc (sizeof (*comp->segments->nodes)
+-						   * comp->segments->node_alloc);
++	      comp->segments->nodes = grub_calloc (comp->segments->node_alloc,
++						   sizeof (*comp->segments->nodes));
+ 	      if (!lv->segments->nodes)
+ 		goto fail2;
+ 	    }
+@@ -1017,7 +1017,7 @@ grub_util_ldm_embed (struct grub_disk *disk, unsigned int *nsectors,
+       *nsectors = lv->size;
+       if (*nsectors > max_nsectors)
+ 	*nsectors = max_nsectors;
+-      *sectors = grub_malloc (*nsectors * sizeof (**sectors));
++      *sectors = grub_calloc (*nsectors, sizeof (**sectors));
+       if (!*sectors)
+ 	return grub_errno;
+       for (i = 0; i < *nsectors; i++)
+diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
+index 86c50c6121..18b3a8bb1d 100644
+--- a/grub-core/disk/luks.c
++++ b/grub-core/disk/luks.c
+@@ -336,7 +336,7 @@ luks_recover_key (grub_disk_t source,
+ 	&& grub_be_to_cpu32 (header.keyblock[i].stripes) > max_stripes)
+       max_stripes = grub_be_to_cpu32 (header.keyblock[i].stripes);
+ 
+-  split_key = grub_malloc (keysize * max_stripes);
++  split_key = grub_calloc (keysize, max_stripes);
+   if (!split_key)
+     return grub_errno;
+ 
+diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
+index 7b265c780c..d1df640b31 100644
+--- a/grub-core/disk/lvm.c
++++ b/grub-core/disk/lvm.c
+@@ -173,7 +173,7 @@ grub_lvm_detect (grub_disk_t disk,
+      first one.  */
+ 
+   /* Allocate buffer space for the circular worst-case scenario. */
+-  metadatabuf = grub_malloc (2 * mda_size);
++  metadatabuf = grub_calloc (2, mda_size);
+   if (! metadatabuf)
+     goto fail;
+ 
+@@ -426,7 +426,7 @@ grub_lvm_detect (grub_disk_t disk,
+ #endif
+ 		  goto lvs_fail;
+ 		}
+-	      lv->segments = grub_zalloc (sizeof (*seg) * lv->segment_count);
++	      lv->segments = grub_calloc (lv->segment_count, sizeof (*seg));
+ 	      seg = lv->segments;
+ 
+ 	      for (i = 0; i < lv->segment_count; i++)
+@@ -483,8 +483,8 @@ grub_lvm_detect (grub_disk_t disk,
+ 		      if (seg->node_count != 1)
+ 			seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
+ 
+-		      seg->nodes = grub_zalloc (sizeof (*stripe)
+-						* seg->node_count);
++		      seg->nodes = grub_calloc (seg->node_count,
++						sizeof (*stripe));
+ 		      stripe = seg->nodes;
+ 
+ 		      p = grub_strstr (p, "stripes = [");
+diff --git a/grub-core/disk/xen/xendisk.c b/grub-core/disk/xen/xendisk.c
+index 48476cbbf9..d6612eebd7 100644
+--- a/grub-core/disk/xen/xendisk.c
++++ b/grub-core/disk/xen/xendisk.c
+@@ -426,7 +426,7 @@ grub_xendisk_init (void)
+   if (!ctr)
+     return;
+ 
+-  virtdisks = grub_malloc (ctr * sizeof (virtdisks[0]));
++  virtdisks = grub_calloc (ctr, sizeof (virtdisks[0]));
+   if (!virtdisks)
+     return;
+   if (grub_xenstore_dir ("device/vbd", fill, &ctr))
+diff --git a/grub-core/efiemu/loadcore.c b/grub-core/efiemu/loadcore.c
+index 44085ef818..2b924623f5 100644
+--- a/grub-core/efiemu/loadcore.c
++++ b/grub-core/efiemu/loadcore.c
+@@ -201,7 +201,7 @@ grub_efiemu_count_symbols (const Elf_Ehdr *e)
+ 
+   grub_efiemu_nelfsyms = (unsigned) s->sh_size / (unsigned) s->sh_entsize;
+   grub_efiemu_elfsyms = (struct grub_efiemu_elf_sym *)
+-    grub_malloc (sizeof (struct grub_efiemu_elf_sym) * grub_efiemu_nelfsyms);
++    grub_calloc (grub_efiemu_nelfsyms, sizeof (struct grub_efiemu_elf_sym));
+ 
+   /* Relocators */
+   for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
+diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c
+index 52a032f7b2..9b8e0d0ad1 100644
+--- a/grub-core/efiemu/mm.c
++++ b/grub-core/efiemu/mm.c
+@@ -554,11 +554,11 @@ grub_efiemu_mmap_sort_and_uniq (void)
+   /* Initialize variables*/
+   grub_memset (present, 0, sizeof (int) * GRUB_EFI_MAX_MEMORY_TYPE);
+   scanline_events = (struct grub_efiemu_mmap_scan *)
+-    grub_malloc (sizeof (struct grub_efiemu_mmap_scan) * 2 * mmap_num);
++    grub_calloc (mmap_num, sizeof (struct grub_efiemu_mmap_scan) * 2);
+ 
+   /* Number of chunks can't increase more than by factor of 2 */
+   result = (grub_efi_memory_descriptor_t *)
+-    grub_malloc (sizeof (grub_efi_memory_descriptor_t) * 2 * mmap_num);
++    grub_calloc (mmap_num, sizeof (grub_efi_memory_descriptor_t) * 2);
+   if (!result || !scanline_events)
+     {
+       grub_free (result);
+@@ -660,7 +660,7 @@ grub_efiemu_mm_do_alloc (void)
+ 
+   /* Preallocate mmap */
+   efiemu_mmap = (grub_efi_memory_descriptor_t *)
+-    grub_malloc (mmap_reserved_size * sizeof (grub_efi_memory_descriptor_t));
++    grub_calloc (mmap_reserved_size, sizeof (grub_efi_memory_descriptor_t));
+   if (!efiemu_mmap)
+     {
+       grub_efiemu_unload ();
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index 85a292557a..8e118b315c 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -293,8 +293,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
+   font->num_chars = sect_length / FONT_CHAR_INDEX_ENTRY_SIZE;
+ 
+   /* Allocate the character index array.  */
+-  font->char_index = grub_malloc (font->num_chars
+-				  * sizeof (struct char_index_entry));
++  font->char_index = grub_calloc (font->num_chars, sizeof (struct char_index_entry));
+   if (!font->char_index)
+     return 1;
+   font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t));
+diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c
+index 6b6a2bc913..220b3712f2 100644
+--- a/grub-core/fs/affs.c
++++ b/grub-core/fs/affs.c
+@@ -301,7 +301,7 @@ grub_affs_read_symlink (grub_fshelp_node_t node)
+       return 0;
+     }
+   latin1[symlink_size] = 0;
+-  utf8 = grub_malloc (symlink_size * GRUB_MAX_UTF8_PER_LATIN1 + 1);
++  utf8 = grub_calloc (GRUB_MAX_UTF8_PER_LATIN1 + 1, symlink_size);
+   if (!utf8)
+     {
+       grub_free (latin1);
+@@ -422,7 +422,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
+ 	return 1;
+     }
+ 
+-  hashtable = grub_zalloc (data->htsize * sizeof (*hashtable));
++  hashtable = grub_calloc (data->htsize, sizeof (*hashtable));
+   if (!hashtable)
+     return 1;
+ 
+@@ -628,7 +628,7 @@ grub_affs_label (grub_device_t device, char **label)
+       len = file.namelen;
+       if (len > sizeof (file.name))
+ 	len = sizeof (file.name);
+-      *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1);
++      *label = grub_calloc (GRUB_MAX_UTF8_PER_LATIN1 + 1, len);
+       if (*label)
+ 	*grub_latin1_to_utf8 ((grub_uint8_t *) *label, file.name, len) = '\0';
+     }
+diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
+index 48bd3d04a5..11272efc1a 100644
+--- a/grub-core/fs/btrfs.c
++++ b/grub-core/fs/btrfs.c
+@@ -413,7 +413,7 @@ lower_bound (struct grub_btrfs_data *data,
+     {
+       desc->allocated = 16;
+       desc->depth = 0;
+-      desc->data = grub_malloc (sizeof (desc->data[0]) * desc->allocated);
++      desc->data = grub_calloc (desc->allocated, sizeof (desc->data[0]));
+       if (!desc->data)
+ 	return grub_errno;
+     }
+@@ -752,7 +752,7 @@ raid56_read_retry (struct grub_btrfs_data *data,
+   grub_err_t ret = GRUB_ERR_OUT_OF_MEMORY;
+   grub_uint64_t i, failed_devices;
+ 
+-  buffers = grub_zalloc (sizeof(*buffers) * nstripes);
++  buffers = grub_calloc (nstripes, sizeof (*buffers));
+   if (!buffers)
+     goto cleanup;
+ 
+@@ -2160,7 +2160,7 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)),
+   *nsectors = 64 * 2 - 1;
+   if (*nsectors > max_nsectors)
+     *nsectors = max_nsectors;
+-  *sectors = grub_malloc (*nsectors * sizeof (**sectors));
++  *sectors = grub_calloc (*nsectors, sizeof (**sectors));
+   if (!*sectors)
+     return grub_errno;
+   for (i = 0; i < *nsectors; i++)
+diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c
+index ac0a40990e..3fe842b4d8 100644
+--- a/grub-core/fs/hfs.c
++++ b/grub-core/fs/hfs.c
+@@ -1360,7 +1360,7 @@ grub_hfs_label (grub_device_t device, char **label)
+       grub_size_t len = data->sblock.volname[0];
+       if (len > sizeof (data->sblock.volname) - 1)
+ 	len = sizeof (data->sblock.volname) - 1;
+-      *label = grub_malloc (len * MAX_UTF8_PER_MAC_ROMAN + 1);
++      *label = grub_calloc (MAX_UTF8_PER_MAC_ROMAN + 1, len);
+       if (*label)
+ 	macroman_to_utf8 (*label, data->sblock.volname + 1,
+ 			  len + 1, 0);
+diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
+index 54786bb1c6..dae43becc9 100644
+--- a/grub-core/fs/hfsplus.c
++++ b/grub-core/fs/hfsplus.c
+@@ -720,7 +720,7 @@ list_nodes (void *record, void *hook_arg)
+   if (! filename)
+     return 0;
+ 
+-  keyname = grub_malloc (grub_be_to_cpu16 (catkey->namelen) * sizeof (*keyname));
++  keyname = grub_calloc (grub_be_to_cpu16 (catkey->namelen), sizeof (*keyname));
+   if (!keyname)
+     {
+       grub_free (filename);
+@@ -1007,7 +1007,7 @@ grub_hfsplus_label (grub_device_t device, char **label)
+     grub_hfsplus_btree_recptr (&data->catalog_tree, node, ptr);
+ 
+   label_len = grub_be_to_cpu16 (catkey->namelen);
+-  label_name = grub_malloc (label_len * sizeof (*label_name));
++  label_name = grub_calloc (label_len, sizeof (*label_name));
+   if (!label_name)
+     {
+       grub_free (node);
+@@ -1029,7 +1029,7 @@ grub_hfsplus_label (grub_device_t device, char **label)
+ 	}
+     }
+ 
+-  *label = grub_malloc (label_len * GRUB_MAX_UTF8_PER_UTF16 + 1);
++  *label = grub_calloc (label_len, GRUB_MAX_UTF8_PER_UTF16 + 1);
+   if (! *label)
+     {
+       grub_free (label_name);
+diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
+index 49c0c632bf..4f1b52a552 100644
+--- a/grub-core/fs/iso9660.c
++++ b/grub-core/fs/iso9660.c
+@@ -331,7 +331,7 @@ grub_iso9660_convert_string (grub_uint8_t *us, int len)
+   int i;
+   grub_uint16_t t[MAX_NAMELEN / 2 + 1];
+ 
+-  p = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1);
++  p = grub_calloc (len, GRUB_MAX_UTF8_PER_UTF16 + 1);
+   if (! p)
+     return NULL;
+ 
+diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
+index fc4e1f678d..2f34f76da8 100644
+--- a/grub-core/fs/ntfs.c
++++ b/grub-core/fs/ntfs.c
+@@ -556,8 +556,8 @@ get_utf8 (grub_uint8_t *in, grub_size_t len)
+   grub_uint16_t *tmp;
+   grub_size_t i;
+ 
+-  buf = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1);
+-  tmp = grub_malloc (len * sizeof (tmp[0]));
++  buf = grub_calloc (len, GRUB_MAX_UTF8_PER_UTF16 + 1);
++  tmp = grub_calloc (len, sizeof (tmp[0]));
+   if (!buf || !tmp)
+     {
+       grub_free (buf);
+diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
+index 50c1fe72f4..90f7fb3791 100644
+--- a/grub-core/fs/sfs.c
++++ b/grub-core/fs/sfs.c
+@@ -266,7 +266,7 @@ grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
+       node->next_extent = node->block;
+       node->cache_size = 0;
+ 
+-      node->cache = grub_malloc (sizeof (node->cache[0]) * cache_size);
++      node->cache = grub_calloc (cache_size, sizeof (node->cache[0]));
+       if (!node->cache)
+ 	{
+ 	  grub_errno = 0;
+diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c
+index 7d63e0c99c..c551ed6b52 100644
+--- a/grub-core/fs/tar.c
++++ b/grub-core/fs/tar.c
+@@ -120,7 +120,7 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
+ 	  if (data->linkname_alloc < linksize + 1)
+ 	    {
+ 	      char *n;
+-	      n = grub_malloc (2 * (linksize + 1));
++	      n = grub_calloc (2, linksize + 1);
+ 	      if (!n)
+ 		return grub_errno;
+ 	      grub_free (data->linkname);
+diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
+index dc8b6e2d1c..a83761674a 100644
+--- a/grub-core/fs/udf.c
++++ b/grub-core/fs/udf.c
+@@ -873,7 +873,7 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf)
+     {
+       unsigned i;
+       utf16len = sz - 1;
+-      utf16 = grub_malloc (utf16len * sizeof (utf16[0]));
++      utf16 = grub_calloc (utf16len, sizeof (utf16[0]));
+       if (!utf16)
+ 	return NULL;
+       for (i = 0; i < utf16len; i++)
+@@ -883,7 +883,7 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf)
+     {
+       unsigned i;
+       utf16len = (sz - 1) / 2;
+-      utf16 = grub_malloc (utf16len * sizeof (utf16[0]));
++      utf16 = grub_calloc (utf16len, sizeof (utf16[0]));
+       if (!utf16)
+ 	return NULL;
+       for (i = 0; i < utf16len; i++)
+diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
+index 2f72e42bf8..381dde556d 100644
+--- a/grub-core/fs/zfs/zfs.c
++++ b/grub-core/fs/zfs/zfs.c
+@@ -3325,7 +3325,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
+ 	}
+       subvol->nkeys = 0;
+       zap_iterate (&keychain_dn, 8, count_zap_keys, &ctx, data);
+-      subvol->keyring = grub_zalloc (subvol->nkeys * sizeof (subvol->keyring[0]));
++      subvol->keyring = grub_calloc (subvol->nkeys, sizeof (subvol->keyring[0]));
+       if (!subvol->keyring)
+ 	{
+ 	  grub_free (fsname);
+@@ -4336,7 +4336,7 @@ grub_zfs_embed (grub_device_t device __attribute__ ((unused)),
+   *nsectors = (VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS);
+   if (*nsectors > max_nsectors)
+     *nsectors = max_nsectors;
+-  *sectors = grub_malloc (*nsectors * sizeof (**sectors));
++  *sectors = grub_calloc (*nsectors, sizeof (**sectors));
+   if (!*sectors)
+     return grub_errno;
+   for (i = 0; i < *nsectors; i++)
+diff --git a/grub-core/gfxmenu/gui_string_util.c b/grub-core/gfxmenu/gui_string_util.c
+index a9a415e312..ba1e1eab31 100644
+--- a/grub-core/gfxmenu/gui_string_util.c
++++ b/grub-core/gfxmenu/gui_string_util.c
+@@ -55,7 +55,7 @@ canonicalize_path (const char *path)
+     if (*p == '/')
+       components++;
+ 
+-  char **path_array = grub_malloc (components * sizeof (*path_array));
++  char **path_array = grub_calloc (components, sizeof (*path_array));
+   if (! path_array)
+     return 0;
+ 
+diff --git a/grub-core/gfxmenu/widget-box.c b/grub-core/gfxmenu/widget-box.c
+index b606028891..470597ded2 100644
+--- a/grub-core/gfxmenu/widget-box.c
++++ b/grub-core/gfxmenu/widget-box.c
+@@ -303,10 +303,10 @@ grub_gfxmenu_create_box (const char *pixmaps_prefix,
+   box->content_height = 0;
+   box->raw_pixmaps =
+     (struct grub_video_bitmap **)
+-    grub_malloc (BOX_NUM_PIXMAPS * sizeof (struct grub_video_bitmap *));
++    grub_calloc (BOX_NUM_PIXMAPS, sizeof (struct grub_video_bitmap *));
+   box->scaled_pixmaps =
+     (struct grub_video_bitmap **)
+-    grub_malloc (BOX_NUM_PIXMAPS * sizeof (struct grub_video_bitmap *));
++    grub_calloc (BOX_NUM_PIXMAPS, sizeof (struct grub_video_bitmap *));
+ 
+   /* Initialize all pixmap pointers to NULL so that proper destruction can
+      be performed if an error is encountered partway through construction.  */
+diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c
+index 6208a97636..43d98a7bdf 100644
+--- a/grub-core/io/gzio.c
++++ b/grub-core/io/gzio.c
+@@ -554,7 +554,7 @@ huft_build (unsigned *b,	/* code lengths in bits (all assumed <= BMAX) */
+ 	      z = 1 << j;	/* table entries for j-bit table */
+ 
+ 	      /* allocate and link in new table */
+-	      q = (struct huft *) grub_zalloc ((z + 1) * sizeof (struct huft));
++	      q = (struct huft *) grub_calloc (z + 1, sizeof (struct huft));
+ 	      if (! q)
+ 		{
+ 		  if (h)
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index 6e1ceb9051..dc31caa213 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -202,7 +202,7 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid,
+ 
+   len = grub_strlen (var);
+   len16 = len * GRUB_MAX_UTF16_PER_UTF8;
+-  var16 = grub_malloc ((len16 + 1) * sizeof (var16[0]));
++  var16 = grub_calloc (len16 + 1, sizeof (var16[0]));
+   if (!var16)
+     return grub_errno;
+   len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL);
+@@ -237,7 +237,7 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
+ 
+   len = grub_strlen (var);
+   len16 = len * GRUB_MAX_UTF16_PER_UTF8;
+-  var16 = grub_malloc ((len16 + 1) * sizeof (var16[0]));
++  var16 = grub_calloc (len16 + 1, sizeof (var16[0]));
+   if (!var16)
+     return NULL;
+   len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL);
+@@ -383,7 +383,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
+ 	  while (len > 0 && fp->path_name[len - 1] == 0)
+ 	    len--;
+ 
+-	  dup_name = grub_malloc (len * sizeof (*dup_name));
++	  dup_name = grub_calloc (len, sizeof (*dup_name));
+ 	  if (!dup_name)
+ 	    {
+ 	      grub_free (name);
+diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c
+index 8ac5239538..f90b6c9ce4 100644
+--- a/grub-core/kern/emu/hostdisk.c
++++ b/grub-core/kern/emu/hostdisk.c
+@@ -627,7 +627,7 @@ static char *
+ grub_util_path_concat_real (size_t n, int ext, va_list ap)
+ {
+   size_t totlen = 0;
+-  char **l = xmalloc ((n + ext) * sizeof (l[0]));
++  char **l = xcalloc (n + ext, sizeof (l[0]));
+   char *r, *p, *pi;
+   size_t i;
+   int first = 1;
+diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c
+index 2b85f4950b..f90be6566b 100644
+--- a/grub-core/kern/fs.c
++++ b/grub-core/kern/fs.c
+@@ -151,7 +151,7 @@ grub_fs_blocklist_open (grub_file_t file, const char *name)
+   while (p);
+ 
+   /* Allocate a block list.  */
+-  blocks = grub_zalloc (sizeof (struct grub_fs_block) * (num + 1));
++  blocks = grub_calloc (num + 1, sizeof (struct grub_fs_block));
+   if (! blocks)
+     return 0;
+ 
+diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
+index 18cad5803b..83c068d61b 100644
+--- a/grub-core/kern/misc.c
++++ b/grub-core/kern/misc.c
+@@ -691,7 +691,7 @@ parse_printf_args (const char *fmt0, struct printf_args *args,
+     args->ptr = args->prealloc;
+   else
+     {
+-      args->ptr = grub_malloc (args->count * sizeof (args->ptr[0]));
++      args->ptr = grub_calloc (args->count, sizeof (args->ptr[0]));
+       if (!args->ptr)
+ 	{
+ 	  grub_errno = GRUB_ERR_NONE;
+diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
+index 78175aac2d..619db3122a 100644
+--- a/grub-core/kern/parser.c
++++ b/grub-core/kern/parser.c
+@@ -213,7 +213,7 @@ grub_parser_split_cmdline (const char *cmdline,
+     return grub_errno;
+   grub_memcpy (args, buffer, bp - buffer);
+ 
+-  *argv = grub_malloc (sizeof (char *) * (*argc + 1));
++  *argv = grub_calloc (*argc + 1, sizeof (char *));
+   if (!*argv)
+     {
+       grub_free (args);
+diff --git a/grub-core/kern/uboot/uboot.c b/grub-core/kern/uboot/uboot.c
+index be4816fe6f..aac8f9ae1f 100644
+--- a/grub-core/kern/uboot/uboot.c
++++ b/grub-core/kern/uboot/uboot.c
+@@ -133,7 +133,7 @@ grub_uboot_dev_enum (void)
+     return num_devices;
+ 
+   max_devices = 2;
+-  enum_devices = grub_malloc (sizeof(struct device_info) * max_devices);
++  enum_devices = grub_calloc (max_devices, sizeof(struct device_info));
+   if (!enum_devices)
+     return 0;
+ 
+diff --git a/grub-core/lib/libgcrypt/cipher/ac.c b/grub-core/lib/libgcrypt/cipher/ac.c
+index f5e946a2d8..63f6fcd11e 100644
+--- a/grub-core/lib/libgcrypt/cipher/ac.c
++++ b/grub-core/lib/libgcrypt/cipher/ac.c
+@@ -185,7 +185,7 @@ ac_data_mpi_copy (gcry_ac_mpi_t *data_mpis, unsigned int data_mpis_n,
+   gcry_mpi_t mpi;
+   char *label;
+ 
+-  data_mpis_new = gcry_malloc (sizeof (*data_mpis_new) * data_mpis_n);
++  data_mpis_new = gcry_calloc (data_mpis_n, sizeof (*data_mpis_new));
+   if (! data_mpis_new)
+     {
+       err = gcry_error_from_errno (errno);
+@@ -572,7 +572,7 @@ _gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp,
+     }
+ 
+   /* Add MPI list.  */
+-  arg_list = gcry_malloc (sizeof (*arg_list) * (data_n + 1));
++  arg_list = gcry_calloc (data_n + 1, sizeof (*arg_list));
+   if (! arg_list)
+     {
+       err = gcry_error_from_errno (errno);
+@@ -1283,7 +1283,7 @@ ac_data_construct (const char *identifier, int include_flags,
+   /* We build a list of arguments to pass to
+      gcry_sexp_build_array().  */
+   data_length = _gcry_ac_data_length (data);
+-  arg_list = gcry_malloc (sizeof (*arg_list) * (data_length * 2));
++  arg_list = gcry_calloc (data_length, sizeof (*arg_list) * 2);
+   if (! arg_list)
+     {
+       err = gcry_error_from_errno (errno);
+@@ -1593,7 +1593,7 @@ _gcry_ac_key_pair_generate (gcry_ac_handle_t handle, unsigned int nbits,
+ 	arg_list_n += 2;
+ 
+   /* Allocate list.  */
+-  arg_list = gcry_malloc (sizeof (*arg_list) * arg_list_n);
++  arg_list = gcry_calloc (arg_list_n, sizeof (*arg_list));
+   if (! arg_list)
+     {
+       err = gcry_error_from_errno (errno);
+diff --git a/grub-core/lib/libgcrypt/cipher/primegen.c b/grub-core/lib/libgcrypt/cipher/primegen.c
+index 2788e349fa..b12e79b192 100644
+--- a/grub-core/lib/libgcrypt/cipher/primegen.c
++++ b/grub-core/lib/libgcrypt/cipher/primegen.c
+@@ -383,7 +383,7 @@ prime_generate_internal (int need_q_factor,
+     }
+ 
+   /* Allocate an array to track pool usage. */
+-  pool_in_use = gcry_malloc (n * sizeof *pool_in_use);
++  pool_in_use = gcry_calloc (n, sizeof *pool_in_use);
+   if (!pool_in_use)
+     {
+       err = gpg_err_code_from_errno (errno);
+@@ -765,7 +765,7 @@ gen_prime (unsigned int nbits, int secret, int randomlevel,
+   if (nbits < 16)
+     log_fatal ("can't generate a prime with less than %d bits\n", 16);
+ 
+-  mods = gcry_xmalloc( no_of_small_prime_numbers * sizeof *mods );
++  mods = gcry_xcalloc( no_of_small_prime_numbers, sizeof *mods);
+   /* Make nbits fit into gcry_mpi_t implementation. */
+   val_2  = mpi_alloc_set_ui( 2 );
+   val_3 = mpi_alloc_set_ui( 3);
+diff --git a/grub-core/lib/libgcrypt/cipher/pubkey.c b/grub-core/lib/libgcrypt/cipher/pubkey.c
+index 910982141e..ca087ad75b 100644
+--- a/grub-core/lib/libgcrypt/cipher/pubkey.c
++++ b/grub-core/lib/libgcrypt/cipher/pubkey.c
+@@ -2941,7 +2941,7 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
+        * array to a format string, so we have to do it this way :-(.  */
+       /* FIXME: There is now such a format specifier, so we can
+          change the code to be more clear. */
+-      arg_list = malloc (nelem * sizeof *arg_list);
++      arg_list = calloc (nelem, sizeof *arg_list);
+       if (!arg_list)
+         {
+           rc = gpg_err_code_from_syserror ();
+@@ -3233,7 +3233,7 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
+         }
+       strcpy (p, "))");
+ 
+-      arg_list = malloc (nelem * sizeof *arg_list);
++      arg_list = calloc (nelem, sizeof *arg_list);
+       if (!arg_list)
+         {
+           rc = gpg_err_code_from_syserror ();
+diff --git a/grub-core/lib/priority_queue.c b/grub-core/lib/priority_queue.c
+index 659be0b7f4..7d5e7c05aa 100644
+--- a/grub-core/lib/priority_queue.c
++++ b/grub-core/lib/priority_queue.c
+@@ -92,7 +92,7 @@ grub_priority_queue_new (grub_size_t elsize,
+ {
+   struct grub_priority_queue *ret;
+   void *els;
+-  els = grub_malloc (elsize * 8);
++  els = grub_calloc (8, elsize);
+   if (!els)
+     return 0;
+   ret = (struct grub_priority_queue *) grub_malloc (sizeof (*ret));
+diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c
+index ee9fa7b4fe..467305b46a 100644
+--- a/grub-core/lib/reed_solomon.c
++++ b/grub-core/lib/reed_solomon.c
+@@ -20,6 +20,7 @@
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
++#define xcalloc calloc
+ #define xmalloc malloc
+ #define grub_memset memset
+ #define grub_memcpy memcpy
+@@ -158,11 +159,9 @@ rs_encode (gf_single_t *data, grub_size_t s, grub_size_t rs)
+   gf_single_t *rs_polynomial;
+   int i, j;
+   gf_single_t *m;
+-  m = xmalloc ((s + rs) * sizeof (gf_single_t));
++  m = xcalloc (s + rs, sizeof (gf_single_t));
+   grub_memcpy (m, data, s * sizeof (gf_single_t));
+-  grub_memset (m + s, 0, rs * sizeof (gf_single_t));
+-  rs_polynomial = xmalloc ((rs + 1) * sizeof (gf_single_t));
+-  grub_memset (rs_polynomial, 0, (rs + 1) * sizeof (gf_single_t));
++  rs_polynomial = xcalloc (rs + 1, sizeof (gf_single_t));
+   rs_polynomial[rs] = 1;
+   /* Multiply with X - a^r */
+   for (j = 0; j < rs; j++)
+diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c
+index ea3ebc719b..5847aac364 100644
+--- a/grub-core/lib/relocator.c
++++ b/grub-core/lib/relocator.c
+@@ -495,9 +495,9 @@ malloc_in_range (struct grub_relocator *rel,
+   }
+ #endif
+ 
+-  eventt = grub_malloc (maxevents * sizeof (events[0]));
++  eventt = grub_calloc (maxevents, sizeof (events[0]));
+   counter = grub_malloc ((DIGITSORT_MASK + 2) * sizeof (counter[0]));
+-  events = grub_malloc (maxevents * sizeof (events[0]));
++  events = grub_calloc (maxevents, sizeof (events[0]));
+   if (!events || !eventt || !counter)
+     {
+       grub_dprintf ("relocator", "events or counter allocation failed %d\n",
+@@ -963,7 +963,7 @@ malloc_in_range (struct grub_relocator *rel,
+ #endif
+     unsigned cural = 0;
+     int oom = 0;
+-    res->subchunks = grub_malloc (sizeof (res->subchunks[0]) * nallocs);
++    res->subchunks = grub_calloc (nallocs, sizeof (res->subchunks[0]));
+     if (!res->subchunks)
+       oom = 1;
+     res->nsubchunks = nallocs;
+@@ -1562,8 +1562,8 @@ grub_relocator_prepare_relocs (struct grub_relocator *rel, grub_addr_t addr,
+ 	    count[(chunk->src & 0xff) + 1]++;
+ 	  }
+     }
+-    from = grub_malloc (nchunks * sizeof (sorted[0]));
+-    to = grub_malloc (nchunks * sizeof (sorted[0]));
++    from = grub_calloc (nchunks, sizeof (sorted[0]));
++    to = grub_calloc (nchunks, sizeof (sorted[0]));
+     if (!from || !to)
+       {
+ 	grub_free (from);
+diff --git a/grub-core/lib/zstd/fse_decompress.c b/grub-core/lib/zstd/fse_decompress.c
+index 72bbead5be..2227b84bc7 100644
+--- a/grub-core/lib/zstd/fse_decompress.c
++++ b/grub-core/lib/zstd/fse_decompress.c
+@@ -82,7 +82,7 @@
+ FSE_DTable* FSE_createDTable (unsigned tableLog)
+ {
+     if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;
+-    return (FSE_DTable*)malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );
++    return (FSE_DTable*)calloc( FSE_DTABLE_SIZE_U32(tableLog), sizeof (U32) );
+ }
+ 
+ void FSE_freeDTable (FSE_DTable* dt)
+diff --git a/grub-core/loader/arm/linux.c b/grub-core/loader/arm/linux.c
+index 092e8e3077..979d425dfb 100644
+--- a/grub-core/loader/arm/linux.c
++++ b/grub-core/loader/arm/linux.c
+@@ -82,7 +82,7 @@ linux_prepare_atag (void *target_atag)
+ 
+   /* some place for cmdline, initrd and terminator.  */
+   tmp_size = get_atag_size (atag_orig) + 20 + (arg_size) / 4;
+-  tmp_atag = grub_malloc (tmp_size * sizeof (grub_uint32_t));
++  tmp_atag = grub_calloc (tmp_size, sizeof (grub_uint32_t));
+   if (!tmp_atag)
+     return grub_errno;
+ 
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 04e815c052..b9a2df34b1 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -126,7 +126,7 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
+   fp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
+   fp->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE;
+ 
+-  path_name = grub_malloc (len * GRUB_MAX_UTF16_PER_UTF8 * sizeof (*path_name));
++  path_name = grub_calloc (len, GRUB_MAX_UTF16_PER_UTF8 * sizeof (*path_name));
+   if (!path_name)
+     return;
+ 
+diff --git a/grub-core/loader/i386/bsdXX.c b/grub-core/loader/i386/bsdXX.c
+index af6741d157..a8d8bf7dae 100644
+--- a/grub-core/loader/i386/bsdXX.c
++++ b/grub-core/loader/i386/bsdXX.c
+@@ -48,7 +48,7 @@ read_headers (grub_file_t file, const char *filename, Elf_Ehdr *e, char **shdr)
+   if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS))
+     return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic"));
+ 
+-  *shdr = grub_malloc ((grub_uint32_t) e->e_shnum * e->e_shentsize);
++  *shdr = grub_calloc (e->e_shnum, e->e_shentsize);
+   if (! *shdr)
+     return grub_errno;
+ 
+diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c
+index e64ed08f58..b7d176b5d3 100644
+--- a/grub-core/loader/i386/xnu.c
++++ b/grub-core/loader/i386/xnu.c
+@@ -295,7 +295,7 @@ grub_xnu_devprop_add_property_utf8 (struct grub_xnu_devprop_device_descriptor *d
+     return grub_errno;
+ 
+   len = grub_strlen (name);
+-  utf16 = grub_malloc (sizeof (grub_uint16_t) * len);
++  utf16 = grub_calloc (len, sizeof (grub_uint16_t));
+   if (!utf16)
+     {
+       grub_free (utf8);
+@@ -331,7 +331,7 @@ grub_xnu_devprop_add_property_utf16 (struct grub_xnu_devprop_device_descriptor *
+   grub_uint16_t *utf16;
+   grub_err_t err;
+ 
+-  utf16 = grub_malloc (sizeof (grub_uint16_t) * namelen);
++  utf16 = grub_calloc (namelen, sizeof (grub_uint16_t));
+   if (!utf16)
+     return grub_errno;
+   grub_memcpy (utf16, name, sizeof (grub_uint16_t) * namelen);
+diff --git a/grub-core/loader/macho.c b/grub-core/loader/macho.c
+index 085f9c6890..05710c48e0 100644
+--- a/grub-core/loader/macho.c
++++ b/grub-core/loader/macho.c
+@@ -97,7 +97,7 @@ grub_macho_file (grub_file_t file, const char *filename, int is_64bit)
+       if (grub_file_seek (macho->file, sizeof (struct grub_macho_fat_header))
+ 	  == (grub_off_t) -1)
+ 	goto fail;
+-      archs = grub_malloc (sizeof (struct grub_macho_fat_arch) * narchs);
++      archs = grub_calloc (narchs, sizeof (struct grub_macho_fat_arch));
+       if (!archs)
+ 	goto fail;
+       if (grub_file_read (macho->file, archs,
+diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c
+index 70cd1db513..cc6853692a 100644
+--- a/grub-core/loader/multiboot_elfxx.c
++++ b/grub-core/loader/multiboot_elfxx.c
+@@ -217,7 +217,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
+     {
+       grub_uint8_t *shdr, *shdrptr;
+ 
+-      shdr = grub_malloc ((grub_uint32_t) ehdr->e_shnum * ehdr->e_shentsize);
++      shdr = grub_calloc (ehdr->e_shnum, ehdr->e_shentsize);
+       if (!shdr)
+ 	return grub_errno;
+       
+diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
+index e0f47e72b0..2f0ebd0b8b 100644
+--- a/grub-core/loader/xnu.c
++++ b/grub-core/loader/xnu.c
+@@ -801,7 +801,7 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)),
+   if (grub_be_to_cpu32 (head.magic) == GRUB_MACHO_FAT_MAGIC)
+     {
+       narchs = grub_be_to_cpu32 (head.nfat_arch);
+-      archs = grub_malloc (sizeof (struct grub_macho_fat_arch) * narchs);
++      archs = grub_calloc (narchs, sizeof (struct grub_macho_fat_arch));
+       if (! archs)
+ 	{
+ 	  grub_file_close (file);
+diff --git a/grub-core/mmap/mmap.c b/grub-core/mmap/mmap.c
+index 6a31cbae32..57b4e9a72a 100644
+--- a/grub-core/mmap/mmap.c
++++ b/grub-core/mmap/mmap.c
+@@ -143,9 +143,9 @@ grub_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
+ 
+   /* Initialize variables. */
+   ctx.scanline_events = (struct grub_mmap_scan *)
+-    grub_malloc (sizeof (struct grub_mmap_scan) * 2 * mmap_num);
++    grub_calloc (mmap_num, sizeof (struct grub_mmap_scan) * 2);
+ 
+-  present = grub_zalloc (sizeof (present[0]) * current_priority);
++  present = grub_calloc (current_priority, sizeof (present[0]));
+ 
+   if (! ctx.scanline_events || !present)
+     {
+diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
+index 558d97ba1e..dd0ffcdaea 100644
+--- a/grub-core/net/bootp.c
++++ b/grub-core/net/bootp.c
+@@ -1559,7 +1559,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
+   if (ncards == 0)
+     return grub_error (GRUB_ERR_NET_NO_CARD, N_("no network card found"));
+ 
+-  ifaces = grub_zalloc (ncards * sizeof (ifaces[0]));
++  ifaces = grub_calloc (ncards, sizeof (ifaces[0]));
+   if (!ifaces)
+     return grub_errno;
+ 
+diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
+index 5d9afe093c..e332d5eb4a 100644
+--- a/grub-core/net/dns.c
++++ b/grub-core/net/dns.c
+@@ -285,8 +285,8 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
+       ptr++;
+       ptr += 4;
+     }
+-  *data->addresses = grub_malloc (sizeof ((*data->addresses)[0])
+-				 * grub_be_to_cpu16 (head->ancount));
++  *data->addresses = grub_calloc (grub_be_to_cpu16 (head->ancount),
++				  sizeof ((*data->addresses)[0]));
+   if (!*data->addresses)
+     {
+       grub_errno = GRUB_ERR_NONE;
+@@ -406,8 +406,8 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
+       dns_cache[h].addresses = 0;
+       dns_cache[h].name = grub_strdup (data->oname);
+       dns_cache[h].naddresses = *data->naddresses;
+-      dns_cache[h].addresses = grub_malloc (*data->naddresses
+-					    * sizeof (dns_cache[h].addresses[0]));
++      dns_cache[h].addresses = grub_calloc (*data->naddresses,
++					    sizeof (dns_cache[h].addresses[0]));
+       dns_cache[h].limit_time = grub_get_time_ms () + 1000 * ttl_all;
+       if (!dns_cache[h].addresses || !dns_cache[h].name)
+ 	{
+@@ -479,7 +479,7 @@ grub_net_dns_lookup (const char *name,
+ 	}
+     }
+ 
+-  sockets = grub_malloc (sizeof (sockets[0]) * n_servers);
++  sockets = grub_calloc (n_servers, sizeof (sockets[0]));
+   if (!sockets)
+     return grub_errno;
+ 
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index b917a75d54..fed7bc57cb 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -333,8 +333,8 @@ grub_cmd_ipv6_autoconf (struct grub_command *cmd __attribute__ ((unused)),
+     ncards++;
+   }
+ 
+-  ifaces = grub_zalloc (ncards * sizeof (ifaces[0]));
+-  slaacs = grub_zalloc (ncards * sizeof (slaacs[0]));
++  ifaces = grub_calloc (ncards, sizeof (ifaces[0]));
++  slaacs = grub_calloc (ncards, sizeof (slaacs[0]));
+   if (!ifaces || !slaacs)
+     {
+       grub_free (ifaces);
+diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c
+index b0ab47d73f..d57fb72faa 100644
+--- a/grub-core/normal/charset.c
++++ b/grub-core/normal/charset.c
+@@ -203,7 +203,7 @@ grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg,
+ {
+   grub_size_t msg_len = grub_strlen (msg);
+ 
+-  *unicode_msg = grub_malloc (msg_len * sizeof (grub_uint32_t));
++  *unicode_msg = grub_calloc (msg_len, sizeof (grub_uint32_t));
+  
+   if (!*unicode_msg)
+     return -1;
+@@ -488,7 +488,7 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen,
+ 	    }
+ 	  else
+ 	    {
+-	      n = grub_malloc (sizeof (n[0]) * (out->ncomb + 1));
++	      n = grub_calloc (out->ncomb + 1, sizeof (n[0]));
+ 	      if (!n)
+ 		{
+ 		  grub_errno = GRUB_ERR_NONE;
+@@ -842,7 +842,7 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical,
+       }							\
+   }
+ 
+-  visual = grub_malloc (sizeof (visual[0]) * logical_len);
++  visual = grub_calloc (logical_len, sizeof (visual[0]));
+   if (!visual)
+     return -1;
+ 
+@@ -1165,8 +1165,8 @@ grub_bidi_logical_to_visual (const grub_uint32_t *logical,
+ {
+   const grub_uint32_t *line_start = logical, *ptr;
+   struct grub_unicode_glyph *visual_ptr;
+-  *visual_out = visual_ptr = grub_malloc (3 * sizeof (visual_ptr[0])
+-					  * (logical_len + 2));
++  *visual_out = visual_ptr = grub_calloc (logical_len + 2,
++					  3 * sizeof (visual_ptr[0]));
+   if (!visual_ptr)
+     return -1;
+   for (ptr = logical; ptr <= logical + logical_len; ptr++)
+diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c
+index c037d5050e..c57242e2ea 100644
+--- a/grub-core/normal/cmdline.c
++++ b/grub-core/normal/cmdline.c
+@@ -41,7 +41,7 @@ grub_err_t
+ grub_set_history (int newsize)
+ {
+   grub_uint32_t **old_hist_lines = hist_lines;
+-  hist_lines = grub_malloc (sizeof (grub_uint32_t *) * newsize);
++  hist_lines = grub_calloc (newsize, sizeof (grub_uint32_t *));
+ 
+   /* Copy the old lines into the new buffer.  */
+   if (old_hist_lines)
+@@ -114,7 +114,7 @@ static void
+ grub_history_set (int pos, grub_uint32_t *s, grub_size_t len)
+ {
+   grub_free (hist_lines[pos]);
+-  hist_lines[pos] = grub_malloc ((len + 1) * sizeof (grub_uint32_t));
++  hist_lines[pos] = grub_calloc (len + 1, sizeof (grub_uint32_t));
+   if (!hist_lines[pos])
+     {
+       grub_print_error ();
+@@ -349,7 +349,7 @@ grub_cmdline_get (const char *prompt_translated)
+   char *ret;
+   unsigned nterms;
+ 
+-  buf = grub_malloc (max_len * sizeof (grub_uint32_t));
++  buf = grub_calloc (max_len, sizeof (grub_uint32_t));
+   if (!buf)
+     return 0;
+ 
+@@ -377,7 +377,7 @@ grub_cmdline_get (const char *prompt_translated)
+     FOR_ACTIVE_TERM_OUTPUTS(cur)
+       nterms++;
+ 
+-    cl_terms = grub_malloc (sizeof (cl_terms[0]) * nterms);
++    cl_terms = grub_calloc (nterms, sizeof (cl_terms[0]));
+     if (!cl_terms)
+       {
+ 	grub_free (buf);
+@@ -385,7 +385,7 @@ grub_cmdline_get (const char *prompt_translated)
+       }
+     cl_term_cur = cl_terms;
+ 
+-    unicode_msg = grub_malloc (msg_len * sizeof (grub_uint32_t));
++    unicode_msg = grub_calloc (msg_len, sizeof (grub_uint32_t));
+     if (!unicode_msg)
+       {
+ 	grub_free (buf);
+@@ -495,7 +495,7 @@ grub_cmdline_get (const char *prompt_translated)
+ 		grub_uint32_t *insert;
+ 
+ 		insertlen = grub_strlen (insertu8);
+-		insert = grub_malloc ((insertlen + 1) * sizeof (grub_uint32_t));
++		insert = grub_calloc (insertlen + 1, sizeof (grub_uint32_t));
+ 		if (!insert)
+ 		  {
+ 		    grub_free (insertu8);
+@@ -602,7 +602,7 @@ grub_cmdline_get (const char *prompt_translated)
+ 
+ 	      grub_free (kill_buf);
+ 
+-	      kill_buf = grub_malloc ((n + 1) * sizeof(grub_uint32_t));
++	      kill_buf = grub_calloc (n + 1, sizeof (grub_uint32_t));
+ 	      if (grub_errno)
+ 		{
+ 		  grub_print_error ();
+diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c
+index cdf3590a36..1993995be6 100644
+--- a/grub-core/normal/menu_entry.c
++++ b/grub-core/normal/menu_entry.c
+@@ -95,8 +95,8 @@ init_line (struct screen *screen, struct line *linep)
+ {
+   linep->len = 0;
+   linep->max_len = 80;
+-  linep->buf = grub_malloc ((linep->max_len + 1) * sizeof (linep->buf[0]));
+-  linep->pos = grub_zalloc (screen->nterms * sizeof (linep->pos[0]));
++  linep->buf = grub_calloc (linep->max_len + 1, sizeof (linep->buf[0]));
++  linep->pos = grub_calloc (screen->nterms, sizeof (linep->pos[0]));
+   if (! linep->buf || !linep->pos)
+     {
+       grub_free (linep->buf);
+@@ -287,7 +287,7 @@ update_screen (struct screen *screen, struct per_term_screen *term_screen,
+ 	  pos = linep->pos + (term_screen - screen->terms);
+ 
+ 	  if (!*pos)
+-	    *pos = grub_zalloc ((linep->len + 1) * sizeof (**pos));
++	    *pos = grub_calloc (linep->len + 1, sizeof (**pos));
+ 
+ 	  if (i == region_start || linep == screen->lines + screen->line
+ 	      || (i > region_start && mode == ALL_LINES))
+@@ -471,7 +471,7 @@ insert_string (struct screen *screen, const char *s, int update)
+ 
+ 	  /* Insert the string.  */
+ 	  current_linep = screen->lines + screen->line;
+-	  unicode_msg = grub_malloc ((p - s) * sizeof (grub_uint32_t));
++	  unicode_msg = grub_calloc (p - s, sizeof (grub_uint32_t));
+ 
+ 	  if (!unicode_msg)
+ 	    return 0;
+@@ -1023,7 +1023,7 @@ complete (struct screen *screen, int continuous, int update)
+   if (completion_buffer.buf)
+     {
+       buflen = grub_strlen (completion_buffer.buf);
+-      ucs4 = grub_malloc (sizeof (grub_uint32_t) * (buflen + 1));
++      ucs4 = grub_calloc (buflen + 1, sizeof (grub_uint32_t));
+       
+       if (!ucs4)
+ 	{
+@@ -1268,7 +1268,7 @@ grub_menu_entry_run (grub_menu_entry_t entry)
+   for (i = 0; i < (unsigned) screen->num_lines; i++)
+     {
+       grub_free (screen->lines[i].pos);
+-      screen->lines[i].pos = grub_zalloc (screen->nterms * sizeof (screen->lines[i].pos[0]));
++      screen->lines[i].pos = grub_calloc (screen->nterms, sizeof (screen->lines[i].pos[0]));
+       if (! screen->lines[i].pos)
+ 	{
+ 	  grub_print_error ();
+@@ -1278,7 +1278,7 @@ grub_menu_entry_run (grub_menu_entry_t entry)
+ 	}
+     }
+ 
+-  screen->terms = grub_zalloc (screen->nterms * sizeof (screen->terms[0]));
++  screen->terms = grub_calloc (screen->nterms, sizeof (screen->terms[0]));
+   if (!screen->terms)
+     {
+       grub_print_error ();
+diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
+index e22bb91f6e..18240e76ce 100644
+--- a/grub-core/normal/menu_text.c
++++ b/grub-core/normal/menu_text.c
+@@ -78,7 +78,7 @@ grub_print_message_indented_real (const char *msg, int margin_left,
+   grub_size_t msg_len = grub_strlen (msg) + 2;
+   int ret = 0;
+ 
+-  unicode_msg = grub_malloc (msg_len * sizeof (grub_uint32_t));
++  unicode_msg = grub_calloc (msg_len, sizeof (grub_uint32_t));
+  
+   if (!unicode_msg)
+     return 0;
+@@ -211,7 +211,7 @@ print_entry (int y, int highlight, grub_menu_entry_t entry,
+ 
+   title = entry ? entry->title : "";
+   title_len = grub_strlen (title);
+-  unicode_title = grub_malloc (title_len * sizeof (*unicode_title));
++  unicode_title = grub_calloc (title_len, sizeof (*unicode_title));
+   if (! unicode_title)
+     /* XXX How to show this error?  */
+     return;
+diff --git a/grub-core/normal/term.c b/grub-core/normal/term.c
+index a1e5c5a0da..cc8c173b6e 100644
+--- a/grub-core/normal/term.c
++++ b/grub-core/normal/term.c
+@@ -264,7 +264,7 @@ grub_term_save_pos (void)
+   FOR_ACTIVE_TERM_OUTPUTS(cur)
+     cnt++;
+ 
+-  ret = grub_malloc (cnt * sizeof (ret[0]));
++  ret = grub_calloc (cnt, sizeof (ret[0]));
+   if (!ret)
+     return NULL;
+ 
+@@ -1013,7 +1013,7 @@ grub_xnputs (const char *str, grub_size_t msg_len)
+ 
+   grub_error_push ();
+ 
+-  unicode_str = grub_malloc (msg_len * sizeof (grub_uint32_t));
++  unicode_str = grub_calloc (msg_len, sizeof (grub_uint32_t));
+  
+   grub_error_pop ();
+ 
+diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
+index 7adc0f30ee..a5bd0752fb 100644
+--- a/grub-core/osdep/linux/getroot.c
++++ b/grub-core/osdep/linux/getroot.c
+@@ -168,7 +168,7 @@ grub_util_raid_getmembers (const char *name, int bootable)
+   if (ret != 0)
+     grub_util_error (_("ioctl GET_ARRAY_INFO error: %s"), strerror (errno));
+ 
+-  devicelist = xmalloc ((info.nr_disks + 1) * sizeof (char *));
++  devicelist = xcalloc (info.nr_disks + 1, sizeof (char *));
+ 
+   for (i = 0, j = 0; j < info.nr_disks; i++)
+     {
+@@ -241,7 +241,7 @@ grub_find_root_devices_from_btrfs (const char *dir)
+       return NULL;
+     }
+ 
+-  ret = xmalloc ((fsi.num_devices + 1) * sizeof (ret[0]));
++  ret = xcalloc (fsi.num_devices + 1, sizeof (ret[0]));
+ 
+   for (i = 1; i <= fsi.max_id && j < fsi.num_devices; i++)
+     {
+@@ -396,7 +396,7 @@ grub_find_root_devices_from_mountinfo (const char *dir, char **relroot)
+   if (relroot)
+     *relroot = NULL;
+ 
+-  entries = xmalloc (entry_max * sizeof (*entries));
++  entries = xcalloc (entry_max, sizeof (*entries));
+ 
+ again:
+   fp = grub_util_fopen ("/proc/self/mountinfo", "r");
+diff --git a/grub-core/osdep/unix/config.c b/grub-core/osdep/unix/config.c
+index 5478030fde..89dc70d93c 100644
+--- a/grub-core/osdep/unix/config.c
++++ b/grub-core/osdep/unix/config.c
+@@ -130,7 +130,7 @@ grub_util_load_config (struct grub_util_config *cfg)
+   if (num_cfgpaths == 0)
+     goto out;
+ 
+-  sorted_cfgpaths = xmalloc (num_cfgpaths * sizeof (*sorted_cfgpaths));
++  sorted_cfgpaths = xcalloc (num_cfgpaths, sizeof (*sorted_cfgpaths));
+   i = 0;
+   if (grub_util_is_regular (cfgfile))
+     sorted_cfgpaths[i++] = xstrdup (cfgfile);
+diff --git a/grub-core/osdep/windows/getroot.c b/grub-core/osdep/windows/getroot.c
+index 661d954619..eada663b26 100644
+--- a/grub-core/osdep/windows/getroot.c
++++ b/grub-core/osdep/windows/getroot.c
+@@ -59,7 +59,7 @@ grub_get_mount_point (const TCHAR *path)
+ 
+   for (ptr = path; *ptr; ptr++);
+   allocsize = (ptr - path + 10) * 2;
+-  out = xmalloc (allocsize * sizeof (out[0]));
++  out = xcalloc (allocsize, sizeof (out[0]));
+ 
+   /* When pointing to EFI system partition GetVolumePathName fails
+      for ESP root and returns abberant information for everything
+diff --git a/grub-core/osdep/windows/hostdisk.c b/grub-core/osdep/windows/hostdisk.c
+index 355100789a..0be3273949 100644
+--- a/grub-core/osdep/windows/hostdisk.c
++++ b/grub-core/osdep/windows/hostdisk.c
+@@ -111,7 +111,7 @@ grub_util_get_windows_path_real (const char *path)
+ 
+   while (1)
+     {
+-      fpa = xmalloc (alloc * sizeof (fpa[0]));
++      fpa = xcalloc (alloc, sizeof (fpa[0]));
+ 
+       len = GetFullPathName (tpath, alloc, fpa, NULL);
+       if (len >= alloc)
+@@ -399,7 +399,7 @@ grub_util_fd_opendir (const char *name)
+   for (l = 0; name_windows[l]; l++);
+   for (l--; l >= 0 && (name_windows[l] == '\\' || name_windows[l] == '/'); l--);
+   l++;
+-  pattern = xmalloc ((l + 3) * sizeof (pattern[0]));
++  pattern = xcalloc (l + 3, sizeof (pattern[0]));
+   memcpy (pattern, name_windows, l * sizeof (pattern[0]));
+   pattern[l] = '\\';
+   pattern[l + 1] = '*';
+diff --git a/grub-core/osdep/windows/init.c b/grub-core/osdep/windows/init.c
+index e8ffd62c6a..6297de6326 100644
+--- a/grub-core/osdep/windows/init.c
++++ b/grub-core/osdep/windows/init.c
+@@ -161,7 +161,7 @@ grub_util_host_init (int *argc __attribute__ ((unused)),
+   LPWSTR *targv;
+ 
+   targv = CommandLineToArgvW (tcmdline, argc);
+-  *argv = xmalloc ((*argc + 1) * sizeof (argv[0]));
++  *argv = xcalloc (*argc + 1, sizeof (argv[0]));
+ 
+   for (i = 0; i < *argc; i++)
+     (*argv)[i] = grub_util_tchar_to_utf8 (targv[i]); 
+diff --git a/grub-core/osdep/windows/platform.c b/grub-core/osdep/windows/platform.c
+index a3f738fb9b..b160949d8e 100644
+--- a/grub-core/osdep/windows/platform.c
++++ b/grub-core/osdep/windows/platform.c
+@@ -231,8 +231,8 @@ grub_install_register_efi (grub_device_t efidir_grub_dev, const char *efidir,
+     grub_util_error ("%s", _("no EFI routines are available when running in BIOS mode"));
+ 
+   distrib8_len = grub_strlen (efi_distributor);
+-  distributor16 = xmalloc ((distrib8_len + 1) * GRUB_MAX_UTF16_PER_UTF8
+-			   * sizeof (grub_uint16_t));
++  distributor16 = xcalloc (distrib8_len + 1,
++			   GRUB_MAX_UTF16_PER_UTF8 * sizeof (grub_uint16_t));
+   distrib16_len = grub_utf8_to_utf16 (distributor16, distrib8_len * GRUB_MAX_UTF16_PER_UTF8,
+ 				      (const grub_uint8_t *) efi_distributor,
+ 				      distrib8_len, 0);
+diff --git a/grub-core/osdep/windows/relpath.c b/grub-core/osdep/windows/relpath.c
+index cb0861744a..478e8ef14d 100644
+--- a/grub-core/osdep/windows/relpath.c
++++ b/grub-core/osdep/windows/relpath.c
+@@ -72,7 +72,7 @@ grub_make_system_path_relative_to_its_root (const char *path)
+       if (dirwindows[0] && dirwindows[1] == ':')
+ 	offset = 2;
+     }
+-  ret = xmalloc (sizeof (ret[0]) * (flen - offset + 2));
++  ret = xcalloc (flen - offset + 2, sizeof (ret[0]));
+   if (dirwindows[offset] != '\\'
+       && dirwindows[offset] != '/'
+       && dirwindows[offset])
+diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c
+index 103f6796f3..72a2e37cd4 100644
+--- a/grub-core/partmap/gpt.c
++++ b/grub-core/partmap/gpt.c
+@@ -199,7 +199,7 @@ gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
+   *nsectors = ctx.len;
+   if (*nsectors > max_nsectors)
+     *nsectors = max_nsectors;
+-  *sectors = grub_malloc (*nsectors * sizeof (**sectors));
++  *sectors = grub_calloc (*nsectors, sizeof (**sectors));
+   if (!*sectors)
+     return grub_errno;
+   for (i = 0; i < *nsectors; i++)
+diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c
+index 7b8e450762..ee3f24982b 100644
+--- a/grub-core/partmap/msdos.c
++++ b/grub-core/partmap/msdos.c
+@@ -337,7 +337,7 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
+       avail_nsectors = *nsectors;
+       if (*nsectors > max_nsectors)
+ 	*nsectors = max_nsectors;
+-      *sectors = grub_malloc (*nsectors * sizeof (**sectors));
++      *sectors = grub_calloc (*nsectors, sizeof (**sectors));
+       if (!*sectors)
+ 	return grub_errno;
+       for (i = 0; i < *nsectors; i++)
+diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
+index ee299fd0ea..c8d6806fe0 100644
+--- a/grub-core/script/execute.c
++++ b/grub-core/script/execute.c
+@@ -553,7 +553,7 @@ gettext_append (struct grub_script_argv *result, const char *orig_str)
+   for (iptr = orig_str; *iptr; iptr++)
+     if (*iptr == '$')
+       dollar_cnt++;
+-  ctx.allowed_strings = grub_malloc (sizeof (ctx.allowed_strings[0]) * dollar_cnt);
++  ctx.allowed_strings = grub_calloc (dollar_cnt, sizeof (ctx.allowed_strings[0]));
+ 
+   if (parse_string (orig_str, gettext_save_allow, &ctx, 0))
+     goto fail;
+diff --git a/grub-core/tests/fake_input.c b/grub-core/tests/fake_input.c
+index 2d60852989..b5eb516be2 100644
+--- a/grub-core/tests/fake_input.c
++++ b/grub-core/tests/fake_input.c
+@@ -49,7 +49,7 @@ grub_terminal_input_fake_sequence (int *seq_in, int nseq_in)
+     saved = grub_term_inputs;
+   if (seq)
+     grub_free (seq);
+-  seq = grub_malloc (nseq_in * sizeof (seq[0]));
++  seq = grub_calloc (nseq_in, sizeof (seq[0]));
+   if (!seq)
+     return;
+ 
+diff --git a/grub-core/tests/video_checksum.c b/grub-core/tests/video_checksum.c
+index 74d5b65e5c..44d0810698 100644
+--- a/grub-core/tests/video_checksum.c
++++ b/grub-core/tests/video_checksum.c
+@@ -336,7 +336,7 @@ grub_video_capture_write_bmp (const char *fname,
+     {
+     case 4:
+       {
+-	grub_uint8_t *buffer = xmalloc (mode_info->width * 3);
++	grub_uint8_t *buffer = xcalloc (3, mode_info->width);
+ 	grub_uint32_t rmask = ((1 << mode_info->red_mask_size) - 1);
+ 	grub_uint32_t gmask = ((1 << mode_info->green_mask_size) - 1);
+ 	grub_uint32_t bmask = ((1 << mode_info->blue_mask_size) - 1);
+@@ -367,7 +367,7 @@ grub_video_capture_write_bmp (const char *fname,
+       }
+     case 3:
+       {
+-	grub_uint8_t *buffer = xmalloc (mode_info->width * 3);
++	grub_uint8_t *buffer = xcalloc (3, mode_info->width);
+ 	grub_uint32_t rmask = ((1 << mode_info->red_mask_size) - 1);
+ 	grub_uint32_t gmask = ((1 << mode_info->green_mask_size) - 1);
+ 	grub_uint32_t bmask = ((1 << mode_info->blue_mask_size) - 1);
+@@ -407,7 +407,7 @@ grub_video_capture_write_bmp (const char *fname,
+       }
+     case 2:
+       {
+-	grub_uint8_t *buffer = xmalloc (mode_info->width * 3);
++	grub_uint8_t *buffer = xcalloc (3, mode_info->width);
+ 	grub_uint16_t rmask = ((1 << mode_info->red_mask_size) - 1);
+ 	grub_uint16_t gmask = ((1 << mode_info->green_mask_size) - 1);
+ 	grub_uint16_t bmask = ((1 << mode_info->blue_mask_size) - 1);
+diff --git a/grub-core/video/capture.c b/grub-core/video/capture.c
+index 4f83c74411..4d3195e017 100644
+--- a/grub-core/video/capture.c
++++ b/grub-core/video/capture.c
+@@ -89,7 +89,7 @@ grub_video_capture_start (const struct grub_video_mode_info *mode_info,
+   framebuffer.mode_info = *mode_info;
+   framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info);
+ 
+-  framebuffer.ptr = grub_malloc (framebuffer.mode_info.height * framebuffer.mode_info.pitch);
++  framebuffer.ptr = grub_calloc (framebuffer.mode_info.height, framebuffer.mode_info.pitch);
+   if (!framebuffer.ptr)
+     return grub_errno;
+   
+diff --git a/grub-core/video/emu/sdl.c b/grub-core/video/emu/sdl.c
+index a2f639f66d..0ebab6f57d 100644
+--- a/grub-core/video/emu/sdl.c
++++ b/grub-core/video/emu/sdl.c
+@@ -172,7 +172,7 @@ grub_video_sdl_set_palette (unsigned int start, unsigned int count,
+       if (start + count > mode_info.number_of_colors)
+ 	count = mode_info.number_of_colors - start;
+ 
+-      tmp = grub_malloc (count * sizeof (tmp[0]));
++      tmp = grub_calloc (count, sizeof (tmp[0]));
+       for (i = 0; i < count; i++)
+ 	{
+ 	  tmp[i].r = palette_data[i].r;
+diff --git a/grub-core/video/i386/pc/vga.c b/grub-core/video/i386/pc/vga.c
+index 01f47112d3..b2f776c997 100644
+--- a/grub-core/video/i386/pc/vga.c
++++ b/grub-core/video/i386/pc/vga.c
+@@ -127,7 +127,7 @@ grub_video_vga_setup (unsigned int width, unsigned int height,
+ 
+   vga_height = height ? : 480;
+ 
+-  framebuffer.temporary_buffer = grub_malloc (vga_height * VGA_WIDTH);
++  framebuffer.temporary_buffer = grub_calloc (vga_height, VGA_WIDTH);
+   framebuffer.front_page = 0;
+   framebuffer.back_page = 0;
+   if (!framebuffer.temporary_buffer)
+diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
+index 777e71334c..61bd645379 100644
+--- a/grub-core/video/readers/png.c
++++ b/grub-core/video/readers/png.c
+@@ -309,7 +309,7 @@ grub_png_decode_image_header (struct grub_png_data *data)
+   if (data->is_16bit || data->is_gray || data->is_palette)
+ #endif
+     {
+-      data->image_data = grub_malloc (data->image_height * data->row_bytes);
++      data->image_data = grub_calloc (data->image_height, data->row_bytes);
+       if (grub_errno)
+         return grub_errno;
+ 
+diff --git a/include/grub/unicode.h b/include/grub/unicode.h
+index a0403e91f9..4de986a857 100644
+--- a/include/grub/unicode.h
++++ b/include/grub/unicode.h
+@@ -293,7 +293,7 @@ grub_unicode_glyph_dup (const struct grub_unicode_glyph *in)
+   grub_memcpy (out, in, sizeof (*in));
+   if (in->ncomb > ARRAY_SIZE (out->combining_inline))
+     {
+-      out->combining_ptr = grub_malloc (in->ncomb * sizeof (out->combining_ptr[0]));
++      out->combining_ptr = grub_calloc (in->ncomb, sizeof (out->combining_ptr[0]));
+       if (!out->combining_ptr)
+ 	{
+ 	  grub_free (out);
+@@ -315,7 +315,7 @@ grub_unicode_set_glyph (struct grub_unicode_glyph *out,
+   grub_memcpy (out, in, sizeof (*in));
+   if (in->ncomb > ARRAY_SIZE (out->combining_inline))
+     {
+-      out->combining_ptr = grub_malloc (in->ncomb * sizeof (out->combining_ptr[0]));
++      out->combining_ptr = grub_calloc (in->ncomb, sizeof (out->combining_ptr[0]));
+       if (!out->combining_ptr)
+ 	return;
+       grub_memcpy (out->combining_ptr, in->combining_ptr,
+diff --git a/util/getroot.c b/util/getroot.c
+index cdd41153c5..6ae35ecaa6 100644
+--- a/util/getroot.c
++++ b/util/getroot.c
+@@ -200,7 +200,7 @@ make_device_name (const char *drive)
+   char *ret, *ptr;
+   const char *iptr;
+ 
+-  ret = xmalloc (strlen (drive) * 2);
++  ret = xcalloc (2, strlen (drive));
+   ptr = ret;
+   for (iptr = drive; *iptr; iptr++)
+     {
+diff --git a/util/grub-file.c b/util/grub-file.c
+index 50c18b6835..b2e7dd69f4 100644
+--- a/util/grub-file.c
++++ b/util/grub-file.c
+@@ -54,7 +54,7 @@ main (int argc, char *argv[])
+ 
+   grub_util_host_init (&argc, &argv);
+ 
+-  argv2 = xmalloc (argc * sizeof (argv2[0]));
++  argv2 = xcalloc (argc, sizeof (argv2[0]));
+ 
+   if (argc == 2 && strcmp (argv[1], "--version") == 0)
+     {
+diff --git a/util/grub-fstest.c b/util/grub-fstest.c
+index f14e02d972..57246af7c6 100644
+--- a/util/grub-fstest.c
++++ b/util/grub-fstest.c
+@@ -650,7 +650,7 @@ argp_parser (int key, char *arg, struct argp_state *state)
+   if (args_count < num_disks)
+     {
+       if (args_count == 0)
+-	images = xmalloc (num_disks * sizeof (images[0]));
++	images = xcalloc (num_disks, sizeof (images[0]));
+       images[args_count] = grub_canonicalize_file_name (arg);
+       args_count++;
+       return 0;
+@@ -734,7 +734,7 @@ main (int argc, char *argv[])
+ 
+   grub_util_host_init (&argc, &argv);
+ 
+-  args = xmalloc (argc * sizeof (args[0]));
++  args = xcalloc (argc, sizeof (args[0]));
+ 
+   argp_parse (&argp, argc, argv, 0, 0, 0);
+ 
+diff --git a/util/grub-install-common.c b/util/grub-install-common.c
+index fdfe2c7ead..447504d3f4 100644
+--- a/util/grub-install-common.c
++++ b/util/grub-install-common.c
+@@ -286,7 +286,7 @@ handle_install_list (struct install_list *il, const char *val,
+       il->n_entries++;
+     }
+   il->n_alloc = il->n_entries + 1;
+-  il->entries = xmalloc (il->n_alloc * sizeof (il->entries[0]));
++  il->entries = xcalloc (il->n_alloc, sizeof (il->entries[0]));
+   ptr = val;
+   for (ce = il->entries; ; ce++)
+     {
+diff --git a/util/grub-install.c b/util/grub-install.c
+index f408b19860..843dfc7c80 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -658,7 +658,7 @@ device_map_check_duplicates (const char *dev_map)
+   if (! fp)
+     return;
+ 
+-  d = xmalloc (alloced * sizeof (d[0]));
++  d = xcalloc (alloced, sizeof (d[0]));
+ 
+   while (fgets (buf, sizeof (buf), fp))
+     {
+@@ -1405,7 +1405,7 @@ main (int argc, char *argv[])
+       ndev++;
+     }
+ 
+-  grub_drives = xmalloc (sizeof (grub_drives[0]) * (ndev + 1)); 
++  grub_drives = xcalloc (ndev + 1, sizeof (grub_drives[0]));
+ 
+   for (curdev = grub_devices, curdrive = grub_drives; *curdev; curdev++,
+        curdrive++)
+diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
+index bc087c2b57..d97d0e7bef 100644
+--- a/util/grub-mkimagexx.c
++++ b/util/grub-mkimagexx.c
+@@ -2294,10 +2294,8 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
+ 		      + grub_host_to_target16 (e->e_shstrndx) * smd.section_entsize);
+   smd.strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
+ 
+-  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);
++  smd.addrs = xcalloc (smd.num_sections, sizeof (*smd.addrs));
++  smd.vaddrs = xcalloc (smd.num_sections, sizeof (*smd.vaddrs));
+ 
+   SUFFIX (locate_sections) (e, kernel_path, &smd, layout, image_target);
+ 
+diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c
+index 45d6140d3e..cb972f120b 100644
+--- a/util/grub-mkrescue.c
++++ b/util/grub-mkrescue.c
+@@ -441,8 +441,8 @@ main (int argc, char *argv[])
+   xorriso = xstrdup ("xorriso");
+   label_font = grub_util_path_concat (2, pkgdatadir, "unicode.pf2");
+ 
+-  argp_argv = xmalloc (sizeof (argp_argv[0]) * argc);
+-  xorriso_tail_argv = xmalloc (sizeof (argp_argv[0]) * argc);
++  argp_argv = xcalloc (argc, sizeof (argp_argv[0]));
++  xorriso_tail_argv = xcalloc (argc, sizeof (argp_argv[0]));
+ 
+   xorriso_tail_argc = 0;
+   /* Program name */
+diff --git a/util/grub-mkstandalone.c b/util/grub-mkstandalone.c
+index 4907d44c0b..edf309717c 100644
+--- a/util/grub-mkstandalone.c
++++ b/util/grub-mkstandalone.c
+@@ -296,7 +296,7 @@ main (int argc, char *argv[])
+   grub_util_host_init (&argc, &argv);
+   grub_util_disable_fd_syncs ();
+ 
+-  files = xmalloc ((argc + 1) * sizeof (files[0]));
++  files = xcalloc (argc + 1, sizeof (files[0]));
+ 
+   argp_parse (&argp, argc, argv, 0, 0, 0);
+ 
+diff --git a/util/grub-pe2elf.c b/util/grub-pe2elf.c
+index 0d4084a108..11331294f1 100644
+--- a/util/grub-pe2elf.c
++++ b/util/grub-pe2elf.c
+@@ -100,9 +100,9 @@ write_section_data (FILE* fp, const char *name, char *image,
+   char *pe_strtab = (image + pe_chdr->symtab_offset
+ 		     + pe_chdr->num_symbols * sizeof (struct grub_pe32_symbol));
+ 
+-  section_map = xmalloc ((2 * pe_chdr->num_sections + 5) * sizeof (int));
++  section_map = xcalloc (2 * pe_chdr->num_sections + 5, sizeof (int));
+   section_map[0] = 0;
+-  shdr = xmalloc ((2 * pe_chdr->num_sections + 5) * sizeof (shdr[0]));
++  shdr = xcalloc (2 * pe_chdr->num_sections + 5, sizeof (shdr[0]));
+   idx = 1;
+   idx_reloc = pe_chdr->num_sections + 1;
+ 
+@@ -233,7 +233,7 @@ write_reloc_section (FILE* fp, const char *name, char *image,
+ 
+       pe_sec = pe_shdr + shdr[i].sh_link;
+       pe_rel = (struct grub_pe32_reloc *) (image + pe_sec->relocations_offset);
+-      rel = (elf_reloc_t *) xmalloc (pe_sec->num_relocations * sizeof (elf_reloc_t));
++      rel = (elf_reloc_t *) xcalloc (pe_sec->num_relocations, sizeof (elf_reloc_t));
+       num_rels = 0;
+       modified = 0;
+ 
+@@ -365,12 +365,10 @@ write_symbol_table (FILE* fp, const char *name, char *image,
+   pe_symtab = (struct grub_pe32_symbol *) (image + pe_chdr->symtab_offset);
+   pe_strtab = (char *) (pe_symtab + pe_chdr->num_symbols);
+ 
+-  symtab = (Elf_Sym *) xmalloc ((pe_chdr->num_symbols + 1) *
+-				sizeof (Elf_Sym));
+-  memset (symtab, 0, (pe_chdr->num_symbols + 1) * sizeof (Elf_Sym));
++  symtab = (Elf_Sym *) xcalloc (pe_chdr->num_symbols + 1, sizeof (Elf_Sym));
+   num_syms = 1;
+ 
+-  symtab_map = (int *) xmalloc (pe_chdr->num_symbols * sizeof (int));
++  symtab_map = (int *) xcalloc (pe_chdr->num_symbols, sizeof (int));
+ 
+   for (i = 0; i < (int) pe_chdr->num_symbols;
+        i += pe_symtab->num_aux + 1, pe_symtab += pe_symtab->num_aux + 1)
+diff --git a/util/grub-probe.c b/util/grub-probe.c
+index 81d27eead5..cbe6ed94ca 100644
+--- a/util/grub-probe.c
++++ b/util/grub-probe.c
+@@ -361,8 +361,8 @@ probe (const char *path, char **device_names, char delim)
+       grub_util_pull_device (*curdev);
+       ndev++;
+     }
+-  
+-  drives_names = xmalloc (sizeof (drives_names[0]) * (ndev + 1)); 
++
++  drives_names = xcalloc (ndev + 1, sizeof (drives_names[0]));
+ 
+   for (curdev = device_names, curdrive = drives_names; *curdev; curdev++,
+        curdrive++)
diff --git a/debian/patches/0085-malloc-Use-overflow-checking-primitives-where-we-do-.patch b/debian/patches/0085-malloc-Use-overflow-checking-primitives-where-we-do-.patch
new file mode 100644
index 0000000..e0bb952
--- /dev/null
+++ b/debian/patches/0085-malloc-Use-overflow-checking-primitives-where-we-do-.patch
@@ -0,0 +1,1319 @@
+From 83e59f56362e11618083f376cbf700861d6b8f2a Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 15 Jun 2020 12:28:27 -0400
+Subject: malloc: Use overflow checking primitives where we do complex
+ allocations
+
+This attempts to fix the places where we do the following where
+arithmetic_expr may include unvalidated data:
+
+  X = grub_malloc(arithmetic_expr);
+
+It accomplishes this by doing the arithmetic ahead of time using grub_add(),
+grub_sub(), grub_mul() and testing for overflow before proceeding.
+
+Among other issues, this fixes:
+  - allocation of integer overflow in grub_video_bitmap_create()
+    reported by Chris Coulson,
+  - allocation of integer overflow in grub_png_decode_image_header()
+    reported by Chris Coulson,
+  - allocation of integer overflow in grub_squash_read_symlink()
+    reported by Chris Coulson,
+  - allocation of integer overflow in grub_ext2_read_symlink()
+    reported by Chris Coulson,
+  - allocation of integer overflow in read_section_as_string()
+    reported by Chris Coulson.
+
+Fixes: CVE-2020-14309, CVE-2020-14310, CVE-2020-14311
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/commands/legacycfg.c | 29 +++++++++++++++----
+ grub-core/commands/wildcard.c  | 36 ++++++++++++++++++++----
+ grub-core/disk/ldm.c           | 32 +++++++++++++++------
+ grub-core/font/font.c          |  7 ++++-
+ grub-core/fs/btrfs.c           | 28 +++++++++++++------
+ grub-core/fs/ext2.c            | 10 ++++++-
+ grub-core/fs/iso9660.c         | 51 ++++++++++++++++++++++++----------
+ grub-core/fs/sfs.c             | 27 ++++++++++++++----
+ grub-core/fs/squash4.c         | 45 ++++++++++++++++++++++--------
+ grub-core/fs/udf.c             | 41 +++++++++++++++++----------
+ grub-core/fs/xfs.c             | 11 +++++---
+ grub-core/fs/zfs/zfs.c         | 22 ++++++++++-----
+ grub-core/fs/zfs/zfscrypt.c    |  7 ++++-
+ grub-core/lib/arg.c            | 20 +++++++++++--
+ grub-core/loader/i386/bsd.c    |  8 +++++-
+ grub-core/net/dns.c            |  9 +++++-
+ grub-core/normal/charset.c     | 10 +++++--
+ grub-core/normal/cmdline.c     | 14 ++++++++--
+ grub-core/normal/menu_entry.c  | 13 +++++++--
+ grub-core/script/argv.c        | 16 +++++++++--
+ grub-core/script/lexer.c       | 21 ++++++++++++--
+ grub-core/video/bitmap.c       | 25 +++++++++++------
+ grub-core/video/readers/png.c  | 13 +++++++--
+ 23 files changed, 382 insertions(+), 113 deletions(-)
+
+diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c
+index 5e3ec0d5e4..cc5971f4db 100644
+--- a/grub-core/commands/legacycfg.c
++++ b/grub-core/commands/legacycfg.c
+@@ -32,6 +32,7 @@
+ #include <grub/auth.h>
+ #include <grub/disk.h>
+ #include <grub/partition.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -104,13 +105,22 @@ legacy_file (const char *filename)
+ 	if (newsuffix)
+ 	  {
+ 	    char *t;
+-	    
++	    grub_size_t sz;
++
++	    if (grub_add (grub_strlen (suffix), grub_strlen (newsuffix), &sz) ||
++		grub_add (sz, 1, &sz))
++	      {
++		grub_errno = GRUB_ERR_OUT_OF_RANGE;
++		goto fail_0;
++	      }
++
+ 	    t = suffix;
+-	    suffix = grub_realloc (suffix, grub_strlen (suffix)
+-				   + grub_strlen (newsuffix) + 1);
++	    suffix = grub_realloc (suffix, sz);
+ 	    if (!suffix)
+ 	      {
+ 		grub_free (t);
++
++ fail_0:
+ 		grub_free (entrysrc);
+ 		grub_free (parsed);
+ 		grub_free (newsuffix);
+@@ -154,13 +164,22 @@ legacy_file (const char *filename)
+ 	  else
+ 	    {
+ 	      char *t;
++	      grub_size_t sz;
++
++	      if (grub_add (grub_strlen (entrysrc), grub_strlen (parsed), &sz) ||
++		  grub_add (sz, 1, &sz))
++		{
++		  grub_errno = GRUB_ERR_OUT_OF_RANGE;
++		  goto fail_1;
++		}
+ 
+ 	      t = entrysrc;
+-	      entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc)
+-				       + grub_strlen (parsed) + 1);
++	      entrysrc = grub_realloc (entrysrc, sz);
+ 	      if (!entrysrc)
+ 		{
+ 		  grub_free (t);
++
++ fail_1:
+ 		  grub_free (parsed);
+ 		  grub_free (suffix);
+ 		  return grub_errno;
+diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c
+index 4a106ca040..cc3290311f 100644
+--- a/grub-core/commands/wildcard.c
++++ b/grub-core/commands/wildcard.c
+@@ -23,6 +23,7 @@
+ #include <grub/file.h>
+ #include <grub/device.h>
+ #include <grub/script_sh.h>
++#include <grub/safemath.h>
+ 
+ #include <regex.h>
+ 
+@@ -48,6 +49,7 @@ merge (char **dest, char **ps)
+   int i;
+   int j;
+   char **p;
++  grub_size_t sz;
+ 
+   if (! dest)
+     return ps;
+@@ -60,7 +62,12 @@ merge (char **dest, char **ps)
+   for (j = 0; ps[j]; j++)
+     ;
+ 
+-  p = grub_realloc (dest, sizeof (char*) * (i + j + 1));
++  if (grub_add (i, j, &sz) ||
++      grub_add (sz, 1, &sz) ||
++      grub_mul (sz, sizeof (char *), &sz))
++    return dest;
++
++  p = grub_realloc (dest, sz);
+   if (! p)
+     {
+       grub_free (dest);
+@@ -115,8 +122,15 @@ make_regex (const char *start, const char *end, regex_t *regexp)
+   char ch;
+   int i = 0;
+   unsigned len = end - start;
+-  char *buffer = grub_malloc (len * 2 + 2 + 1); /* worst case size. */
++  char *buffer;
++  grub_size_t sz;
+ 
++  /* Worst case size is (len * 2 + 2 + 1). */
++  if (grub_mul (len, 2, &sz) ||
++      grub_add (sz, 3, &sz))
++    return 1;
++
++  buffer = grub_malloc (sz);
+   if (! buffer)
+     return 1;
+ 
+@@ -226,6 +240,7 @@ match_devices_iter (const char *name, void *data)
+   struct match_devices_ctx *ctx = data;
+   char **t;
+   char *buffer;
++  grub_size_t sz;
+ 
+   /* skip partitions if asked to. */
+   if (ctx->noparts && grub_strchr (name, ','))
+@@ -239,11 +254,16 @@ match_devices_iter (const char *name, void *data)
+   if (regexec (ctx->regexp, buffer, 0, 0, 0))
+     {
+       grub_dprintf ("expand", "not matched\n");
++ fail:
+       grub_free (buffer);
+       return 0;
+     }
+ 
+-  t = grub_realloc (ctx->devs, sizeof (char*) * (ctx->ndev + 2));
++  if (grub_add (ctx->ndev, 2, &sz) ||
++      grub_mul (sz, sizeof (char *), &sz))
++    goto fail;
++
++  t = grub_realloc (ctx->devs, sz);
+   if (! t)
+     {
+       grub_free (buffer);
+@@ -300,6 +320,7 @@ match_files_iter (const char *name,
+   struct match_files_ctx *ctx = data;
+   char **t;
+   char *buffer;
++  grub_size_t sz;
+ 
+   /* skip . and .. names */
+   if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0)
+@@ -315,9 +336,14 @@ match_files_iter (const char *name,
+   if (! buffer)
+     return 1;
+ 
+-  t = grub_realloc (ctx->files, sizeof (char*) * (ctx->nfile + 2));
+-  if (! t)
++  if (grub_add (ctx->nfile, 2, &sz) ||
++      grub_mul (sz, sizeof (char *), &sz))
++    goto fail;
++
++  t = grub_realloc (ctx->files, sz);
++  if (!t)
+     {
++ fail:
+       grub_free (buffer);
+       return 1;
+     }
+diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
+index e6323701ab..58f8a53e1a 100644
+--- a/grub-core/disk/ldm.c
++++ b/grub-core/disk/ldm.c
+@@ -25,6 +25,7 @@
+ #include <grub/msdos_partition.h>
+ #include <grub/gpt_partition.h>
+ #include <grub/i18n.h>
++#include <grub/safemath.h>
+ 
+ #ifdef GRUB_UTIL
+ #include <grub/emu/misc.h>
+@@ -289,6 +290,7 @@ make_vg (grub_disk_t disk,
+       struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
+ 				/ sizeof (struct grub_ldm_vblk)];
+       unsigned i;
++      grub_size_t sz;
+       err = grub_disk_read (disk, cursec, 0,
+ 			    sizeof(vblk), &vblk);
+       if (err)
+@@ -350,7 +352,13 @@ make_vg (grub_disk_t disk,
+ 	      grub_free (lv);
+ 	      goto fail2;
+ 	    }
+-	  lv->name = grub_malloc (*ptr + 1);
++	  if (grub_add (*ptr, 1, &sz))
++	    {
++	      grub_free (lv->internal_id);
++	      grub_free (lv);
++	      goto fail2;
++	    }
++	  lv->name = grub_malloc (sz);
+ 	  if (!lv->name)
+ 	    {
+ 	      grub_free (lv->internal_id);
+@@ -599,10 +607,13 @@ make_vg (grub_disk_t disk,
+ 	  if (lv->segments->node_alloc == lv->segments->node_count)
+ 	    {
+ 	      void *t;
+-	      lv->segments->node_alloc *= 2; 
+-	      t = grub_realloc (lv->segments->nodes,
+-				sizeof (*lv->segments->nodes)
+-				* lv->segments->node_alloc);
++	      grub_size_t sz;
++
++	      if (grub_mul (lv->segments->node_alloc, 2, &lv->segments->node_alloc) ||
++		  grub_mul (lv->segments->node_alloc, sizeof (*lv->segments->nodes), &sz))
++		goto fail2;
++
++	      t = grub_realloc (lv->segments->nodes, sz);
+ 	      if (!t)
+ 		goto fail2;
+ 	      lv->segments->nodes = t;
+@@ -723,10 +734,13 @@ make_vg (grub_disk_t disk,
+ 	      if (comp->segment_alloc == comp->segment_count)
+ 		{
+ 		  void *t;
+-		  comp->segment_alloc *= 2;
+-		  t = grub_realloc (comp->segments,
+-				    comp->segment_alloc
+-				    * sizeof (*comp->segments));
++		  grub_size_t sz;
++
++		  if (grub_mul (comp->segment_alloc, 2, &comp->segment_alloc) ||
++		      grub_mul (comp->segment_alloc, sizeof (*comp->segments), &sz))
++		    goto fail2;
++
++		  t = grub_realloc (comp->segments, sz);
+ 		  if (!t)
+ 		    goto fail2;
+ 		  comp->segments = t;
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index 8e118b315c..5edb477ac2 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -30,6 +30,7 @@
+ #include <grub/unicode.h>
+ #include <grub/fontformat.h>
+ #include <grub/env.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -360,9 +361,13 @@ static char *
+ read_section_as_string (struct font_file_section *section)
+ {
+   char *str;
++  grub_size_t sz;
+   grub_ssize_t ret;
+ 
+-  str = grub_malloc (section->length + 1);
++  if (grub_add (section->length, 1, &sz))
++    return NULL;
++
++  str = grub_malloc (sz);
+   if (!str)
+     return 0;
+ 
+diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
+index 11272efc1a..2b65bd56a0 100644
+--- a/grub-core/fs/btrfs.c
++++ b/grub-core/fs/btrfs.c
+@@ -40,6 +40,7 @@
+ #include <grub/btrfs.h>
+ #include <grub/crypto.h>
+ #include <grub/diskfilter.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -329,9 +330,13 @@ save_ref (struct grub_btrfs_leaf_descriptor *desc,
+   if (desc->allocated < desc->depth)
+     {
+       void *newdata;
+-      desc->allocated *= 2;
+-      newdata = grub_realloc (desc->data, sizeof (desc->data[0])
+-			      * desc->allocated);
++      grub_size_t sz;
++
++      if (grub_mul (desc->allocated, 2, &desc->allocated) ||
++	  grub_mul (desc->allocated, sizeof (desc->data[0]), &sz))
++	return GRUB_ERR_OUT_OF_RANGE;
++
++      newdata = grub_realloc (desc->data, sz);
+       if (!newdata)
+ 	return grub_errno;
+       desc->data = newdata;
+@@ -622,16 +627,21 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id)
+   if (data->n_devices_attached > data->n_devices_allocated)
+     {
+       void *tmp;
+-      data->n_devices_allocated = 2 * data->n_devices_attached + 1;
+-      data->devices_attached
+-	= grub_realloc (tmp = data->devices_attached,
+-			data->n_devices_allocated
+-			* sizeof (data->devices_attached[0]));
++      grub_size_t sz;
++
++      if (grub_mul (data->n_devices_attached, 2, &data->n_devices_allocated) ||
++	  grub_add (data->n_devices_allocated, 1, &data->n_devices_allocated) ||
++	  grub_mul (data->n_devices_allocated, sizeof (data->devices_attached[0]), &sz))
++	goto fail;
++
++      data->devices_attached = grub_realloc (tmp = data->devices_attached, sz);
+       if (!data->devices_attached)
+ 	{
++	  data->devices_attached = tmp;
++
++ fail:
+ 	  if (ctx.dev_found)
+ 	    grub_device_close (ctx.dev_found);
+-	  data->devices_attached = tmp;
+ 	  return NULL;
+ 	}
+     }
+diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
+index 9b389802a3..ac33bcd68c 100644
+--- a/grub-core/fs/ext2.c
++++ b/grub-core/fs/ext2.c
+@@ -46,6 +46,7 @@
+ #include <grub/dl.h>
+ #include <grub/types.h>
+ #include <grub/fshelp.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -703,6 +704,7 @@ grub_ext2_read_symlink (grub_fshelp_node_t node)
+ {
+   char *symlink;
+   struct grub_fshelp_node *diro = node;
++  grub_size_t sz;
+ 
+   if (! diro->inode_read)
+     {
+@@ -717,7 +719,13 @@ grub_ext2_read_symlink (grub_fshelp_node_t node)
+        }
+     }
+ 
+-  symlink = grub_malloc (grub_le_to_cpu32 (diro->inode.size) + 1);
++  if (grub_add (grub_le_to_cpu32 (diro->inode.size), 1, &sz))
++    {
++      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
++      return NULL;
++    }
++
++  symlink = grub_malloc (sz);
+   if (! symlink)
+     return 0;
+ 
+diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
+index 4f1b52a552..7ba5b300bc 100644
+--- a/grub-core/fs/iso9660.c
++++ b/grub-core/fs/iso9660.c
+@@ -28,6 +28,7 @@
+ #include <grub/fshelp.h>
+ #include <grub/charset.h>
+ #include <grub/datetime.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -531,8 +532,13 @@ add_part (struct iterate_dir_ctx *ctx,
+ 	  int len2)
+ {
+   int size = ctx->symlink ? grub_strlen (ctx->symlink) : 0;
++  grub_size_t sz;
+ 
+-  ctx->symlink = grub_realloc (ctx->symlink, size + len2 + 1);
++  if (grub_add (size, len2, &sz) ||
++      grub_add (sz, 1, &sz))
++    return;
++
++  ctx->symlink = grub_realloc (ctx->symlink, sz);
+   if (! ctx->symlink)
+     return;
+ 
+@@ -560,17 +566,24 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
+ 	{
+ 	  grub_size_t off = 0, csize = 1;
+ 	  char *old;
++	  grub_size_t sz;
++
+ 	  csize = entry->len - 5;
+ 	  old = ctx->filename;
+ 	  if (ctx->filename_alloc)
+ 	    {
+ 	      off = grub_strlen (ctx->filename);
+-	      ctx->filename = grub_realloc (ctx->filename, csize + off + 1);
++	      if (grub_add (csize, off, &sz) ||
++		  grub_add (sz, 1, &sz))
++		return GRUB_ERR_OUT_OF_RANGE;
++	      ctx->filename = grub_realloc (ctx->filename, sz);
+ 	    }
+ 	  else
+ 	    {
+ 	      off = 0;
+-	      ctx->filename = grub_zalloc (csize + 1);
++	      if (grub_add (csize, 1, &sz))
++		return GRUB_ERR_OUT_OF_RANGE;
++	      ctx->filename = grub_zalloc (sz);
+ 	    }
+ 	  if (!ctx->filename)
+ 	    {
+@@ -776,14 +789,18 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
+ 	    if (node->have_dirents >= node->alloc_dirents)
+ 	      {
+ 		struct grub_fshelp_node *new_node;
+-		node->alloc_dirents *= 2;
+-		new_node = grub_realloc (node, 
+-					 sizeof (struct grub_fshelp_node)
+-					 + ((node->alloc_dirents
+-					     - ARRAY_SIZE (node->dirents))
+-					    * sizeof (node->dirents[0])));
++		grub_size_t sz;
++
++		if (grub_mul (node->alloc_dirents, 2, &node->alloc_dirents) ||
++		    grub_sub (node->alloc_dirents, ARRAY_SIZE (node->dirents), &sz) ||
++		    grub_mul (sz, sizeof (node->dirents[0]), &sz) ||
++		    grub_add (sz, sizeof (struct grub_fshelp_node), &sz))
++		  goto fail_0;
++
++		new_node = grub_realloc (node, sz);
+ 		if (!new_node)
+ 		  {
++ fail_0:
+ 		    if (ctx.filename_alloc)
+ 		      grub_free (ctx.filename);
+ 		    grub_free (node);
+@@ -799,14 +816,18 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
+ 		* sizeof (node->dirents[0]) < grub_strlen (ctx.symlink) + 1)
+ 	      {
+ 		struct grub_fshelp_node *new_node;
+-		new_node = grub_realloc (node,
+-					 sizeof (struct grub_fshelp_node)
+-					 + ((node->alloc_dirents
+-					     - ARRAY_SIZE (node->dirents))
+-					    * sizeof (node->dirents[0]))
+-					 + grub_strlen (ctx.symlink) + 1);
++		grub_size_t sz;
++
++		if (grub_sub (node->alloc_dirents, ARRAY_SIZE (node->dirents), &sz) ||
++		    grub_mul (sz, sizeof (node->dirents[0]), &sz) ||
++		    grub_add (sz, sizeof (struct grub_fshelp_node) + 1, &sz) ||
++		    grub_add (sz, grub_strlen (ctx.symlink), &sz))
++		  goto fail_1;
++
++		new_node = grub_realloc (node, sz);
+ 		if (!new_node)
+ 		  {
++ fail_1:
+ 		    if (ctx.filename_alloc)
+ 		      grub_free (ctx.filename);
+ 		    grub_free (node);
+diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
+index 90f7fb3791..de2b107a4a 100644
+--- a/grub-core/fs/sfs.c
++++ b/grub-core/fs/sfs.c
+@@ -26,6 +26,7 @@
+ #include <grub/types.h>
+ #include <grub/fshelp.h>
+ #include <grub/charset.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -307,10 +308,15 @@ grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
+       if (node->cache && node->cache_size >= node->cache_allocated)
+ 	{
+ 	  struct cache_entry *e = node->cache;
+-	  e = grub_realloc (node->cache,node->cache_allocated * 2
+-			    * sizeof (e[0]));
++	  grub_size_t sz;
++
++	  if (grub_mul (node->cache_allocated, 2 * sizeof (e[0]), &sz))
++	    goto fail;
++
++	  e = grub_realloc (node->cache, sz);
+ 	  if (!e)
+ 	    {
++ fail:
+ 	      grub_errno = 0;
+ 	      grub_free (node->cache);
+ 	      node->cache = 0;
+@@ -477,10 +483,16 @@ grub_sfs_create_node (struct grub_fshelp_node **node,
+   grub_size_t len = grub_strlen (name);
+   grub_uint8_t *name_u8;
+   int ret;
++  grub_size_t sz;
++
++  if (grub_mul (len, GRUB_MAX_UTF8_PER_LATIN1, &sz) ||
++      grub_add (sz, 1, &sz))
++    return 1;
++
+   *node = grub_malloc (sizeof (**node));
+   if (!*node)
+     return 1;
+-  name_u8 = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1);
++  name_u8 = grub_malloc (sz);
+   if (!name_u8)
+     {
+       grub_free (*node);
+@@ -724,8 +736,13 @@ grub_sfs_label (grub_device_t device, char **label)
+   data = grub_sfs_mount (disk);
+   if (data)
+     {
+-      grub_size_t len = grub_strlen (data->label);
+-      *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1);
++      grub_size_t sz, len = grub_strlen (data->label);
++
++      if (grub_mul (len, GRUB_MAX_UTF8_PER_LATIN1, &sz) ||
++	  grub_add (sz, 1, &sz))
++	return GRUB_ERR_OUT_OF_RANGE;
++
++      *label = grub_malloc (sz);
+       if (*label)
+ 	*grub_latin1_to_utf8 ((grub_uint8_t *) *label,
+ 			      (const grub_uint8_t *) data->label,
+diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c
+index 95d5c1e1ff..785123894e 100644
+--- a/grub-core/fs/squash4.c
++++ b/grub-core/fs/squash4.c
+@@ -26,6 +26,7 @@
+ #include <grub/types.h>
+ #include <grub/fshelp.h>
+ #include <grub/deflate.h>
++#include <grub/safemath.h>
+ #include <minilzo.h>
+ 
+ #include "xz.h"
+@@ -459,7 +460,17 @@ grub_squash_read_symlink (grub_fshelp_node_t node)
+ {
+   char *ret;
+   grub_err_t err;
+-  ret = grub_malloc (grub_le_to_cpu32 (node->ino.symlink.namelen) + 1);
++  grub_size_t sz;
++
++  if (grub_add (grub_le_to_cpu32 (node->ino.symlink.namelen), 1, &sz))
++    {
++      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
++      return NULL;
++    }
++
++  ret = grub_malloc (sz);
++  if (!ret)
++    return NULL;
+ 
+   err = read_chunk (node->data, ret,
+ 		    grub_le_to_cpu32 (node->ino.symlink.namelen),
+@@ -506,11 +517,16 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
+ 
+   {
+     grub_fshelp_node_t node;
+-    node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
++    grub_size_t sz;
++
++    if (grub_mul (dir->stsize, sizeof (dir->stack[0]), &sz) ||
++	grub_add (sz, sizeof (*node), &sz))
++      return 0;
++
++    node = grub_malloc (sz);
+     if (!node)
+       return 0;
+-    grub_memcpy (node, dir,
+-		 sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
++    grub_memcpy (node, dir, sz);
+     if (hook (".", GRUB_FSHELP_DIR, node, hook_data))
+       return 1;
+ 
+@@ -518,12 +534,15 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
+       {
+ 	grub_err_t err;
+ 
+-	node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
++	if (grub_mul (dir->stsize, sizeof (dir->stack[0]), &sz) ||
++	    grub_add (sz, sizeof (*node), &sz))
++	  return 0;
++
++	node = grub_malloc (sz);
+ 	if (!node)
+ 	  return 0;
+ 
+-	grub_memcpy (node, dir,
+-		     sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
++	grub_memcpy (node, dir, sz);
+ 
+ 	node->stsize--;
+ 	err = read_chunk (dir->data, &node->ino, sizeof (node->ino),
+@@ -557,6 +576,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
+ 	  enum grub_fshelp_filetype filetype = GRUB_FSHELP_REG;
+ 	  struct grub_squash_dirent di;
+ 	  struct grub_squash_inode ino;
++	  grub_size_t sz;
+ 
+ 	  err = read_chunk (dir->data, &di, sizeof (di),
+ 			    grub_le_to_cpu64 (dir->data->sb.diroffset)
+@@ -589,13 +609,16 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
+ 	  if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_SYMLINK)
+ 	    filetype = GRUB_FSHELP_SYMLINK;
+ 
+-	  node = grub_malloc (sizeof (*node)
+-			      + (dir->stsize + 1) * sizeof (dir->stack[0]));
++	  if (grub_add (dir->stsize, 1, &sz) ||
++	      grub_mul (sz, sizeof (dir->stack[0]), &sz) ||
++	      grub_add (sz, sizeof (*node), &sz))
++	    return 0;
++
++	  node = grub_malloc (sz);
+ 	  if (! node)
+ 	    return 0;
+ 
+-	  grub_memcpy (node, dir,
+-		       sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
++	  grub_memcpy (node, dir, sz - sizeof(dir->stack[0]));
+ 
+ 	  node->ino = ino;
+ 	  node->stack[node->stsize].ino_chunk = grub_le_to_cpu32 (dh.ino_chunk);
+diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
+index a83761674a..21ac7f4460 100644
+--- a/grub-core/fs/udf.c
++++ b/grub-core/fs/udf.c
+@@ -28,6 +28,7 @@
+ #include <grub/charset.h>
+ #include <grub/datetime.h>
+ #include <grub/udf.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -890,9 +891,19 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf)
+ 	utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2];
+     }
+   if (!outbuf)
+-    outbuf = grub_malloc (utf16len * GRUB_MAX_UTF8_PER_UTF16 + 1);
++    {
++      grub_size_t size;
++
++      if (grub_mul (utf16len, GRUB_MAX_UTF8_PER_UTF16, &size) ||
++	  grub_add (size, 1, &size))
++	goto fail;
++
++      outbuf = grub_malloc (size);
++    }
+   if (outbuf)
+     *grub_utf16_to_utf8 ((grub_uint8_t *) outbuf, utf16, utf16len) = '\0';
++
++ fail:
+   grub_free (utf16);
+   return outbuf;
+ }
+@@ -1005,7 +1016,7 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
+   grub_size_t sz = U64 (node->block.fe.file_size);
+   grub_uint8_t *raw;
+   const grub_uint8_t *ptr;
+-  char *out, *optr;
++  char *out = NULL, *optr;
+ 
+   if (sz < 4)
+     return NULL;
+@@ -1013,14 +1024,16 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
+   if (!raw)
+     return NULL;
+   if (grub_udf_read_file (node, NULL, NULL, 0, sz, (char *) raw) < 0)
+-    {
+-      grub_free (raw);
+-      return NULL;
+-    }
++    goto fail_1;
+ 
+-  out = grub_malloc (sz * 2 + 1);
++  if (grub_mul (sz, 2, &sz) ||
++      grub_add (sz, 1, &sz))
++    goto fail_0;
++
++  out = grub_malloc (sz);
+   if (!out)
+     {
++ fail_0:
+       grub_free (raw);
+       return NULL;
+     }
+@@ -1031,17 +1044,17 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
+     {
+       grub_size_t s;
+       if ((grub_size_t) (ptr - raw + 4) > sz)
+-	goto fail;
++	goto fail_1;
+       if (!(ptr[2] == 0 && ptr[3] == 0))
+-	goto fail;
++	goto fail_1;
+       s = 4 + ptr[1];
+       if ((grub_size_t) (ptr - raw + s) > sz)
+-	goto fail;
++	goto fail_1;
+       switch (*ptr)
+ 	{
+ 	case 1:
+ 	  if (ptr[1])
+-	    goto fail;
++	    goto fail_1;
+ 	  /* Fallthrough.  */
+ 	case 2:
+ 	  /* in 4 bytes. out: 1 byte.  */
+@@ -1066,11 +1079,11 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
+ 	  if (optr != out)
+ 	    *optr++ = '/';
+ 	  if (!read_string (ptr + 4, s - 4, optr))
+-	    goto fail;
++	    goto fail_1;
+ 	  optr += grub_strlen (optr);
+ 	  break;
+ 	default:
+-	  goto fail;
++	  goto fail_1;
+ 	}
+       ptr += s;
+     }
+@@ -1078,7 +1091,7 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
+   grub_free (raw);
+   return out;
+ 
+- fail:
++ fail_1:
+   grub_free (raw);
+   grub_free (out);
+   grub_error (GRUB_ERR_BAD_FS, "invalid symlink");
+diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
+index 96ffecbfc9..ea6590290b 100644
+--- a/grub-core/fs/xfs.c
++++ b/grub-core/fs/xfs.c
+@@ -25,6 +25,7 @@
+ #include <grub/dl.h>
+ #include <grub/types.h>
+ #include <grub/fshelp.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -899,6 +900,7 @@ static struct grub_xfs_data *
+ grub_xfs_mount (grub_disk_t disk)
+ {
+   struct grub_xfs_data *data = 0;
++  grub_size_t sz;
+ 
+   data = grub_zalloc (sizeof (struct grub_xfs_data));
+   if (!data)
+@@ -913,10 +915,11 @@ grub_xfs_mount (grub_disk_t disk)
+   if (!grub_xfs_sb_valid(data))
+     goto fail;
+ 
+-  data = grub_realloc (data,
+-		       sizeof (struct grub_xfs_data)
+-		       - sizeof (struct grub_xfs_inode)
+-		       + grub_xfs_inode_size(data) + 1);
++  if (grub_add (grub_xfs_inode_size (data),
++      sizeof (struct grub_xfs_data) - sizeof (struct grub_xfs_inode) + 1, &sz))
++    goto fail;
++
++  data = grub_realloc (data, sz);
+ 
+   if (! data)
+     goto fail;
+diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
+index 381dde556d..36d0373a6a 100644
+--- a/grub-core/fs/zfs/zfs.c
++++ b/grub-core/fs/zfs/zfs.c
+@@ -55,6 +55,7 @@
+ #include <grub/deflate.h>
+ #include <grub/crypto.h>
+ #include <grub/i18n.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -773,11 +774,14 @@ fill_vdev_info (struct grub_zfs_data *data,
+   if (data->n_devices_attached > data->n_devices_allocated)
+     {
+       void *tmp;
+-      data->n_devices_allocated = 2 * data->n_devices_attached + 1;
+-      data->devices_attached
+-	= grub_realloc (tmp = data->devices_attached,
+-			data->n_devices_allocated
+-			* sizeof (data->devices_attached[0]));
++      grub_size_t sz;
++
++      if (grub_mul (data->n_devices_attached, 2, &data->n_devices_allocated) ||
++	  grub_add (data->n_devices_allocated, 1, &data->n_devices_allocated) ||
++	  grub_mul (data->n_devices_allocated, sizeof (data->devices_attached[0]), &sz))
++	return GRUB_ERR_OUT_OF_RANGE;
++
++      data->devices_attached = grub_realloc (tmp = data->devices_attached, sz);
+       if (!data->devices_attached)
+ 	{
+ 	  data->devices_attached = tmp;
+@@ -3468,14 +3472,18 @@ grub_zfs_nvlist_lookup_nvlist (const char *nvlist, const char *name)
+ {
+   char *nvpair;
+   char *ret;
+-  grub_size_t size;
++  grub_size_t size, sz;
+   int found;
+ 
+   found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair,
+ 			     &size, 0);
+   if (!found)
+     return 0;
+-  ret = grub_zalloc (size + 3 * sizeof (grub_uint32_t));
++
++  if (grub_add (size, 3 * sizeof (grub_uint32_t), &sz))
++      return 0;
++
++  ret = grub_zalloc (sz);
+   if (!ret)
+     return 0;
+   grub_memcpy (ret, nvlist, sizeof (grub_uint32_t));
+diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c
+index 1402e0bc29..de3b015f58 100644
+--- a/grub-core/fs/zfs/zfscrypt.c
++++ b/grub-core/fs/zfs/zfscrypt.c
+@@ -22,6 +22,7 @@
+ #include <grub/misc.h>
+ #include <grub/disk.h>
+ #include <grub/partition.h>
++#include <grub/safemath.h>
+ #include <grub/dl.h>
+ #include <grub/types.h>
+ #include <grub/zfs/zfs.h>
+@@ -82,9 +83,13 @@ grub_zfs_add_key (grub_uint8_t *key_in,
+ 		  int passphrase)
+ {
+   struct grub_zfs_wrap_key *key;
++  grub_size_t sz;
++
+   if (!passphrase && keylen > 32)
+     keylen = 32;
+-  key = grub_malloc (sizeof (*key) + keylen);
++  if (grub_add (sizeof (*key), keylen, &sz))
++    return GRUB_ERR_OUT_OF_RANGE;
++  key = grub_malloc (sz);
+   if (!key)
+     return grub_errno;
+   key->is_passphrase = passphrase;
+diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c
+index fd7744a6ff..3288609a5e 100644
+--- a/grub-core/lib/arg.c
++++ b/grub-core/lib/arg.c
+@@ -23,6 +23,7 @@
+ #include <grub/term.h>
+ #include <grub/extcmd.h>
+ #include <grub/i18n.h>
++#include <grub/safemath.h>
+ 
+ /* Built-in parser for default options.  */
+ static const struct grub_arg_option help_options[] =
+@@ -216,7 +217,13 @@ static inline grub_err_t
+ add_arg (char ***argl, int *num, char *s)
+ {
+   char **p = *argl;
+-  *argl = grub_realloc (*argl, (++(*num) + 1) * sizeof (char *));
++  grub_size_t sz;
++
++  if (grub_add (++(*num), 1, &sz) ||
++      grub_mul (sz, sizeof (char *), &sz))
++    return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
++
++  *argl = grub_realloc (*argl, sz);
+   if (! *argl)
+     {
+       grub_free (p);
+@@ -431,6 +438,7 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc,
+   grub_size_t argcnt;
+   struct grub_arg_list *list;
+   const struct grub_arg_option *options;
++  grub_size_t sz0, sz1;
+ 
+   options = extcmd->options;
+   if (! options)
+@@ -443,7 +451,15 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc,
+ 	argcnt += ((grub_size_t) argc + 1) / 2 + 1; /* max possible for any option */
+     }
+ 
+-  list = grub_zalloc (sizeof (*list) * i + sizeof (char*) * argcnt);
++  if (grub_mul (sizeof (*list), i, &sz0) ||
++      grub_mul (sizeof (char *), argcnt, &sz1) ||
++      grub_add (sz0, sz1, &sz0))
++    {
++      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
++      return 0;
++    }
++
++  list = grub_zalloc (sz0);
+   if (! list)
+     return 0;
+ 
+diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c
+index 5b9b92d6ba..ef0d63afc8 100644
+--- a/grub-core/loader/i386/bsd.c
++++ b/grub-core/loader/i386/bsd.c
+@@ -35,6 +35,7 @@
+ #include <grub/ns8250.h>
+ #include <grub/bsdlabel.h>
+ #include <grub/crypto.h>
++#include <grub/safemath.h>
+ #include <grub/verify.h>
+ #ifdef GRUB_MACHINE_PCBIOS
+ #include <grub/machine/int.h>
+@@ -1013,11 +1014,16 @@ grub_netbsd_add_modules (void)
+   struct grub_netbsd_btinfo_modules *mods;
+   unsigned i;
+   grub_err_t err;
++  grub_size_t sz;
+ 
+   for (mod = netbsd_mods; mod; mod = mod->next)
+     modcnt++;
+ 
+-  mods = grub_malloc (sizeof (*mods) + sizeof (mods->mods[0]) * modcnt);
++  if (grub_mul (modcnt, sizeof (mods->mods[0]), &sz) ||
++      grub_add (sz, sizeof (*mods), &sz))
++    return GRUB_ERR_OUT_OF_RANGE;
++
++  mods = grub_malloc (sz);
+   if (!mods)
+     return grub_errno;
+ 
+diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
+index e332d5eb4a..906ec7d678 100644
+--- a/grub-core/net/dns.c
++++ b/grub-core/net/dns.c
+@@ -22,6 +22,7 @@
+ #include <grub/i18n.h>
+ #include <grub/err.h>
+ #include <grub/time.h>
++#include <grub/safemath.h>
+ 
+ struct dns_cache_element
+ {
+@@ -51,9 +52,15 @@ grub_net_add_dns_server (const struct grub_net_network_level_address *s)
+     {
+       int na = dns_servers_alloc * 2;
+       struct grub_net_network_level_address *ns;
++      grub_size_t sz;
++
+       if (na < 8)
+ 	na = 8;
+-      ns = grub_realloc (dns_servers, na * sizeof (ns[0]));
++
++      if (grub_mul (na, sizeof (ns[0]), &sz))
++	return GRUB_ERR_OUT_OF_RANGE;
++
++      ns = grub_realloc (dns_servers, sz);
+       if (!ns)
+ 	return grub_errno;
+       dns_servers_alloc = na;
+diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c
+index d57fb72faa..4dfcc31078 100644
+--- a/grub-core/normal/charset.c
++++ b/grub-core/normal/charset.c
+@@ -48,6 +48,7 @@
+ #include <grub/unicode.h>
+ #include <grub/term.h>
+ #include <grub/normal.h>
++#include <grub/safemath.h>
+ 
+ #if HAVE_FONT_SOURCE
+ #include "widthspec.h"
+@@ -464,6 +465,7 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen,
+ 	{
+ 	  struct grub_unicode_combining *n;
+ 	  unsigned j;
++	  grub_size_t sz;
+ 
+ 	  if (!haveout)
+ 	    continue;
+@@ -477,10 +479,14 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen,
+ 	    n = out->combining_inline;
+ 	  else if (out->ncomb > (int) ARRAY_SIZE (out->combining_inline))
+ 	    {
+-	      n = grub_realloc (out->combining_ptr,
+-				sizeof (n[0]) * (out->ncomb + 1));
++	      if (grub_add (out->ncomb, 1, &sz) ||
++		  grub_mul (sz, sizeof (n[0]), &sz))
++		goto fail;
++
++	      n = grub_realloc (out->combining_ptr, sz);
+ 	      if (!n)
+ 		{
++ fail:
+ 		  grub_errno = GRUB_ERR_NONE;
+ 		  continue;
+ 		}
+diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c
+index c57242e2ea..de03fe63b3 100644
+--- a/grub-core/normal/cmdline.c
++++ b/grub-core/normal/cmdline.c
+@@ -28,6 +28,7 @@
+ #include <grub/env.h>
+ #include <grub/i18n.h>
+ #include <grub/charset.h>
++#include <grub/safemath.h>
+ 
+ static grub_uint32_t *kill_buf;
+ 
+@@ -307,12 +308,21 @@ cl_insert (struct cmdline_term *cl_terms, unsigned nterms,
+   if (len + (*llen) >= (*max_len))
+     {
+       grub_uint32_t *nbuf;
+-      (*max_len) *= 2;
+-      nbuf = grub_realloc ((*buf), sizeof (grub_uint32_t) * (*max_len));
++      grub_size_t sz;
++
++      if (grub_mul (*max_len, 2, max_len) ||
++	  grub_mul (*max_len, sizeof (grub_uint32_t), &sz))
++	{
++	  grub_errno = GRUB_ERR_OUT_OF_RANGE;
++	  goto fail;
++	}
++
++      nbuf = grub_realloc ((*buf), sz);
+       if (nbuf)
+ 	(*buf) = nbuf;
+       else
+ 	{
++ fail:
+ 	  grub_print_error ();
+ 	  grub_errno = GRUB_ERR_NONE;
+ 	  (*max_len) /= 2;
+diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c
+index 1993995be6..50eef918cf 100644
+--- a/grub-core/normal/menu_entry.c
++++ b/grub-core/normal/menu_entry.c
+@@ -27,6 +27,7 @@
+ #include <grub/auth.h>
+ #include <grub/i18n.h>
+ #include <grub/charset.h>
++#include <grub/safemath.h>
+ 
+ enum update_mode
+   {
+@@ -113,10 +114,18 @@ ensure_space (struct line *linep, int extra)
+ {
+   if (linep->max_len < linep->len + extra)
+     {
+-      linep->max_len = 2 * (linep->len + extra);
+-      linep->buf = grub_realloc (linep->buf, (linep->max_len + 1) * sizeof (linep->buf[0]));
++      grub_size_t sz0, sz1;
++
++      if (grub_add (linep->len, extra, &sz0) ||
++	  grub_mul (sz0, 2, &sz0) ||
++	  grub_add (sz0, 1, &sz1) ||
++	  grub_mul (sz1, sizeof (linep->buf[0]), &sz1))
++	return 0;
++
++      linep->buf = grub_realloc (linep->buf, sz1);
+       if (! linep->buf)
+ 	return 0;
++      linep->max_len = sz0;
+     }
+ 
+   return 1;
+diff --git a/grub-core/script/argv.c b/grub-core/script/argv.c
+index 217ec5d1e1..5751fdd570 100644
+--- a/grub-core/script/argv.c
++++ b/grub-core/script/argv.c
+@@ -20,6 +20,7 @@
+ #include <grub/mm.h>
+ #include <grub/misc.h>
+ #include <grub/script_sh.h>
++#include <grub/safemath.h>
+ 
+ /* Return nearest power of two that is >= v.  */
+ static unsigned
+@@ -81,11 +82,16 @@ int
+ grub_script_argv_next (struct grub_script_argv *argv)
+ {
+   char **p = argv->args;
++  grub_size_t sz;
+ 
+   if (argv->args && argv->argc && argv->args[argv->argc - 1] == 0)
+     return 0;
+ 
+-  p = grub_realloc (p, round_up_exp ((argv->argc + 2) * sizeof (char *)));
++  if (grub_add (argv->argc, 2, &sz) ||
++      grub_mul (sz, sizeof (char *), &sz))
++    return 1;
++
++  p = grub_realloc (p, round_up_exp (sz));
+   if (! p)
+     return 1;
+ 
+@@ -105,13 +111,19 @@ grub_script_argv_append (struct grub_script_argv *argv, const char *s,
+ {
+   grub_size_t a;
+   char *p = argv->args[argv->argc - 1];
++  grub_size_t sz;
+ 
+   if (! s)
+     return 0;
+ 
+   a = p ? grub_strlen (p) : 0;
+ 
+-  p = grub_realloc (p, round_up_exp ((a + slen + 1) * sizeof (char)));
++  if (grub_add (a, slen, &sz) ||
++      grub_add (sz, 1, &sz) ||
++      grub_mul (sz, sizeof (char), &sz))
++    return 1;
++
++  p = grub_realloc (p, round_up_exp (sz));
+   if (! p)
+     return 1;
+ 
+diff --git a/grub-core/script/lexer.c b/grub-core/script/lexer.c
+index c6bd3172fa..5fb0cbd0bc 100644
+--- a/grub-core/script/lexer.c
++++ b/grub-core/script/lexer.c
+@@ -24,6 +24,7 @@
+ #include <grub/mm.h>
+ #include <grub/script_sh.h>
+ #include <grub/i18n.h>
++#include <grub/safemath.h>
+ 
+ #define yytext_ptr char *
+ #include "grub_script.tab.h"
+@@ -110,10 +111,14 @@ grub_script_lexer_record (struct grub_parser_param *parser, char *str)
+       old = lexer->recording;
+       if (lexer->recordlen < len)
+ 	lexer->recordlen = len;
+-      lexer->recordlen *= 2;
++
++      if (grub_mul (lexer->recordlen, 2, &lexer->recordlen))
++	goto fail;
++
+       lexer->recording = grub_realloc (lexer->recording, lexer->recordlen);
+       if (!lexer->recording)
+ 	{
++ fail:
+ 	  grub_free (old);
+ 	  lexer->recordpos = 0;
+ 	  lexer->recordlen = 0;
+@@ -130,7 +135,7 @@ int
+ grub_script_lexer_yywrap (struct grub_parser_param *parserstate,
+ 			  const char *input)
+ {
+-  grub_size_t len = 0;
++  grub_size_t len = 0, sz;
+   char *p = 0;
+   char *line = 0;
+   YY_BUFFER_STATE buffer;
+@@ -168,12 +173,22 @@ grub_script_lexer_yywrap (struct grub_parser_param *parserstate,
+     }
+   else if (len && line[len - 1] != '\n')
+     {
+-      p = grub_realloc (line, len + 2);
++      if (grub_add (len, 2, &sz))
++	{
++	  grub_free (line);
++	  grub_script_yyerror (parserstate, N_("overflow is detected"));
++	  return 1;
++	}
++
++      p = grub_realloc (line, sz);
+       if (p)
+ 	{
+ 	  p[len++] = '\n';
+ 	  p[len] = '\0';
+ 	}
++      else
++	grub_free (line);
++
+       line = p;
+     }
+ 
+diff --git a/grub-core/video/bitmap.c b/grub-core/video/bitmap.c
+index b2e0315665..6256e209a6 100644
+--- a/grub-core/video/bitmap.c
++++ b/grub-core/video/bitmap.c
+@@ -23,6 +23,7 @@
+ #include <grub/mm.h>
+ #include <grub/misc.h>
+ #include <grub/i18n.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -58,7 +59,7 @@ grub_video_bitmap_create (struct grub_video_bitmap **bitmap,
+                           enum grub_video_blit_format blit_format)
+ {
+   struct grub_video_mode_info *mode_info;
+-  unsigned int size;
++  grub_size_t size;
+ 
+   if (!bitmap)
+     return grub_error (GRUB_ERR_BUG, "invalid argument");
+@@ -137,19 +138,25 @@ grub_video_bitmap_create (struct grub_video_bitmap **bitmap,
+ 
+   mode_info->pitch = width * mode_info->bytes_per_pixel;
+ 
+-  /* Calculate size needed for the data.  */
+-  size = (width * mode_info->bytes_per_pixel) * height;
++  /* Calculate size needed for the data. */
++  if (grub_mul (width, mode_info->bytes_per_pixel, &size) ||
++      grub_mul (size, height, &size))
++    {
++      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
++      goto fail;
++    }
+ 
+   (*bitmap)->data = grub_zalloc (size);
+   if (! (*bitmap)->data)
+-    {
+-      grub_free (*bitmap);
+-      *bitmap = 0;
+-
+-      return grub_errno;
+-    }
++    goto fail;
+ 
+   return GRUB_ERR_NONE;
++
++ fail:
++  grub_free (*bitmap);
++  *bitmap = NULL;
++
++  return grub_errno;
+ }
+ 
+ /* Frees all resources allocated by bitmap.  */
+diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
+index 61bd645379..0157ff7420 100644
+--- a/grub-core/video/readers/png.c
++++ b/grub-core/video/readers/png.c
+@@ -23,6 +23,7 @@
+ #include <grub/mm.h>
+ #include <grub/misc.h>
+ #include <grub/bufio.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -301,9 +302,17 @@ grub_png_decode_image_header (struct grub_png_data *data)
+       data->bpp <<= 1;
+ 
+   data->color_bits = color_bits;
+-  data->row_bytes = data->image_width * data->bpp;
++
++  if (grub_mul (data->image_width, data->bpp, &data->row_bytes))
++    return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
++
+   if (data->color_bits <= 4)
+-    data->row_bytes = (data->image_width * data->color_bits + 7) / 8;
++    {
++      if (grub_mul (data->image_width, data->color_bits + 7, &data->row_bytes))
++	return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
++
++      data->row_bytes >>= 3;
++    }
+ 
+ #ifndef GRUB_CPU_WORDS_BIGENDIAN
+   if (data->is_16bit || data->is_gray || data->is_palette)
diff --git a/debian/patches/0086-iso9660-Don-t-leak-memory-on-realloc-failures.patch b/debian/patches/0086-iso9660-Don-t-leak-memory-on-realloc-failures.patch
new file mode 100644
index 0000000..438d655
--- /dev/null
+++ b/debian/patches/0086-iso9660-Don-t-leak-memory-on-realloc-failures.patch
@@ -0,0 +1,65 @@
+From 3daaf33550e0fc35de5a51de337e7d5e4bd1bbfd Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Sat, 4 Jul 2020 12:25:09 -0400
+Subject: iso9660: Don't leak memory on realloc() failures
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/iso9660.c | 24 ++++++++++++++++++++----
+ 1 file changed, 20 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
+index 7ba5b300bc..5ec4433b8f 100644
+--- a/grub-core/fs/iso9660.c
++++ b/grub-core/fs/iso9660.c
+@@ -533,14 +533,20 @@ add_part (struct iterate_dir_ctx *ctx,
+ {
+   int size = ctx->symlink ? grub_strlen (ctx->symlink) : 0;
+   grub_size_t sz;
++  char *new;
+ 
+   if (grub_add (size, len2, &sz) ||
+       grub_add (sz, 1, &sz))
+     return;
+ 
+-  ctx->symlink = grub_realloc (ctx->symlink, sz);
+-  if (! ctx->symlink)
+-    return;
++  new = grub_realloc (ctx->symlink, sz);
++  if (!new)
++    {
++      grub_free (ctx->symlink);
++      ctx->symlink = NULL;
++      return;
++    }
++  ctx->symlink = new;
+ 
+   grub_memcpy (ctx->symlink + size, part, len2);
+   ctx->symlink[size + len2] = 0;  
+@@ -634,7 +640,12 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
+ 		   is the length.  Both are part of the `Component
+ 		   Record'.  */
+ 		if (ctx->symlink && !ctx->was_continue)
+-		  add_part (ctx, "/", 1);
++		  {
++		    add_part (ctx, "/", 1);
++		    if (grub_errno)
++		      return grub_errno;
++		  }
++
+ 		add_part (ctx, (char *) &entry->data[pos + 2],
+ 			  entry->data[pos + 1]);
+ 		ctx->was_continue = (entry->data[pos] & 1);
+@@ -653,6 +664,11 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
+ 	      add_part (ctx, "/", 1);
+ 	      break;
+ 	    }
++
++	  /* Check if grub_realloc() failed in add_part(). */
++	  if (grub_errno)
++	    return grub_errno;
++
+ 	  /* In pos + 1 the length of the `Component Record' is
+ 	     stored.  */
+ 	  pos += entry->data[pos + 1] + 2;
diff --git a/debian/patches/0087-font-Do-not-load-more-than-one-NAME-section.patch b/debian/patches/0087-font-Do-not-load-more-than-one-NAME-section.patch
new file mode 100644
index 0000000..2935ce4
--- /dev/null
+++ b/debian/patches/0087-font-Do-not-load-more-than-one-NAME-section.patch
@@ -0,0 +1,34 @@
+From b762411ec388017c77379629298e90f93dec75d7 Mon Sep 17 00:00:00 2001
+From: Daniel Kiper <daniel.kiper@oracle.com>
+Date: Tue, 7 Jul 2020 15:36:26 +0200
+Subject: font: Do not load more than one NAME section
+
+The GRUB font file can have one NAME section only. Though if somebody
+crafts a broken font file with many NAME sections and loads it then the
+GRUB leaks memory. So, prevent against that by loading first NAME
+section and failing in controlled way on following one.
+
+Reported-by: Chris Coulson <chris.coulson@canonical.com>
+Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
+Reviewed-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
+---
+ grub-core/font/font.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index 5edb477ac2..d09bb38d89 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -532,6 +532,12 @@ grub_font_load (const char *filename)
+       if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FONT_NAME,
+ 		       sizeof (FONT_FORMAT_SECTION_NAMES_FONT_NAME) - 1) == 0)
+ 	{
++	  if (font->name != NULL)
++	    {
++	      grub_error (GRUB_ERR_BAD_FONT, "invalid font file: too many NAME sections");
++	      goto fail;
++	    }
++
+ 	  font->name = read_section_as_string (&section);
+ 	  if (!font->name)
+ 	    goto fail;
diff --git a/debian/patches/0088-gfxmenu-Fix-double-free-in-load_image.patch b/debian/patches/0088-gfxmenu-Fix-double-free-in-load_image.patch
new file mode 100644
index 0000000..dbf1ae4
--- /dev/null
+++ b/debian/patches/0088-gfxmenu-Fix-double-free-in-load_image.patch
@@ -0,0 +1,32 @@
+From 58e72a15fa61adffe8015da0eb093d2e93380ee0 Mon Sep 17 00:00:00 2001
+From: Alexey Makhalov <amakhalov@vmware.com>
+Date: Wed, 8 Jul 2020 20:41:56 +0000
+Subject: gfxmenu: Fix double free in load_image()
+
+self->bitmap should be zeroed after free. Otherwise, there is a chance
+to double free (USE_AFTER_FREE) it later in rescale_image().
+
+Fixes: CID 292472
+
+Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/gfxmenu/gui_image.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/gfxmenu/gui_image.c b/grub-core/gfxmenu/gui_image.c
+index 29784ed2d9..6b2e976f16 100644
+--- a/grub-core/gfxmenu/gui_image.c
++++ b/grub-core/gfxmenu/gui_image.c
+@@ -195,7 +195,10 @@ load_image (grub_gui_image_t self, const char *path)
+     return grub_errno;
+ 
+   if (self->bitmap && (self->bitmap != self->raw_bitmap))
+-    grub_video_bitmap_destroy (self->bitmap);
++    {
++      grub_video_bitmap_destroy (self->bitmap);
++      self->bitmap = 0;
++    }
+   if (self->raw_bitmap)
+     grub_video_bitmap_destroy (self->raw_bitmap);
+ 
diff --git a/debian/patches/0089-lzma-Make-sure-we-don-t-dereference-past-array.patch b/debian/patches/0089-lzma-Make-sure-we-don-t-dereference-past-array.patch
new file mode 100644
index 0000000..eb283a5
--- /dev/null
+++ b/debian/patches/0089-lzma-Make-sure-we-don-t-dereference-past-array.patch
@@ -0,0 +1,48 @@
+From d6f176758a8d2ab9cd81646e7e2e825682a0fdfe Mon Sep 17 00:00:00 2001
+From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Date: Thu, 9 Jul 2020 03:05:23 +0000
+Subject: lzma: Make sure we don't dereference past array
+
+The two dimensional array p->posSlotEncoder[4][64] is being dereferenced
+using the GetLenToPosState() macro which checks if len is less than 5,
+and if so subtracts 2 from it. If len = 0, that is 0 - 2 = 4294967294.
+Obviously we don't want to dereference that far out so we check if the
+position found is greater or equal kNumLenToPosStates (4) and bail out.
+
+N.B.: Upstream LZMA 18.05 and later has this function completely rewritten
+without any history.
+
+Fixes: CID 51526
+
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/lib/LzmaEnc.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/lib/LzmaEnc.c b/grub-core/lib/LzmaEnc.c
+index f2ec04a8c2..753e56a95e 100644
+--- a/grub-core/lib/LzmaEnc.c
++++ b/grub-core/lib/LzmaEnc.c
+@@ -1877,13 +1877,19 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
+       }
+       else
+       {
+-        UInt32 posSlot;
++        UInt32 posSlot, lenToPosState;
+         RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
+         p->state = kMatchNextStates[p->state];
+         LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
+         pos -= LZMA_NUM_REPS;
+         GetPosSlot(pos, posSlot);
+-        RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
++        lenToPosState = GetLenToPosState(len);
++        if (lenToPosState >= kNumLenToPosStates)
++        {
++          p->result = SZ_ERROR_DATA;
++          return CheckErrors(p);
++        }
++        RcTree_Encode(&p->rc, p->posSlotEncoder[lenToPosState], kNumPosSlotBits, posSlot);
+ 
+         if (posSlot >= kStartPosModelIndex)
+         {
diff --git a/debian/patches/0090-tftp-Do-not-use-priority-queue.patch b/debian/patches/0090-tftp-Do-not-use-priority-queue.patch
new file mode 100644
index 0000000..df1a56c
--- /dev/null
+++ b/debian/patches/0090-tftp-Do-not-use-priority-queue.patch
@@ -0,0 +1,279 @@
+From c68bccd83bec72174cfbfb258e7329adb309879d Mon Sep 17 00:00:00 2001
+From: Alexey Makhalov <amakhalov@vmware.com>
+Date: Thu, 9 Jul 2020 08:10:40 +0000
+Subject: tftp: Do not use priority queue
+
+There is not need to reassemble the order of blocks. Per RFC 1350,
+server must wait for the ACK, before sending next block. Data packets
+can be served immediately without putting them to priority queue.
+
+Logic to handle incoming packet is this:
+  - if packet block id equal to expected block id, then
+    process the packet,
+  - if packet block id is less than expected - this is retransmit
+    of old packet, then ACK it and drop the packet,
+  - if packet block id is more than expected - that shouldn't
+    happen, just drop the packet.
+
+It makes the tftp receive path code simpler, smaller and faster.
+As a benefit, this change fixes CID# 73624 and CID# 96690, caused
+by following while loop:
+
+  while (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) == 0)
+
+where tftph pointer is not moving from one iteration to another, causing
+to serve same packet again. Luckily, double serving didn't happen due to
+data->block++ during the first iteration.
+
+Fixes: CID 73624, CID 96690
+
+Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/tftp.c | 171 ++++++++++++++-----------------------------
+ 1 file changed, 53 insertions(+), 118 deletions(-)
+
+diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
+index a0817a075d..e6566fa176 100644
+--- a/grub-core/net/tftp.c
++++ b/grub-core/net/tftp.c
+@@ -25,7 +25,6 @@
+ #include <grub/mm.h>
+ #include <grub/dl.h>
+ #include <grub/file.h>
+-#include <grub/priority_queue.h>
+ #include <grub/i18n.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+@@ -106,31 +105,8 @@ typedef struct tftp_data
+   int have_oack;
+   struct grub_error_saved save_err;
+   grub_net_udp_socket_t sock;
+-  grub_priority_queue_t pq;
+ } *tftp_data_t;
+ 
+-static int
+-cmp_block (grub_uint16_t a, grub_uint16_t b)
+-{
+-  grub_int16_t i = (grub_int16_t) (a - b);
+-  if (i > 0)
+-    return +1;
+-  if (i < 0)
+-    return -1;
+-  return 0;
+-}
+-
+-static int
+-cmp (const void *a__, const void *b__)
+-{
+-  struct grub_net_buff *a_ = *(struct grub_net_buff **) a__;
+-  struct grub_net_buff *b_ = *(struct grub_net_buff **) b__;
+-  struct tftphdr *a = (struct tftphdr *) a_->data;
+-  struct tftphdr *b = (struct tftphdr *) b_->data;
+-  /* We want the first elements to be on top.  */
+-  return -cmp_block (grub_be_to_cpu16 (a->u.data.block), grub_be_to_cpu16 (b->u.data.block));
+-}
+-
+ static grub_err_t
+ ack (tftp_data_t data, grub_uint64_t block)
+ {
+@@ -207,73 +183,60 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
+ 	  return GRUB_ERR_NONE;
+ 	}
+ 
+-      err = grub_priority_queue_push (data->pq, &nb);
+-      if (err)
+-	return err;
+-
+-      {
+-	struct grub_net_buff **nb_top_p, *nb_top;
+-	while (1)
+-	  {
+-	    nb_top_p = grub_priority_queue_top (data->pq);
+-	    if (!nb_top_p)
+-	      return GRUB_ERR_NONE;
+-	    nb_top = *nb_top_p;
+-	    tftph = (struct tftphdr *) nb_top->data;
+-	    if (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) >= 0)
+-	      break;
+-	    ack (data, grub_be_to_cpu16 (tftph->u.data.block));
+-	    grub_netbuff_free (nb_top);
+-	    grub_priority_queue_pop (data->pq);
+-	  }
+-	while (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) == 0)
+-	  {
+-	    unsigned size;
+-
+-	    grub_priority_queue_pop (data->pq);
+-
+-	    if (file->device->net->packs.count < 50)
++      /* Ack old/retransmitted block. */
++      if (grub_be_to_cpu16 (tftph->u.data.block) < data->block + 1)
++	ack (data, grub_be_to_cpu16 (tftph->u.data.block));
++      /* Ignore unexpected block. */
++      else if (grub_be_to_cpu16 (tftph->u.data.block) > data->block + 1)
++	grub_dprintf ("tftp", "TFTP unexpected block # %d\n", tftph->u.data.block);
++      else
++	{
++	  unsigned size;
++
++	  if (file->device->net->packs.count < 50)
++	    {
+ 	      err = ack (data, data->block + 1);
+-	    else
+-	      {
+-		file->device->net->stall = 1;
+-		err = 0;
+-	      }
+-	    if (err)
+-	      return err;
+-
+-	    err = grub_netbuff_pull (nb_top, sizeof (tftph->opcode) +
+-				     sizeof (tftph->u.data.block));
+-	    if (err)
+-	      return err;
+-	    size = nb_top->tail - nb_top->data;
+-
+-	    data->block++;
+-	    if (size < data->block_size)
+-	      {
+-		if (data->ack_sent < data->block)
+-		  ack (data, data->block);
+-		file->device->net->eof = 1;
+-		file->device->net->stall = 1;
+-		grub_net_udp_close (data->sock);
+-		data->sock = NULL;
+-	      }
+-	    /* Prevent garbage in broken cards. Is it still necessary
+-	       given that IP implementation has been fixed?
+-	     */
+-	    if (size > data->block_size)
+-	      {
+-		err = grub_netbuff_unput (nb_top, size - data->block_size);
+-		if (err)
+-		  return err;
+-	      }
+-	    /* If there is data, puts packet in socket list. */
+-	    if ((nb_top->tail - nb_top->data) > 0)
+-	      grub_net_put_packet (&file->device->net->packs, nb_top);
+-	    else
+-	      grub_netbuff_free (nb_top);
+-	  }
+-      }
++	      if (err)
++		return err;
++	    }
++	  else
++	    file->device->net->stall = 1;
++
++	  err = grub_netbuff_pull (nb, sizeof (tftph->opcode) +
++				   sizeof (tftph->u.data.block));
++	  if (err)
++	    return err;
++	  size = nb->tail - nb->data;
++
++	  data->block++;
++	  if (size < data->block_size)
++	    {
++	      if (data->ack_sent < data->block)
++		ack (data, data->block);
++	      file->device->net->eof = 1;
++	      file->device->net->stall = 1;
++	      grub_net_udp_close (data->sock);
++	      data->sock = NULL;
++	    }
++	  /*
++	   * Prevent garbage in broken cards. Is it still necessary
++	   * given that IP implementation has been fixed?
++	   */
++	  if (size > data->block_size)
++	    {
++	      err = grub_netbuff_unput (nb, size - data->block_size);
++	      if (err)
++		return err;
++	    }
++	  /* If there is data, puts packet in socket list. */
++	  if ((nb->tail - nb->data) > 0)
++	    {
++	      grub_net_put_packet (&file->device->net->packs, nb);
++	      /* Do not free nb. */
++	      return GRUB_ERR_NONE;
++	    }
++	}
++      grub_netbuff_free (nb);
+       return GRUB_ERR_NONE;
+     case TFTP_ERROR:
+       data->have_oack = 1;
+@@ -287,19 +250,6 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
+     }
+ }
+ 
+-static void
+-destroy_pq (tftp_data_t data)
+-{
+-  struct grub_net_buff **nb_p;
+-  while ((nb_p = grub_priority_queue_top (data->pq)))
+-    {
+-      grub_netbuff_free (*nb_p);
+-      grub_priority_queue_pop (data->pq);
+-    }
+-
+-  grub_priority_queue_destroy (data->pq);
+-}
+-
+ static grub_err_t
+ tftp_open (struct grub_file *file, const char *filename)
+ {
+@@ -373,20 +323,9 @@ tftp_open (struct grub_file *file, const char *filename)
+   file->not_easily_seekable = 1;
+   file->data = data;
+ 
+-  data->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp);
+-  if (!data->pq)
+-    {
+-      grub_free (data);
+-      return grub_errno;
+-    }
+-
+   err = grub_net_resolve_address (file->device->net->server, &addr);
+   if (err)
+     {
+-      grub_dprintf ("tftp", "file_size is %llu, block_size is %llu\n",
+-		    (unsigned long long)data->file_size,
+-		    (unsigned long long)data->block_size);
+-      destroy_pq (data);
+       grub_free (data);
+       return err;
+     }
+@@ -396,7 +335,6 @@ tftp_open (struct grub_file *file, const char *filename)
+ 				  file);
+   if (!data->sock)
+     {
+-      destroy_pq (data);
+       grub_free (data);
+       return grub_errno;
+     }
+@@ -410,7 +348,6 @@ tftp_open (struct grub_file *file, const char *filename)
+       if (err)
+ 	{
+ 	  grub_net_udp_close (data->sock);
+-	  destroy_pq (data);
+ 	  grub_free (data);
+ 	  return err;
+ 	}
+@@ -427,7 +364,6 @@ tftp_open (struct grub_file *file, const char *filename)
+   if (grub_errno)
+     {
+       grub_net_udp_close (data->sock);
+-      destroy_pq (data);
+       grub_free (data);
+       return grub_errno;
+     }
+@@ -470,7 +406,6 @@ tftp_close (struct grub_file *file)
+ 	grub_print_error ();
+       grub_net_udp_close (data->sock);
+     }
+-  destroy_pq (data);
+   grub_free (data);
+   return GRUB_ERR_NONE;
+ }
diff --git a/debian/patches/0091-script-Remove-unused-fields-from-grub_script_functio.patch b/debian/patches/0091-script-Remove-unused-fields-from-grub_script_functio.patch
new file mode 100644
index 0000000..4865443
--- /dev/null
+++ b/debian/patches/0091-script-Remove-unused-fields-from-grub_script_functio.patch
@@ -0,0 +1,29 @@
+From fd60c9a66288bf80f4da18e9832436bf2e6c1e65 Mon Sep 17 00:00:00 2001
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Fri, 10 Jul 2020 11:21:14 +0100
+Subject: script: Remove unused fields from grub_script_function struct
+
+Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ include/grub/script_sh.h | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h
+index 360c2be1f0..b382bcf09b 100644
+--- a/include/grub/script_sh.h
++++ b/include/grub/script_sh.h
+@@ -359,13 +359,8 @@ struct grub_script_function
+   /* The script function.  */
+   struct grub_script *func;
+ 
+-  /* The flags.  */
+-  unsigned flags;
+-
+   /* The next element.  */
+   struct grub_script_function *next;
+-
+-  int references;
+ };
+ typedef struct grub_script_function *grub_script_function_t;
+ 
diff --git a/debian/patches/0092-script-Avoid-a-use-after-free-when-redefining-a-func.patch b/debian/patches/0092-script-Avoid-a-use-after-free-when-redefining-a-func.patch
new file mode 100644
index 0000000..08e4973
--- /dev/null
+++ b/debian/patches/0092-script-Avoid-a-use-after-free-when-redefining-a-func.patch
@@ -0,0 +1,104 @@
+From ce9f66f0a86e6cbfd866e431df87f205537380f5 Mon Sep 17 00:00:00 2001
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Fri, 10 Jul 2020 14:41:45 +0100
+Subject: script: Avoid a use-after-free when redefining a function during
+ execution
+
+Defining a new function with the same name as a previously defined
+function causes the grub_script and associated resources for the
+previous function to be freed. If the previous function is currently
+executing when a function with the same name is defined, this results
+in use-after-frees when processing subsequent commands in the original
+function.
+
+Instead, reject a new function definition if it has the same name as
+a previously defined function, and that function is currently being
+executed. Although a behavioural change, this should be backwards
+compatible with existing configurations because they can't be
+dependent on the current behaviour without being broken.
+
+Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/script/execute.c  |  2 ++
+ grub-core/script/function.c | 16 +++++++++++++---
+ grub-core/script/parser.y   |  3 ++-
+ include/grub/script_sh.h    |  2 ++
+ 4 files changed, 19 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
+index c8d6806fe0..7e028e1355 100644
+--- a/grub-core/script/execute.c
++++ b/grub-core/script/execute.c
+@@ -838,7 +838,9 @@ grub_script_function_call (grub_script_function_t func, int argc, char **args)
+   old_scope = scope;
+   scope = &new_scope;
+ 
++  func->executing++;
+   ret = grub_script_execute (func->func);
++  func->executing--;
+ 
+   function_return = 0;
+   active_loops = loops;
+diff --git a/grub-core/script/function.c b/grub-core/script/function.c
+index d36655e510..3aad04bf9d 100644
+--- a/grub-core/script/function.c
++++ b/grub-core/script/function.c
+@@ -34,6 +34,7 @@ grub_script_function_create (struct grub_script_arg *functionname_arg,
+   func = (grub_script_function_t) grub_malloc (sizeof (*func));
+   if (! func)
+     return 0;
++  func->executing = 0;
+ 
+   func->name = grub_strdup (functionname_arg->str);
+   if (! func->name)
+@@ -60,10 +61,19 @@ grub_script_function_create (struct grub_script_arg *functionname_arg,
+       grub_script_function_t q;
+ 
+       q = *p;
+-      grub_script_free (q->func);
+-      q->func = cmd;
+       grub_free (func);
+-      func = q;
++      if (q->executing > 0)
++        {
++          grub_error (GRUB_ERR_BAD_ARGUMENT,
++		      N_("attempt to redefine a function being executed"));
++          func = NULL;
++        }
++      else
++        {
++          grub_script_free (q->func);
++          q->func = cmd;
++          func = q;
++        }
+     }
+   else
+     {
+diff --git a/grub-core/script/parser.y b/grub-core/script/parser.y
+index 4f0ab8319e..f80b86b6f1 100644
+--- a/grub-core/script/parser.y
++++ b/grub-core/script/parser.y
+@@ -289,7 +289,8 @@ function: "function" "name"
+ 	      grub_script_mem_free (state->func_mem);
+ 	    else {
+ 	      script->children = state->scripts;
+-	      grub_script_function_create ($2, script);
++	      if (!grub_script_function_create ($2, script))
++		grub_script_free (script);
+ 	    }
+ 
+ 	    state->scripts = $<scripts>3;
+diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h
+index b382bcf09b..6c48e07512 100644
+--- a/include/grub/script_sh.h
++++ b/include/grub/script_sh.h
+@@ -361,6 +361,8 @@ struct grub_script_function
+ 
+   /* The next element.  */
+   struct grub_script_function *next;
++
++  unsigned executing;
+ };
+ typedef struct grub_script_function *grub_script_function_t;
+ 
diff --git a/debian/patches/0093-hfsplus-fix-two-more-overflows.patch b/debian/patches/0093-hfsplus-fix-two-more-overflows.patch
new file mode 100644
index 0000000..cb67208
--- /dev/null
+++ b/debian/patches/0093-hfsplus-fix-two-more-overflows.patch
@@ -0,0 +1,53 @@
+From 4be2c61fdd94238b4e529f018eddea12f6ba5361 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Sun, 19 Jul 2020 14:43:31 -0400
+Subject: hfsplus: fix two more overflows
+
+Both node->size and node->namelen come from the supplied filesystem,
+which may be user-supplied.  We can't trust them for the math unless we
+know they don't overflow; making sure they go through calloc() first
+will give us that.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
+---
+ grub-core/fs/hfsplus.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
+index dae43becc9..9c4e4c88c9 100644
+--- a/grub-core/fs/hfsplus.c
++++ b/grub-core/fs/hfsplus.c
+@@ -31,6 +31,7 @@
+ #include <grub/hfs.h>
+ #include <grub/charset.h>
+ #include <grub/hfsplus.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -475,8 +476,12 @@ grub_hfsplus_read_symlink (grub_fshelp_node_t node)
+ {
+   char *symlink;
+   grub_ssize_t numread;
++  grub_size_t sz = node->size;
+ 
+-  symlink = grub_malloc (node->size + 1);
++  if (grub_add (sz, 1, &sz))
++    return NULL;
++
++  symlink = grub_malloc (sz);
+   if (!symlink)
+     return 0;
+ 
+@@ -715,8 +720,8 @@ list_nodes (void *record, void *hook_arg)
+   if (type == GRUB_FSHELP_UNKNOWN)
+     return 0;
+ 
+-  filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen)
+-			  * GRUB_MAX_UTF8_PER_UTF16 + 1);
++  filename = grub_calloc (grub_be_to_cpu16 (catkey->namelen),
++			  GRUB_MAX_UTF8_PER_UTF16 + 1);
+   if (! filename)
+     return 0;
+ 
diff --git a/debian/patches/0094-lvm-fix-two-more-potential-data-dependent-alloc-over.patch b/debian/patches/0094-lvm-fix-two-more-potential-data-dependent-alloc-over.patch
new file mode 100644
index 0000000..36e67c6
--- /dev/null
+++ b/debian/patches/0094-lvm-fix-two-more-potential-data-dependent-alloc-over.patch
@@ -0,0 +1,98 @@
+From 9082c7d5ed8d9ffb15a12d6bcb10a86ca9c8a860 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Sun, 19 Jul 2020 15:48:20 -0400
+Subject: lvm: fix two more potential data-dependent alloc overflows
+
+It appears to be possible to make a (possibly invalid) lvm PV with a
+metadata size field that overflows our type when adding it to the
+address we've allocated.  Even if it doesn't, it may be possible to do
+so with the math using the outcome of that as an operand.  Check them
+both.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/disk/lvm.c | 39 +++++++++++++++++++++++++++++++--------
+ 1 file changed, 31 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
+index d1df640b31..d154f7c01b 100644
+--- a/grub-core/disk/lvm.c
++++ b/grub-core/disk/lvm.c
+@@ -25,6 +25,7 @@
+ #include <grub/lvm.h>
+ #include <grub/partition.h>
+ #include <grub/i18n.h>
++#include <grub/safemath.h>
+ 
+ #ifdef GRUB_UTIL
+ #include <grub/emu/misc.h>
+@@ -102,10 +103,11 @@ grub_lvm_detect (grub_disk_t disk,
+ {
+   grub_err_t err;
+   grub_uint64_t mda_offset, mda_size;
++  grub_size_t ptr;
+   char buf[GRUB_LVM_LABEL_SIZE];
+   char vg_id[GRUB_LVM_ID_STRLEN+1];
+   char pv_id[GRUB_LVM_ID_STRLEN+1];
+-  char *metadatabuf, *p, *q, *vgname;
++  char *metadatabuf, *mda_end, *p, *q, *vgname;
+   struct grub_lvm_label_header *lh = (struct grub_lvm_label_header *) buf;
+   struct grub_lvm_pv_header *pvh;
+   struct grub_lvm_disk_locn *dlocn;
+@@ -205,19 +207,31 @@ grub_lvm_detect (grub_disk_t disk,
+ 		   grub_le_to_cpu64 (rlocn->size) -
+ 		   grub_le_to_cpu64 (mdah->size));
+     }
+-  p = q = metadatabuf + grub_le_to_cpu64 (rlocn->offset);
+ 
+-  while (*q != ' ' && q < metadatabuf + mda_size)
+-    q++;
+-
+-  if (q == metadatabuf + mda_size)
++  if (grub_add ((grub_size_t)metadatabuf,
++		(grub_size_t)grub_le_to_cpu64 (rlocn->offset),
++		&ptr))
+     {
++error_parsing_metadata:
+ #ifdef GRUB_UTIL
+       grub_util_info ("error parsing metadata");
+ #endif
+       goto fail2;
+     }
+ 
++  p = q = (char *)ptr;
++
++  if (grub_add ((grub_size_t)metadatabuf, (grub_size_t)mda_size, &ptr))
++    goto error_parsing_metadata;
++
++  mda_end = (char *)ptr;
++
++  while (*q != ' ' && q < mda_end)
++    q++;
++
++  if (q == mda_end)
++    goto error_parsing_metadata;
++
+   vgname_len = q - p;
+   vgname = grub_malloc (vgname_len + 1);
+   if (!vgname)
+@@ -367,8 +381,17 @@ grub_lvm_detect (grub_disk_t disk,
+ 	      {
+ 		const char *iptr;
+ 		char *optr;
+-		lv->fullname = grub_malloc (sizeof ("lvm/") - 1 + 2 * vgname_len
+-					    + 1 + 2 * s + 1);
++		grub_size_t sz0 = vgname_len, sz1 = s;
++
++		if (grub_mul (sz0, 2, &sz0) ||
++		    grub_add (sz0, 1, &sz0) ||
++		    grub_mul (sz1, 2, &sz1) ||
++		    grub_add (sz1, 1, &sz1) ||
++		    grub_add (sz0, sz1, &sz0) ||
++		    grub_add (sz0, sizeof ("lvm/") - 1, &sz0))
++		  goto lvs_fail;
++
++		lv->fullname = grub_malloc (sz0);
+ 		if (!lv->fullname)
+ 		  goto lvs_fail;
+ 
diff --git a/debian/patches/0095-efi-fix-some-malformed-device-path-arithmetic-errors.patch b/debian/patches/0095-efi-fix-some-malformed-device-path-arithmetic-errors.patch
new file mode 100644
index 0000000..7509a9d
--- /dev/null
+++ b/debian/patches/0095-efi-fix-some-malformed-device-path-arithmetic-errors.patch
@@ -0,0 +1,247 @@
+From c9148b4f42091e840b2659504401dab230f7d817 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Sun, 19 Jul 2020 16:53:27 -0400
+Subject: efi: fix some malformed device path arithmetic errors.
+
+Several places we take the length of a device path and subtract 4 from
+it, without ever checking that it's >= 4.  There are also cases where
+this kind of malformation will result in unpredictable iteration,
+including treating the length from one dp node as the type in the next
+node.  These are all errors, no matter where the data comes from.
+
+This patch adds a checking macro, GRUB_EFI_DEVICE_PATH_VALID(), which
+can be used in several places, and makes GRUB_EFI_NEXT_DEVICE_PATH()
+return NULL and GRUB_EFI_END_ENTIRE_DEVICE_PATH() evaluate as true when
+the length is too small.  Additionally, it makes several places in the
+code check for and return errors in these cases.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/kern/efi/efi.c           | 67 +++++++++++++++++++++++++-----
+ grub-core/loader/efi/chainloader.c | 19 ++++++++-
+ grub-core/loader/i386/xnu.c        |  9 ++--
+ include/grub/efi/api.h             | 14 ++++---
+ 4 files changed, 88 insertions(+), 21 deletions(-)
+
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index dc31caa213..b1a8b39b49 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -332,7 +332,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
+ 
+   dp = dp0;
+ 
+-  while (1)
++  while (dp)
+     {
+       grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
+       grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
+@@ -342,9 +342,15 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
+       if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
+ 	       && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
+ 	{
+-	  grub_efi_uint16_t len;
+-	  len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
+-		 / sizeof (grub_efi_char16_t));
++	  grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
++
++	  if (len < 4)
++	    {
++	      grub_error (GRUB_ERR_OUT_OF_RANGE,
++			  "malformed EFI Device Path node has length=%d", len);
++	      return NULL;
++	    }
++	  len = (len - 4) / sizeof (grub_efi_char16_t);
+ 	  filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 2;
+ 	}
+ 
+@@ -360,7 +366,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
+   if (!name)
+     return NULL;
+ 
+-  while (1)
++  while (dp)
+     {
+       grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
+       grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
+@@ -376,8 +382,15 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
+ 
+ 	  *p++ = '/';
+ 
+-	  len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
+-		 / sizeof (grub_efi_char16_t));
++	  len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
++	  if (len < 4)
++	    {
++	      grub_error (GRUB_ERR_OUT_OF_RANGE,
++			  "malformed EFI Device Path node has length=%d", len);
++	      return NULL;
++	    }
++
++	  len = (len - 4) / sizeof (grub_efi_char16_t);
+ 	  fp = (grub_efi_file_path_device_path_t *) dp;
+ 	  /* According to EFI spec Path Name is NULL terminated */
+ 	  while (len > 0 && fp->path_name[len - 1] == 0)
+@@ -452,7 +465,26 @@ grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp)
+        ;
+        p = GRUB_EFI_NEXT_DEVICE_PATH (p))
+     {
+-      total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
++      grub_size_t len = GRUB_EFI_DEVICE_PATH_LENGTH (p);
++
++      /*
++       * In the event that we find a node that's completely garbage, for
++       * example if we get to 0x7f 0x01 0x02 0x00 ... (EndInstance with a size
++       * of 2), GRUB_EFI_END_ENTIRE_DEVICE_PATH() will be true and
++       * GRUB_EFI_NEXT_DEVICE_PATH() will return NULL, so we won't continue,
++       * and neither should our consumers, but there won't be any error raised
++       * even though the device path is junk.
++       *
++       * This keeps us from passing junk down back to our caller.
++       */
++      if (len < 4)
++	{
++	  grub_error (GRUB_ERR_OUT_OF_RANGE,
++		      "malformed EFI Device Path node has length=%d", len);
++	  return NULL;
++	}
++
++      total_size += len;
+       if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
+ 	break;
+     }
+@@ -497,7 +529,7 @@ dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor)
+ void
+ grub_efi_print_device_path (grub_efi_device_path_t *dp)
+ {
+-  while (1)
++  while (GRUB_EFI_DEVICE_PATH_VALID (dp))
+     {
+       grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
+       grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
+@@ -909,7 +941,11 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
+     /* Return non-zero.  */
+     return 1;
+ 
+-  while (1)
++  if (dp1 == dp2)
++    return 0;
++
++  while (GRUB_EFI_DEVICE_PATH_VALID (dp1)
++	 && GRUB_EFI_DEVICE_PATH_VALID (dp2))
+     {
+       grub_efi_uint8_t type1, type2;
+       grub_efi_uint8_t subtype1, subtype2;
+@@ -945,5 +981,16 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
+       dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
+     }
+ 
++  /*
++   * There's no "right" answer here, but we probably don't want to call a valid
++   * dp and an invalid dp equal, so pick one way or the other.
++   */
++  if (GRUB_EFI_DEVICE_PATH_VALID (dp1) &&
++      !GRUB_EFI_DEVICE_PATH_VALID (dp2))
++    return 1;
++  else if (!GRUB_EFI_DEVICE_PATH_VALID (dp1) &&
++	   GRUB_EFI_DEVICE_PATH_VALID (dp2))
++    return -1;
++
+   return 0;
+ }
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index b9a2df34b1..f8a34cd491 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -126,6 +126,12 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
+   fp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
+   fp->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE;
+ 
++  if (!GRUB_EFI_DEVICE_PATH_VALID ((grub_efi_device_path_t *)fp))
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI Device Path is invalid");
++      return;
++    }
++
+   path_name = grub_calloc (len, GRUB_MAX_UTF16_PER_UTF8 * sizeof (*path_name));
+   if (!path_name)
+     return;
+@@ -166,9 +172,18 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
+ 
+   size = 0;
+   d = dp;
+-  while (1)
++  while (d)
+     {
+-      size += GRUB_EFI_DEVICE_PATH_LENGTH (d);
++      grub_size_t len = GRUB_EFI_DEVICE_PATH_LENGTH (d);
++
++      if (len < 4)
++	{
++	  grub_error (GRUB_ERR_OUT_OF_RANGE,
++		      "malformed EFI Device Path node has length=%d", len);
++	  return NULL;
++	}
++
++      size += len;
+       if ((GRUB_EFI_END_ENTIRE_DEVICE_PATH (d)))
+ 	break;
+       d = GRUB_EFI_NEXT_DEVICE_PATH (d);
+diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c
+index b7d176b5d3..c50cb54109 100644
+--- a/grub-core/loader/i386/xnu.c
++++ b/grub-core/loader/i386/xnu.c
+@@ -516,14 +516,15 @@ grub_cmd_devprop_load (grub_command_t cmd __attribute__ ((unused)),
+ 
+       devhead = buf;
+       buf = devhead + 1;
+-      dpstart = buf;
++      dp = dpstart = buf;
+ 
+-      do
++      while (GRUB_EFI_DEVICE_PATH_VALID (dp) && buf < bufend)
+ 	{
+-	  dp = buf;
+ 	  buf = (char *) buf + GRUB_EFI_DEVICE_PATH_LENGTH (dp);
++	  if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
++	    break;
++	  dp = buf;
+ 	}
+-      while (!GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp) && buf < bufend);
+ 
+       dev = grub_xnu_devprop_add_device (dpstart, (char *) buf
+ 					 - (char *) dpstart);
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 9824fbcd0d..08bff60b51 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -640,6 +640,7 @@ typedef struct grub_efi_device_path grub_efi_device_path_protocol_t;
+ #define GRUB_EFI_DEVICE_PATH_TYPE(dp)		((dp)->type & 0x7f)
+ #define GRUB_EFI_DEVICE_PATH_SUBTYPE(dp)	((dp)->subtype)
+ #define GRUB_EFI_DEVICE_PATH_LENGTH(dp)		((dp)->length)
++#define GRUB_EFI_DEVICE_PATH_VALID(dp)		((dp) != NULL && GRUB_EFI_DEVICE_PATH_LENGTH (dp) >= 4)
+ 
+ /* The End of Device Path nodes.  */
+ #define GRUB_EFI_END_DEVICE_PATH_TYPE			(0xff & 0x7f)
+@@ -648,13 +649,16 @@ typedef struct grub_efi_device_path grub_efi_device_path_protocol_t;
+ #define GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE		0x01
+ 
+ #define GRUB_EFI_END_ENTIRE_DEVICE_PATH(dp)	\
+-  (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_END_DEVICE_PATH_TYPE \
+-   && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) \
+-       == GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE))
++  (!GRUB_EFI_DEVICE_PATH_VALID (dp) || \
++   (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_END_DEVICE_PATH_TYPE \
++    && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) \
++	== GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE)))
+ 
+ #define GRUB_EFI_NEXT_DEVICE_PATH(dp)	\
+-  ((grub_efi_device_path_t *) ((char *) (dp) \
+-                               + GRUB_EFI_DEVICE_PATH_LENGTH (dp)))
++  (GRUB_EFI_DEVICE_PATH_VALID (dp) \
++   ? ((grub_efi_device_path_t *) \
++      ((char *) (dp) + GRUB_EFI_DEVICE_PATH_LENGTH (dp))) \
++   : NULL)
+ 
+ /* Hardware Device Path.  */
+ #define GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE		1
diff --git a/debian/patches/0096-linuxefi-fail-kernel-validation-without-shim-protoco.patch b/debian/patches/0096-linuxefi-fail-kernel-validation-without-shim-protoco.patch
new file mode 100644
index 0000000..0e0f9e5
--- /dev/null
+++ b/debian/patches/0096-linuxefi-fail-kernel-validation-without-shim-protoco.patch
@@ -0,0 +1,90 @@
+From a37688a7dd2a14b66aa88005a9473f017aa84d17 Mon Sep 17 00:00:00 2001
+From: Dimitri John Ledkov <xnox@ubuntu.com>
+Date: Wed, 22 Jul 2020 11:31:43 +0100
+Subject: linuxefi: fail kernel validation without shim protocol.
+
+If certificates that signed grub are installed into db, grub can be
+booted directly. It will then boot any kernel without signature
+validation. The booted kernel will think it was booted in secureboot
+mode and will implement lockdown, yet it could have been tampered.
+
+CVE-2020-15705
+
+Reported-by: Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>
+Signed-off-by: Dimitri John Ledkov <xnox@ubuntu.com>
+---
+ grub-core/loader/arm64/linux.c     | 13 +++++++++----
+ grub-core/loader/efi/chainloader.c |  1 +
+ grub-core/loader/efi/linux.c       |  1 +
+ grub-core/loader/i386/efi/linux.c  |  2 +-
+ 4 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
+index 1a5296a60c..3f5496fc55 100644
+--- a/grub-core/loader/arm64/linux.c
++++ b/grub-core/loader/arm64/linux.c
+@@ -34,6 +34,7 @@
+ #include <grub/i18n.h>
+ #include <grub/lib/cmdline.h>
+ #include <grub/verify.h>
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -342,11 +343,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+   grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
+ 
+-  rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size);
+-  if (rc < 0)
++  if (grub_efi_secure_boot ())
+     {
+-      grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
+-      goto fail;
++      rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size);
++      if (rc <= 0)
++        {
++          grub_error (GRUB_ERR_INVALID_COMMAND,
++		      N_("%s has invalid signature"), argv[0]);
++          goto fail;
++        }
+     }
+ 
+   cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index f8a34cd491..cf89cedf8d 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -1096,6 +1096,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ 
+       return 0;
+     }
++  // -1 fall-through to fail
+ 
+   grub_file_close (file);
+   grub_device_close (dev);
+diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
+index e372b26a1b..f6d30bcf7c 100644
+--- a/grub-core/loader/efi/linux.c
++++ b/grub-core/loader/efi/linux.c
+@@ -34,6 +34,7 @@ struct grub_efi_shim_lock
+ };
+ typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
+ 
++// Returns 1 on success, -1 on error, 0 when not available
+ int
+ grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
+ {
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 2929da7a29..e357bf67c6 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -199,7 +199,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   if (grub_efi_secure_boot ())
+     {
+       rc = grub_linuxefi_secure_validate (kernel, filelen);
+-      if (rc < 0)
++      if (rc <= 0)
+ 	{
+ 	  grub_error (GRUB_ERR_ACCESS_DENIED, N_("%s has invalid signature"),
+ 		      argv[0]);
diff --git a/debian/patches/0097-Fix-a-regression-caused-by-efi-fix-some-malformed-de.patch b/debian/patches/0097-Fix-a-regression-caused-by-efi-fix-some-malformed-de.patch
new file mode 100644
index 0000000..fd7f502
--- /dev/null
+++ b/debian/patches/0097-Fix-a-regression-caused-by-efi-fix-some-malformed-de.patch
@@ -0,0 +1,84 @@
+From 77a41770dfb138bc68c43f86a6e9d05188a0da4f Mon Sep 17 00:00:00 2001
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Wed, 22 Jul 2020 17:06:04 +0100
+Subject: Fix a regression caused by "efi: fix some malformed device path
+ arithmetic errors"
+
+This commit introduced a bogus check inside copy_file_path to
+determine whether the destination grub_efi_file_path_device_path_t
+was valid before anything was copied to it. Depending on the
+contents of the heap buffer, this check could fail which would
+result in copy_file_path returning early.
+
+Without any error propagated to the caller, make_file_path would
+then try to advance the invalid device path node with
+GRUB_EFI_NEXT_DEVICE_PATH, which would also fail, returning a NULL
+pointer that would subsequently be dereferenced.
+
+Remove the bogus check, and also propagate errors from copy_file_path.
+---
+ grub-core/loader/efi/chainloader.c | 25 +++++++++++++------------
+ 1 file changed, 13 insertions(+), 12 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index cf89cedf8d..d0c53077e8 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -116,7 +116,7 @@ grub_chainloader_boot (void)
+   return grub_errno;
+ }
+ 
+-static void
++static grub_err_t
+ copy_file_path (grub_efi_file_path_device_path_t *fp,
+ 		const char *str, grub_efi_uint16_t len)
+ {
+@@ -126,15 +126,9 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
+   fp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
+   fp->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE;
+ 
+-  if (!GRUB_EFI_DEVICE_PATH_VALID ((grub_efi_device_path_t *)fp))
+-    {
+-      grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI Device Path is invalid");
+-      return;
+-    }
+-
+   path_name = grub_calloc (len, GRUB_MAX_UTF16_PER_UTF8 * sizeof (*path_name));
+   if (!path_name)
+-    return;
++    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed to allocate path buffer");
+ 
+   size = grub_utf8_to_utf16 (path_name, len * GRUB_MAX_UTF16_PER_UTF8,
+ 			     (const grub_uint8_t *) str, len, 0);
+@@ -147,6 +141,7 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
+   fp->path_name[size++] = '\0';
+   fp->header.length = size * sizeof (grub_efi_char16_t) + sizeof (*fp);
+   grub_free (path_name);
++  return GRUB_ERR_NONE;
+ }
+ 
+ static grub_efi_device_path_t *
+@@ -204,13 +199,19 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
+   /* Fill the file path for the directory.  */
+   d = (grub_efi_device_path_t *) ((char *) file_path
+ 				  + ((char *) d - (char *) dp));
+-  copy_file_path ((grub_efi_file_path_device_path_t *) d,
+-		  dir_start, dir_end - dir_start);
++  if (copy_file_path ((grub_efi_file_path_device_path_t *) d,
++		      dir_start, dir_end - dir_start) != GRUB_ERR_NONE)
++    {
++    fail:
++      grub_free (file_path);
++      return 0;
++    }
+ 
+   /* Fill the file path for the file.  */
+   d = GRUB_EFI_NEXT_DEVICE_PATH (d);
+-  copy_file_path ((grub_efi_file_path_device_path_t *) d,
+-		  dir_end + 1, grub_strlen (dir_end + 1));
++  if (copy_file_path ((grub_efi_file_path_device_path_t *) d,
++		      dir_end + 1, grub_strlen (dir_end + 1)) != GRUB_ERR_NONE)
++    goto fail;
+ 
+   /* Fill the end of device path nodes.  */
+   d = GRUB_EFI_NEXT_DEVICE_PATH (d);
diff --git a/debian/patches/0098-efi-Fix-use-after-free-in-halt-reboot-path.patch b/debian/patches/0098-efi-Fix-use-after-free-in-halt-reboot-path.patch
new file mode 100644
index 0000000..7ea7d7d
--- /dev/null
+++ b/debian/patches/0098-efi-Fix-use-after-free-in-halt-reboot-path.patch
@@ -0,0 +1,175 @@
+From 1e7e07cfd5c1caa76479b10e85e6a703d64e0fea Mon Sep 17 00:00:00 2001
+From: Alexey Makhalov <amakhalov@vmware.com>
+Date: Mon, 20 Jul 2020 23:03:05 +0000
+Subject: efi: Fix use-after-free in halt/reboot path
+
+commit 92bfc33db984 ("efi: Free malloc regions on exit")
+introduced memory freeing in grub_efi_fini(), which is
+used not only by exit path but by halt/reboot one as well.
+As result of memory freeing, code and data regions used by
+modules, such as halt, reboot, acpi (used by halt) also got
+freed. After return to module code, CPU executes, filled
+by UEFI firmware (tested with edk2), 0xAFAFAFAF pattern as
+a code. Which leads to #UD exception later.
+
+grub> halt
+!!!! X64 Exception Type - 06(#UD - Invalid Opcode)  CPU Apic ID - 00000000 !!!!
+RIP  - 0000000003F4EC28, CS  - 0000000000000038, RFLAGS - 0000000000200246
+RAX  - 0000000000000000, RCX - 00000000061DA188, RDX - 0A74C0854DC35D41
+RBX  - 0000000003E10E08, RSP - 0000000007F0F860, RBP - 0000000000000000
+RSI  - 00000000064DB768, RDI - 000000000832C5C3
+R8   - 0000000000000002, R9  - 0000000000000000, R10 - 00000000061E2E52
+R11  - 0000000000000020, R12 - 0000000003EE5C1F, R13 - 00000000061E0FF4
+R14  - 0000000003E10D80, R15 - 00000000061E2F60
+DS   - 0000000000000030, ES  - 0000000000000030, FS  - 0000000000000030
+GS   - 0000000000000030, SS  - 0000000000000030
+CR0  - 0000000080010033, CR2 - 0000000000000000, CR3 - 0000000007C01000
+CR4  - 0000000000000668, CR8 - 0000000000000000
+DR0  - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
+DR3  - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
+GDTR - 00000000079EEA98 0000000000000047, LDTR - 0000000000000000
+IDTR - 0000000007598018 0000000000000FFF,   TR - 0000000000000000
+FXSAVE_STATE - 0000000007F0F4C0
+
+Proposal here is to continue to free allocated memory for
+exit boot services path but keep it for halt/reboot path
+as it won't be much security concern here.
+Introduced GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY
+loader flag to be used by efi halt/reboot path.
+
+Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
+Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
+---
+ grub-core/kern/arm/efi/init.c   | 3 +++
+ grub-core/kern/arm64/efi/init.c | 3 +++
+ grub-core/kern/efi/efi.c        | 3 ++-
+ grub-core/kern/efi/init.c       | 1 -
+ grub-core/kern/i386/efi/init.c  | 9 +++++++--
+ grub-core/kern/ia64/efi/init.c  | 9 +++++++--
+ grub-core/kern/riscv/efi/init.c | 3 +++
+ grub-core/lib/efi/halt.c        | 3 ++-
+ include/grub/loader.h           | 1 +
+ 9 files changed, 28 insertions(+), 7 deletions(-)
+
+diff --git a/grub-core/kern/arm/efi/init.c b/grub-core/kern/arm/efi/init.c
+index 06df60e2f0..40c3b467fc 100644
+--- a/grub-core/kern/arm/efi/init.c
++++ b/grub-core/kern/arm/efi/init.c
+@@ -71,4 +71,7 @@ grub_machine_fini (int flags)
+   efi_call_1 (b->close_event, tmr_evt);
+ 
+   grub_efi_fini ();
++
++  if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
++    grub_efi_memory_fini ();
+ }
+diff --git a/grub-core/kern/arm64/efi/init.c b/grub-core/kern/arm64/efi/init.c
+index 6224999ec9..5010caefd6 100644
+--- a/grub-core/kern/arm64/efi/init.c
++++ b/grub-core/kern/arm64/efi/init.c
+@@ -57,4 +57,7 @@ grub_machine_fini (int flags)
+     return;
+ 
+   grub_efi_fini ();
++
++  if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
++    grub_efi_memory_fini ();
+ }
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index b1a8b39b49..88bbd34eac 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -157,7 +157,8 @@ grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
+ void
+ grub_reboot (void)
+ {
+-  grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
++  grub_machine_fini (GRUB_LOADER_FLAG_NORETURN |
++		     GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY);
+   efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
+               GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
+   for (;;) ;
+diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
+index 3dfdf2d22b..2c31847bf6 100644
+--- a/grub-core/kern/efi/init.c
++++ b/grub-core/kern/efi/init.c
+@@ -80,5 +80,4 @@ grub_efi_fini (void)
+ {
+   grub_efidisk_fini ();
+   grub_console_fini ();
+-  grub_efi_memory_fini ();
+ }
+diff --git a/grub-core/kern/i386/efi/init.c b/grub-core/kern/i386/efi/init.c
+index da499aba04..deb2eacd8d 100644
+--- a/grub-core/kern/i386/efi/init.c
++++ b/grub-core/kern/i386/efi/init.c
+@@ -39,6 +39,11 @@ grub_machine_init (void)
+ void
+ grub_machine_fini (int flags)
+ {
+-  if (flags & GRUB_LOADER_FLAG_NORETURN)
+-    grub_efi_fini ();
++  if (!(flags & GRUB_LOADER_FLAG_NORETURN))
++    return;
++
++  grub_efi_fini ();
++
++  if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
++    grub_efi_memory_fini ();
+ }
+diff --git a/grub-core/kern/ia64/efi/init.c b/grub-core/kern/ia64/efi/init.c
+index b5ecbd0912..f1965571b1 100644
+--- a/grub-core/kern/ia64/efi/init.c
++++ b/grub-core/kern/ia64/efi/init.c
+@@ -70,6 +70,11 @@ grub_machine_init (void)
+ void
+ grub_machine_fini (int flags)
+ {
+-  if (flags & GRUB_LOADER_FLAG_NORETURN)
+-    grub_efi_fini ();
++  if (!(flags & GRUB_LOADER_FLAG_NORETURN))
++    return;
++
++  grub_efi_fini ();
++
++  if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
++    grub_efi_memory_fini ();
+ }
+diff --git a/grub-core/kern/riscv/efi/init.c b/grub-core/kern/riscv/efi/init.c
+index 7eb1969d0b..38795fe674 100644
+--- a/grub-core/kern/riscv/efi/init.c
++++ b/grub-core/kern/riscv/efi/init.c
+@@ -73,4 +73,7 @@ grub_machine_fini (int flags)
+     return;
+ 
+   grub_efi_fini ();
++
++  if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
++    grub_efi_memory_fini ();
+ }
+diff --git a/grub-core/lib/efi/halt.c b/grub-core/lib/efi/halt.c
+index 5859f0498a..29d4136416 100644
+--- a/grub-core/lib/efi/halt.c
++++ b/grub-core/lib/efi/halt.c
+@@ -28,7 +28,8 @@
+ void
+ grub_halt (void)
+ {
+-  grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
++  grub_machine_fini (GRUB_LOADER_FLAG_NORETURN |
++		     GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY);
+ #if !defined(__ia64__) && !defined(__arm__) && !defined(__aarch64__) && \
+     !defined(__riscv)
+   grub_acpi_halt ();
+diff --git a/include/grub/loader.h b/include/grub/loader.h
+index 7f82a499fd..b208642821 100644
+--- a/include/grub/loader.h
++++ b/include/grub/loader.h
+@@ -33,6 +33,7 @@ enum
+ {
+   GRUB_LOADER_FLAG_NORETURN = 1,
+   GRUB_LOADER_FLAG_PXE_NOT_UNLOAD = 2,
++  GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY = 4,
+ };
+ 
+ void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void),
diff --git a/debian/patches/0099-chainloader-Avoid-a-double-free-when-validation-fail.patch b/debian/patches/0099-chainloader-Avoid-a-double-free-when-validation-fail.patch
new file mode 100644
index 0000000..42d6ff3
--- /dev/null
+++ b/debian/patches/0099-chainloader-Avoid-a-double-free-when-validation-fail.patch
@@ -0,0 +1,42 @@
+From 06a88955852ba3c301f3a37c99faa813bd7262c8 Mon Sep 17 00:00:00 2001
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Thu, 23 Jul 2020 14:02:17 +0100
+Subject: chainloader: Avoid a double free when validation fails
+
+---
+ grub-core/loader/efi/chainloader.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index d0c53077e8..144a6549df 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -1085,6 +1085,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   if (rc > 0)
+     {
+       grub_file_close (file);
++      if (orig_dev)
++	dev = orig_dev;
++      grub_device_close (dev);
+       grub_loader_set (grub_secureboot_chainloader_boot,
+ 		       grub_secureboot_chainloader_unload, 0);
+       return 0;
+@@ -1093,15 +1096,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+     {
+       grub_load_and_start_image(boot_image);
+       grub_file_close (file);
++      if (orig_dev)
++	dev = orig_dev;
++      grub_device_close (dev);
+       grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
+ 
+       return 0;
+     }
+   // -1 fall-through to fail
+ 
+-  grub_file_close (file);
+-  grub_device_close (dev);
+-
+ fail:
+   if (orig_dev)
+     {
diff --git a/debian/patches/0100-relocator-Protect-grub_relocator_alloc_chunk_addr-in.patch b/debian/patches/0100-relocator-Protect-grub_relocator_alloc_chunk_addr-in.patch
new file mode 100644
index 0000000..34464ab
--- /dev/null
+++ b/debian/patches/0100-relocator-Protect-grub_relocator_alloc_chunk_addr-in.patch
@@ -0,0 +1,146 @@
+From d1e511e940a1f2577f568e11076df02c7a221042 Mon Sep 17 00:00:00 2001
+From: Alexey Makhalov <amakhalov@vmware.com>
+Date: Wed, 15 Jul 2020 06:42:37 +0000
+Subject: relocator: Protect grub_relocator_alloc_chunk_addr() input args
+ against integer underflow/overflow
+
+Use arithmetic macros from safemath.h to accomplish it. In this commit,
+I didn't want to be too paranoid to check every possible math equation
+for overflow/underflow. Only obvious places (with non zero chance of
+overflow/underflow) were refactored.
+
+Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/loader/i386/linux.c    |  9 +++++++--
+ grub-core/loader/i386/pc/linux.c |  9 +++++++--
+ grub-core/loader/i386/xen.c      | 12 ++++++++++--
+ grub-core/loader/xnu.c           | 11 +++++++----
+ 4 files changed, 31 insertions(+), 10 deletions(-)
+
+diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
+index 991eb29db9..4e14eb1887 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -36,6 +36,7 @@
+ #include <grub/lib/cmdline.h>
+ #include <grub/linux.h>
+ #include <grub/machine/kernel.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -550,9 +551,13 @@ grub_linux_boot (void)
+ 
+   {
+     grub_relocator_chunk_t ch;
++    grub_size_t sz;
++
++    if (grub_add (ctx.real_size, efi_mmap_size, &sz))
++      return GRUB_ERR_OUT_OF_RANGE;
++
+     err = grub_relocator_alloc_chunk_addr (relocator, &ch,
+-					   ctx.real_mode_target,
+-					   (ctx.real_size + efi_mmap_size));
++					   ctx.real_mode_target, sz);
+     if (err)
+      return err;
+     real_mode_mem = get_virtual_current_address (ch);
+diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
+index 3866f048bb..81ab3c0c15 100644
+--- a/grub-core/loader/i386/pc/linux.c
++++ b/grub-core/loader/i386/pc/linux.c
+@@ -36,6 +36,7 @@
+ #include <grub/lib/cmdline.h>
+ #include <grub/linux.h>
+ #include <grub/efi/sb.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -231,8 +232,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+     setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
+ 
+   real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
+-  grub_linux16_prot_size = grub_file_size (file)
+-    - real_size - GRUB_DISK_SECTOR_SIZE;
++  if (grub_sub (grub_file_size (file), real_size, &grub_linux16_prot_size) ||
++      grub_sub (grub_linux16_prot_size, GRUB_DISK_SECTOR_SIZE, &grub_linux16_prot_size))
++    {
++      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
++      goto fail;
++    }
+ 
+   if (! grub_linux_is_bzimage
+       && GRUB_LINUX_ZIMAGE_ADDR + grub_linux16_prot_size
+diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
+index 8f662c8ac8..cd24874ca3 100644
+--- a/grub-core/loader/i386/xen.c
++++ b/grub-core/loader/i386/xen.c
+@@ -41,6 +41,7 @@
+ #include <grub/linux.h>
+ #include <grub/i386/memory.h>
+ #include <grub/verify.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -636,6 +637,7 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)),
+   grub_relocator_chunk_t ch;
+   grub_addr_t kern_start;
+   grub_addr_t kern_end;
++  grub_size_t sz;
+ 
+   if (argc == 0)
+     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+@@ -703,8 +705,14 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)),
+ 
+   xen_state.max_addr = ALIGN_UP (kern_end, PAGE_SIZE);
+ 
+-  err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, kern_start,
+-					 kern_end - kern_start);
++
++  if (grub_sub (kern_end, kern_start, &sz))
++    {
++      err = GRUB_ERR_OUT_OF_RANGE;
++      goto fail;
++    }
++
++  err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, kern_start, sz);
+   if (err)
+     goto fail;
+   kern_chunk_src = get_virtual_current_address (ch);
+diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
+index 2f0ebd0b8b..3fd653993f 100644
+--- a/grub-core/loader/xnu.c
++++ b/grub-core/loader/xnu.c
+@@ -35,6 +35,7 @@
+ #include <grub/i18n.h>
+ #include <grub/verify.h>
+ #include <grub/efi/sb.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -60,15 +61,17 @@ grub_xnu_heap_malloc (int size, void **src, grub_addr_t *target)
+ {
+   grub_err_t err;
+   grub_relocator_chunk_t ch;
++  grub_addr_t tgt;
++
++  if (grub_add (grub_xnu_heap_target_start, grub_xnu_heap_size, &tgt))
++    return GRUB_ERR_OUT_OF_RANGE;
+   
+-  err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, &ch,
+-					 grub_xnu_heap_target_start
+-					 + grub_xnu_heap_size, size);
++  err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, &ch, tgt, size);
+   if (err)
+     return err;
+ 
+   *src = get_virtual_current_address (ch);
+-  *target = grub_xnu_heap_target_start + grub_xnu_heap_size;
++  *target = tgt;
+   grub_xnu_heap_size += size;
+   grub_dprintf ("xnu", "val=%p\n", *src);
+   return GRUB_ERR_NONE;
diff --git a/debian/patches/0101-relocator-Protect-grub_relocator_alloc_chunk_align-m.patch b/debian/patches/0101-relocator-Protect-grub_relocator_alloc_chunk_align-m.patch
new file mode 100644
index 0000000..5f955e5
--- /dev/null
+++ b/debian/patches/0101-relocator-Protect-grub_relocator_alloc_chunk_align-m.patch
@@ -0,0 +1,334 @@
+From 91276109ad6be0700b9fee507063f01df0692070 Mon Sep 17 00:00:00 2001
+From: Alexey Makhalov <amakhalov@vmware.com>
+Date: Wed, 8 Jul 2020 01:44:38 +0000
+Subject: relocator: Protect grub_relocator_alloc_chunk_align() max_addr
+ against integer underflow
+
+This commit introduces integer underflow mitigation in max_addr calculation
+in grub_relocator_alloc_chunk_align() invocation.
+
+It consists of 2 fixes:
+  1. Introduced grub_relocator_alloc_chunk_align_safe() wrapper function to perform
+     sanity check for min/max and size values, and to make safe invocation of
+     grub_relocator_alloc_chunk_align() with validated max_addr value. Replace all
+     invocations such as grub_relocator_alloc_chunk_align(..., min_addr, max_addr - size, size, ...)
+     by grub_relocator_alloc_chunk_align_safe(..., min_addr, max_addr, size, ...).
+  2. Introduced UP_TO_TOP32(s) macro for the cases where max_addr is 32-bit top
+     address (0xffffffff - size + 1) or similar.
+
+Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/lib/i386/relocator.c        | 28 ++++++++++----------------
+ grub-core/lib/mips/relocator.c        |  6 ++----
+ grub-core/lib/powerpc/relocator.c     |  6 ++----
+ grub-core/lib/x86_64/efi/relocator.c  |  7 +++----
+ grub-core/loader/i386/linux.c         |  5 ++---
+ grub-core/loader/i386/multiboot_mbi.c |  7 +++----
+ grub-core/loader/i386/pc/linux.c      |  6 ++----
+ grub-core/loader/mips/linux.c         |  9 +++------
+ grub-core/loader/multiboot.c          |  2 +-
+ grub-core/loader/multiboot_elfxx.c    | 10 ++++-----
+ grub-core/loader/multiboot_mbi2.c     | 10 ++++-----
+ grub-core/loader/xnu_resume.c         |  2 +-
+ include/grub/relocator.h              | 29 +++++++++++++++++++++++++++
+ 13 files changed, 69 insertions(+), 58 deletions(-)
+
+diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c
+index 71dd4f0ab0..34cbe834fa 100644
+--- a/grub-core/lib/i386/relocator.c
++++ b/grub-core/lib/i386/relocator.c
+@@ -83,11 +83,10 @@ grub_relocator32_boot (struct grub_relocator *rel,
+   /* Specific memory range due to Global Descriptor Table for use by payload
+      that we will store in returned chunk.  The address range and preference
+      are based on "THE LINUX/x86 BOOT PROTOCOL" specification.  */
+-  err = grub_relocator_alloc_chunk_align (rel, &ch, 0x1000,
+-					  0x9a000 - RELOCATOR_SIZEOF (32),
+-					  RELOCATOR_SIZEOF (32), 16,
+-					  GRUB_RELOCATOR_PREFERENCE_LOW,
+-					  avoid_efi_bootservices);
++  err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0x1000, 0x9a000,
++					       RELOCATOR_SIZEOF (32), 16,
++					       GRUB_RELOCATOR_PREFERENCE_LOW,
++					       avoid_efi_bootservices);
+   if (err)
+     return err;
+ 
+@@ -125,13 +124,10 @@ grub_relocator16_boot (struct grub_relocator *rel,
+   grub_relocator_chunk_t ch;
+ 
+   /* Put it higher than the byte it checks for A20 check.  */
+-  err = grub_relocator_alloc_chunk_align (rel, &ch, 0x8010,
+-					  0xa0000 - RELOCATOR_SIZEOF (16)
+-					  - GRUB_RELOCATOR16_STACK_SIZE,
+-					  RELOCATOR_SIZEOF (16)
+-					  + GRUB_RELOCATOR16_STACK_SIZE, 16,
+-					  GRUB_RELOCATOR_PREFERENCE_NONE,
+-					  0);
++  err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0x8010, 0xa0000,
++					       RELOCATOR_SIZEOF (16) +
++					       GRUB_RELOCATOR16_STACK_SIZE, 16,
++					       GRUB_RELOCATOR_PREFERENCE_NONE, 0);
+   if (err)
+     return err;
+ 
+@@ -183,11 +179,9 @@ grub_relocator64_boot (struct grub_relocator *rel,
+   void *relst;
+   grub_relocator_chunk_t ch;
+ 
+-  err = grub_relocator_alloc_chunk_align (rel, &ch, min_addr,
+-					  max_addr - RELOCATOR_SIZEOF (64),
+-					  RELOCATOR_SIZEOF (64), 16,
+-					  GRUB_RELOCATOR_PREFERENCE_NONE,
+-					  0);
++  err = grub_relocator_alloc_chunk_align_safe (rel, &ch, min_addr, max_addr,
++					       RELOCATOR_SIZEOF (64), 16,
++					       GRUB_RELOCATOR_PREFERENCE_NONE, 0);
+   if (err)
+     return err;
+ 
+diff --git a/grub-core/lib/mips/relocator.c b/grub-core/lib/mips/relocator.c
+index 9d5f49cb93..743b213e69 100644
+--- a/grub-core/lib/mips/relocator.c
++++ b/grub-core/lib/mips/relocator.c
+@@ -120,10 +120,8 @@ grub_relocator32_boot (struct grub_relocator *rel,
+   unsigned i;
+   grub_addr_t vtarget;
+ 
+-  err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
+-					  (0xffffffff - stateset_size)
+-					  + 1, stateset_size,
+-					  sizeof (grub_uint32_t),
++  err = grub_relocator_alloc_chunk_align (rel, &ch, 0, UP_TO_TOP32 (stateset_size),
++					  stateset_size, sizeof (grub_uint32_t),
+ 					  GRUB_RELOCATOR_PREFERENCE_NONE, 0);
+   if (err)
+     return err;
+diff --git a/grub-core/lib/powerpc/relocator.c b/grub-core/lib/powerpc/relocator.c
+index bdf2b111be..8ffb8b6868 100644
+--- a/grub-core/lib/powerpc/relocator.c
++++ b/grub-core/lib/powerpc/relocator.c
+@@ -115,10 +115,8 @@ grub_relocator32_boot (struct grub_relocator *rel,
+   unsigned i;
+   grub_relocator_chunk_t ch;
+ 
+-  err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
+-					  (0xffffffff - stateset_size)
+-					  + 1, stateset_size,
+-					  sizeof (grub_uint32_t),
++  err = grub_relocator_alloc_chunk_align (rel, &ch, 0, UP_TO_TOP32 (stateset_size),
++					  stateset_size, sizeof (grub_uint32_t),
+ 					  GRUB_RELOCATOR_PREFERENCE_NONE, 0);
+   if (err)
+     return err;
+diff --git a/grub-core/lib/x86_64/efi/relocator.c b/grub-core/lib/x86_64/efi/relocator.c
+index 3caef7a402..7d200a125e 100644
+--- a/grub-core/lib/x86_64/efi/relocator.c
++++ b/grub-core/lib/x86_64/efi/relocator.c
+@@ -50,10 +50,9 @@ grub_relocator64_efi_boot (struct grub_relocator *rel,
+    * 64-bit relocator code may live above 4 GiB quite well.
+    * However, I do not want ask for problems. Just in case.
+    */
+-  err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
+-					  0x100000000 - RELOCATOR_SIZEOF (64_efi),
+-					  RELOCATOR_SIZEOF (64_efi), 16,
+-					  GRUB_RELOCATOR_PREFERENCE_NONE, 1);
++  err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0, 0x100000000,
++					       RELOCATOR_SIZEOF (64_efi), 16,
++					       GRUB_RELOCATOR_PREFERENCE_NONE, 1);
+   if (err)
+     return err;
+ 
+diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
+index 4e14eb1887..04bd78a1fa 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -184,9 +184,8 @@ allocate_pages (grub_size_t prot_size, grub_size_t *align,
+ 	for (; err && *align + 1 > min_align; (*align)--)
+ 	  {
+ 	    grub_errno = GRUB_ERR_NONE;
+-	    err = grub_relocator_alloc_chunk_align (relocator, &ch,
+-						    0x1000000,
+-						    0xffffffff & ~prot_size,
++	    err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000000,
++						    UP_TO_TOP32 (prot_size),
+ 						    prot_size, 1 << *align,
+ 						    GRUB_RELOCATOR_PREFERENCE_LOW,
+ 						    1);
+diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c
+index ad3cc292fd..a67d9d0a80 100644
+--- a/grub-core/loader/i386/multiboot_mbi.c
++++ b/grub-core/loader/i386/multiboot_mbi.c
+@@ -466,10 +466,9 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
+ 
+   bufsize = grub_multiboot_get_mbi_size ();
+ 
+-  err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
+-					  0x10000, 0xa0000 - bufsize,
+-					  bufsize, 4,
+-					  GRUB_RELOCATOR_PREFERENCE_NONE, 0);
++  err = grub_relocator_alloc_chunk_align_safe (grub_multiboot_relocator, &ch,
++					       0x10000, 0xa0000, bufsize, 4,
++					       GRUB_RELOCATOR_PREFERENCE_NONE, 0);
+   if (err)
+     return err;
+   ptrorig = get_virtual_current_address (ch);
+diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
+index 81ab3c0c15..6400a5b91d 100644
+--- a/grub-core/loader/i386/pc/linux.c
++++ b/grub-core/loader/i386/pc/linux.c
+@@ -463,10 +463,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ 
+   {
+     grub_relocator_chunk_t ch;
+-    err = grub_relocator_alloc_chunk_align (relocator, &ch,
+-					    addr_min, addr_max - size,
+-					    size, 0x1000,
+-					    GRUB_RELOCATOR_PREFERENCE_HIGH, 0);
++    err = grub_relocator_alloc_chunk_align_safe (relocator, &ch, addr_min, addr_max, size,
++						 0x1000, GRUB_RELOCATOR_PREFERENCE_HIGH, 0);
+     if (err)
+       return err;
+     initrd_chunk = get_virtual_current_address (ch);
+diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c
+index 7b723bf189..e4ed95921d 100644
+--- a/grub-core/loader/mips/linux.c
++++ b/grub-core/loader/mips/linux.c
+@@ -442,12 +442,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   {
+     grub_relocator_chunk_t ch;
+ 
+-    err = grub_relocator_alloc_chunk_align (relocator, &ch,
+-					    (target_addr & 0x1fffffff)
+-					    + linux_size + 0x10000,
+-					    (0x10000000 - size),
+-					    size, 0x10000,
+-					    GRUB_RELOCATOR_PREFERENCE_NONE, 0);
++    err = grub_relocator_alloc_chunk_align_safe (relocator, &ch, (target_addr & 0x1fffffff) +
++						 linux_size + 0x10000, 0x10000000, size,
++						 0x10000, GRUB_RELOCATOR_PREFERENCE_NONE, 0);
+ 
+     if (err)
+       goto fail;
+diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
+index 3e6ad166dc..3e286908dd 100644
+--- a/grub-core/loader/multiboot.c
++++ b/grub-core/loader/multiboot.c
+@@ -404,7 +404,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
+   {
+     grub_relocator_chunk_t ch;
+     err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch,
+-					    lowest_addr, (0xffffffff - size) + 1,
++					    lowest_addr, UP_TO_TOP32 (size),
+ 					    size, MULTIBOOT_MOD_ALIGN,
+ 					    GRUB_RELOCATOR_PREFERENCE_NONE, 1);
+     if (err)
+diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c
+index cc6853692a..f2318e0d16 100644
+--- a/grub-core/loader/multiboot_elfxx.c
++++ b/grub-core/loader/multiboot_elfxx.c
+@@ -109,10 +109,10 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
+       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,
+-					      mld->min_addr, mld->max_addr - load_size,
+-					      load_size, mld->align ? mld->align : 1,
+-					      mld->preference, mld->avoid_efi_boot_services);
++      err = grub_relocator_alloc_chunk_align_safe (GRUB_MULTIBOOT (relocator), &ch,
++						   mld->min_addr, mld->max_addr,
++						   load_size, mld->align ? mld->align : 1,
++						   mld->preference, mld->avoid_efi_boot_services);
+ 
+       if (err)
+         {
+@@ -256,7 +256,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
+ 	    continue;
+ 
+ 	  err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch, 0,
+-						  (0xffffffff - sh->sh_size) + 1,
++						  UP_TO_TOP32 (sh->sh_size),
+ 						  sh->sh_size, sh->sh_addralign,
+ 						  GRUB_RELOCATOR_PREFERENCE_NONE,
+ 						  mld->avoid_efi_boot_services);
+diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
+index 53da786151..3ec2092839 100644
+--- a/grub-core/loader/multiboot_mbi2.c
++++ b/grub-core/loader/multiboot_mbi2.c
+@@ -295,10 +295,10 @@ grub_multiboot2_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_multiboot2_relocator, &ch,
+-						  mld.min_addr, mld.max_addr - code_size,
+-						  code_size, mld.align ? mld.align : 1,
+-						  mld.preference, keep_bs);
++	  err = grub_relocator_alloc_chunk_align_safe (grub_multiboot2_relocator, &ch,
++						       mld.min_addr, mld.max_addr,
++						       code_size, mld.align ? mld.align : 1,
++						       mld.preference, keep_bs);
+ 	}
+       else
+ 	err = grub_relocator_alloc_chunk_addr (grub_multiboot2_relocator,
+@@ -708,7 +708,7 @@ grub_multiboot2_make_mbi (grub_uint32_t *target)
+   COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % sizeof (grub_properly_aligned_t) == 0);
+ 
+   err = grub_relocator_alloc_chunk_align (grub_multiboot2_relocator, &ch,
+-					  0, 0xffffffff - bufsize,
++					  0, UP_TO_TOP32 (bufsize),
+ 					  bufsize, MULTIBOOT_TAG_ALIGN,
+ 					  GRUB_RELOCATOR_PREFERENCE_NONE, 1);
+   if (err)
+diff --git a/grub-core/loader/xnu_resume.c b/grub-core/loader/xnu_resume.c
+index 8089804d48..d648ef0cd3 100644
+--- a/grub-core/loader/xnu_resume.c
++++ b/grub-core/loader/xnu_resume.c
+@@ -129,7 +129,7 @@ grub_xnu_resume (char *imagename)
+   {
+     grub_relocator_chunk_t ch;
+     err = grub_relocator_alloc_chunk_align (grub_xnu_relocator, &ch, 0,
+-					    (0xffffffff - hibhead.image_size) + 1,
++					    UP_TO_TOP32 (hibhead.image_size),
+ 					    hibhead.image_size,
+ 					    GRUB_XNU_PAGESIZE,
+ 					    GRUB_RELOCATOR_PREFERENCE_NONE, 0);
+diff --git a/include/grub/relocator.h b/include/grub/relocator.h
+index 24d8672d22..1b3bdd92ac 100644
+--- a/include/grub/relocator.h
++++ b/include/grub/relocator.h
+@@ -49,6 +49,35 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel,
+ 				  int preference,
+ 				  int avoid_efi_boot_services);
+ 
++/*
++ * Wrapper for grub_relocator_alloc_chunk_align() with purpose of
++ * protecting against integer underflow.
++ *
++ * Compare to its callee, max_addr has different meaning here.
++ * It covers entire chunk and not just start address of the chunk.
++ */
++static inline grub_err_t
++grub_relocator_alloc_chunk_align_safe (struct grub_relocator *rel,
++				       grub_relocator_chunk_t *out,
++				       grub_phys_addr_t min_addr,
++				       grub_phys_addr_t max_addr,
++				       grub_size_t size, grub_size_t align,
++				       int preference,
++				       int avoid_efi_boot_services)
++{
++  /* Sanity check and ensure following equation (max_addr - size) is safe. */
++  if (max_addr < size || (max_addr - size) < min_addr)
++    return GRUB_ERR_OUT_OF_RANGE;
++
++  return grub_relocator_alloc_chunk_align (rel, out, min_addr,
++					   max_addr - size,
++					   size, align, preference,
++					   avoid_efi_boot_services);
++}
++
++/* Top 32-bit address minus s bytes and plus 1 byte. */
++#define UP_TO_TOP32(s)	((~(s) & 0xffffffff) + 1)
++
+ #define GRUB_RELOCATOR_PREFERENCE_NONE 0
+ #define GRUB_RELOCATOR_PREFERENCE_LOW 1
+ #define GRUB_RELOCATOR_PREFERENCE_HIGH 2
diff --git a/debian/patches/0102-relocator-Fix-grub_relocator_alloc_chunk_align-top-m.patch b/debian/patches/0102-relocator-Fix-grub_relocator_alloc_chunk_align-top-m.patch
new file mode 100644
index 0000000..a4d7edd
--- /dev/null
+++ b/debian/patches/0102-relocator-Fix-grub_relocator_alloc_chunk_align-top-m.patch
@@ -0,0 +1,42 @@
+From f5102243ac5d0cc9a319b2f5c4cbc2c518d0d137 Mon Sep 17 00:00:00 2001
+From: Alexey Makhalov <amakhalov@vmware.com>
+Date: Fri, 17 Jul 2020 05:17:26 +0000
+Subject: relocator: Fix grub_relocator_alloc_chunk_align() top memory
+ allocation
+
+Current implementation of grub_relocator_alloc_chunk_align()
+does not allow allocation of the top byte.
+
+Assuming input args are:
+  max_addr = 0xfffff000;
+  size = 0x1000;
+
+And this is valid. But following overflow protection will
+unnecessarily move max_addr one byte down (to 0xffffefff):
+  if (max_addr > ~size)
+    max_addr = ~size;
+
+~size + 1 will fix the situation. In addition, check size
+for non zero to do not zero max_addr.
+
+Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/lib/relocator.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c
+index 5847aac364..f2c1944c28 100644
+--- a/grub-core/lib/relocator.c
++++ b/grub-core/lib/relocator.c
+@@ -1386,8 +1386,8 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel,
+   };
+   grub_addr_t min_addr2 = 0, max_addr2;
+ 
+-  if (max_addr > ~size)
+-    max_addr = ~size;
++  if (size && (max_addr > ~size))
++    max_addr = ~size + 1;
+ 
+ #ifdef GRUB_MACHINE_PCBIOS
+   if (min_addr < 0x1000)
diff --git a/debian/patches/0103-linux-loader-avoid-overflow-on-initrd-size-calculati.patch b/debian/patches/0103-linux-loader-avoid-overflow-on-initrd-size-calculati.patch
new file mode 100644
index 0000000..0bf8d98
--- /dev/null
+++ b/debian/patches/0103-linux-loader-avoid-overflow-on-initrd-size-calculati.patch
@@ -0,0 +1,25 @@
+From 3390bca8bde1f29b8d449f28d5a1fa4f08598af8 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Fri, 24 Jul 2020 13:57:27 -0400
+Subject: linux loader: avoid overflow on initrd size calculation
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/linux.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
+index 471b214d6c..25624ebc11 100644
+--- a/grub-core/loader/linux.c
++++ b/grub-core/loader/linux.c
+@@ -151,8 +151,8 @@ grub_initrd_init (int argc, char *argv[],
+   initrd_ctx->nfiles = 0;
+   initrd_ctx->components = 0;
+ 
+-  initrd_ctx->components = grub_zalloc (argc
+-					* sizeof (initrd_ctx->components[0]));
++  initrd_ctx->components = grub_calloc (argc,
++					sizeof (initrd_ctx->components[0]));
+   if (!initrd_ctx->components)
+     return grub_errno;
+ 
diff --git a/debian/patches/0104-linux-Fix-integer-overflows-in-initrd-size-handling.patch b/debian/patches/0104-linux-Fix-integer-overflows-in-initrd-size-handling.patch
new file mode 100644
index 0000000..e7c41b2
--- /dev/null
+++ b/debian/patches/0104-linux-Fix-integer-overflows-in-initrd-size-handling.patch
@@ -0,0 +1,165 @@
+From 5ae3595759c09e23b48fa2bb35abbe1f66c529bc Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Sat, 25 Jul 2020 12:15:37 +0100
+Subject: linux: Fix integer overflows in initrd size handling
+
+These could be triggered by a crafted filesystem with very large files.
+
+Fixes: CVE-2020-15707
+
+Signed-off-by: Colin Watson <cjwatson@debian.org>
+Reviewed-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
+---
+ grub-core/loader/linux.c | 74 +++++++++++++++++++++++++++++-----------
+ 1 file changed, 54 insertions(+), 20 deletions(-)
+
+diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
+index 25624ebc11..e9f819ee95 100644
+--- a/grub-core/loader/linux.c
++++ b/grub-core/loader/linux.c
+@@ -4,6 +4,7 @@
+ #include <grub/misc.h>
+ #include <grub/file.h>
+ #include <grub/mm.h>
++#include <grub/safemath.h>
+ 
+ struct newc_head
+ {
+@@ -98,13 +99,13 @@ free_dir (struct dir *root)
+   grub_free (root);
+ }
+ 
+-static grub_size_t
++static grub_err_t
+ insert_dir (const char *name, struct dir **root,
+-	    grub_uint8_t *ptr)
++	    grub_uint8_t *ptr, grub_size_t *size)
+ {
+   struct dir *cur, **head = root;
+   const char *cb, *ce = name;
+-  grub_size_t size = 0;
++  *size = 0;
+   while (1)
+     {
+       for (cb = ce; *cb == '/'; cb++);
+@@ -130,14 +131,22 @@ insert_dir (const char *name, struct dir **root,
+ 	      ptr = make_header (ptr, name, ce - name,
+ 				 040777, 0);
+ 	    }
+-	  size += ALIGN_UP ((ce - (char *) name)
+-			    + sizeof (struct newc_head), 4);
++	  if (grub_add (*size,
++		        ALIGN_UP ((ce - (char *) name)
++				  + sizeof (struct newc_head), 4),
++			size))
++	    {
++	      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
++	      grub_free (n->name);
++	      grub_free (n);
++	      return grub_errno;
++	    }
+ 	  *head = n;
+ 	  cur = n;
+ 	}
+       root = &cur->next;
+     }
+-  return size;
++  return GRUB_ERR_NONE;
+ }
+ 
+ grub_err_t
+@@ -173,26 +182,33 @@ grub_initrd_init (int argc, char *argv[],
+ 	  eptr = grub_strchr (ptr, ':');
+ 	  if (eptr)
+ 	    {
++	      grub_size_t dir_size, name_len;
++
+ 	      initrd_ctx->components[i].newc_name = grub_strndup (ptr, eptr - ptr);
+-	      if (!initrd_ctx->components[i].newc_name)
++	      if (!initrd_ctx->components[i].newc_name ||
++		  insert_dir (initrd_ctx->components[i].newc_name, &root, 0,
++			      &dir_size))
+ 		{
+ 		  grub_initrd_close (initrd_ctx);
+ 		  return grub_errno;
+ 		}
+-	      initrd_ctx->size
+-		+= ALIGN_UP (sizeof (struct newc_head)
+-			    + grub_strlen (initrd_ctx->components[i].newc_name),
+-			     4);
+-	      initrd_ctx->size += insert_dir (initrd_ctx->components[i].newc_name,
+-					      &root, 0);
++	      name_len = grub_strlen (initrd_ctx->components[i].newc_name);
++	      if (grub_add (initrd_ctx->size,
++			    ALIGN_UP (sizeof (struct newc_head) + name_len, 4),
++			    &initrd_ctx->size) ||
++		  grub_add (initrd_ctx->size, dir_size, &initrd_ctx->size))
++		goto overflow;
+ 	      newc = 1;
+ 	      fname = eptr + 1;
+ 	    }
+ 	}
+       else if (newc)
+ 	{
+-	  initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head)
+-					+ sizeof ("TRAILER!!!") - 1, 4);
++	  if (grub_add (initrd_ctx->size,
++			ALIGN_UP (sizeof (struct newc_head)
++				  + sizeof ("TRAILER!!!") - 1, 4),
++			&initrd_ctx->size))
++	    goto overflow;
+ 	  free_dir (root);
+ 	  root = 0;
+ 	  newc = 0;
+@@ -208,19 +224,29 @@ grub_initrd_init (int argc, char *argv[],
+       initrd_ctx->nfiles++;
+       initrd_ctx->components[i].size
+ 	= grub_file_size (initrd_ctx->components[i].file);
+-      initrd_ctx->size += initrd_ctx->components[i].size;
++      if (grub_add (initrd_ctx->size, initrd_ctx->components[i].size,
++		    &initrd_ctx->size))
++	goto overflow;
+     }
+ 
+   if (newc)
+     {
+       initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4);
+-      initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head)
+-				    + sizeof ("TRAILER!!!") - 1, 4);
++      if (grub_add (initrd_ctx->size,
++		    ALIGN_UP (sizeof (struct newc_head)
++			      + sizeof ("TRAILER!!!") - 1, 4),
++		    &initrd_ctx->size))
++	goto overflow;
+       free_dir (root);
+       root = 0;
+     }
+   
+   return GRUB_ERR_NONE;
++
++overflow:
++  free_dir (root);
++  grub_initrd_close (initrd_ctx);
++  return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
+ }
+ 
+ grub_size_t
+@@ -261,8 +287,16 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
+ 
+       if (initrd_ctx->components[i].newc_name)
+ 	{
+-	  ptr += insert_dir (initrd_ctx->components[i].newc_name,
+-			     &root, ptr);
++	  grub_size_t dir_size;
++
++	  if (insert_dir (initrd_ctx->components[i].newc_name, &root, ptr,
++			  &dir_size))
++	    {
++	      free_dir (root);
++	      grub_initrd_close (initrd_ctx);
++	      return grub_errno;
++	    }
++	  ptr += dir_size;
+ 	  ptr = make_header (ptr, initrd_ctx->components[i].newc_name,
+ 			     grub_strlen (initrd_ctx->components[i].newc_name),
+ 			     0100777,
diff --git a/debian/patches/0105-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch b/debian/patches/0105-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch
new file mode 100644
index 0000000..c364981
--- /dev/null
+++ b/debian/patches/0105-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch
@@ -0,0 +1,50 @@
+From c15dfc896951a0d1fa03576a3354c59a873cb019 Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@debian.org>
+Date: Mon, 27 Jul 2020 14:22:12 +0100
+Subject: efilinux: Fix integer overflows in grub_cmd_initrd
+
+These could be triggered by an extremely large number of arguments to
+the initrd command on 32-bit architectures, or a crafted filesystem with
+very large files on any architecture.
+
+Fixes: CVE-2020-15707
+
+Signed-off-by: Colin Watson <cjwatson@debian.org>
+---
+ grub-core/loader/i386/efi/linux.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index e357bf67c6..381459ce08 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -28,6 +28,7 @@
+ #include <grub/efi/efi.h>
+ #include <grub/efi/linux.h>
+ #include <grub/efi/sb.h>
++#include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -94,7 +95,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-  files = grub_zalloc (argc * sizeof (files[0]));
++  files = grub_calloc (argc, sizeof (files[0]));
+   if (!files)
+     goto fail;
+ 
+@@ -104,7 +105,11 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+       if (! files[i])
+         goto fail;
+       nfiles++;
+-      size += ALIGN_UP (grub_file_size (files[i]), 4);
++      if (grub_add (size, ALIGN_UP (grub_file_size (files[i]), 4), &size))
++	{
++	  grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
++	  goto fail;
++	}
+     }
+ 
+   initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
diff --git a/debian/patches/at_keyboard-module-init.patch b/debian/patches/at_keyboard-module-init.patch
index e385168..fe36d6e 100644
--- a/debian/patches/at_keyboard-module-init.patch
+++ b/debian/patches/at_keyboard-module-init.patch
@@ -1,4 +1,4 @@
-From 030f7c065c91bdfa93fbe666b7bc284af3bb5167 Mon Sep 17 00:00:00 2001
+From 5365f46e0c28babd3ec09fa2c665b946ac9b3d0f Mon Sep 17 00:00:00 2001
 From: Jeroen Dekkers <jeroen@dekkers.ch>
 Date: Sat, 12 Jan 2019 21:02:18 +0100
 Subject: at_keyboard: initialize keyboard in module init if keyboard is ready
@@ -16,7 +16,7 @@ Patch-Name: at_keyboard-module-init.patch
  1 file changed, 9 insertions(+)
 
 diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c
-index f0a986eb1..d4395c201 100644
+index f0a986eb17..d4395c2019 100644
 --- a/grub-core/term/at_keyboard.c
 +++ b/grub-core/term/at_keyboard.c
 @@ -244,6 +244,14 @@ grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
diff --git a/debian/patches/bash-completion-drop-have-checks.patch b/debian/patches/bash-completion-drop-have-checks.patch
index dd28964..806cf54 100644
--- a/debian/patches/bash-completion-drop-have-checks.patch
+++ b/debian/patches/bash-completion-drop-have-checks.patch
@@ -1,4 +1,4 @@
-From c4f631afd9d93fcfdf4a8a41e72c37818220b31a Mon Sep 17 00:00:00 2001
+From c3bac3061438a6308dc0191e72e295957270c755 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@debian.org>
 Date: Fri, 16 Nov 2018 16:37:02 +0000
 Subject: bash-completion: Drop "have" checks
@@ -16,7 +16,7 @@ Patch-Name: bash-completion-drop-have-checks.patch
  1 file changed, 13 insertions(+), 26 deletions(-)
 
 diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in
-index 44bf135b9..d4235e7ef 100644
+index 44bf135b9f..d4235e7ef8 100644
 --- a/util/bash-completion.d/grub-completion.bash.in
 +++ b/util/bash-completion.d/grub-completion.bash.in
 @@ -166,13 +166,11 @@ _grub_set_entry () {
diff --git a/debian/patches/blacklist-1440x900x32.patch b/debian/patches/blacklist-1440x900x32.patch
index 927df3e..432726d 100644
--- a/debian/patches/blacklist-1440x900x32.patch
+++ b/debian/patches/blacklist-1440x900x32.patch
@@ -1,4 +1,4 @@
-From 49e89abd1779d3b755d3fbc56a7d4859f39f7792 Mon Sep 17 00:00:00 2001
+From a48eec06d4c5c5d1e808b52c1193044c09d638c2 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:11 +0000
 Subject: Blacklist 1440x900x32 from VBE preferred mode handling
@@ -13,7 +13,7 @@ Patch-Name: blacklist-1440x900x32.patch
  1 file changed, 9 insertions(+)
 
 diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c
-index b7f911926..4b1bd7d5e 100644
+index b7f911926d..4b1bd7d5ea 100644
 --- a/grub-core/video/i386/pc/vbe.c
 +++ b/grub-core/video/i386/pc/vbe.c
 @@ -1054,6 +1054,15 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
diff --git a/debian/patches/bootp-new-net_bootp6-command.patch b/debian/patches/bootp-new-net_bootp6-command.patch
index 82964a8..67f690b 100644
--- a/debian/patches/bootp-new-net_bootp6-command.patch
+++ b/debian/patches/bootp-new-net_bootp6-command.patch
@@ -1,4 +1,4 @@
-From ed6f9313a2965716f779f23826e9f74f3074bc8b Mon Sep 17 00:00:00 2001
+From c5375c14deee6e8fd23a018d583495e5c4f95930 Mon Sep 17 00:00:00 2001
 From: Michael Chang <mchang@suse.com>
 Date: Thu, 27 Oct 2016 17:41:04 -0400
 Subject: bootp: New net_bootp6 command
@@ -17,7 +17,7 @@ Patch-Name: bootp-new-net_bootp6-command.patch
  3 files changed, 1018 insertions(+), 1 deletion(-)
 
 diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
-index 04cfbb045..21c1824ef 100644
+index 04cfbb0450..21c1824efb 100644
 --- a/grub-core/net/bootp.c
 +++ b/grub-core/net/bootp.c
 @@ -24,6 +24,98 @@
@@ -969,7 +969,7 @@ index 04cfbb045..21c1824ef 100644
 +  grub_unregister_command (cmd_bootp6);
  }
 diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
-index ea5edf8f1..01410798b 100644
+index ea5edf8f1f..01410798b3 100644
 --- a/grub-core/net/ip.c
 +++ b/grub-core/net/ip.c
 @@ -239,6 +239,45 @@ handle_dgram (struct grub_net_buff *nb,
@@ -1019,7 +1019,7 @@ index ea5edf8f1..01410798b 100644
        {
  	const struct grub_net_bootp_packet *bootp;
 diff --git a/include/grub/net.h b/include/grub/net.h
-index cc114286e..58cff96d2 100644
+index cc114286ea..58cff96d2a 100644
 --- a/include/grub/net.h
 +++ b/include/grub/net.h
 @@ -448,6 +448,66 @@ struct grub_net_bootp_packet
diff --git a/debian/patches/bootp-process-dhcpack-http-boot.patch b/debian/patches/bootp-process-dhcpack-http-boot.patch
index 6372a32..aabd41a 100644
--- a/debian/patches/bootp-process-dhcpack-http-boot.patch
+++ b/debian/patches/bootp-process-dhcpack-http-boot.patch
@@ -1,4 +1,4 @@
-From cddbc2be5f993322a43b2660da588129c19b510a Mon Sep 17 00:00:00 2001
+From 6e1e440798cf53f89f0e5a177d781f0b3d4bc1ca Mon Sep 17 00:00:00 2001
 From: Michael Chang <mchang@suse.com>
 Date: Thu, 27 Oct 2016 17:42:19 -0400
 Subject: bootp: Add processing DHCPACK packet from HTTP Boot
@@ -24,7 +24,7 @@ Patch-Name: bootp-process-dhcpack-http-boot.patch
  2 files changed, 60 insertions(+), 1 deletion(-)
 
 diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
-index 21c1824ef..558d97ba1 100644
+index 21c1824efb..558d97ba1e 100644
 --- a/grub-core/net/bootp.c
 +++ b/grub-core/net/bootp.c
 @@ -154,7 +154,7 @@ struct grub_dhcp_request_options
@@ -109,7 +109,7 @@ index 21c1824ef..558d97ba1 100644
        },
        GRUB_NET_BOOTP_END,
 diff --git a/include/grub/net.h b/include/grub/net.h
-index 58cff96d2..b5f9e617e 100644
+index 58cff96d2a..b5f9e617e5 100644
 --- a/include/grub/net.h
 +++ b/include/grub/net.h
 @@ -523,6 +523,7 @@ enum
diff --git a/debian/patches/cherrypick-lsefisystab-define-smbios3.patch b/debian/patches/cherrypick-lsefisystab-define-smbios3.patch
new file mode 100644
index 0000000..48619ef
--- /dev/null
+++ b/debian/patches/cherrypick-lsefisystab-define-smbios3.patch
@@ -0,0 +1,45 @@
+From 7a7aa7f7da952420277726d4e2279716d1738aa6 Mon Sep 17 00:00:00 2001
+From: David Michael <fedora.dm0@gmail.com>
+Date: Fri, 5 Jul 2019 08:47:02 -0400
+Subject: lsefisystab: Define SMBIOS3 entry point structures for EFI
+
+This adds the GUID and includes it in lsefisystab output.
+
+Signed-off-by: David Michael <fedora.dm0@gmail.com>
+Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+(cherry picked from commit 261df54f170c6d87258eb37ef17d62690720696b)
+Patch-Name: cherrypick-lsefisystab-define-smbios3.patch
+---
+ grub-core/commands/efi/lsefisystab.c | 1 +
+ include/grub/efi/api.h               | 5 +++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/grub-core/commands/efi/lsefisystab.c b/grub-core/commands/efi/lsefisystab.c
+index df10302218..7c039c5097 100644
+--- a/grub-core/commands/efi/lsefisystab.c
++++ b/grub-core/commands/efi/lsefisystab.c
+@@ -48,6 +48,7 @@ static const struct guid_mapping guid_mappings[] =
+     { GRUB_EFI_MPS_TABLE_GUID, "MPS"},
+     { GRUB_EFI_SAL_TABLE_GUID, "SAL"},
+     { GRUB_EFI_SMBIOS_TABLE_GUID, "SMBIOS"},
++    { GRUB_EFI_SMBIOS3_TABLE_GUID, "SMBIOS3"},
+     { GRUB_EFI_SYSTEM_RESOURCE_TABLE_GUID, "SYSTEM RESOURCE TABLE"},
+     { GRUB_EFI_TIANO_CUSTOM_DECOMPRESS_GUID, "TIANO CUSTOM DECOMPRESS"},
+     { GRUB_EFI_TSC_FREQUENCY_GUID, "TSC FREQUENCY"},
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 75befd10e5..9824fbcd0d 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -314,6 +314,11 @@
+     { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+   }
+ 
++#define GRUB_EFI_SMBIOS3_TABLE_GUID	\
++  { 0xf2fd1544, 0x9794, 0x4a2c, \
++    { 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 } \
++  }
++
+ #define GRUB_EFI_SAL_TABLE_GUID \
+   { 0xeb9d2d32, 0x2d88, 0x11d3, \
+       { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
diff --git a/debian/patches/cherrypick-lsefisystab-show-dtb.patch b/debian/patches/cherrypick-lsefisystab-show-dtb.patch
new file mode 100644
index 0000000..727628f
--- /dev/null
+++ b/debian/patches/cherrypick-lsefisystab-show-dtb.patch
@@ -0,0 +1,40 @@
+From b67cba441eece77123d08105d447128e09593194 Mon Sep 17 00:00:00 2001
+From: Heinrich Schuchardt <xypron.glpk@gmx.de>
+Date: Sat, 6 Jul 2019 11:11:02 +0200
+Subject: lsefisystab: Add support for device tree table
+
+The device tree may passed by the firmware as UEFI configuration
+table. Let lsefisystab display a short text and not only the GUID
+for the device tree.
+
+Here is an example output:
+
+  grub> lsefisystab
+  Address: 0xbff694d8
+  Signature: 5453595320494249 revision: 00020046
+  Vendor: Das U-Boot, Version=20190700
+  2 tables:
+  0xbe741000  eb9d2d31-2d88-11d3-9a160090273fc14d   SMBIOS
+  0x87f00000  b1b621d5-f19c-41a5-830bd9152c69aae0   DEVICE TREE
+
+Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
+Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+(cherry picked from commit 15cfd02b74e862bda20626a6e4e2f8a1d201733a)
+Patch-Name: cherrypick-lsefisystab-show-dtb.patch
+---
+ grub-core/commands/efi/lsefisystab.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/grub-core/commands/efi/lsefisystab.c b/grub-core/commands/efi/lsefisystab.c
+index 7c039c5097..902788250e 100644
+--- a/grub-core/commands/efi/lsefisystab.c
++++ b/grub-core/commands/efi/lsefisystab.c
+@@ -40,6 +40,7 @@ static const struct guid_mapping guid_mappings[] =
+     { GRUB_EFI_CRC32_GUIDED_SECTION_EXTRACTION_GUID,
+       "CRC32 GUIDED SECTION EXTRACTION"},
+     { GRUB_EFI_DEBUG_IMAGE_INFO_TABLE_GUID, "DEBUG IMAGE INFO"},
++    { GRUB_EFI_DEVICE_TREE_GUID, "DEVICE TREE"},
+     { GRUB_EFI_DXE_SERVICES_TABLE_GUID, "DXE SERVICES"},
+     { GRUB_EFI_HCDP_TABLE_GUID, "HCDP"},
+     { GRUB_EFI_HOB_LIST_GUID, "HOB LIST"},
diff --git a/debian/patches/cherrypick-smbios-module.patch b/debian/patches/cherrypick-smbios-module.patch
new file mode 100644
index 0000000..a0a649e
--- /dev/null
+++ b/debian/patches/cherrypick-smbios-module.patch
@@ -0,0 +1,771 @@
+From 1eea32e0f58e90b1a7682f01b06c68f56349fb3d Mon Sep 17 00:00:00 2001
+From: David Michael <fedora.dm0@gmail.com>
+Date: Fri, 5 Jul 2019 08:47:09 -0400
+Subject: smbios: Add a module for retrieving SMBIOS information
+
+The following are two use cases from Rajat Jain <rajatjain@juniper.net>:
+
+  1) We have a board that boots Linux and this board itself can be plugged
+     into one of different chassis types. We need to pass different
+     parameters to the kernel based on the "CHASSIS_TYPE" information
+     that is passed by the bios in the DMI/SMBIOS tables.
+
+  2) We may have a USB stick that can go into multiple boards, and the
+     exact kernel to be loaded depends on the machine information
+     (PRODUCT_NAME etc) passed via the DMI.
+
+Signed-off-by: David Michael <fedora.dm0@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+(cherry picked from commit 688023cd0ac4c985fd0e2ec477fcf1ec33a0e49c)
+Patch-Name: cherrypick-smbios-module.patch
+---
+ docs/grub.texi                       |  75 ++++++
+ grub-core/Makefile.core.def          |  15 ++
+ grub-core/commands/efi/smbios.c      |  61 +++++
+ grub-core/commands/i386/pc/smbios.c  |  52 ++++
+ grub-core/commands/smbios.c          | 374 +++++++++++++++++++++++++++
+ grub-core/efiemu/i386/pc/cfgtables.c |  15 +-
+ include/grub/smbios.h                |  69 +++++
+ 7 files changed, 650 insertions(+), 11 deletions(-)
+ create mode 100644 grub-core/commands/efi/smbios.c
+ create mode 100644 grub-core/commands/i386/pc/smbios.c
+ create mode 100644 grub-core/commands/smbios.c
+ create mode 100644 include/grub/smbios.h
+
+diff --git a/docs/grub.texi b/docs/grub.texi
+index 1baa0fa20f..d573f32cbb 100644
+--- a/docs/grub.texi
++++ b/docs/grub.texi
+@@ -3976,6 +3976,7 @@ you forget a command, you can run the command @command{help}
+ * sha256sum::                   Compute or check SHA256 hash
+ * sha512sum::                   Compute or check SHA512 hash
+ * sleep::                       Wait for a specified number of seconds
++* smbios::                      Retrieve SMBIOS information
+ * source::                      Read a configuration file in same context
+ * test::                        Check file types and compare values
+ * true::                        Do nothing, successfully
+@@ -5115,6 +5116,80 @@ if timeout was interrupted by @key{ESC}.
+ @end deffn
+ 
+ 
++@node smbios
++@subsection smbios
++
++@deffn Command smbios @
++ [@option{--type} @var{type}] @
++ [@option{--handle} @var{handle}] @
++ [@option{--match} @var{match}] @
++ (@option{--get-byte} | @option{--get-word} | @option{--get-dword} | @
++  @option{--get-qword} | @option{--get-string} | @option{--get-uuid}) @
++ @var{offset} @
++ [@option{--set} @var{variable}]
++Retrieve SMBIOS information.
++
++The @command{smbios} command returns the value of a field in an SMBIOS
++structure.  The following options determine which structure to select.
++
++@itemize @bullet
++@item
++Specifying @option{--type} will select structures with a matching
++@var{type}.  The type can be any integer from 0 to 255.
++@item
++Specifying @option{--handle} will select structures with a matching
++@var{handle}.  The handle can be any integer from 0 to 65535.
++@item
++Specifying @option{--match} will select structure number @var{match} in the
++filtered list of structures; e.g. @code{smbios --type 4 --match 2} will select
++the second Process Information (Type 4) structure.  The list is always ordered
++the same as the hardware's SMBIOS table.  The match number must be a positive
++integer.  If unspecified, the first matching structure will be selected.
++@end itemize
++
++The remaining options determine which field in the selected SMBIOS structure to
++return.  Only one of these options may be specified at a time.
++
++@itemize @bullet
++@item
++When given @option{--get-byte}, return the value of the byte
++at @var{offset} bytes into the selected SMBIOS structure.
++It will be formatted as an unsigned decimal integer.
++@item
++When given @option{--get-word}, return the value of the word (two bytes)
++at @var{offset} bytes into the selected SMBIOS structure.
++It will be formatted as an unsigned decimal integer.
++@item
++When given @option{--get-dword}, return the value of the dword (four bytes)
++at @var{offset} bytes into the selected SMBIOS structure.
++It will be formatted as an unsigned decimal integer.
++@item
++When given @option{--get-qword}, return the value of the qword (eight bytes)
++at @var{offset} bytes into the selected SMBIOS structure.
++It will be formatted as an unsigned decimal integer.
++@item
++When given @option{--get-string}, return the string with its index found
++at @var{offset} bytes into the selected SMBIOS structure.
++@item
++When given @option{--get-uuid}, return the value of the UUID (sixteen bytes)
++at @var{offset} bytes into the selected SMBIOS structure.
++It will be formatted as lower-case hyphenated hexadecimal digits, with the
++first three fields as little-endian, and the rest printed byte-by-byte.
++@end itemize
++
++The default action is to print the value of the requested field to the console,
++but a variable name can be specified with @option{--set} to store the value
++instead of printing it.
++
++For example, this will store and then display the system manufacturer's name.
++
++@example
++smbios --type 1 --get-string 4 --set system_manufacturer
++echo $system_manufacturer
++@end example
++@end deffn
++
++
+ @node source
+ @subsection source
+ 
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 33e75021da..9b20f33355 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -1106,6 +1106,21 @@ module = {
+   common = commands/sleep.c;
+ };
+ 
++module = {
++  name = smbios;
++
++  common = commands/smbios.c;
++  efi = commands/efi/smbios.c;
++  i386_pc = commands/i386/pc/smbios.c;
++  i386_coreboot = commands/i386/pc/smbios.c;
++  i386_multiboot = commands/i386/pc/smbios.c;
++
++  enable = efi;
++  enable = i386_pc;
++  enable = i386_coreboot;
++  enable = i386_multiboot;
++};
++
+ module = {
+   name = suspend;
+   ieee1275 = commands/ieee1275/suspend.c;
+diff --git a/grub-core/commands/efi/smbios.c b/grub-core/commands/efi/smbios.c
+new file mode 100644
+index 0000000000..75202d5aad
+--- /dev/null
++++ b/grub-core/commands/efi/smbios.c
+@@ -0,0 +1,61 @@
++/* smbios.c - get smbios tables. */
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2019  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/smbios.h>
++#include <grub/misc.h>
++#include <grub/efi/efi.h>
++#include <grub/efi/api.h>
++
++struct grub_smbios_eps *
++grub_machine_smbios_get_eps (void)
++{
++  unsigned i;
++  static grub_efi_packed_guid_t smbios_guid = GRUB_EFI_SMBIOS_TABLE_GUID;
++
++  for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
++    {
++      grub_efi_packed_guid_t *guid =
++	&grub_efi_system_table->configuration_table[i].vendor_guid;
++
++      if (! grub_memcmp (guid, &smbios_guid, sizeof (grub_efi_packed_guid_t)))
++	return (struct grub_smbios_eps *)
++	  grub_efi_system_table->configuration_table[i].vendor_table;
++    }
++
++  return 0;
++}
++
++struct grub_smbios_eps3 *
++grub_machine_smbios_get_eps3 (void)
++{
++  unsigned i;
++  static grub_efi_packed_guid_t smbios3_guid = GRUB_EFI_SMBIOS3_TABLE_GUID;
++
++  for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
++    {
++      grub_efi_packed_guid_t *guid =
++	&grub_efi_system_table->configuration_table[i].vendor_guid;
++
++      if (! grub_memcmp (guid, &smbios3_guid, sizeof (grub_efi_packed_guid_t)))
++	return (struct grub_smbios_eps3 *)
++	  grub_efi_system_table->configuration_table[i].vendor_table;
++    }
++
++  return 0;
++}
+diff --git a/grub-core/commands/i386/pc/smbios.c b/grub-core/commands/i386/pc/smbios.c
+new file mode 100644
+index 0000000000..069d663673
+--- /dev/null
++++ b/grub-core/commands/i386/pc/smbios.c
+@@ -0,0 +1,52 @@
++/* smbios.c - get smbios tables. */
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2019  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/acpi.h>
++#include <grub/smbios.h>
++#include <grub/misc.h>
++
++struct grub_smbios_eps *
++grub_machine_smbios_get_eps (void)
++{
++  grub_uint8_t *ptr;
++
++  grub_dprintf ("smbios", "Looking for SMBIOS EPS. Scanning BIOS\n");
++
++  for (ptr = (grub_uint8_t *) 0xf0000; ptr < (grub_uint8_t *) 0x100000; ptr += 16)
++    if (grub_memcmp (ptr, "_SM_", 4) == 0
++	&& grub_byte_checksum (ptr, sizeof (struct grub_smbios_eps)) == 0)
++      return (struct grub_smbios_eps *) ptr;
++
++  return 0;
++}
++
++struct grub_smbios_eps3 *
++grub_machine_smbios_get_eps3 (void)
++{
++  grub_uint8_t *ptr;
++
++  grub_dprintf ("smbios", "Looking for SMBIOS3 EPS. Scanning BIOS\n");
++
++  for (ptr = (grub_uint8_t *) 0xf0000; ptr < (grub_uint8_t *) 0x100000; ptr += 16)
++    if (grub_memcmp (ptr, "_SM3_", 5) == 0
++	&& grub_byte_checksum (ptr, sizeof (struct grub_smbios_eps3)) == 0)
++      return (struct grub_smbios_eps3 *) ptr;
++
++  return 0;
++}
+diff --git a/grub-core/commands/smbios.c b/grub-core/commands/smbios.c
+new file mode 100644
+index 0000000000..7a6a391fc1
+--- /dev/null
++++ b/grub-core/commands/smbios.c
+@@ -0,0 +1,374 @@
++/* smbios.c - retrieve smbios information. */
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2019  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/env.h>
++#include <grub/extcmd.h>
++#include <grub/i18n.h>
++#include <grub/misc.h>
++#include <grub/mm.h>
++#include <grub/smbios.h>
++
++GRUB_MOD_LICENSE ("GPLv3+");
++
++/* Abstract useful values found in either the SMBIOS3 or SMBIOS EPS. */
++static struct {
++  grub_addr_t start;
++  grub_addr_t end;
++  grub_uint16_t structures;
++} table_desc;
++
++static grub_extcmd_t cmd;
++
++/* Locate the SMBIOS entry point structure depending on the hardware. */
++struct grub_smbios_eps *
++grub_smbios_get_eps (void)
++{
++  static struct grub_smbios_eps *eps = NULL;
++
++  if (eps != NULL)
++    return eps;
++
++  eps = grub_machine_smbios_get_eps ();
++
++  return eps;
++}
++
++/* Locate the SMBIOS3 entry point structure depending on the hardware. */
++static struct grub_smbios_eps3 *
++grub_smbios_get_eps3 (void)
++{
++  static struct grub_smbios_eps3 *eps = NULL;
++
++  if (eps != NULL)
++    return eps;
++
++  eps = grub_machine_smbios_get_eps3 ();
++
++  return eps;
++}
++
++/*
++ * These functions convert values from the various SMBIOS structure field types
++ * into a string formatted to be returned to the user.  They expect that the
++ * structure and offset were already validated.  When the requested data is
++ * successfully retrieved and formatted, the pointer to the string is returned;
++ * otherwise, NULL is returned on failure.  Don't free the result.
++ */
++
++static const char *
++grub_smbios_format_byte (const grub_uint8_t *structure, grub_uint8_t offset)
++{
++  static char buffer[sizeof ("255")];
++
++  grub_snprintf (buffer, sizeof (buffer), "%u", structure[offset]);
++
++  return (const char *)buffer;
++}
++
++static const char *
++grub_smbios_format_word (const grub_uint8_t *structure, grub_uint8_t offset)
++{
++  static char buffer[sizeof ("65535")];
++
++  grub_uint16_t value = grub_get_unaligned16 (structure + offset);
++  grub_snprintf (buffer, sizeof (buffer), "%u", value);
++
++  return (const char *)buffer;
++}
++
++static const char *
++grub_smbios_format_dword (const grub_uint8_t *structure, grub_uint8_t offset)
++{
++  static char buffer[sizeof ("4294967295")];
++
++  grub_uint32_t value = grub_get_unaligned32 (structure + offset);
++  grub_snprintf (buffer, sizeof (buffer), "%" PRIuGRUB_UINT32_T, value);
++
++  return (const char *)buffer;
++}
++
++static const char *
++grub_smbios_format_qword (const grub_uint8_t *structure, grub_uint8_t offset)
++{
++  static char buffer[sizeof ("18446744073709551615")];
++
++  grub_uint64_t value = grub_get_unaligned64 (structure + offset);
++  grub_snprintf (buffer, sizeof (buffer), "%" PRIuGRUB_UINT64_T, value);
++
++  return (const char *)buffer;
++}
++
++static const char *
++grub_smbios_get_string (const grub_uint8_t *structure, grub_uint8_t offset)
++{
++  const grub_uint8_t *ptr = structure + structure[1];
++  const grub_uint8_t *table_end = (const grub_uint8_t *)table_desc.end;
++  const grub_uint8_t referenced_string_number = structure[offset];
++  grub_uint8_t i;
++
++  /* A string referenced with zero is interpreted as unset. */
++  if (referenced_string_number == 0)
++    return NULL;
++
++  /* Search the string set. */
++  for (i = 1; *ptr != 0 && ptr < table_end; i++)
++    if (i == referenced_string_number)
++      {
++        const char *str = (const char *)ptr;
++        while (*ptr++ != 0)
++          if (ptr >= table_end)
++            return NULL; /* The string isn't terminated. */
++        return str;
++      }
++    else
++      while (*ptr++ != 0 && ptr < table_end);
++
++  /* The string number is greater than the number of strings in the set. */
++  return NULL;
++}
++
++static const char *
++grub_smbios_format_uuid (const grub_uint8_t *structure, grub_uint8_t offset)
++{
++  static char buffer[sizeof ("ffffffff-ffff-ffff-ffff-ffffffffffff")];
++  const grub_uint8_t *f = structure + offset; /* little-endian fields */
++  const grub_uint8_t *g = f + 8; /* byte-by-byte fields */
++
++  grub_snprintf (buffer, sizeof (buffer),
++                 "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
++                 "%02x%02x-%02x%02x%02x%02x%02x%02x",
++                 f[3], f[2], f[1], f[0], f[5], f[4], f[7], f[6],
++                 g[0], g[1], g[2], g[3], g[4], g[5], g[6], g[7]);
++
++  return (const char *)buffer;
++}
++
++/* List the field formatting functions and the number of bytes they need. */
++static const struct {
++  const char *(*format) (const grub_uint8_t *structure, grub_uint8_t offset);
++  grub_uint8_t field_length;
++} field_extractors[] = {
++  {grub_smbios_format_byte, 1},
++  {grub_smbios_format_word, 2},
++  {grub_smbios_format_dword, 4},
++  {grub_smbios_format_qword, 8},
++  {grub_smbios_get_string, 1},
++  {grub_smbios_format_uuid, 16}
++};
++
++/* List command options, with structure field getters ordered as above. */
++#define FIRST_GETTER_OPT (3)
++#define SETTER_OPT (FIRST_GETTER_OPT + ARRAY_SIZE(field_extractors))
++
++static const struct grub_arg_option options[] = {
++  {"type",       't', 0, N_("Match structures with the given type."),
++                         N_("type"), ARG_TYPE_INT},
++  {"handle",     'h', 0, N_("Match structures with the given handle."),
++                         N_("handle"), ARG_TYPE_INT},
++  {"match",      'm', 0, N_("Select a structure when several match."),
++                         N_("match"), ARG_TYPE_INT},
++  {"get-byte",   'b', 0, N_("Get the byte's value at the given offset."),
++                         N_("offset"), ARG_TYPE_INT},
++  {"get-word",   'w', 0, N_("Get two bytes' value at the given offset."),
++                         N_("offset"), ARG_TYPE_INT},
++  {"get-dword",  'd', 0, N_("Get four bytes' value at the given offset."),
++                         N_("offset"), ARG_TYPE_INT},
++  {"get-qword",  'q', 0, N_("Get eight bytes' value at the given offset."),
++                         N_("offset"), ARG_TYPE_INT},
++  {"get-string", 's', 0, N_("Get the string specified at the given offset."),
++                         N_("offset"), ARG_TYPE_INT},
++  {"get-uuid",   'u', 0, N_("Get the UUID's value at the given offset."),
++                         N_("offset"), ARG_TYPE_INT},
++  {"set",       '\0', 0, N_("Store the value in the given variable name."),
++                         N_("variable"), ARG_TYPE_STRING},
++  {0, 0, 0, 0, 0, 0}
++};
++
++/*
++ * Return a matching SMBIOS structure.
++ *
++ * This method can use up to three criteria for selecting a structure:
++ *   - The "type" field                  (use -1 to ignore)
++ *   - The "handle" field                (use -1 to ignore)
++ *   - Which to return if several match  (use  0 to ignore)
++ *
++ * The return value is a pointer to the first matching structure.  If no
++ * structures match the given parameters, NULL is returned.
++ */
++static const grub_uint8_t *
++grub_smbios_match_structure (const grub_int16_t type,
++                             const grub_int32_t handle,
++                             const grub_uint16_t match)
++{
++  const grub_uint8_t *ptr = (const grub_uint8_t *)table_desc.start;
++  const grub_uint8_t *table_end = (const grub_uint8_t *)table_desc.end;
++  grub_uint16_t structures = table_desc.structures;
++  grub_uint16_t structure_count = 0;
++  grub_uint16_t matches = 0;
++
++  while (ptr < table_end
++         && ptr[1] >= 4 /* Valid structures include the 4-byte header. */
++         && (structure_count++ < structures || structures == 0))
++    {
++      grub_uint16_t structure_handle = grub_get_unaligned16 (ptr + 2);
++      grub_uint8_t structure_type = ptr[0];
++
++      if ((handle < 0 || handle == structure_handle)
++          && (type < 0 || type == structure_type)
++          && (match == 0 || match == ++matches))
++        return ptr;
++      else
++        {
++          ptr += ptr[1];
++          while ((*ptr++ != 0 || *ptr++ != 0) && ptr < table_end);
++        }
++
++      if (structure_type == GRUB_SMBIOS_TYPE_END_OF_TABLE)
++        break;
++    }
++
++  return NULL;
++}
++
++static grub_err_t
++grub_cmd_smbios (grub_extcmd_context_t ctxt,
++                 int argc __attribute__ ((unused)),
++                 char **argv __attribute__ ((unused)))
++{
++  struct grub_arg_list *state = ctxt->state;
++
++  grub_int16_t type = -1;
++  grub_int32_t handle = -1;
++  grub_uint16_t match = 0;
++  grub_uint8_t offset = 0;
++
++  const grub_uint8_t *structure;
++  const char *value;
++  grub_int32_t option;
++  grub_int8_t field_type = -1;
++  grub_uint8_t i;
++
++  if (table_desc.start == 0)
++    return grub_error (GRUB_ERR_IO,
++                       N_("the SMBIOS entry point structure was not found"));
++
++  /* Read the given filtering options. */
++  if (state[0].set)
++    {
++      option = grub_strtol (state[0].arg, NULL, 0);
++      if (option < 0 || option > 255)
++        return grub_error (GRUB_ERR_BAD_ARGUMENT,
++                           N_("the type must be between 0 and 255"));
++      type = (grub_int16_t)option;
++    }
++  if (state[1].set)
++    {
++      option = grub_strtol (state[1].arg, NULL, 0);
++      if (option < 0 || option > 65535)
++        return grub_error (GRUB_ERR_BAD_ARGUMENT,
++                           N_("the handle must be between 0 and 65535"));
++      handle = (grub_int32_t)option;
++    }
++  if (state[2].set)
++    {
++      option = grub_strtol (state[2].arg, NULL, 0);
++      if (option <= 0 || option > 65535)
++        return grub_error (GRUB_ERR_BAD_ARGUMENT,
++                           N_("the match must be a positive integer"));
++      match = (grub_uint16_t)option;
++    }
++
++  /* Determine the data type of the structure field to retrieve. */
++  for (i = 0; i < ARRAY_SIZE(field_extractors); i++)
++    if (state[FIRST_GETTER_OPT + i].set)
++      {
++        if (field_type >= 0)
++          return grub_error (GRUB_ERR_BAD_ARGUMENT,
++                             N_("only one --get option is usable at a time"));
++        field_type = i;
++      }
++
++  /* Require a choice of a structure field to return. */
++  if (field_type < 0)
++    return grub_error (GRUB_ERR_BAD_ARGUMENT,
++                       N_("one of the --get options is required"));
++
++  /* Locate a matching SMBIOS structure. */
++  structure = grub_smbios_match_structure (type, handle, match);
++  if (structure == NULL)
++    return grub_error (GRUB_ERR_IO,
++                       N_("no structure matched the given options"));
++
++  /* Ensure the requested byte offset is inside the structure. */
++  option = grub_strtol (state[FIRST_GETTER_OPT + field_type].arg, NULL, 0);
++  if (option < 0 || option >= structure[1])
++    return grub_error (GRUB_ERR_OUT_OF_RANGE,
++                       N_("the given offset is outside the structure"));
++
++  /* Ensure the requested data type at the offset is inside the structure. */
++  offset = (grub_uint8_t)option;
++  if (offset + field_extractors[field_type].field_length > structure[1])
++    return grub_error (GRUB_ERR_OUT_OF_RANGE,
++                       N_("the field ends outside the structure"));
++
++  /* Format the requested structure field into a readable string. */
++  value = field_extractors[field_type].format (structure, offset);
++  if (value == NULL)
++    return grub_error (GRUB_ERR_IO,
++                       N_("failed to retrieve the structure field"));
++
++  /* Store or print the formatted value. */
++  if (state[SETTER_OPT].set)
++    grub_env_set (state[SETTER_OPT].arg, value);
++  else
++    grub_printf ("%s\n", value);
++
++  return GRUB_ERR_NONE;
++}
++
++GRUB_MOD_INIT(smbios)
++{
++  struct grub_smbios_eps3 *eps3;
++  struct grub_smbios_eps *eps;
++
++  if ((eps3 = grub_smbios_get_eps3 ()))
++    {
++      table_desc.start = (grub_addr_t)eps3->table_address;
++      table_desc.end = table_desc.start + eps3->maximum_table_length;
++      table_desc.structures = 0; /* SMBIOS3 drops the structure count. */
++    }
++  else if ((eps = grub_smbios_get_eps ()))
++    {
++      table_desc.start = (grub_addr_t)eps->intermediate.table_address;
++      table_desc.end = table_desc.start + eps->intermediate.table_length;
++      table_desc.structures = eps->intermediate.structures;
++    }
++
++  cmd = grub_register_extcmd ("smbios", grub_cmd_smbios, 0,
++                              N_("[-t type] [-h handle] [-m match] "
++                                 "(-b|-w|-d|-q|-s|-u) offset "
++                                 "[--set variable]"),
++                              N_("Retrieve SMBIOS information."), options);
++}
++
++GRUB_MOD_FINI(smbios)
++{
++  grub_unregister_extcmd (cmd);
++}
+diff --git a/grub-core/efiemu/i386/pc/cfgtables.c b/grub-core/efiemu/i386/pc/cfgtables.c
+index 492c07c468..e5fffb7d4a 100644
+--- a/grub-core/efiemu/i386/pc/cfgtables.c
++++ b/grub-core/efiemu/i386/pc/cfgtables.c
+@@ -22,11 +22,11 @@
+ #include <grub/misc.h>
+ #include <grub/mm.h>
+ #include <grub/acpi.h>
++#include <grub/smbios.h>
+ 
+ grub_err_t
+ grub_machine_efiemu_init_tables (void)
+ {
+-  grub_uint8_t *ptr;
+   void *table;
+   grub_err_t err;
+   grub_efi_guid_t smbios = GRUB_EFI_SMBIOS_TABLE_GUID;
+@@ -57,17 +57,10 @@ grub_machine_efiemu_init_tables (void)
+       if (err)
+ 	return err;
+     }
+-
+-  for (ptr = (grub_uint8_t *) 0xf0000; ptr < (grub_uint8_t *) 0x100000;
+-       ptr += 16)
+-    if (grub_memcmp (ptr, "_SM_", 4) == 0
+-	&& grub_byte_checksum (ptr, *(ptr + 5)) == 0)
+-      break;
+-
+-  if (ptr < (grub_uint8_t *) 0x100000)
++  table = grub_smbios_get_eps ();
++  if (table)
+     {
+-      grub_dprintf ("efiemu", "Registering SMBIOS\n");
+-      err = grub_efiemu_register_configuration_table (smbios, 0, 0, ptr);
++      err = grub_efiemu_register_configuration_table (smbios, 0, 0, table);
+       if (err)
+ 	return err;
+     }
+diff --git a/include/grub/smbios.h b/include/grub/smbios.h
+new file mode 100644
+index 0000000000..15ec260b32
+--- /dev/null
++++ b/include/grub/smbios.h
+@@ -0,0 +1,69 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2019  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_SMBIOS_HEADER
++#define GRUB_SMBIOS_HEADER	1
++
++#include <grub/symbol.h>
++#include <grub/types.h>
++
++#define GRUB_SMBIOS_TYPE_END_OF_TABLE ((grub_uint8_t)127)
++
++struct grub_smbios_ieps
++{
++  grub_uint8_t anchor[5]; /* "_DMI_" */
++  grub_uint8_t checksum;
++  grub_uint16_t table_length;
++  grub_uint32_t table_address;
++  grub_uint16_t structures;
++  grub_uint8_t revision;
++} GRUB_PACKED;
++
++struct grub_smbios_eps
++{
++  grub_uint8_t anchor[4]; /* "_SM_" */
++  grub_uint8_t checksum;
++  grub_uint8_t length; /* 0x1f */
++  grub_uint8_t version_major;
++  grub_uint8_t version_minor;
++  grub_uint16_t maximum_structure_size;
++  grub_uint8_t revision;
++  grub_uint8_t formatted[5];
++  struct grub_smbios_ieps intermediate;
++} GRUB_PACKED;
++
++struct grub_smbios_eps3
++{
++  grub_uint8_t anchor[5]; /* "_SM3_" */
++  grub_uint8_t checksum;
++  grub_uint8_t length; /* 0x18 */
++  grub_uint8_t version_major;
++  grub_uint8_t version_minor;
++  grub_uint8_t docrev;
++  grub_uint8_t revision;
++  grub_uint8_t reserved;
++  grub_uint32_t maximum_table_length;
++  grub_uint64_t table_address;
++} GRUB_PACKED;
++
++extern struct grub_smbios_eps *grub_machine_smbios_get_eps (void);
++extern struct grub_smbios_eps3 *grub_machine_smbios_get_eps3 (void);
++
++extern struct grub_smbios_eps *EXPORT_FUNC (grub_smbios_get_eps) (void);
++
++#endif /* ! GRUB_SMBIOS_HEADER */
diff --git a/debian/patches/core-in-fs.patch b/debian/patches/core-in-fs.patch
index 1ba3b4b..b8e13d3 100644
--- a/debian/patches/core-in-fs.patch
+++ b/debian/patches/core-in-fs.patch
@@ -11,7 +11,7 @@ Patch-Name: core-in-fs.patch
  1 file changed, 8 insertions(+)
 
 diff --git a/util/setup.c b/util/setup.c
-index 6f88f3cc4..fbdf2fcc5 100644
+index 6f88f3cc43..fbdf2fcc59 100644
 --- a/util/setup.c
 +++ b/util/setup.c
 @@ -58,6 +58,8 @@
diff --git a/debian/patches/default-grub-d.patch b/debian/patches/default-grub-d.patch
index cb95f70..cf024d6 100644
--- a/debian/patches/default-grub-d.patch
+++ b/debian/patches/default-grub-d.patch
@@ -1,4 +1,4 @@
-From 413121ddac2aa1484b0dc6fd3a32aad0d417aa80 Mon Sep 17 00:00:00 2001
+From c3ad86f659b0a1af2033086101936f3a17e67a0a Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:10 +0000
 Subject: Read /etc/default/grub.d/*.cfg after /etc/default/grub
@@ -14,7 +14,7 @@ Patch-Name: default-grub-d.patch
  2 files changed, 98 insertions(+), 21 deletions(-)
 
 diff --git a/grub-core/osdep/unix/config.c b/grub-core/osdep/unix/config.c
-index 65effa9f3..5478030fd 100644
+index 65effa9f3a..5478030fde 100644
 --- a/grub-core/osdep/unix/config.c
 +++ b/grub-core/osdep/unix/config.c
 @@ -24,6 +24,8 @@
@@ -178,7 +178,7 @@ index 65effa9f3..5478030fd 100644
 +  free (cfgdir);
  }
 diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
-index b506d63bf..d18bf972f 100644
+index b506d63bf9..d18bf972f7 100644
 --- a/util/grub-mkconfig.in
 +++ b/util/grub-mkconfig.in
 @@ -164,6 +164,11 @@ fi
diff --git a/debian/patches/disable-floppies.patch b/debian/patches/disable-floppies.patch
index 7d4835e..981b9ec 100644
--- a/debian/patches/disable-floppies.patch
+++ b/debian/patches/disable-floppies.patch
@@ -13,7 +13,7 @@ Patch-Name: disable-floppies.patch
  1 file changed, 12 insertions(+)
 
 diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c
-index e9ec680cd..8ac523953 100644
+index e9ec680cdb..8ac5239538 100644
 --- a/grub-core/kern/emu/hostdisk.c
 +++ b/grub-core/kern/emu/hostdisk.c
 @@ -532,6 +532,18 @@ read_device_map (const char *dev_map)
diff --git a/debian/patches/dpkg-version-comparison.patch b/debian/patches/dpkg-version-comparison.patch
index 86e5c7e..929070f 100644
--- a/debian/patches/dpkg-version-comparison.patch
+++ b/debian/patches/dpkg-version-comparison.patch
@@ -12,7 +12,7 @@ Patch-Name: dpkg-version-comparison.patch
  1 file changed, 4 insertions(+), 3 deletions(-)
 
 diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
-index 0f801cab3..b6606c16e 100644
+index 0f801cab3e..b6606c16e0 100644
 --- a/util/grub-mkconfig_lib.in
 +++ b/util/grub-mkconfig_lib.in
 @@ -239,8 +239,9 @@ version_test_numeric ()
diff --git a/debian/patches/efi-variable-storage-minimise-writes.patch b/debian/patches/efi-variable-storage-minimise-writes.patch
index 1a75709..44ac1ae 100644
--- a/debian/patches/efi-variable-storage-minimise-writes.patch
+++ b/debian/patches/efi-variable-storage-minimise-writes.patch
@@ -1,4 +1,4 @@
-From 4746efb5deb68fb95ea5b172fef043a03c0532b7 Mon Sep 17 00:00:00 2001
+From b18e6318f49373c1018be8b6d34266a009f10ae8 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 11 Mar 2019 11:17:43 +0000
 Subject: Minimise writes to EFI variable storage
@@ -60,7 +60,7 @@ Patch-Name: efi-variable-storage-minimise-writes.patch
  create mode 100644 grub-core/osdep/unix/efivar.c
 
 diff --git a/INSTALL b/INSTALL
-index 8acb40902..342c158e9 100644
+index 8acb409023..342c158e91 100644
 --- a/INSTALL
 +++ b/INSTALL
 @@ -41,6 +41,11 @@ configuring the GRUB.
@@ -76,10 +76,10 @@ index 8acb40902..342c158e9 100644
  
  * libdevmapper 1.02.34 or later (recommended)
 diff --git a/Makefile.util.def b/Makefile.util.def
-index 8a24b23f0..59e41423b 100644
+index ce133e694e..504d1c0581 100644
 --- a/Makefile.util.def
 +++ b/Makefile.util.def
-@@ -558,6 +558,8 @@ program = {
+@@ -565,6 +565,8 @@ program = {
    common = grub-core/osdep/compress.c;
    extra_dist = grub-core/osdep/unix/compress.c;
    extra_dist = grub-core/osdep/basic/compress.c;
@@ -88,7 +88,7 @@ index 8a24b23f0..59e41423b 100644
    common = util/editenv.c;
    common = grub-core/osdep/blocklist.c;
    common = grub-core/osdep/config.c;
-@@ -571,12 +573,15 @@ program = {
+@@ -578,12 +580,15 @@ program = {
    common = grub-core/kern/emu/argp_common.c;
    common = grub-core/osdep/init.c;
  
@@ -104,7 +104,7 @@ index 8a24b23f0..59e41423b 100644
  
    condition = COND_HAVE_EXEC;
  };
-@@ -605,6 +610,8 @@ program = {
+@@ -612,6 +617,8 @@ program = {
    extra_dist = grub-core/osdep/basic/no_platform.c;
    extra_dist = grub-core/osdep/unix/platform.c;
    common = grub-core/osdep/compress.c;
@@ -113,7 +113,7 @@ index 8a24b23f0..59e41423b 100644
    common = util/editenv.c;
    common = grub-core/osdep/blocklist.c;
    common = grub-core/osdep/config.c;
-@@ -618,12 +625,15 @@ program = {
+@@ -625,12 +632,15 @@ program = {
    common = grub-core/kern/emu/argp_common.c;
    common = grub-core/osdep/init.c;
  
@@ -129,7 +129,7 @@ index 8a24b23f0..59e41423b 100644
  };
  
  program = {
-@@ -645,6 +655,8 @@ program = {
+@@ -652,6 +662,8 @@ program = {
    common = grub-core/osdep/platform.c;
    common = grub-core/osdep/platform_unix.c;
    common = grub-core/osdep/compress.c;
@@ -138,7 +138,7 @@ index 8a24b23f0..59e41423b 100644
    common = util/editenv.c;
    common = grub-core/osdep/blocklist.c;
    common = grub-core/osdep/config.c;
-@@ -657,12 +669,15 @@ program = {
+@@ -664,12 +676,15 @@ program = {
    common = grub-core/kern/emu/argp_common.c;
    common = grub-core/osdep/init.c;
  
@@ -154,7 +154,7 @@ index 8a24b23f0..59e41423b 100644
  };
  
  program = {
-@@ -684,6 +699,8 @@ program = {
+@@ -691,6 +706,8 @@ program = {
    common = grub-core/osdep/platform.c;
    common = grub-core/osdep/platform_unix.c;
    common = grub-core/osdep/compress.c;
@@ -163,7 +163,7 @@ index 8a24b23f0..59e41423b 100644
    common = util/editenv.c;
    common = grub-core/osdep/blocklist.c;
    common = grub-core/osdep/config.c;
-@@ -693,12 +710,15 @@ program = {
+@@ -700,12 +717,15 @@ program = {
    common = grub-core/kern/emu/argp_common.c;
    common = grub-core/osdep/init.c;
  
@@ -180,7 +180,7 @@ index 8a24b23f0..59e41423b 100644
  
  script = {
 diff --git a/configure.ac b/configure.ac
-index e382c7480..883245553 100644
+index e382c7480d..883245553d 100644
 --- a/configure.ac
 +++ b/configure.ac
 @@ -443,6 +443,18 @@ AC_CHECK_HEADER([util.h], [
@@ -204,7 +204,7 @@ index e382c7480..883245553 100644
    CFLAGS="$HOST_CFLAGS -Wtrampolines -Werror"
 diff --git a/grub-core/osdep/efivar.c b/grub-core/osdep/efivar.c
 new file mode 100644
-index 000000000..d2750e252
+index 0000000000..d2750e2524
 --- /dev/null
 +++ b/grub-core/osdep/efivar.c
 @@ -0,0 +1,3 @@
@@ -213,7 +213,7 @@ index 000000000..d2750e252
 +#endif
 diff --git a/grub-core/osdep/unix/efivar.c b/grub-core/osdep/unix/efivar.c
 new file mode 100644
-index 000000000..4a58328b4
+index 0000000000..4a58328b42
 --- /dev/null
 +++ b/grub-core/osdep/unix/efivar.c
 @@ -0,0 +1,508 @@
@@ -726,7 +726,7 @@ index 000000000..4a58328b4
 +
 +#endif /* HAVE_EFIVAR */
 diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
-index 9c439326a..b561174ea 100644
+index 9c439326a0..b561174ea9 100644
 --- a/grub-core/osdep/unix/platform.c
 +++ b/grub-core/osdep/unix/platform.c
 @@ -19,15 +19,12 @@
@@ -856,7 +856,7 @@ index 9c439326a..b561174ea 100644
  
  void
 diff --git a/include/grub/util/install.h b/include/grub/util/install.h
-index 8aeb5c4f2..a521f1663 100644
+index 8aeb5c4f20..a521f1663f 100644
 --- a/include/grub/util/install.h
 +++ b/include/grub/util/install.h
 @@ -219,6 +219,11 @@ grub_install_get_default_x86_platform (void);
@@ -872,10 +872,10 @@ index 8aeb5c4f2..a521f1663 100644
  grub_install_register_efi (grub_device_t efidir_grub_dev,
  			   const char *efifile_path,
 diff --git a/util/grub-install.c b/util/grub-install.c
-index 6462d3c70..d66de7f8e 100644
+index 4bad8de612..63462e4e09 100644
 --- a/util/grub-install.c
 +++ b/util/grub-install.c
-@@ -2059,7 +2059,7 @@ main (int argc, char *argv[])
+@@ -2084,7 +2084,7 @@ main (int argc, char *argv[])
  					       "\\System\\Library\\CoreServices",
  					       efi_distributor);
  	      if (ret)
@@ -884,7 +884,7 @@ index 6462d3c70..d66de7f8e 100644
  				 strerror (ret));
  	    }
  
-@@ -2173,7 +2173,7 @@ main (int argc, char *argv[])
+@@ -2201,7 +2201,7 @@ main (int argc, char *argv[])
  	  ret = grub_install_register_efi (efidir_grub_dev,
  					   efifile_path, efi_distributor);
  	  if (ret)
diff --git a/debian/patches/efinet-set-dns-from-uefi-proto.patch b/debian/patches/efinet-set-dns-from-uefi-proto.patch
index 016ff5b..fdf062b 100644
--- a/debian/patches/efinet-set-dns-from-uefi-proto.patch
+++ b/debian/patches/efinet-set-dns-from-uefi-proto.patch
@@ -1,4 +1,4 @@
-From 2a8c1fc36074fe7ac673839c5434e7e2f1498cd3 Mon Sep 17 00:00:00 2001
+From 5e2600c379b6ef398a18081b65367f0674c935dc Mon Sep 17 00:00:00 2001
 From: Michael Chang <mchang@suse.com>
 Date: Thu, 27 Oct 2016 17:43:21 -0400
 Subject: efinet: Setting DNS server from UEFI protocol
@@ -35,7 +35,7 @@ Patch-Name: efinet-set-dns-from-uefi-proto.patch
  2 files changed, 239 insertions(+)
 
 diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
-index 2d3b00f0e..82a28fb6e 100644
+index 2d3b00f0e1..82a28fb6e9 100644
 --- a/grub-core/net/drivers/efi/efinet.c
 +++ b/grub-core/net/drivers/efi/efinet.c
 @@ -30,6 +30,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
@@ -244,7 +244,7 @@ index 2d3b00f0e..82a28fb6e 100644
      }
  
 diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
-index 664cea37b..75befd10e 100644
+index 664cea37b5..75befd10e5 100644
 --- a/include/grub/efi/api.h
 +++ b/include/grub/efi/api.h
 @@ -334,6 +334,16 @@
diff --git a/debian/patches/efinet-set-network-from-uefi-devpath.patch b/debian/patches/efinet-set-network-from-uefi-devpath.patch
index 0af7fed..d0d2240 100644
--- a/debian/patches/efinet-set-network-from-uefi-devpath.patch
+++ b/debian/patches/efinet-set-network-from-uefi-devpath.patch
@@ -1,4 +1,4 @@
-From 9ac73ba5acca6446e278cdff274ef679783d9919 Mon Sep 17 00:00:00 2001
+From 521dfb27bc786d0567c97b704381677f57c4cfe4 Mon Sep 17 00:00:00 2001
 From: Michael Chang <mchang@suse.com>
 Date: Thu, 27 Oct 2016 17:43:05 -0400
 Subject: efinet: Setting network from UEFI device path
@@ -34,7 +34,7 @@ Patch-Name: efinet-set-network-from-uefi-devpath.patch
  2 files changed, 270 insertions(+), 9 deletions(-)
 
 diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
-index fc90415f2..2d3b00f0e 100644
+index fc90415f29..2d3b00f0e1 100644
 --- a/grub-core/net/drivers/efi/efinet.c
 +++ b/grub-core/net/drivers/efi/efinet.c
 @@ -23,6 +23,7 @@
@@ -358,7 +358,7 @@ index fc90415f2..2d3b00f0e 100644
    }
  }
 diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
-index ca6cdc159..664cea37b 100644
+index ca6cdc1596..664cea37b5 100644
 --- a/include/grub/efi/api.h
 +++ b/include/grub/efi/api.h
 @@ -825,6 +825,8 @@ struct grub_efi_ipv4_device_path
diff --git a/debian/patches/efinet-uefi-ipv6-pxe-support.patch b/debian/patches/efinet-uefi-ipv6-pxe-support.patch
index 6c2b4fb..d1f2c02 100644
--- a/debian/patches/efinet-uefi-ipv6-pxe-support.patch
+++ b/debian/patches/efinet-uefi-ipv6-pxe-support.patch
@@ -1,4 +1,4 @@
-From 36a71e2c21b5cdfb93617dc4faff628672e9a2b7 Mon Sep 17 00:00:00 2001
+From efa94cf400cddc721b15210e46471c867cf727e1 Mon Sep 17 00:00:00 2001
 From: Michael Chang <mchang@suse.com>
 Date: Thu, 27 Oct 2016 17:41:21 -0400
 Subject: efinet: UEFI IPv6 PXE support
@@ -17,7 +17,7 @@ Patch-Name: efinet-uefi-ipv6-pxe-support.patch
  2 files changed, 73 insertions(+), 6 deletions(-)
 
 diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
-index 5388f952b..fc90415f2 100644
+index 5388f952ba..fc90415f29 100644
 --- a/grub-core/net/drivers/efi/efinet.c
 +++ b/grub-core/net/drivers/efi/efinet.c
 @@ -378,11 +378,25 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
@@ -52,7 +52,7 @@ index 5388f952b..fc90415f2 100644
    }
  }
 diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
-index addcbfa8f..ca6cdc159 100644
+index addcbfa8fb..ca6cdc1596 100644
 --- a/include/grub/efi/api.h
 +++ b/include/grub/efi/api.h
 @@ -1452,14 +1452,67 @@ typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output
diff --git a/debian/patches/fix-lockdown.patch b/debian/patches/fix-lockdown.patch
deleted file mode 100644
index 2c4e20b..0000000
--- a/debian/patches/fix-lockdown.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From 5f17e85530102bc92cb09796d878d6e399a4986d Mon Sep 17 00:00:00 2001
-From: Luca Boccassi <bluca@debian.org>
-Date: Tue, 15 May 2018 11:36:46 +0100
-Subject: Do not overwrite sentinel byte in boot_params, breaks lockdown
-
-grub currently copies the entire boot_params, which includes setting
-sentinel byte to 0xff, which triggers sanitize_boot_params in the kernel
-which in turn clears various boot_params variables, including the
-indication that the bootloader chain is verified and thus the kernel
-disables lockdown mode.  According to the information on the Fedora bug
-tracker, only the information from byte 0x1f1 is necessary, so start
-copying from there instead.
-
-Author: Luca Boccassi <bluca@debian.org>
-Bug-Fedora: https://bugzilla.redhat.com/show_bug.cgi?id=1418360
-Forwarded: no
-
-Patch-Name: fix-lockdown.patch
----
- grub-core/loader/i386/efi/linux.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
-index 16372a0c8..34605dfed 100644
---- a/grub-core/loader/i386/efi/linux.c
-+++ b/grub-core/loader/i386/efi/linux.c
-@@ -28,6 +28,7 @@
- #include <grub/lib/cmdline.h>
- #include <grub/linux.h>
- #include <grub/efi/efi.h>
-+#include <stddef.h>
- 
- GRUB_MOD_LICENSE ("GPLv3+");
- 
-@@ -334,7 +335,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
-       lh.code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
-     }
- 
--  grub_memcpy (params, &lh, 2 * 512);
-+  /* do not overwrite below boot_params->hdr to avoid setting the sentinel byte */
-+  start = offsetof (struct linux_kernel_params, setup_sects);
-+  grub_memcpy ((grub_uint8_t *)params + start, (grub_uint8_t *)&lh + start, 2 * 512 - start);
- 
-   params->type_of_loader = 0x21;
- 
diff --git a/debian/patches/gettext-quiet.patch b/debian/patches/gettext-quiet.patch
index 09977de..6e5d4c2 100644
--- a/debian/patches/gettext-quiet.patch
+++ b/debian/patches/gettext-quiet.patch
@@ -1,4 +1,4 @@
-From 5264381cd94fc29aea05e50654df364e131e777f Mon Sep 17 00:00:00 2001
+From 02b91d62746f4bde8349bbd605b18fb354a85048 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:02 +0000
 Subject: Silence error messages when translations are unavailable
@@ -13,7 +13,7 @@ Patch-Name: gettext-quiet.patch
  1 file changed, 5 insertions(+)
 
 diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c
-index 4d02e62c1..2a19389f2 100644
+index 4d02e62c10..2a19389f2a 100644
 --- a/grub-core/gettext/gettext.c
 +++ b/grub-core/gettext/gettext.c
 @@ -427,6 +427,11 @@ grub_gettext_init_ext (struct grub_gettext_context *ctx,
diff --git a/debian/patches/gfxpayload-dynamic.patch b/debian/patches/gfxpayload-dynamic.patch
index fc222d2..efdaa14 100644
--- a/debian/patches/gfxpayload-dynamic.patch
+++ b/debian/patches/gfxpayload-dynamic.patch
@@ -1,4 +1,4 @@
-From bff220e7e6189f09678b9a25e9e92fc65b327268 Mon Sep 17 00:00:00 2001
+From 40e9945c86cb9ea3d2a23789e7cdbce9905387e1 Mon Sep 17 00:00:00 2001
 From: Evan Broder <evan@ebroder.net>
 Date: Mon, 13 Jan 2014 12:13:29 +0000
 Subject: Add configure option to enable gfxpayload=keep dynamically
@@ -18,11 +18,12 @@ Patch-Name: gfxpayload-dynamic.patch
  grub-core/commands/i386/pc/hwmatch.c | 146 +++++++++++++++++++++++++++
  include/grub/file.h                  |   1 +
  util/grub.d/10_linux.in              |  37 ++++++-
- 5 files changed, 200 insertions(+), 3 deletions(-)
+ util/grub.d/10_linux_zfs.in          |  46 ++++++++-
+ 6 files changed, 243 insertions(+), 6 deletions(-)
  create mode 100644 grub-core/commands/i386/pc/hwmatch.c
 
 diff --git a/configure.ac b/configure.ac
-index 7dda5bb32..dbc429ce0 100644
+index 7dda5bb32b..dbc429ce0a 100644
 --- a/configure.ac
 +++ b/configure.ac
 @@ -1879,6 +1879,17 @@ else
@@ -44,7 +45,7 @@ index 7dda5bb32..dbc429ce0 100644
  
  AC_SUBST([FONT_SOURCE])
 diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
-index 67a98abbb..836bf0a59 100644
+index 474a63e68c..aadb4cdff8 100644
 --- a/grub-core/Makefile.core.def
 +++ b/grub-core/Makefile.core.def
 @@ -971,6 +971,14 @@ module = {
@@ -64,7 +65,7 @@ index 67a98abbb..836bf0a59 100644
    common = commands/keystatus.c;
 diff --git a/grub-core/commands/i386/pc/hwmatch.c b/grub-core/commands/i386/pc/hwmatch.c
 new file mode 100644
-index 000000000..6de07cecc
+index 0000000000..6de07cecc8
 --- /dev/null
 +++ b/grub-core/commands/i386/pc/hwmatch.c
 @@ -0,0 +1,146 @@
@@ -215,7 +216,7 @@ index 000000000..6de07cecc
 +  grub_unregister_command (cmd);
 +}
 diff --git a/include/grub/file.h b/include/grub/file.h
-index 31567483c..e3c4cae2b 100644
+index 31567483cc..e3c4cae2b5 100644
 --- a/include/grub/file.h
 +++ b/include/grub/file.h
 @@ -122,6 +122,7 @@ enum grub_file_type
@@ -227,7 +228,7 @@ index 31567483c..e3c4cae2b 100644
      GRUB_FILE_TYPE_LOADENV,
      GRUB_FILE_TYPE_SAVEENV,
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index 51cdb5e1d..2f5217358 100644
+index 2be66c7028..09393c28ee 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -23,6 +23,7 @@ datarootdir="@datarootdir@"
@@ -238,7 +239,7 @@ index 51cdb5e1d..2f5217358 100644
  
  . "$pkgdatadir/grub-mkconfig_lib"
  
-@@ -145,9 +146,10 @@ linux_entry ()
+@@ -149,9 +150,10 @@ linux_entry ()
        if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then
  	  echo "	load_video" | sed "s/^/$submenu_indentation/"
        fi
@@ -252,7 +253,7 @@ index 51cdb5e1d..2f5217358 100644
    fi
  
    echo "	insmod gzio" | sed "s/^/$submenu_indentation/"
-@@ -226,6 +228,35 @@ prepare_root_cache=
+@@ -230,6 +232,35 @@ prepare_root_cache=
  boot_device_id=
  title_correction_code=
  
@@ -288,3 +289,81 @@ index 51cdb5e1d..2f5217358 100644
  # Extra indentation to add to menu entries in a submenu. We're not in a submenu
  # yet, so it's empty. In a submenu it will be equal to '\t' (one tab).
  submenu_indentation=""
+diff --git a/util/grub.d/10_linux_zfs.in b/util/grub.d/10_linux_zfs.in
+index ec4b49d9d7..8cd7d12851 100755
+--- a/util/grub.d/10_linux_zfs.in
++++ b/util/grub.d/10_linux_zfs.in
+@@ -22,6 +22,7 @@ datarootdir="@datarootdir@"
+ ubuntu_recovery="@UBUNTU_RECOVERY@"
+ quiet_boot="@QUIET_BOOT@"
+ quick_boot="@QUICK_BOOT@"
++gfxpayload_dynamic="@GFXPAYLOAD_DYNAMIC@"
+ 
+ . "${pkgdatadir}/grub-mkconfig_lib"
+ 
+@@ -716,6 +717,41 @@ generate_grub_menu_metadata() {
+     done
+ }
+ 
++# Print the configuration part common to all sections
++# Note:
++#   If 10_linux runs these part will be defined twice in grub configuration
++print_menu_prologue() {
++    # Use ELILO's generic "efifb" when it's known to be available.
++    # FIXME: We need an interface to select vesafb in case efifb can't be used.
++    GRUB_GFXPAYLOAD_LINUX="${GRUB_GFXPAYLOAD_LINUX:-}"
++    if [ "${GRUB_GFXPAYLOAD_LINUX}" != "" ] || [ "${gfxpayload_dynamic}" = 0 ]; then
++        echo "set linux_gfx_mode=${GRUB_GFXPAYLOAD_LINUX}"
++    else
++        cat << EOF
++if [ "\${recordfail}" != 1 ]; then
++  if [ -e \${prefix}/gfxblacklist.txt ]; then
++    if hwmatch \${prefix}/gfxblacklist.txt 3; then
++      if [ \${match} = 0 ]; then
++        set linux_gfx_mode=keep
++      else
++        set linux_gfx_mode=text
++      fi
++    else
++      set linux_gfx_mode=text
++    fi
++  else
++    set linux_gfx_mode=keep
++  fi
++else
++  set linux_gfx_mode=text
++fi
++EOF
++    fi
++    cat << EOF
++export linux_gfx_mode
++EOF
++}
++
+ # Cache for prepare_grub_to_access_device call
+ # $1: boot_device
+ # $2: submenu_level
+@@ -776,9 +812,11 @@ zfs_linux_entry () {
+         if [ "${GRUB_GFXPAYLOAD_LINUX}" != "text" ]; then
+             echo "${submenu_indentation}	load_video"
+         fi
+-        if [ "${ubuntu_recovery}" = 0 ] || [ "${type}" != "recovery" ]; then
+-            echo "${submenu_indentation}	set gfxpayload=\${linux_gfx_mode}"
+-        fi
++    fi
++
++    if ([ "${ubuntu_recovery}" = 0 ] || [ "${type}" != "recovery" ]) && \
++        ([ "${GRUB_GFXPAYLOAD_LINUX}" != "" ] || [ "${gfxpayload_dynamic}" = 1 ]); then
++        echo "${submenu_indentation}	set gfxpayload=\${linux_gfx_mode}"
+     fi
+ 
+     echo "${submenu_indentation}	insmod gzio"
+@@ -841,6 +879,8 @@ generate_grub_menu() {
+         GRUB_CMDLINE_LINUX_RECOVERY="${GRUB_CMDLINE_LINUX_RECOVERY} nomodeset"
+     fi
+ 
++    print_menu_prologue
++
+     # IFS is set to TAB (ASCII 0x09)
+     echo "${menu_metadata}" |
+     {
diff --git a/debian/patches/gfxpayload-keep-default.patch b/debian/patches/gfxpayload-keep-default.patch
index 4ef95cf..8f48114 100644
--- a/debian/patches/gfxpayload-keep-default.patch
+++ b/debian/patches/gfxpayload-keep-default.patch
@@ -1,6 +1,6 @@
-From d768f3c486db716fe662b32afc1327f27fad012b Mon Sep 17 00:00:00 2001
-From: Colin Watson <cjwatson@debian.org>
-Date: Mon, 13 Jan 2014 12:12:57 +0000
+From 6b3668640698cff6e0f57bba665a594c11f02841 Mon Sep 17 00:00:00 2001
+From: Didier Roche <didrocks@ubuntu.com>
+Date: Tue, 31 Mar 2020 15:09:45 +0200
 Subject: Disable gfxpayload=keep by default
 
 Setting gfxpayload=keep has been known to cause efifb to be
@@ -19,14 +19,15 @@ Last-Update: 2013-12-25
 
 Patch-Name: gfxpayload-keep-default.patch
 ---
- util/grub.d/10_linux.in | 4 ----
- 1 file changed, 4 deletions(-)
+ util/grub.d/10_linux.in     | 4 ----
+ util/grub.d/10_linux_zfs.in | 4 ----
+ 2 files changed, 8 deletions(-)
 
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index 4532266be..dd5a60c71 100644
+index a75096609a..f839b3b55f 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
-@@ -114,10 +114,6 @@ linux_entry ()
+@@ -118,10 +118,6 @@ linux_entry ()
    # FIXME: We need an interface to select vesafb in case efifb can't be used.
    if [ "x$GRUB_GFXPAYLOAD_LINUX" = x ]; then
        echo "	load_video" | sed "s/^/$submenu_indentation/"
@@ -37,3 +38,18 @@ index 4532266be..dd5a60c71 100644
    else
        if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then
  	  echo "	load_video" | sed "s/^/$submenu_indentation/"
+diff --git a/util/grub.d/10_linux_zfs.in b/util/grub.d/10_linux_zfs.in
+index 5ec65fa941..b24587f0a5 100755
+--- a/util/grub.d/10_linux_zfs.in
++++ b/util/grub.d/10_linux_zfs.in
+@@ -744,10 +744,6 @@ zfs_linux_entry () {
+     # FIXME: We need an interface to select vesafb in case efifb can't be used.
+     if [ "${GRUB_GFXPAYLOAD_LINUX}" = "" ]; then
+         echo "${submenu_indentation}	load_video"
+-        if grep -qx "CONFIG_FB_EFI=y" "${config}" 2> /dev/null \
+-            && grep -qx "CONFIG_VT_HW_CONSOLE_BINDING=y" "${config}" 2> /dev/null; then
+-            echo "${submenu_indentation}	set gfxpayload=keep"
+-        fi
+     else
+         if [ "${GRUB_GFXPAYLOAD_LINUX}" != "text" ]; then
+             echo "${submenu_indentation}	load_video"
diff --git a/debian/patches/grub-install-backup-and-restore.patch b/debian/patches/grub-install-backup-and-restore.patch
new file mode 100644
index 0000000..b947b44
--- /dev/null
+++ b/debian/patches/grub-install-backup-and-restore.patch
@@ -0,0 +1,175 @@
+From 0843387b9bedf43212e3148c0c9b6d013565c87e Mon Sep 17 00:00:00 2001
+From: Dimitri John Ledkov <xnox@ubuntu.com>
+Date: Wed, 19 Aug 2020 01:49:09 +0100
+Subject: grub-install: Add backup and restore
+
+Refactor clean_grub_dir to create a backup of all the files, instead
+of just irrevocably removing them as the first action. If available,
+register on_exit handle to restore the backup if any errors occur, or
+remove the backup if everything was successful. If on_exit is not
+available, the backup remains on disk for manual recovery.
+
+This allows safer upgrades of MBR & modules, such that
+modules/images/fonts/translations are consistent with MBR in case of
+errors. For example accidental grub-install /dev/non-existent-disk
+currently clobbers and upgrades modules in /boot/grub, despite not
+actually updating any MBR. This increases peak disk-usage slightly, by
+requiring temporarily twice the disk space to complete grub-install.
+
+Also add modinfo.sh to the cleanup/backup/restore codepath, to ensure
+it is also cleaned / backed up / restored.
+
+Signed-off-by: Dimitri John Ledkov <xnox@ubuntu.com>
+
+Patch-Name: grub-install-backup-and-restore.patch
+---
+ configure.ac               |   2 +-
+ util/grub-install-common.c | 105 +++++++++++++++++++++++++++++++------
+ 2 files changed, 91 insertions(+), 16 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 1819188f9f..6a88b9b0c0 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -420,7 +420,7 @@ else
+ fi
+ 
+ # Check for functions and headers.
+-AC_CHECK_FUNCS(posix_memalign memalign getextmntent)
++AC_CHECK_FUNCS(posix_memalign memalign getextmntent on_exit)
+ AC_CHECK_HEADERS(sys/param.h sys/mount.h sys/mnttab.h limits.h)
+ 
+ # glibc 2.25 still includes sys/sysmacros.h in sys/types.h but emits deprecation
+diff --git a/util/grub-install-common.c b/util/grub-install-common.c
+index 447504d3f4..a883b6daef 100644
+--- a/util/grub-install-common.c
++++ b/util/grub-install-common.c
+@@ -185,38 +185,113 @@ grub_install_mkdir_p (const char *dst)
+   free (t);
+ }
+ 
++static int
++strcmp_ext (const char *a, const char *b, const char *ext)
++{
++  char *bsuffix = grub_util_path_concat_ext (1, b, ext);
++  int r = strcmp (a, bsuffix);
++  free (bsuffix);
++  return r;
++}
++
++enum clean_grub_dir_mode
++{
++  CLEAN = 0,
++  CLEAN_BACKUP = 1,
++  CREATE_BACKUP = 2,
++  RESTORE_BACKUP = 3,
++};
++
+ static void
+-clean_grub_dir (const char *di)
++clean_grub_dir_real (const char *di, enum clean_grub_dir_mode mode)
+ {
+   grub_util_fd_dir_t d;
+   grub_util_fd_dirent_t de;
++  char suffix[2] = "";
++
++  if ((mode == CLEAN_BACKUP) || (mode == RESTORE_BACKUP))
++    {
++      strcpy (suffix, "-");
++    }
+ 
+   d = grub_util_fd_opendir (di);
+   if (!d)
+-    grub_util_error (_("cannot open directory `%s': %s"),
+-		     di, grub_util_fd_strerror ());
++    {
++      if (mode == CLEAN_BACKUP)
++	return;
++      grub_util_error (_("cannot open directory `%s': %s"),
++		       di, grub_util_fd_strerror ());
++    }
+ 
+   while ((de = grub_util_fd_readdir (d)))
+     {
+       const char *ext = strrchr (de->d_name, '.');
+-      if ((ext && (strcmp (ext, ".mod") == 0
+-		   || strcmp (ext, ".lst") == 0
+-		   || strcmp (ext, ".img") == 0
+-		   || strcmp (ext, ".mo") == 0)
+-	   && strcmp (de->d_name, "menu.lst") != 0)
+-	  || strcmp (de->d_name, "efiemu32.o") == 0
+-	  || strcmp (de->d_name, "efiemu64.o") == 0)
++      if ((ext && (strcmp_ext (ext, ".mod", suffix) == 0
++		   || strcmp_ext (ext, ".lst", suffix) == 0
++		   || strcmp_ext (ext, ".img", suffix) == 0
++		   || strcmp_ext (ext, ".mo", suffix) == 0)
++	   && strcmp_ext (de->d_name, "menu.lst", suffix) != 0)
++	  || strcmp_ext (de->d_name, "modinfo.sh", suffix) == 0
++	  || strcmp_ext (de->d_name, "efiemu32.o", suffix) == 0
++	  || strcmp_ext (de->d_name, "efiemu64.o", suffix) == 0)
+ 	{
+-	  char *x = grub_util_path_concat (2, di, de->d_name);
+-	  if (grub_util_unlink (x) < 0)
+-	    grub_util_error (_("cannot delete `%s': %s"), x,
+-			     grub_util_fd_strerror ());
+-	  free (x);
++	  char *srcf = grub_util_path_concat (2, di, de->d_name);
++
++	  if (mode == CREATE_BACKUP)
++	    {
++	      char *dstf = grub_util_path_concat_ext (2, di, de->d_name, "-");
++	      if (grub_util_rename (srcf, dstf) < 0)
++		grub_util_error (_("cannot backup `%s': %s"), srcf,
++				 grub_util_fd_strerror ());
++	      free (dstf);
++	    }
++	  else if (mode == RESTORE_BACKUP)
++	    {
++	      char *dstf = grub_util_path_concat_ext (2, di, de->d_name);
++	      dstf[strlen (dstf) - 1] = 0;
++	      if (grub_util_rename (srcf, dstf) < 0)
++		grub_util_error (_("cannot restore `%s': %s"), dstf,
++				 grub_util_fd_strerror ());
++	      free (dstf);
++	    }
++	  else
++	    {
++	      if (grub_util_unlink (srcf) < 0)
++		grub_util_error (_("cannot delete `%s': %s"), srcf,
++				 grub_util_fd_strerror ());
++	    }
++	  free (srcf);
+ 	}
+     }
+   grub_util_fd_closedir (d);
+ }
+ 
++static void
++restore_backup_on_exit (int status, void *arg)
++{
++  if (status == 0)
++    {
++      clean_grub_dir_real ((char *) arg, CLEAN_BACKUP);
++    }
++  else
++    {
++      clean_grub_dir_real ((char *) arg, CLEAN);
++      clean_grub_dir_real ((char *) arg, RESTORE_BACKUP);
++    }
++  free (arg);
++  arg = NULL;
++}
++
++static void
++clean_grub_dir (const char *di)
++{
++  clean_grub_dir_real (di, CLEAN_BACKUP);
++  clean_grub_dir_real (di, CREATE_BACKUP);
++#if defined(HAVE_ON_EXIT)
++  on_exit (restore_backup_on_exit, strdup (di));
++#endif
++}
++
+ struct install_list
+ {
+   int is_default;
diff --git a/debian/patches/grub-install-pvxen-paths.patch b/debian/patches/grub-install-pvxen-paths.patch
index ab6d95b..b1ca1c4 100644
--- a/debian/patches/grub-install-pvxen-paths.patch
+++ b/debian/patches/grub-install-pvxen-paths.patch
@@ -1,4 +1,4 @@
-From 8e6b05dbc0a21e8d2a6e8ef2bb831f0bf8ff3a6d Mon Sep 17 00:00:00 2001
+From 66bbce074947abe680475dacfb1cde35b7c17ef3 Mon Sep 17 00:00:00 2001
 From: Ian Campbell <ijc@hellion.org.uk>
 Date: Sat, 6 Sep 2014 12:20:12 +0100
 Subject: grub-install: Install PV Xen binaries into the upstream specified
@@ -28,10 +28,10 @@ v2: Respect bootdir, create /boot/xen as needed.
  1 file changed, 22 insertions(+), 2 deletions(-)
 
 diff --git a/util/grub-install.c b/util/grub-install.c
-index 73c623107..f511cfc72 100644
+index 70d6700de8..64c292383f 100644
 --- a/util/grub-install.c
 +++ b/util/grub-install.c
-@@ -2055,6 +2055,28 @@ main (int argc, char *argv[])
+@@ -2058,6 +2058,28 @@ main (int argc, char *argv[])
  	}
        break;
  
@@ -60,7 +60,7 @@ index 73c623107..f511cfc72 100644
      case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
      case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
      case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
-@@ -2064,8 +2086,6 @@ main (int argc, char *argv[])
+@@ -2067,8 +2089,6 @@ main (int argc, char *argv[])
      case GRUB_INSTALL_PLATFORM_MIPSEL_ARC:
      case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
      case GRUB_INSTALL_PLATFORM_I386_QEMU:
diff --git a/debian/patches/grub-install-removable-shim.patch b/debian/patches/grub-install-removable-shim.patch
deleted file mode 100644
index eed719a..0000000
--- a/debian/patches/grub-install-removable-shim.patch
+++ /dev/null
@@ -1,193 +0,0 @@
-From 3d51b212987d47da2b8c65a911140bbbc2fd3153 Mon Sep 17 00:00:00 2001
-From: Steve McIntyre <93sam@debian.org>
-Date: Fri, 14 Jun 2019 16:37:11 +0100
-Subject: Deal with --force-extra-removable with signed shim too
-
-In this case, we need both the signed shim as /EFI/BOOT/BOOTXXX.EFI
-and signed Grub as /EFI/BOOT/grubXXX.efi.
-
-Also install the BOOTXXX.CSV into /EFI/debian, and FBXXX.EFI into
-/EFI/BOOT/ so that it can work when needed (*iff* we're updating the
-NVRAM).
-
-[cjwatson: Refactored also_install_removable somewhat for brevity and so
-that we're using consistent case-insensitive logic.]
-
-Bug-Debian: https://bugs.debian.org/930531
-Last-Update: 2019-06-14
-
-Patch-Name: grub-install-removable-shim.patch
----
- util/grub-install.c | 84 ++++++++++++++++++++++++++++++++++++---------
- 1 file changed, 67 insertions(+), 17 deletions(-)
-
-diff --git a/util/grub-install.c b/util/grub-install.c
-index d66de7f8e..35d150c33 100644
---- a/util/grub-install.c
-+++ b/util/grub-install.c
-@@ -883,17 +883,13 @@ check_component_exists(const char *dir,
- static void
- also_install_removable(const char *src,
- 		       const char *base_efidir,
--		       const char *efi_suffix_upper)
-+		       const char *efi_file,
-+		       int is_needed)
- {
--  char *efi_file = NULL;
-   char *dst = NULL;
-   char *cur = NULL;
-   char *found = NULL;
- 
--  if (!efi_suffix_upper)
--    grub_util_error ("%s", _("efi_suffix_upper not set"));
--  efi_file = xasprintf ("BOOT%s.EFI", efi_suffix_upper);
--
-   /* We need to install in $base_efidir/EFI/BOOT/$efi_file, but we
-    * need to cope with case-insensitive stuff here. Build the path one
-    * component at a time, checking for existing matches each time. */
-@@ -927,10 +923,9 @@ also_install_removable(const char *src,
-   cur = xstrdup (dst);
-   free (dst);
-   free (found);
--  grub_install_copy_file (src, cur, 1);
-+  grub_install_copy_file (src, cur, is_needed);
- 
-   free (cur);
--  free (efi_file);
- }
- 
- int
-@@ -2076,11 +2071,14 @@ main (int argc, char *argv[])
-     case GRUB_INSTALL_PLATFORM_IA64_EFI:
-       {
- 	char *dst = grub_util_path_concat (2, efidir, efi_file);
-+	char *removable_file = xasprintf ("BOOT%s.EFI", efi_suffix_upper);
-+
- 	if (uefi_secure_boot)
- 	  {
- 	    char *shim_signed = NULL;
- 	    char *mok_signed = NULL, *mok_file = NULL;
- 	    char *fb_signed = NULL, *fb_file = NULL;
-+	    char *csv_file = NULL;
- 	    char *config_dst;
- 	    FILE *config_dst_f;
- 
-@@ -2089,11 +2087,15 @@ main (int argc, char *argv[])
- 	    mok_file = xasprintf ("mm%s.efi", efi_suffix);
- 	    fb_signed = xasprintf ("fb%s.efi.signed", efi_suffix);
- 	    fb_file = xasprintf ("fb%s.efi", efi_suffix);
-+	    csv_file = xasprintf ("BOOT%s.CSV", efi_suffix_upper);
-+
-+	    /* If we have a signed shim binary, install that and all
-+	       its helpers in the normal vendor path */
- 
- 	    if (grub_util_is_regular (shim_signed))
- 	      {
- 		char *chained_base, *chained_dst;
--		char *mok_src, *mok_dst, *fb_src, *fb_dst;
-+		char *mok_src, *mok_dst, *fb_src, *fb_dst, *csv_src, *csv_dst;
- 		if (!removable)
- 		  {
- 		    free (efi_file);
-@@ -2105,8 +2107,6 @@ main (int argc, char *argv[])
- 		chained_base = xasprintf ("grub%s.efi", efi_suffix);
- 		chained_dst = grub_util_path_concat (2, efidir, chained_base);
- 		grub_install_copy_file (efi_signed, chained_dst, 1);
--		free (chained_dst);
--		free (chained_base);
- 
- 		/* Not critical, so not an error if they are not present (as it
- 		   won't be for older releases); but if we have them, make
-@@ -2117,8 +2117,6 @@ main (int argc, char *argv[])
- 						    mok_file);
- 		grub_install_copy_file (mok_src,
- 					mok_dst, 0);
--		free (mok_src);
--		free (mok_dst);
- 
- 		fb_src = grub_util_path_concat (2, "/usr/lib/shim/",
- 						    fb_signed);
-@@ -2126,27 +2124,79 @@ main (int argc, char *argv[])
- 						    fb_file);
- 		grub_install_copy_file (fb_src,
- 					fb_dst, 0);
-+
-+		csv_src = grub_util_path_concat (2, "/usr/lib/shim/",
-+						    csv_file);
-+		csv_dst = grub_util_path_concat (2, efidir,
-+						    csv_file);
-+		grub_install_copy_file (csv_src,
-+					csv_dst, 0);
-+
-+		/* Install binaries into .../EFI/BOOT too:
-+		   the shim binary
-+		   the grub binary
-+		   the shim fallback binary (not fatal on failure) */
-+		if (force_extra_removable)
-+		  {
-+		    grub_util_info ("Secure boot: installing shim and image into rm path");
-+		    also_install_removable (shim_signed, base_efidir, removable_file, 1);
-+
-+		    also_install_removable (efi_signed, base_efidir, chained_base, 1);
-+
-+		    /* If we're updating the NVRAM, add fallback too - it
-+			will re-update the NVRAM later if things break */
-+		    if (update_nvram)
-+		      also_install_removable (fb_src, base_efidir, fb_file, 0);
-+		  }
-+
-+		free (chained_dst);
-+		free (chained_base);
-+		free (mok_src);
-+		free (mok_dst);
- 		free (fb_src);
- 		free (fb_dst);
-+		free (csv_src);
-+		free (csv_dst);
- 	      }
- 	    else
--	      grub_install_copy_file (efi_signed, dst, 1);
-+	      {
-+		/* Tried to install for secure boot, but no signed
-+		   shim found. Fall back to just installing the signed
-+		   grub binary */
-+		grub_util_info ("Secure boot (no shim): installing signed grub binary");
-+		grub_install_copy_file (efi_signed, dst, 1);
-+		if (force_extra_removable)
-+		  {
-+		    grub_util_info ("Secure boot (no shim): installing signed grub binary into rm path");
-+		    also_install_removable (efi_signed, base_efidir, removable_file, 1);
-+		  }
-+	      }
- 
-+	    /* In either case, install our grub.cfg */
- 	    config_dst = grub_util_path_concat (2, efidir, "grub.cfg");
- 	    grub_install_copy_file (load_cfg, config_dst, 1);
- 	    config_dst_f = grub_util_fopen (config_dst, "ab");
- 	    fprintf (config_dst_f, "configfile $prefix/grub.cfg\n");
- 	    fclose (config_dst_f);
- 	    free (config_dst);
--	    if (force_extra_removable)
--	      also_install_removable(efi_signed, base_efidir, efi_suffix_upper);
-+
-+	    free (csv_file);
-+	    free (fb_file);
-+	    free (fb_signed);
-+	    free (mok_file);
-+	    free (mok_signed);
-+	    free (shim_signed);
- 	  }
- 	else
- 	  {
-+	    /* No secure boot - just install our newly-generated image */
-+	    grub_util_info ("No Secure Boot: installing core image");
- 	    grub_install_copy_file (imgfile, dst, 1);
- 	    if (force_extra_removable)
--	      also_install_removable(imgfile, base_efidir, efi_suffix_upper);
-+	      also_install_removable (imgfile, base_efidir, removable_file, 1);
- 	  }
-+
-+	free (removable_file);
- 	free (dst);
-       }
-       if (!removable && update_nvram)
diff --git a/debian/patches/grub-legacy-0-based-partitions.patch b/debian/patches/grub-legacy-0-based-partitions.patch
index 2039c3f..09439dc 100644
--- a/debian/patches/grub-legacy-0-based-partitions.patch
+++ b/debian/patches/grub-legacy-0-based-partitions.patch
@@ -13,7 +13,7 @@ Patch-Name: grub-legacy-0-based-partitions.patch
  1 file changed, 14 insertions(+)
 
 diff --git a/util/getroot.c b/util/getroot.c
-index 847406fba..cdd41153c 100644
+index 847406fbab..cdd41153c5 100644
 --- a/util/getroot.c
 +++ b/util/getroot.c
 @@ -245,6 +245,20 @@ find_partition (grub_disk_t dsk __attribute__ ((unused)),
diff --git a/debian/patches/grub.cfg-400.patch b/debian/patches/grub.cfg-400.patch
index 1fee91a..4731767 100644
--- a/debian/patches/grub.cfg-400.patch
+++ b/debian/patches/grub.cfg-400.patch
@@ -9,7 +9,7 @@ Patch-Name: grub.cfg-400.patch
  1 file changed, 4 insertions(+)
 
 diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
-index 9f477ff05..45cd4cc54 100644
+index 9f477ff054..45cd4cc541 100644
 --- a/util/grub-mkconfig.in
 +++ b/util/grub-mkconfig.in
 @@ -276,6 +276,10 @@ for i in "${grub_mkconfig_dir}"/* ; do
diff --git a/debian/patches/ieee1275-clear-reset.patch b/debian/patches/ieee1275-clear-reset.patch
index df20ada..3d73e0c 100644
--- a/debian/patches/ieee1275-clear-reset.patch
+++ b/debian/patches/ieee1275-clear-reset.patch
@@ -1,4 +1,4 @@
-From e1ceeb130e1dc5b4206107fb41488eff08316820 Mon Sep 17 00:00:00 2001
+From 8bec2a413fc7fe8f2a48d37d8127322ebc96971d Mon Sep 17 00:00:00 2001
 From: Paulo Flabiano Smorigo <pfsmorigo@linux.vnet.ibm.com>
 Date: Thu, 25 Sep 2014 18:41:29 -0300
 Subject: Include a text attribute reset in the clear command for ppc
@@ -18,7 +18,7 @@ Patch-Name: ieee1275-clear-reset.patch
  1 file changed, 1 insertion(+), 1 deletion(-)
 
 diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c
-index d317efa36..63892ad42 100644
+index d317efa368..63892ad427 100644
 --- a/grub-core/term/terminfo.c
 +++ b/grub-core/term/terminfo.c
 @@ -151,7 +151,7 @@ grub_terminfo_set_current (struct grub_term_output *term,
diff --git a/debian/patches/ignore-grub_func_test-failures.patch b/debian/patches/ignore-grub_func_test-failures.patch
index 7efd112..76734f6 100644
--- a/debian/patches/ignore-grub_func_test-failures.patch
+++ b/debian/patches/ignore-grub_func_test-failures.patch
@@ -1,4 +1,4 @@
-From 2efd14b497f45150a23c7977e5c45285d258d42c Mon Sep 17 00:00:00 2001
+From a4eaed2b739501db9b1009cd778fc72e9670f9ce Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@debian.org>
 Date: Mon, 13 Jan 2014 12:13:32 +0000
 Subject: Ignore functional test failures for now as they are broken
@@ -14,7 +14,7 @@ Patch-Name: ignore-grub_func_test-failures.patch
  1 file changed, 3 insertions(+), 1 deletion(-)
 
 diff --git a/tests/grub_func_test.in b/tests/grub_func_test.in
-index c67f9e422..728cd6e06 100644
+index c67f9e4225..728cd6e066 100644
 --- a/tests/grub_func_test.in
 +++ b/tests/grub_func_test.in
 @@ -16,6 +16,8 @@ out=`echo all_functional_test | @builddir@/grub-shell --timeout=3600 --files="/b
diff --git a/debian/patches/insmod-xzio-and-lzopio-on-xen.patch b/debian/patches/insmod-xzio-and-lzopio-on-xen.patch
index 1a82d7f..6570f74 100644
--- a/debian/patches/insmod-xzio-and-lzopio-on-xen.patch
+++ b/debian/patches/insmod-xzio-and-lzopio-on-xen.patch
@@ -1,4 +1,4 @@
-From 7b5ed0cc355424e434744162d03cc43a483ac0f4 Mon Sep 17 00:00:00 2001
+From c58c9d77ccd16511db098247b5cbba5abcaac99f Mon Sep 17 00:00:00 2001
 From: Ian Campbell <ijc@debian.org>
 Date: Sun, 30 Nov 2014 12:12:52 +0000
 Subject: Arrange to insmod xzio and lzopio when booting a kernel as a Xen
@@ -16,14 +16,15 @@ Last-Update: 2014-11-30
 
 Patch-Name: insmod-xzio-and-lzopio-on-xen.patch
 ---
- util/grub.d/10_linux.in | 1 +
- 1 file changed, 1 insertion(+)
+ util/grub.d/10_linux.in     | 1 +
+ util/grub.d/10_linux_zfs.in | 1 +
+ 2 files changed, 2 insertions(+)
 
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index ba945582e..8a74c677b 100644
+index 2c418c5ec8..85b30084ad 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
-@@ -162,6 +162,7 @@ linux_entry ()
+@@ -166,6 +166,7 @@ linux_entry ()
    fi
  
    echo "	insmod gzio" | sed "s/^/$submenu_indentation/"
@@ -31,3 +32,15 @@ index ba945582e..8a74c677b 100644
  
    if [ x$dirname = x/ ]; then
      if [ -z "${prepare_root_cache}" ]; then
+diff --git a/util/grub.d/10_linux_zfs.in b/util/grub.d/10_linux_zfs.in
+index 4477fa6061..4c48abef01 100755
+--- a/util/grub.d/10_linux_zfs.in
++++ b/util/grub.d/10_linux_zfs.in
+@@ -838,6 +838,7 @@ zfs_linux_entry () {
+     fi
+ 
+     echo "${submenu_indentation}	insmod gzio"
++    echo "${submenu_indentation}	if [ \"\${grub_platform}\" = xen ]; then insmod xzio; insmod lzopio; fi"
+ 
+     echo "$(prepare_grub_to_access_device_cached "${boot_device}" "${submenu_level}")"
+ 
diff --git a/debian/patches/install-efi-fallback.patch b/debian/patches/install-efi-fallback.patch
index 4913c36..5a36b4e 100644
--- a/debian/patches/install-efi-fallback.patch
+++ b/debian/patches/install-efi-fallback.patch
@@ -1,4 +1,4 @@
-From 4b5ab05a5428e6acae087a819b5daeb17b36e5f5 Mon Sep 17 00:00:00 2001
+From 8a5b764a450f0d67f940c2ffbe80eae053753c19 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:05 +0000
 Subject: Fall back to non-EFI if booted using EFI but -efi is missing
@@ -19,7 +19,7 @@ Patch-Name: install-efi-fallback.patch
  1 file changed, 35 insertions(+), 5 deletions(-)
 
 diff --git a/grub-core/osdep/linux/platform.c b/grub-core/osdep/linux/platform.c
-index e28a79dab..2e7f72086 100644
+index e28a79dab3..2e7f720869 100644
 --- a/grub-core/osdep/linux/platform.c
 +++ b/grub-core/osdep/linux/platform.c
 @@ -19,10 +19,12 @@
diff --git a/debian/patches/install-efi-ubuntu-flavours.patch b/debian/patches/install-efi-ubuntu-flavours.patch
index 5d8aad9..1a6023c 100644
--- a/debian/patches/install-efi-ubuntu-flavours.patch
+++ b/debian/patches/install-efi-ubuntu-flavours.patch
@@ -1,4 +1,4 @@
-From 8054cd148e7a9e3cfa546d60c06b436fb73cf803 Mon Sep 17 00:00:00 2001
+From 73faf5c430fe03ec081a838af0e96ad4c42ab26f Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:27 +0000
 Subject: Cope with Kubuntu setting GRUB_DISTRIBUTOR
@@ -17,7 +17,7 @@ Patch-Name: install-efi-ubuntu-flavours.patch
  1 file changed, 2 insertions(+)
 
 diff --git a/util/grub-install.c b/util/grub-install.c
-index b0c7c7c37..e5e9e439d 100644
+index e1e40cf2b5..f0d59c1809 100644
 --- a/util/grub-install.c
 +++ b/util/grub-install.c
 @@ -1115,6 +1115,8 @@ main (int argc, char *argv[])
diff --git a/debian/patches/install-locale-langpack.patch b/debian/patches/install-locale-langpack.patch
index 34c0176..531fb38 100644
--- a/debian/patches/install-locale-langpack.patch
+++ b/debian/patches/install-locale-langpack.patch
@@ -1,4 +1,4 @@
-From b7350821785e3c924f70720532c19a3a91966115 Mon Sep 17 00:00:00 2001
+From 50921522fab0f4ce529b6c7acd6354b1b3cff2b1 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:07 +0000
 Subject: Prefer translations from Ubuntu language packs if available
@@ -13,7 +13,7 @@ Patch-Name: install-locale-langpack.patch
  1 file changed, 30 insertions(+), 7 deletions(-)
 
 diff --git a/util/grub-install-common.c b/util/grub-install-common.c
-index ca0ac612a..fdfe2c7ea 100644
+index ca0ac612ac..fdfe2c7ead 100644
 --- a/util/grub-install-common.c
 +++ b/util/grub-install-common.c
 @@ -609,17 +609,25 @@ get_localedir (void)
diff --git a/debian/patches/install-powerpc-machtypes.patch b/debian/patches/install-powerpc-machtypes.patch
index 21d91af..0bd6bcc 100644
--- a/debian/patches/install-powerpc-machtypes.patch
+++ b/debian/patches/install-powerpc-machtypes.patch
@@ -1,4 +1,4 @@
-From 786580f06e6f715d6cb9a778926959b33134bb32 Mon Sep 17 00:00:00 2001
+From 2b3e762ebb12ce0d5a562dd36d23bca5d78aa61c Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@debian.org>
 Date: Tue, 28 Jan 2014 14:40:02 +0000
 Subject: Port yaboot logic for various powerpc machine types
@@ -25,7 +25,7 @@ Patch-Name: install-powerpc-machtypes.patch
  6 files changed, 119 insertions(+), 6 deletions(-)
 
 diff --git a/grub-core/osdep/basic/platform.c b/grub-core/osdep/basic/platform.c
-index a7dafd85a..6c293ed2d 100644
+index a7dafd85a9..6c293ed2d0 100644
 --- a/grub-core/osdep/basic/platform.c
 +++ b/grub-core/osdep/basic/platform.c
 @@ -30,3 +30,8 @@ grub_install_get_default_x86_platform (void)
@@ -38,7 +38,7 @@ index a7dafd85a..6c293ed2d 100644
 +  return "generic";
 +}
 diff --git a/grub-core/osdep/linux/platform.c b/grub-core/osdep/linux/platform.c
-index 2e7f72086..5b37366d4 100644
+index 2e7f720869..5b37366d4d 100644
 --- a/grub-core/osdep/linux/platform.c
 +++ b/grub-core/osdep/linux/platform.c
 @@ -24,6 +24,7 @@
@@ -125,7 +125,7 @@ index 2e7f72086..5b37366d4 100644
 +  return machtype;
 +}
 diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
-index 55b8f4016..9c439326a 100644
+index 55b8f40162..9c439326a0 100644
 --- a/grub-core/osdep/unix/platform.c
 +++ b/grub-core/osdep/unix/platform.c
 @@ -218,13 +218,29 @@ grub_install_register_ieee1275 (int is_prep, const char *install_device,
@@ -165,7 +165,7 @@ index 55b8f4016..9c439326a 100644
  
    free (boot_device);
 diff --git a/grub-core/osdep/windows/platform.c b/grub-core/osdep/windows/platform.c
-index 7eb53fe01..e19a3d9a8 100644
+index 7eb53fe01b..e19a3d9a8a 100644
 --- a/grub-core/osdep/windows/platform.c
 +++ b/grub-core/osdep/windows/platform.c
 @@ -128,6 +128,12 @@ grub_install_get_default_x86_platform (void)
@@ -182,7 +182,7 @@ index 7eb53fe01..e19a3d9a8 100644
  get_efi_variable (const wchar_t *varname, ssize_t *len)
  {
 diff --git a/include/grub/util/install.h b/include/grub/util/install.h
-index 2631b1074..8aeb5c4f2 100644
+index 2631b10745..8aeb5c4f20 100644
 --- a/include/grub/util/install.h
 +++ b/include/grub/util/install.h
 @@ -216,6 +216,9 @@ grub_install_get_default_arm_platform (void);
@@ -196,7 +196,7 @@ index 2631b1074..8aeb5c4f2 100644
  grub_install_register_efi (grub_device_t efidir_grub_dev,
  			   const char *efifile_path,
 diff --git a/util/grub-install.c b/util/grub-install.c
-index e5e9e439d..73c623107 100644
+index f0d59c1809..70d6700de8 100644
 --- a/util/grub-install.c
 +++ b/util/grub-install.c
 @@ -1177,7 +1177,18 @@ main (int argc, char *argv[])
diff --git a/debian/patches/install-stage2-confusion.patch b/debian/patches/install-stage2-confusion.patch
index 214a7f6..fafe60f 100644
--- a/debian/patches/install-stage2-confusion.patch
+++ b/debian/patches/install-stage2-confusion.patch
@@ -1,4 +1,4 @@
-From 81cb5ffcbdc273cb57ccc355342d81cf34d8a7b7 Mon Sep 17 00:00:00 2001
+From bd93043d187b87d8faa11135f3414d67da95a167 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@debian.org>
 Date: Mon, 13 Jan 2014 12:12:58 +0000
 Subject: If GRUB Legacy is still around, tell packaging to ignore it
@@ -13,7 +13,7 @@ Patch-Name: install-stage2-confusion.patch
  1 file changed, 14 insertions(+)
 
 diff --git a/util/grub-install.c b/util/grub-install.c
-index 8a55ad4b8..3b4606eef 100644
+index 8a55ad4b8d..3b4606eef1 100644
 --- a/util/grub-install.c
 +++ b/util/grub-install.c
 @@ -42,6 +42,7 @@
diff --git a/debian/patches/linuxefi.patch b/debian/patches/linuxefi.patch
deleted file mode 100644
index a9339a6..0000000
--- a/debian/patches/linuxefi.patch
+++ /dev/null
@@ -1,550 +0,0 @@
-From ef8f04c26dcbcc449bc03c1a304e1a4398e7b5ca Mon Sep 17 00:00:00 2001
-From: Matthew Garrett <mjg@redhat.com>
-Date: Mon, 13 Jan 2014 12:13:15 +0000
-Subject: Add "linuxefi" loader which avoids ExitBootServices
-
-Origin: vendor, http://pkgs.fedoraproject.org/cgit/grub2.git/tree/grub2-linuxefi.patch
-Author: Colin Watson <cjwatson@ubuntu.com>
-Author: Steve Langasek <steve.langasek@canonical.com>
-Author: Linn Crosetto <linn@hpe.com>
-Forwarded: no
-Last-Update: 2019-06-26
-
-Patch-Name: linuxefi.patch
----
- grub-core/Makefile.core.def       |   7 +
- grub-core/kern/efi/mm.c           |  32 +++
- grub-core/loader/i386/efi/linux.c | 381 ++++++++++++++++++++++++++++++
- grub-core/loader/i386/linux.c     |  41 ++++
- include/grub/efi/efi.h            |   3 +
- 5 files changed, 464 insertions(+)
- create mode 100644 grub-core/loader/i386/efi/linux.c
-
-diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
-index 474a63e68..67a98abbb 100644
---- a/grub-core/Makefile.core.def
-+++ b/grub-core/Makefile.core.def
-@@ -1849,6 +1849,13 @@ module = {
-   enable = x86_64_efi;
- };
- 
-+module = {
-+  name = linuxefi;
-+  efi = loader/i386/efi/linux.c;
-+  enable = i386_efi;
-+  enable = x86_64_efi;
-+};
-+
- module = {
-   name = chain;
-   efi = loader/efi/chainloader.c;
-diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
-index b02fab1b1..a9e37108c 100644
---- a/grub-core/kern/efi/mm.c
-+++ b/grub-core/kern/efi/mm.c
-@@ -113,6 +113,38 @@ grub_efi_drop_alloc (grub_efi_physical_address_t address,
-     }
- }
- 
-+/* Allocate pages below a specified address */
-+void *
-+grub_efi_allocate_pages_max (grub_efi_physical_address_t max,
-+			     grub_efi_uintn_t pages)
-+{
-+  grub_efi_status_t status;
-+  grub_efi_boot_services_t *b;
-+  grub_efi_physical_address_t address = max;
-+
-+  if (max > 0xffffffff)
-+    return 0;
-+
-+  b = grub_efi_system_table->boot_services;
-+  status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address);
-+
-+  if (status != GRUB_EFI_SUCCESS)
-+    return 0;
-+
-+  if (address == 0)
-+    {
-+      /* Uggh, the address 0 was allocated... This is too annoying,
-+	 so reallocate another one.  */
-+      address = max;
-+      status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address);
-+      grub_efi_free_pages (0, pages);
-+      if (status != GRUB_EFI_SUCCESS)
-+	return 0;
-+    }
-+
-+  return (void *) ((grub_addr_t) address);
-+}
-+
- /* Allocate pages. Return the pointer to the first of allocated pages.  */
- void *
- grub_efi_allocate_pages_real (grub_efi_physical_address_t address,
-diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
-new file mode 100644
-index 000000000..16372a0c8
---- /dev/null
-+++ b/grub-core/loader/i386/efi/linux.c
-@@ -0,0 +1,381 @@
-+/*
-+ *  GRUB  --  GRand Unified Bootloader
-+ *  Copyright (C) 2012  Free Software Foundation, Inc.
-+ *
-+ *  GRUB is free software: you can redistribute it and/or modify
-+ *  it under the terms of the GNU General Public License as published by
-+ *  the Free Software Foundation, either version 3 of the License, or
-+ *  (at your option) any later version.
-+ *
-+ *  GRUB is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *  GNU General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU General Public License
-+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include <grub/loader.h>
-+#include <grub/file.h>
-+#include <grub/err.h>
-+#include <grub/misc.h>
-+#include <grub/types.h>
-+#include <grub/mm.h>
-+#include <grub/cpu/linux.h>
-+#include <grub/command.h>
-+#include <grub/i18n.h>
-+#include <grub/lib/cmdline.h>
-+#include <grub/linux.h>
-+#include <grub/efi/efi.h>
-+
-+GRUB_MOD_LICENSE ("GPLv3+");
-+
-+static grub_dl_t my_mod;
-+static int loaded;
-+static void *kernel_mem;
-+static grub_uint64_t kernel_size;
-+static grub_uint8_t *initrd_mem;
-+static grub_uint32_t handover_offset;
-+struct linux_kernel_params *params;
-+static char *linux_cmdline;
-+
-+#define BYTES_TO_PAGES(bytes)   (((bytes) + 0xfff) >> 12)
-+
-+#define SHIM_LOCK_GUID \
-+  { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
-+
-+struct grub_efi_shim_lock
-+{
-+  grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
-+};
-+typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
-+
-+static grub_efi_boolean_t
-+grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
-+{
-+  grub_efi_guid_t guid = SHIM_LOCK_GUID;
-+  grub_efi_shim_lock_t *shim_lock;
-+  grub_efi_status_t status;
-+
-+  if (! grub_efi_secure_boot())
-+    {
-+      grub_dprintf ("linuxefi", "secure boot not enabled, not validating");
-+      return 1;
-+    }
-+
-+  grub_dprintf ("linuxefi", "Locating shim protocol\n");
-+  shim_lock = grub_efi_locate_protocol(&guid, NULL);
-+
-+  if (!shim_lock)
-+    {
-+      grub_dprintf ("linuxefi", "shim not available\n");
-+      return 0;
-+    }
-+
-+  grub_dprintf ("linuxefi", "Asking shim to verify kernel signature\n");
-+  status = shim_lock->verify(data, size);
-+  if (status == GRUB_EFI_SUCCESS)
-+    {
-+      grub_dprintf ("linuxefi", "Kernel signature verification passed\n");
-+      return 1;
-+    }
-+
-+  grub_dprintf ("linuxefi", "Kernel signature verification failed (0x%lx)\n",
-+		(unsigned long) status);
-+  return 0;
-+}
-+
-+typedef void(*handover_func)(void *, grub_efi_system_table_t *, struct linux_kernel_params *);
-+
-+static grub_err_t
-+grub_linuxefi_boot (void)
-+{
-+  handover_func hf;
-+  int offset = 0;
-+
-+#ifdef __x86_64__
-+  offset = 512;
-+#endif
-+
-+  hf = (handover_func)((char *)kernel_mem + handover_offset + offset);
-+
-+  asm volatile ("cli");
-+
-+  hf (grub_efi_image_handle, grub_efi_system_table, params);
-+
-+  /* Not reached */
-+  return GRUB_ERR_NONE;
-+}
-+
-+static grub_err_t
-+grub_linuxefi_unload (void)
-+{
-+  grub_dl_unref (my_mod);
-+  loaded = 0;
-+  if (initrd_mem)
-+    grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, BYTES_TO_PAGES(params->ramdisk_size));
-+  if (linux_cmdline)
-+    grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)linux_cmdline, BYTES_TO_PAGES(params->cmdline_size + 1));
-+  if (kernel_mem)
-+    grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
-+  if (params)
-+    grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)params, BYTES_TO_PAGES(16384));
-+  return GRUB_ERR_NONE;
-+}
-+
-+static grub_err_t
-+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
-+                 int argc, char *argv[])
-+{
-+  grub_size_t size = 0;
-+  struct grub_linux_initrd_context initrd_ctx;
-+
-+  if (argc == 0)
-+    {
-+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
-+      goto fail;
-+    }
-+
-+  if (!loaded)
-+    {
-+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
-+      goto fail;
-+    }
-+
-+  if (grub_initrd_init (argc, argv, &initrd_ctx))
-+    goto fail;
-+
-+  size = grub_get_initrd_size (&initrd_ctx);
-+
-+  initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
-+
-+  if (!initrd_mem)
-+    {
-+      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
-+      goto fail;
-+    }
-+
-+  grub_dprintf ("linuxefi", "initrd_mem = %lx\n", (unsigned long) initrd_mem);
-+
-+  params->ramdisk_size = size;
-+  params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem;
-+
-+  if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
-+    goto fail;
-+
-+  params->ramdisk_size = size;
-+
-+ fail:
-+  grub_initrd_close (&initrd_ctx);
-+
-+  if (initrd_mem && grub_errno)
-+    grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, BYTES_TO_PAGES(size));
-+
-+  return grub_errno;
-+}
-+
-+static grub_err_t
-+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
-+		int argc, char *argv[])
-+{
-+  grub_file_t file = 0;
-+  struct linux_i386_kernel_header lh;
-+  grub_ssize_t len, start, filelen;
-+  void *kernel;
-+
-+  grub_dl_ref (my_mod);
-+
-+  if (argc == 0)
-+    {
-+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
-+      goto fail;
-+    }
-+
-+  file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
-+  if (! file)
-+    goto fail;
-+
-+  filelen = grub_file_size (file);
-+
-+  kernel = grub_malloc(filelen);
-+
-+  if (!kernel)
-+    {
-+      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
-+      goto fail;
-+    }
-+
-+  if (grub_file_read (file, kernel, filelen) != filelen)
-+    {
-+      grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]);
-+      goto fail;
-+    }
-+
-+  if (! grub_linuxefi_secure_validate (kernel, filelen))
-+    {
-+      grub_error (GRUB_ERR_ACCESS_DENIED, N_("%s has invalid signature"), argv[0]);
-+      grub_free (kernel);
-+      goto fail;
-+    }
-+
-+  grub_file_seek (file, 0);
-+
-+  grub_free(kernel);
-+
-+  params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
-+
-+  if (! params)
-+    {
-+      grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
-+      goto fail;
-+    }
-+
-+  grub_dprintf ("linuxefi", "params = %lx\n", (unsigned long) params);
-+
-+  grub_memset (params, 0, 16384);
-+
-+  if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
-+    {
-+      if (!grub_errno)
-+	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
-+		    argv[0]);
-+      goto fail;
-+    }
-+
-+  if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
-+    {
-+      grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number"));
-+      goto fail;
-+    }
-+
-+  if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
-+    {
-+      grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
-+      goto fail;
-+    }
-+
-+  if (lh.version < grub_cpu_to_le16 (0x020b))
-+    {
-+      grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
-+      goto fail;
-+    }
-+
-+  if (!lh.handover_offset)
-+    {
-+      grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
-+      goto fail;
-+    }
-+
-+  linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
-+					 BYTES_TO_PAGES(lh.cmdline_size + 1));
-+
-+  if (!linux_cmdline)
-+    {
-+      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
-+      goto fail;
-+    }
-+
-+  grub_dprintf ("linuxefi", "linux_cmdline = %lx\n",
-+		(unsigned long) linux_cmdline);
-+
-+  grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
-+  {
-+    grub_err_t err;
-+    err = grub_create_loader_cmdline (argc, argv,
-+				      linux_cmdline
-+				      + sizeof (LINUX_IMAGE) - 1,
-+				      lh.cmdline_size
-+				      - (sizeof (LINUX_IMAGE) - 1),
-+				      GRUB_VERIFY_KERNEL_CMDLINE);
-+    if (err)
-+      goto fail;
-+  }
-+
-+  lh.cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
-+
-+  handover_offset = lh.handover_offset;
-+
-+  start = (lh.setup_sects + 1) * 512;
-+  len = grub_file_size(file) - start;
-+
-+  kernel_mem = grub_efi_allocate_fixed(lh.pref_address,
-+				       BYTES_TO_PAGES(lh.init_size));
-+
-+  if (!kernel_mem)
-+    kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
-+					     BYTES_TO_PAGES(lh.init_size));
-+
-+  if (!kernel_mem)
-+    {
-+      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
-+      goto fail;
-+    }
-+
-+  grub_dprintf ("linuxefi", "kernel_mem = %lx\n", (unsigned long) kernel_mem);
-+
-+  if (grub_file_seek (file, start) == (grub_off_t) -1)
-+    {
-+      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
-+		  argv[0]);
-+      goto fail;
-+    }
-+
-+  if (grub_file_read (file, kernel_mem, len) != len && !grub_errno)
-+    {
-+      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
-+		  argv[0]);
-+    }
-+
-+  if (grub_errno == GRUB_ERR_NONE)
-+    {
-+      grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
-+      loaded = 1;
-+      lh.code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
-+    }
-+
-+  grub_memcpy (params, &lh, 2 * 512);
-+
-+  params->type_of_loader = 0x21;
-+
-+ fail:
-+
-+  if (file)
-+    grub_file_close (file);
-+
-+  if (grub_errno != GRUB_ERR_NONE)
-+    {
-+      grub_dl_unref (my_mod);
-+      loaded = 0;
-+    }
-+
-+  if (linux_cmdline && !loaded)
-+    grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)linux_cmdline, BYTES_TO_PAGES(lh.cmdline_size + 1));
-+
-+  if (kernel_mem && !loaded)
-+    grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
-+
-+  if (params && !loaded)
-+    grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)params, BYTES_TO_PAGES(16384));
-+
-+  return grub_errno;
-+}
-+
-+static grub_command_t cmd_linux, cmd_initrd;
-+
-+GRUB_MOD_INIT(linuxefi)
-+{
-+  cmd_linux =
-+    grub_register_command ("linuxefi", grub_cmd_linux,
-+                           0, N_("Load Linux."));
-+  cmd_initrd =
-+    grub_register_command ("initrdefi", grub_cmd_initrd,
-+                           0, N_("Load initrd."));
-+  my_mod = mod;
-+}
-+
-+GRUB_MOD_FINI(linuxefi)
-+{
-+  grub_unregister_command (cmd_linux);
-+  grub_unregister_command (cmd_initrd);
-+}
-diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
-index d0501e229..2eab9bb10 100644
---- a/grub-core/loader/i386/linux.c
-+++ b/grub-core/loader/i386/linux.c
-@@ -76,6 +76,8 @@ static grub_size_t maximal_cmdline_size;
- static struct linux_kernel_params linux_params;
- static char *linux_cmdline;
- #ifdef GRUB_MACHINE_EFI
-+static int using_linuxefi;
-+static grub_command_t initrdefi_cmd;
- static grub_efi_uintn_t efi_mmap_size;
- #else
- static const grub_size_t efi_mmap_size = 0;
-@@ -651,6 +653,39 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
- 
-   grub_dl_ref (my_mod);
- 
-+#ifdef GRUB_MACHINE_EFI
-+  using_linuxefi = 0;
-+  if (grub_efi_secure_boot ())
-+    {
-+      /* linuxefi requires a successful signature check and then hand over
-+	 to the kernel without calling ExitBootServices. */
-+      grub_dl_t mod;
-+      grub_command_t linuxefi_cmd;
-+
-+      grub_dprintf ("linux", "Secure Boot enabled: trying linuxefi\n");
-+
-+      mod = grub_dl_load ("linuxefi");
-+      if (mod)
-+	{
-+	  grub_dl_ref (mod);
-+	  linuxefi_cmd = grub_command_find ("linuxefi");
-+	  initrdefi_cmd = grub_command_find ("initrdefi");
-+	  if (linuxefi_cmd && initrdefi_cmd)
-+	    {
-+	      (linuxefi_cmd->func) (linuxefi_cmd, argc, argv);
-+	      if (grub_errno == GRUB_ERR_NONE)
-+		{
-+		  grub_dprintf ("linux", "Handing off to linuxefi\n");
-+		  using_linuxefi = 1;
-+		  return GRUB_ERR_NONE;
-+		}
-+	      grub_dprintf ("linux", "linuxefi failed (%d)\n", grub_errno);
-+	      goto fail;
-+	    }
-+	}
-+    }
-+#endif
-+
-   if (argc == 0)
-     {
-       grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
-@@ -1036,6 +1071,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
-   grub_err_t err;
-   struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
- 
-+#ifdef GRUB_MACHINE_EFI
-+  /* If we're using linuxefi, just forward to initrdefi.  */
-+  if (using_linuxefi && initrdefi_cmd)
-+    return (initrdefi_cmd->func) (initrdefi_cmd, argc, argv);
-+#endif
-+
-   if (argc == 0)
-     {
-       grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
-diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
-index a237952b3..085ee0524 100644
---- a/include/grub/efi/efi.h
-+++ b/include/grub/efi/efi.h
-@@ -47,6 +47,9 @@ 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_allocate_pages_max) (grub_efi_physical_address_t max,
-+					  grub_efi_uintn_t pages);
- void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address,
- 				       grub_efi_uintn_t pages);
- grub_efi_uintn_t EXPORT_FUNC(grub_efi_find_mmap_size) (void);
diff --git a/debian/patches/maybe-quiet.patch b/debian/patches/maybe-quiet.patch
index cf987a6..da80c4b 100644
--- a/debian/patches/maybe-quiet.patch
+++ b/debian/patches/maybe-quiet.patch
@@ -1,6 +1,6 @@
-From 2904de3e9a1f2789442813696c3fbbd59b993443 Mon Sep 17 00:00:00 2001
-From: Colin Watson <cjwatson@ubuntu.com>
-Date: Mon, 13 Jan 2014 12:13:26 +0000
+From 139c9faecee68370e4b46d50ca51d0524029212c Mon Sep 17 00:00:00 2001
+From: Didier Roche <didrocks@ubuntu.com>
+Date: Tue, 31 Mar 2020 15:20:15 +0200
 Subject: Add configure option to reduce visual clutter at boot time
 
 If this option is enabled, then do all of the following:
@@ -43,10 +43,11 @@ Patch-Name: maybe-quiet.patch
  grub-core/normal/main.c           | 11 +++++++++++
  grub-core/normal/menu.c           | 17 +++++++++++++++--
  util/grub.d/10_linux.in           | 15 +++++++++++----
- 9 files changed, 111 insertions(+), 6 deletions(-)
+ util/grub.d/10_linux_zfs.in       |  9 +++++++--
+ 10 files changed, 118 insertions(+), 8 deletions(-)
 
 diff --git a/config.h.in b/config.h.in
-index 9e8f9911b..d2c4ce8e5 100644
+index 9e8f9911b1..d2c4ce8e51 100644
 --- a/config.h.in
 +++ b/config.h.in
 @@ -12,6 +12,8 @@
@@ -59,7 +60,7 @@ index 9e8f9911b..d2c4ce8e5 100644
  /* We don't need those.  */
  #define MINILZO_CFG_SKIP_LZO_PTR 1
 diff --git a/configure.ac b/configure.ac
-index 1e5abc67d..ea00ccd69 100644
+index 1e5abc67d9..ea00ccd691 100644
 --- a/configure.ac
 +++ b/configure.ac
 @@ -1857,6 +1857,17 @@ else
@@ -92,7 +93,7 @@ index 1e5abc67d..ea00ccd69 100644
  echo "*******************************************************"
  ]
 diff --git a/grub-core/boot/i386/pc/boot.S b/grub-core/boot/i386/pc/boot.S
-index 2bd0b2d28..b0c0f2225 100644
+index 2bd0b2d286..b0c0f2225e 100644
 --- a/grub-core/boot/i386/pc/boot.S
 +++ b/grub-core/boot/i386/pc/boot.S
 @@ -19,6 +19,9 @@
@@ -124,7 +125,7 @@ index 2bd0b2d28..b0c0f2225 100644
  	movw	$disk_address_packet, %si
  
 diff --git a/grub-core/boot/i386/pc/diskboot.S b/grub-core/boot/i386/pc/diskboot.S
-index c1addc0df..9b6d7a7ed 100644
+index c1addc0df2..9b6d7a7edc 100644
 --- a/grub-core/boot/i386/pc/diskboot.S
 +++ b/grub-core/boot/i386/pc/diskboot.S
 @@ -18,6 +18,9 @@
@@ -204,7 +205,7 @@ index c1addc0df..9b6d7a7ed 100644
  
  notification_step:	.asciz "."
 diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
-index 9cad0c448..714b63d67 100644
+index 9cad0c4485..714b63d674 100644
 --- a/grub-core/kern/main.c
 +++ b/grub-core/kern/main.c
 @@ -264,15 +264,25 @@ reclaim_module_space (void)
@@ -247,7 +248,7 @@ index 9cad0c448..714b63d67 100644
    grub_rescue_run ();
  }
 diff --git a/grub-core/kern/rescue_reader.c b/grub-core/kern/rescue_reader.c
-index dcd7d4439..a93524eab 100644
+index dcd7d44397..a93524eabb 100644
 --- a/grub-core/kern/rescue_reader.c
 +++ b/grub-core/kern/rescue_reader.c
 @@ -78,7 +78,9 @@ grub_rescue_read_line (char **line, int cont,
@@ -261,7 +262,7 @@ index dcd7d4439..a93524eab 100644
    while (1)
      {
 diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
-index 1b03dfd57..0aa389fa1 100644
+index 1b03dfd57b..0aa389fa16 100644
 --- a/grub-core/normal/main.c
 +++ b/grub-core/normal/main.c
 @@ -389,6 +389,15 @@ static grub_err_t
@@ -291,7 +292,7 @@ index 1b03dfd57..0aa389fa1 100644
    while (1)
      {
 diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
-index 3611ee9ea..ebf5a0f10 100644
+index 3611ee9ea7..ebf5a0f109 100644
 --- a/grub-core/normal/menu.c
 +++ b/grub-core/normal/menu.c
 @@ -827,12 +827,18 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
@@ -338,7 +339,7 @@ index 3611ee9ea..ebf5a0f10 100644
        if (auto_boot)
  	grub_menu_execute_with_fallback (menu, e, autobooted,
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index 61335e908..2e4dff9fb 100644
+index cb1cc200e4..479a8bf4e5 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -21,6 +21,7 @@ prefix="@prefix@"
@@ -349,7 +350,7 @@ index 61335e908..2e4dff9fb 100644
  
  . "$pkgdatadir/grub-mkconfig_lib"
  
-@@ -158,10 +159,12 @@ linux_entry ()
+@@ -162,10 +163,12 @@ linux_entry ()
      fi
      printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/"
    fi
@@ -364,7 +365,7 @@ index 61335e908..2e4dff9fb 100644
    if test -d /sys/firmware/efi && test -e "${linux}.efi.signed"; then
      sed "s/^/$submenu_indentation/" << EOF
  	linux	${rel_dirname}/${basename}.efi.signed root=${linux_root_device_thisversion} ro ${args}
-@@ -173,13 +176,17 @@ EOF
+@@ -177,13 +180,17 @@ EOF
    fi
    if test -n "${initrd}" ; then
      # TRANSLATORS: ramdisk isn't identifier. Should be translated.
@@ -384,3 +385,37 @@ index 61335e908..2e4dff9fb 100644
  	initrd	$(echo $initrd_path)
  EOF
    fi
+diff --git a/util/grub.d/10_linux_zfs.in b/util/grub.d/10_linux_zfs.in
+index bd4f1a2123..3a0e6d1035 100755
+--- a/util/grub.d/10_linux_zfs.in
++++ b/util/grub.d/10_linux_zfs.in
+@@ -20,6 +20,7 @@ set -e
+ prefix="@prefix@"
+ datarootdir="@datarootdir@"
+ ubuntu_recovery="@UBUNTU_RECOVERY@"
++quiet_boot="@QUIET_BOOT@"
+ 
+ . "${pkgdatadir}/grub-mkconfig_lib"
+ 
+@@ -779,7 +780,9 @@ zfs_linux_entry () {
+ 
+     echo "$(prepare_grub_to_access_device_cached "${boot_device}" "${submenu_level}")"
+ 
+-    echo "${submenu_indentation}	echo $(gettext_printf "Loading Linux %s ..." ${kernel_version} | grub_quote)"
++    if [ "${quiet_boot}" = 0 ] || [ "${type}" != simple ]; then
++        echo "${submenu_indentation}	echo $(gettext_printf "Loading Linux %s ..." ${kernel_version} | grub_quote)"
++    fi
+ 
+     linux_default_args="${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+     if [ ${type} = "recovery" ]; then
+@@ -788,7 +791,9 @@ zfs_linux_entry () {
+ 
+     echo "${submenu_indentation}	linux	${kernel} root=ZFS=${dataset} ro ${linux_default_args} ${kernel_additional_args}"
+ 
+-    echo "${submenu_indentation}	echo '$(gettext_printf "Loading initial ramdisk ..." | grub_quote)'"
++    if [ "${quiet_boot}" = 0 ] || [ "${type}" != simple ]; then
++        echo "${submenu_indentation}	echo '$(gettext_printf "Loading initial ramdisk ..." | grub_quote)'"
++    fi
+     echo "${submenu_indentation}	initrd	${initrd}"
+     echo "${submenu_indentation}}"
+ }
diff --git a/debian/patches/mkconfig-loopback.patch b/debian/patches/mkconfig-loopback.patch
index 28054e0..ce4465d 100644
--- a/debian/patches/mkconfig-loopback.patch
+++ b/debian/patches/mkconfig-loopback.patch
@@ -1,4 +1,4 @@
-From eac8d3f2f35c3478673698c800b21d425faf6326 Mon Sep 17 00:00:00 2001
+From 3883a00c8f4a4f59b6a677622776d5bf51337b65 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@debian.org>
 Date: Mon, 13 Jan 2014 12:13:00 +0000
 Subject: Handle filesystems loop-mounted on file images
@@ -21,7 +21,7 @@ Patch-Name: mkconfig-loopback.patch
  3 files changed, 34 insertions(+)
 
 diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
-index b6606c16e..b05df554d 100644
+index b6606c16e0..b05df554da 100644
 --- a/util/grub-mkconfig_lib.in
 +++ b/util/grub-mkconfig_lib.in
 @@ -133,6 +133,22 @@ prepare_grub_to_access_device ()
@@ -63,7 +63,7 @@ index b6606c16e..b05df554d 100644
  
  grub_get_device_id ()
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index dd5a60c71..8c22c79f6 100644
+index f839b3b55f..d927b60ae2 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -40,6 +40,11 @@ fi
@@ -79,7 +79,7 @@ index dd5a60c71..8c22c79f6 100644
  esac
  
 diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
-index 96179ea61..9a8d42fb5 100644
+index 96179ea613..9a8d42fb57 100644
 --- a/util/grub.d/20_linux_xen.in
 +++ b/util/grub.d/20_linux_xen.in
 @@ -40,6 +40,11 @@ fi
diff --git a/debian/patches/mkconfig-mid-upgrade.patch b/debian/patches/mkconfig-mid-upgrade.patch
index 182d7fe..c033bba 100644
--- a/debian/patches/mkconfig-mid-upgrade.patch
+++ b/debian/patches/mkconfig-mid-upgrade.patch
@@ -1,4 +1,4 @@
-From d9aea1d0f76bb3e284531a0076c08665fb98b591 Mon Sep 17 00:00:00 2001
+From 16f168810740a2fd3defa4856ead7b8ded2d1fb5 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:03 +0000
 Subject: Bail out if trying to run grub-mkconfig during upgrade to 2.00
@@ -20,7 +20,7 @@ Patch-Name: mkconfig-mid-upgrade.patch
  1 file changed, 7 insertions(+)
 
 diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
-index 45cd4cc54..b506d63bf 100644
+index 45cd4cc541..b506d63bf9 100644
 --- a/util/grub-mkconfig.in
 +++ b/util/grub-mkconfig.in
 @@ -102,6 +102,13 @@ do
diff --git a/debian/patches/mkconfig-nonexistent-loopback.patch b/debian/patches/mkconfig-nonexistent-loopback.patch
index 4c7e010..9ff8309 100644
--- a/debian/patches/mkconfig-nonexistent-loopback.patch
+++ b/debian/patches/mkconfig-nonexistent-loopback.patch
@@ -1,4 +1,4 @@
-From 0207e6937271a475ec2f89fc9f751e138254579d Mon Sep 17 00:00:00 2001
+From 0a12aab871f0e938738305d89fc1e32915ea7fda Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:08 +0000
 Subject: Avoid getting confused by inaccessible loop device backing paths
@@ -14,7 +14,7 @@ Patch-Name: mkconfig-nonexistent-loopback.patch
  2 files changed, 6 insertions(+), 5 deletions(-)
 
 diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
-index b05df554d..fe6319abe 100644
+index b05df554da..fe6319abe0 100644
 --- a/util/grub-mkconfig_lib.in
 +++ b/util/grub-mkconfig_lib.in
 @@ -143,7 +143,7 @@ prepare_grub_to_access_device ()
@@ -27,7 +27,7 @@ index b05df554d..fe6319abe 100644
        esac
      ;;
 diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
-index 775ceb2e0..b7e1147c4 100644
+index 775ceb2e04..b7e1147c41 100644
 --- a/util/grub.d/30_os-prober.in
 +++ b/util/grub.d/30_os-prober.in
 @@ -219,6 +219,11 @@ EOF
diff --git a/debian/patches/mkconfig-other-inits.patch b/debian/patches/mkconfig-other-inits.patch
index 563680b..4b504fb 100644
--- a/debian/patches/mkconfig-other-inits.patch
+++ b/debian/patches/mkconfig-other-inits.patch
@@ -1,4 +1,4 @@
-From 025817840e1674f9159bb602dde699deec035181 Mon Sep 17 00:00:00 2001
+From 22359dec23434867f467cb704aa771fd63e5ecd9 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@debian.org>
 Date: Sat, 3 Jan 2015 12:04:59 +0000
 Subject: Generate alternative init entries in advanced menu
@@ -18,7 +18,7 @@ Patch-Name: mkconfig-other-inits.patch
  2 files changed, 21 insertions(+)
 
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index 8a74c677b..0cd4cf5c0 100644
+index 85b30084ad..dff84edea5 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -32,6 +32,7 @@ export TEXTDOMAIN=@PACKAGE@
@@ -29,7 +29,7 @@ index 8a74c677b..0cd4cf5c0 100644
  
  if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
    OS=GNU/Linux
-@@ -127,6 +128,8 @@ linux_entry ()
+@@ -131,6 +132,8 @@ linux_entry ()
        case $type in
  	  recovery)
  	      title="$(gettext_printf "%s, with Linux %s (%s)" "${os}" "${version}" "$(gettext "${GRUB_RECOVERY_TITLE}")")" ;;
@@ -38,7 +38,7 @@ index 8a74c677b..0cd4cf5c0 100644
  	  *)
  	      title="$(gettext_printf "%s, with Linux %s" "${os}" "${version}")" ;;
        esac
-@@ -381,6 +384,13 @@ while [ "x$list" != "x" ] ; do
+@@ -385,6 +388,13 @@ while [ "x$list" != "x" ] ; do
  
    linux_entry "${OS}" "${version}" advanced \
                "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
@@ -53,7 +53,7 @@ index 8a74c677b..0cd4cf5c0 100644
      linux_entry "${OS}" "${version}" recovery \
                  "${GRUB_CMDLINE_LINUX_RECOVERY} ${GRUB_CMDLINE_LINUX}"
 diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
-index f2ee0532b..81e5f0d7e 100644
+index f2ee0532bd..81e5f0d7e4 100644
 --- a/util/grub.d/20_linux_xen.in
 +++ b/util/grub.d/20_linux_xen.in
 @@ -27,6 +27,7 @@ export TEXTDOMAIN=@PACKAGE@
diff --git a/debian/patches/mkconfig-recovery-title.patch b/debian/patches/mkconfig-recovery-title.patch
index d4e079d..c398318 100644
--- a/debian/patches/mkconfig-recovery-title.patch
+++ b/debian/patches/mkconfig-recovery-title.patch
@@ -1,4 +1,4 @@
-From 1ff07175f797154b36c322acaf33ec7e562c7502 Mon Sep 17 00:00:00 2001
+From cc1216264113d2471a5ee5d472358e265fde1ab5 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:33 +0000
 Subject: Add GRUB_RECOVERY_TITLE option
@@ -16,12 +16,13 @@ Patch-Name: mkconfig-recovery-title.patch
  util/grub.d/10_hurd.in      | 4 ++--
  util/grub.d/10_kfreebsd.in  | 2 +-
  util/grub.d/10_linux.in     | 2 +-
+ util/grub.d/10_linux_zfs.in | 8 ++++----
  util/grub.d/10_netbsd.in    | 2 +-
  util/grub.d/20_linux_xen.in | 2 +-
- 7 files changed, 17 insertions(+), 7 deletions(-)
+ 8 files changed, 21 insertions(+), 11 deletions(-)
 
 diff --git a/docs/grub.texi b/docs/grub.texi
-index a835d0ae4..3ec35d315 100644
+index a835d0ae42..3ec35d315a 100644
 --- a/docs/grub.texi
 +++ b/docs/grub.texi
 @@ -1536,6 +1536,11 @@ a console is restricted or limited.
@@ -37,7 +38,7 @@ index a835d0ae4..3ec35d315 100644
  
  The following options are still accepted for compatibility with existing
 diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
-index 307214310..9c1da6477 100644
+index 3072143105..9c1da64771 100644
 --- a/util/grub-mkconfig.in
 +++ b/util/grub-mkconfig.in
 @@ -196,6 +196,10 @@ GRUB_ACTUAL_DEFAULT="$GRUB_DEFAULT"
@@ -62,7 +63,7 @@ index 307214310..9c1da6477 100644
  if test "x${grub_cfg}" != "x"; then
    rm -f "${grub_cfg}.new"
 diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in
-index 59a9a48a2..7fa3a3fbd 100644
+index 59a9a48a2f..7fa3a3fbd8 100644
 --- a/util/grub.d/10_hurd.in
 +++ b/util/grub.d/10_hurd.in
 @@ -88,8 +88,8 @@ hurd_entry () {
@@ -77,7 +78,7 @@ index 59a9a48a2..7fa3a3fbd 100644
  	  title="$(gettext_printf "%s, with Hurd %s" "${OS}" "${kernel_base}")"
  	  oldtitle="$OS using $kernel_base"
 diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in
-index 9d8e8fd85..8301d361a 100644
+index 9d8e8fd852..8301d361a1 100644
 --- a/util/grub.d/10_kfreebsd.in
 +++ b/util/grub.d/10_kfreebsd.in
 @@ -76,7 +76,7 @@ kfreebsd_entry ()
@@ -90,10 +91,10 @@ index 9d8e8fd85..8301d361a 100644
  	  title="$(gettext_printf "%s, with kFreeBSD %s" "${os}" "${version}")"
        fi
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index 174d547bb..ba945582e 100644
+index cc2dd855ab..2c418c5ec8 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
-@@ -126,7 +126,7 @@ linux_entry ()
+@@ -130,7 +130,7 @@ linux_entry ()
    if [ x$type != xsimple ] ; then
        case $type in
  	  recovery)
@@ -102,8 +103,42 @@ index 174d547bb..ba945582e 100644
  	  *)
  	      title="$(gettext_printf "%s, with Linux %s" "${os}" "${version}")" ;;
        esac
+diff --git a/util/grub.d/10_linux_zfs.in b/util/grub.d/10_linux_zfs.in
+index 48a4e68976..4477fa6061 100755
+--- a/util/grub.d/10_linux_zfs.in
++++ b/util/grub.d/10_linux_zfs.in
+@@ -957,7 +957,7 @@ generate_grub_menu() {
+ 
+                     GRUB_DISABLE_RECOVERY=${GRUB_DISABLE_RECOVERY:-}
+                     if [ "${GRUB_DISABLE_RECOVERY}" != "true" ]; then
+-                        title="$(gettext_printf "%s%s, with Linux %s (recovery mode)" "${last_booted_kernel_marker}" "${name}" "${kernel_version}")"
++                        title="$(gettext_printf "%s%s, with Linux %s (%s)" "${last_booted_kernel_marker}" "${name}" "${kernel_version}" "$(gettext "${GRUB_RECOVERY_TITLE}")")"
+                         zfs_linux_entry 1 "${title}" "recovery" "${dataset}" "${device}" "${initrd}" "${kernel}"
+                     fi
+                     at_least_one_entry=1
+@@ -985,9 +985,9 @@ generate_grub_menu() {
+ 
+                         GRUB_DISABLE_RECOVERY="${GRUB_DISABLE_RECOVERY:-}"
+                         if [ "${GRUB_DISABLE_RECOVERY}" != "true" ]; then
+-                            title="$(gettext_printf "Revert system only (recovery mode)")"
++                            title="$(gettext_printf "Revert system only (%s)" "$(gettext "${GRUB_RECOVERY_TITLE}")")"
+                             zfs_linux_entry 2 "${title}" "recovery" "${dataset}" "${device}" "${initrd}" "${kernel}"
+-                            title="$(gettext_printf "Revert system and user data (recovery mode)")"
++                            title="$(gettext_printf "Revert system and user data (%s)" "$(gettext "${GRUB_RECOVERY_TITLE}")")"
+                             zfs_linux_entry 2 "${title}" "recovery" "${dataset}" "${device}" "${initrd}" "${kernel}" "zsys-revert=userdata"
+                         fi
+                     # Non-zsys: boot temporarly on snapshots or rollback (destroying intermediate snapshots)
+@@ -997,7 +997,7 @@ generate_grub_menu() {
+ 
+                         GRUB_DISABLE_RECOVERY="${GRUB_DISABLE_RECOVERY:-}"
+                         if [ "${GRUB_DISABLE_RECOVERY}" != "true" ]; then
+-                            title="$(gettext_printf "One time boot (recovery mode)")"
++                            title="$(gettext_printf "One time boot (%s)" "$(gettext "${GRUB_RECOVERY_TITLE}")")"
+                             zfs_linux_entry 2 "${title}" "recovery" "${dataset}" "${device}" "${initrd}" "${kernel}"
+                         fi
+ 
 diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in
-index 874f59969..bb29cc046 100644
+index 874f59969e..bb29cc0468 100644
 --- a/util/grub.d/10_netbsd.in
 +++ b/util/grub.d/10_netbsd.in
 @@ -102,7 +102,7 @@ netbsd_entry ()
@@ -116,7 +151,7 @@ index 874f59969..bb29cc046 100644
  	  title="$(gettext_printf "%s, with kernel %s (via %s)" "${OS}" "$(echo ${kernel} | sed -e 's,^.*/,,')" "${loader}")"
        fi
 diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
-index 9a8d42fb5..f2ee0532b 100644
+index 9a8d42fb57..f2ee0532bd 100644
 --- a/util/grub.d/20_linux_xen.in
 +++ b/util/grub.d/20_linux_xen.in
 @@ -105,7 +105,7 @@ linux_entry ()
diff --git a/debian/patches/mkconfig-signed-kernel.patch b/debian/patches/mkconfig-signed-kernel.patch
index d8d9782..79ae0da 100644
--- a/debian/patches/mkconfig-signed-kernel.patch
+++ b/debian/patches/mkconfig-signed-kernel.patch
@@ -1,6 +1,6 @@
-From 912c4e7152065635c44e433aeee86131e869d54b Mon Sep 17 00:00:00 2001
-From: Colin Watson <cjwatson@ubuntu.com>
-Date: Mon, 13 Jan 2014 12:13:21 +0000
+From 16c328eee53e3fe8c24db8c2438a7410755c58db Mon Sep 17 00:00:00 2001
+From: Didier Roche <didrocks@ubuntu.com>
+Date: Tue, 31 Mar 2020 15:17:45 +0200
 Subject: Generate configuration for signed UEFI kernels if available
 
 Forwarded: no
@@ -8,14 +8,15 @@ Last-Update: 2013-12-25
 
 Patch-Name: mkconfig-signed-kernel.patch
 ---
- util/grub.d/10_linux.in | 15 +++++++++++++++
- 1 file changed, 15 insertions(+)
+ util/grub.d/10_linux.in     | 15 +++++++++++++++
+ util/grub.d/10_linux_zfs.in | 21 +++++++++++++++++++++
+ 2 files changed, 36 insertions(+)
 
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index fd87a124d..61335e908 100644
+index 19e4df4ad8..cb1cc200e4 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
-@@ -161,8 +161,16 @@ linux_entry ()
+@@ -165,8 +165,16 @@ linux_entry ()
    message="$(gettext_printf "Loading Linux %s ..." ${version})"
    sed "s/^/$submenu_indentation/" << EOF
  	echo	'$(echo "$message" | grub_quote)'
@@ -32,7 +33,7 @@ index fd87a124d..61335e908 100644
    if test -n "${initrd}" ; then
      # TRANSLATORS: ramdisk isn't identifier. Should be translated.
      message="$(gettext_printf "Loading initial ramdisk ...")"
-@@ -214,6 +222,13 @@ submenu_indentation=""
+@@ -218,6 +226,13 @@ submenu_indentation=""
  is_top_level=true
  while [ "x$list" != "x" ] ; do
    linux=`version_find_latest $list`
@@ -46,3 +47,42 @@ index fd87a124d..61335e908 100644
    gettext_printf "Found linux image: %s\n" "$linux" >&2
    basename=`basename $linux`
    dirname=`dirname $linux`
+diff --git a/util/grub.d/10_linux_zfs.in b/util/grub.d/10_linux_zfs.in
+index 7f88e771e0..bd4f1a2123 100755
+--- a/util/grub.d/10_linux_zfs.in
++++ b/util/grub.d/10_linux_zfs.in
+@@ -339,6 +339,16 @@ try_default_layout_bpool() {
+     validate_system_dataset "${candidate_dataset}" "boot" "${mntdir}" "${snapshot_name}"
+ }
+ 
++# Return if secure boot is enabled on that system
++is_secure_boot_enabled() {
++    if LANG=C mokutil --sb-state 2>/dev/null | grep -qi enabled; then
++        echo "true"
++        return
++    fi
++    echo "false"
++    return
++}
++
+ # Given a filesystem or snapshot dataset, returns dataset|machine id|pretty name|last used
+ # $1 is dataset we want information from
+ # $2 is the temporary mount directory to use
+@@ -412,6 +422,17 @@ get_dataset_info() {
+             continue
+         fi
+ 
++        # Filters entry if efi/non efi.
++        # Note that for now we allow kernel without .efi.signed as those are signed kernel
++        # on ubuntu, loaded by the shim.
++        case "${linux}" in
++            *.efi.signed)
++                if [ "$(is_secure_boot_enabled)" = "false" ]; then
++                    continue
++                fi
++            ;;
++        esac
++
+         linux_basename=$(basename "${linux}")
+         linux_dirname=$(dirname "${linux}")
+         version=$(echo "${linux_basename}" | sed -e "s,^[^0-9]*-,,g")
diff --git a/debian/patches/mkconfig-ubuntu-distributor.patch b/debian/patches/mkconfig-ubuntu-distributor.patch
index 39d3e9e..d1e2f67 100644
--- a/debian/patches/mkconfig-ubuntu-distributor.patch
+++ b/debian/patches/mkconfig-ubuntu-distributor.patch
@@ -1,4 +1,4 @@
-From b81e9404d10f1af1715c0c5f8783d712bf5af660 Mon Sep 17 00:00:00 2001
+From 77ada294ae9feca7e4202f454ddf56245eee16bf Mon Sep 17 00:00:00 2001
 From: Mario Limonciello <Mario_Limonciello@dell.com>
 Date: Mon, 13 Jan 2014 12:13:14 +0000
 Subject: Remove GNU/Linux from default distributor string for Ubuntu
@@ -12,11 +12,12 @@ Last-Update: 2013-12-25
 
 Patch-Name: mkconfig-ubuntu-distributor.patch
 ---
- util/grub.d/10_linux.in | 9 ++++++++-
- 1 file changed, 8 insertions(+), 1 deletion(-)
+ util/grub.d/10_linux.in     | 9 ++++++++-
+ util/grub.d/10_linux_zfs.in | 9 ++++++++-
+ 2 files changed, 16 insertions(+), 2 deletions(-)
 
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index 0509ac680..fd87a124d 100644
+index fcd3033872..19e4df4ad8 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -32,7 +32,14 @@ CLASS="--class gnu-linux --class gnu --class os"
@@ -35,3 +36,23 @@ index 0509ac680..fd87a124d 100644
    CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1|LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}"
  fi
  
+diff --git a/util/grub.d/10_linux_zfs.in b/util/grub.d/10_linux_zfs.in
+index de4d215900..7f88e771e0 100755
+--- a/util/grub.d/10_linux_zfs.in
++++ b/util/grub.d/10_linux_zfs.in
+@@ -790,7 +790,14 @@ generate_grub_menu() {
+     if [ "${GRUB_DISTRIBUTOR}" = "" ] ; then
+         OS=GNU/Linux
+     else
+-        OS="${GRUB_DISTRIBUTOR} GNU/Linux"
++        case ${GRUB_DISTRIBUTOR} in
++            Ubuntu|Kubuntu)
++            OS="${GRUB_DISTRIBUTOR}"
++            ;;
++            *)
++            OS="${GRUB_DISTRIBUTOR} GNU/Linux"
++            ;;
++        esac
+         CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1 | LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}"
+     fi
+ 
diff --git a/debian/patches/mkconfig-ubuntu-recovery.patch b/debian/patches/mkconfig-ubuntu-recovery.patch
index a943118..097df91 100644
--- a/debian/patches/mkconfig-ubuntu-recovery.patch
+++ b/debian/patches/mkconfig-ubuntu-recovery.patch
@@ -1,6 +1,6 @@
-From 8d20c29dbd3dfb7a475ade30d33b9d9b80069107 Mon Sep 17 00:00:00 2001
-From: Colin Watson <cjwatson@ubuntu.com>
-Date: Mon, 13 Jan 2014 12:13:06 +0000
+From 51814873e68db3d990a080f705e6562ef140b416 Mon Sep 17 00:00:00 2001
+From: Didier Roche <didrocks@ubuntu.com>
+Date: Tue, 31 Mar 2020 15:16:36 +0200
 Subject: "single" -> "recovery" when friendly-recovery is installed
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
@@ -19,11 +19,12 @@ Patch-Name: mkconfig-ubuntu-recovery.patch
 ---
  configure.ac                | 11 +++++++++++
  util/grub.d/10_linux.in     | 16 ++++++++++++++--
+ util/grub.d/10_linux_zfs.in | 15 +++++++++++++--
  util/grub.d/30_os-prober.in |  2 +-
- 3 files changed, 26 insertions(+), 3 deletions(-)
+ 4 files changed, 39 insertions(+), 5 deletions(-)
 
 diff --git a/configure.ac b/configure.ac
-index 7656f2434..1e5abc67d 100644
+index 7656f2434e..1e5abc67d9 100644
 --- a/configure.ac
 +++ b/configure.ac
 @@ -1846,6 +1846,17 @@ fi
@@ -45,7 +46,7 @@ index 7656f2434..1e5abc67d 100644
  
  AC_SUBST([FONT_SOURCE])
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index 8c22c79f6..0509ac680 100644
+index d927b60ae2..fcd3033872 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -20,6 +20,7 @@ set -e
@@ -56,7 +57,7 @@ index 8c22c79f6..0509ac680 100644
  
  . "$pkgdatadir/grub-mkconfig_lib"
  
-@@ -84,6 +85,15 @@ esac
+@@ -88,6 +89,15 @@ esac
  
  title_correction_code=
  
@@ -72,7 +73,7 @@ index 8c22c79f6..0509ac680 100644
  linux_entry ()
  {
    os="$1"
-@@ -123,7 +133,9 @@ linux_entry ()
+@@ -127,7 +137,9 @@ linux_entry ()
        if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then
  	  echo "	load_video" | sed "s/^/$submenu_indentation/"
        fi
@@ -83,7 +84,7 @@ index 8c22c79f6..0509ac680 100644
    fi
  
    echo "	insmod gzio" | sed "s/^/$submenu_indentation/"
-@@ -280,7 +292,7 @@ while [ "x$list" != "x" ] ; do
+@@ -284,7 +296,7 @@ while [ "x$list" != "x" ] ; do
                "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
    if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
      linux_entry "${OS}" "${version}" recovery \
@@ -92,8 +93,55 @@ index 8c22c79f6..0509ac680 100644
    fi
  
    list=`echo $list | tr ' ' '\n' | fgrep -vx "$linux" | tr '\n' ' '`
+diff --git a/util/grub.d/10_linux_zfs.in b/util/grub.d/10_linux_zfs.in
+index b24587f0a5..de4d215900 100755
+--- a/util/grub.d/10_linux_zfs.in
++++ b/util/grub.d/10_linux_zfs.in
+@@ -19,6 +19,7 @@ set -e
+ 
+ prefix="@prefix@"
+ datarootdir="@datarootdir@"
++ubuntu_recovery="@UBUNTU_RECOVERY@"
+ 
+ . "${pkgdatadir}/grub-mkconfig_lib"
+ 
+@@ -748,7 +749,9 @@ zfs_linux_entry () {
+         if [ "${GRUB_GFXPAYLOAD_LINUX}" != "text" ]; then
+             echo "${submenu_indentation}	load_video"
+         fi
+-        echo "${submenu_indentation}	set gfxpayload=\${linux_gfx_mode}"
++        if [ "${ubuntu_recovery}" = 0 ] || [ "${type}" != "recovery" ]; then
++            echo "${submenu_indentation}	set gfxpayload=\${linux_gfx_mode}"
++        fi
+     fi
+ 
+     echo "${submenu_indentation}	insmod gzio"
+@@ -759,7 +762,7 @@ zfs_linux_entry () {
+ 
+     linux_default_args="${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+     if [ ${type} = "recovery" ]; then
+-        linux_default_args="single ${GRUB_CMDLINE_LINUX}"
++        linux_default_args="${GRUB_CMDLINE_LINUX_RECOVERY} ${GRUB_CMDLINE_LINUX}"
+     fi
+ 
+     echo "${submenu_indentation}	linux	${kernel} root=ZFS=${dataset} ro ${linux_default_args} ${kernel_additional_args}"
+@@ -791,6 +794,14 @@ generate_grub_menu() {
+         CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1 | LC_ALL=C sed 's,[^[:alnum:]_],_,g') ${CLASS}"
+     fi
+ 
++    if [ -x /lib/recovery-mode/recovery-menu ]; then
++        GRUB_CMDLINE_LINUX_RECOVERY=recovery
++    else
++        GRUB_CMDLINE_LINUX_RECOVERY=single
++    fi
++    if [ "${ubuntu_recovery}" = 1 ]; then
++        GRUB_CMDLINE_LINUX_RECOVERY="${GRUB_CMDLINE_LINUX_RECOVERY} nomodeset"
++    fi
+ 
+     # IFS is set to TAB (ASCII 0x09)
+     echo "${menu_metadata}" |
 diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
-index 515a68c7a..775ceb2e0 100644
+index 515a68c7aa..775ceb2e04 100644
 --- a/util/grub.d/30_os-prober.in
 +++ b/util/grub.d/30_os-prober.in
 @@ -220,7 +220,7 @@ EOF
diff --git a/debian/patches/mkrescue-efi-modules.patch b/debian/patches/mkrescue-efi-modules.patch
index db44eea..54d15e4 100644
--- a/debian/patches/mkrescue-efi-modules.patch
+++ b/debian/patches/mkrescue-efi-modules.patch
@@ -1,4 +1,4 @@
-From b1e5197cab859b271d539c8e4a9f2928b23b66b2 Mon Sep 17 00:00:00 2001
+From 20edd1abb590756c35b886849a15d17d80f82170 Mon Sep 17 00:00:00 2001
 From: Mario Limonciello <Mario_Limonciello@dell.com>
 Date: Mon, 13 Jan 2014 12:12:59 +0000
 Subject: Build vfat into EFI boot images
@@ -14,7 +14,7 @@ Patch-Name: mkrescue-efi-modules.patch
  1 file changed, 2 insertions(+)
 
 diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c
-index ce2cbc4f1..45d6140d3 100644
+index ce2cbc4f10..45d6140d3e 100644
 --- a/util/grub-mkrescue.c
 +++ b/util/grub-mkrescue.c
 @@ -750,6 +750,7 @@ main (int argc, char *argv[])
diff --git a/debian/patches/net-read-bracketed-ipv6-addr.patch b/debian/patches/net-read-bracketed-ipv6-addr.patch
index 335718d..76e97c9 100644
--- a/debian/patches/net-read-bracketed-ipv6-addr.patch
+++ b/debian/patches/net-read-bracketed-ipv6-addr.patch
@@ -1,4 +1,4 @@
-From 9d6491949d9e80faa4ef9f699db08a68b6f0d9ba Mon Sep 17 00:00:00 2001
+From 370386aaaed787b4b9082cd75f155f1b21350878 Mon Sep 17 00:00:00 2001
 From: Aaron Miller <aaronmiller@fb.com>
 Date: Thu, 27 Oct 2016 17:39:49 -0400
 Subject: net: read bracketed ipv6 addrs and port numbers
@@ -16,7 +16,7 @@ Patch-Name: net-read-bracketed-ipv6-addr.patch
  4 files changed, 110 insertions(+), 11 deletions(-)
 
 diff --git a/grub-core/net/http.c b/grub-core/net/http.c
-index 5aa4ad3be..f182d7b87 100644
+index 5aa4ad3bef..f182d7b871 100644
 --- a/grub-core/net/http.c
 +++ b/grub-core/net/http.c
 @@ -312,12 +312,14 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
@@ -74,7 +74,7 @@ index 5aa4ad3be..f182d7b87 100644
  				  file);
    if (!data->sock)
 diff --git a/grub-core/net/net.c b/grub-core/net/net.c
-index d5d726a31..b917a75d5 100644
+index d5d726a315..b917a75d54 100644
 --- a/grub-core/net/net.c
 +++ b/grub-core/net/net.c
 @@ -437,6 +437,12 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
@@ -211,7 +211,7 @@ index d5d726a31..b917a75d5 100644
  	  }
        }
 diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
-index 7d90bf66e..a0817a075 100644
+index 7d90bf66e7..a0817a075d 100644
 --- a/grub-core/net/tftp.c
 +++ b/grub-core/net/tftp.c
 @@ -314,6 +314,7 @@ tftp_open (struct grub_file *file, const char *filename)
@@ -241,7 +241,7 @@ index 7d90bf66e..a0817a075 100644
    if (!data->sock)
      {
 diff --git a/include/grub/net.h b/include/grub/net.h
-index 4a9069a14..cc114286e 100644
+index 4a9069a147..cc114286ea 100644
 --- a/include/grub/net.h
 +++ b/include/grub/net.h
 @@ -270,6 +270,7 @@ typedef struct grub_net
diff --git a/debian/patches/no-devicetree-if-secure-boot.patch b/debian/patches/no-devicetree-if-secure-boot.patch
index b8b7bdf..c56d2e3 100644
--- a/debian/patches/no-devicetree-if-secure-boot.patch
+++ b/debian/patches/no-devicetree-if-secure-boot.patch
@@ -1,4 +1,4 @@
-From 68414261f692279b987ecccb9cb80e4e84d3c1dc Mon Sep 17 00:00:00 2001
+From 7419d200192a1214872a70852200922529baa7b8 Mon Sep 17 00:00:00 2001
 From: Peter Jones <pjones@redhat.com>
 Date: Wed, 24 Apr 2019 10:03:04 -0400
 Subject: Forbid the "devicetree" command when Secure Boot is enabled.
@@ -17,7 +17,7 @@ Patch-Name: no-devicetree-if-secure-boot.patch
  2 files changed, 20 insertions(+)
 
 diff --git a/grub-core/loader/arm/linux.c b/grub-core/loader/arm/linux.c
-index 51684914c..092e8e307 100644
+index 51684914cf..092e8e3077 100644
 --- a/grub-core/loader/arm/linux.c
 +++ b/grub-core/loader/arm/linux.c
 @@ -30,6 +30,10 @@
@@ -47,7 +47,7 @@ index 51684914c..092e8e307 100644
    if (!dtb)
      return grub_errno;
 diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c
-index ee9c5592c..f0c2d91be 100644
+index ee9c5592c7..f0c2d91be2 100644
 --- a/grub-core/loader/efi/fdt.c
 +++ b/grub-core/loader/efi/fdt.c
 @@ -123,6 +123,14 @@ grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
diff --git a/debian/patches/no-insmod-on-sb.patch b/debian/patches/no-insmod-on-sb.patch
index 28cbe7d..5ed0187 100644
--- a/debian/patches/no-insmod-on-sb.patch
+++ b/debian/patches/no-insmod-on-sb.patch
@@ -1,4 +1,4 @@
-From 46b1bebed9ab58e5e769a6239dec7a295d9212aa Mon Sep 17 00:00:00 2001
+From df8702b930179447a7ecaf8bb0f9842522967a41 Mon Sep 17 00:00:00 2001
 From: Matthew Garrett <mjg@redhat.com>
 Date: Mon, 13 Jan 2014 12:13:09 +0000
 Subject: Don't permit loading modules on UEFI secure boot
@@ -16,7 +16,7 @@ Patch-Name: no-insmod-on-sb.patch
  3 files changed, 42 insertions(+)
 
 diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
-index 48eb5e7b6..074dfc3c6 100644
+index 48eb5e7b62..074dfc3c6f 100644
 --- a/grub-core/kern/dl.c
 +++ b/grub-core/kern/dl.c
 @@ -38,6 +38,10 @@
@@ -47,7 +47,7 @@ index 48eb5e7b6..074dfc3c6 100644
  
    file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE);
 diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
-index 6e1ceb905..96204e39b 100644
+index 6e1ceb9051..96204e39b9 100644
 --- a/grub-core/kern/efi/efi.c
 +++ b/grub-core/kern/efi/efi.c
 @@ -273,6 +273,34 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
@@ -86,7 +86,7 @@ index 6e1ceb905..96204e39b 100644
  
  /* Search the mods section from the PE32/PE32+ image. This code uses
 diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
-index e90e00dc4..a237952b3 100644
+index e90e00dc43..a237952b37 100644
 --- a/include/grub/efi/efi.h
 +++ b/include/grub/efi/efi.h
 @@ -82,6 +82,7 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var,
diff --git a/debian/patches/olpc-prefix-hack.patch b/debian/patches/olpc-prefix-hack.patch
index b14c333..d40729f 100644
--- a/debian/patches/olpc-prefix-hack.patch
+++ b/debian/patches/olpc-prefix-hack.patch
@@ -11,7 +11,7 @@ Patch-Name: olpc-prefix-hack.patch
  1 file changed, 11 insertions(+)
 
 diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
-index d483e35ee..8b089b48d 100644
+index d483e35eed..8b089b48d0 100644
 --- a/grub-core/kern/ieee1275/init.c
 +++ b/grub-core/kern/ieee1275/init.c
 @@ -76,6 +76,7 @@ grub_exit (void)
diff --git a/debian/patches/ppc64el-disable-vsx.patch b/debian/patches/ppc64el-disable-vsx.patch
index 83872fc..3aef631 100644
--- a/debian/patches/ppc64el-disable-vsx.patch
+++ b/debian/patches/ppc64el-disable-vsx.patch
@@ -1,4 +1,4 @@
-From ed02b830bb2ecc1cce75a75f6985fd92e9332365 Mon Sep 17 00:00:00 2001
+From 7736a6a5e58402b8f88d053ce2409b2d16262be5 Mon Sep 17 00:00:00 2001
 From: Paulo Flabiano Smorigo <pfsmorigo@linux.vnet.ibm.com>
 Date: Thu, 25 Sep 2014 19:33:39 -0300
 Subject: Disable VSX instruction
@@ -21,7 +21,7 @@ Patch-Name: ppc64el-disable-vsx.patch
  1 file changed, 12 insertions(+)
 
 diff --git a/grub-core/kern/powerpc/ieee1275/startup.S b/grub-core/kern/powerpc/ieee1275/startup.S
-index 21c884b43..de9a9601a 100644
+index 21c884b433..de9a9601a9 100644
 --- a/grub-core/kern/powerpc/ieee1275/startup.S
 +++ b/grub-core/kern/powerpc/ieee1275/startup.S
 @@ -20,6 +20,8 @@
diff --git a/debian/patches/probe-fusionio.patch b/debian/patches/probe-fusionio.patch
index 0873841..ad7ef51 100644
--- a/debian/patches/probe-fusionio.patch
+++ b/debian/patches/probe-fusionio.patch
@@ -1,4 +1,4 @@
-From d13c402298bbee39239f4378e312c128e5fb0a88 Mon Sep 17 00:00:00 2001
+From c89a80f695775566c7f184ec19b4ad34f58906bb Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:31 +0000
 Subject: Probe FusionIO devices
@@ -14,7 +14,7 @@ Patch-Name: probe-fusionio.patch
  2 files changed, 32 insertions(+)
 
 diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
-index 90d92d3ad..7adc0f30e 100644
+index 90d92d3ad5..7adc0f30ee 100644
 --- a/grub-core/osdep/linux/getroot.c
 +++ b/grub-core/osdep/linux/getroot.c
 @@ -950,6 +950,19 @@ grub_util_part_to_disk (const char *os_dev, struct stat *st,
@@ -38,7 +38,7 @@ index 90d92d3ad..7adc0f30e 100644
  
    return path;
 diff --git a/util/deviceiter.c b/util/deviceiter.c
-index a4971ef42..dddc50da7 100644
+index a4971ef429..dddc50da7a 100644
 --- a/util/deviceiter.c
 +++ b/util/deviceiter.c
 @@ -383,6 +383,12 @@ get_nvme_disk_name (char *name, int controller, int namespace)
diff --git a/debian/patches/quick-boot-lvm.patch b/debian/patches/quick-boot-lvm.patch
index 1679a67..e313019 100644
--- a/debian/patches/quick-boot-lvm.patch
+++ b/debian/patches/quick-boot-lvm.patch
@@ -1,4 +1,4 @@
-From 23e25d42b55a01146a4683c4bc30e821f0366101 Mon Sep 17 00:00:00 2001
+From 193f060dd7c98d850e81a0b73383ff19c4374d64 Mon Sep 17 00:00:00 2001
 From: Steve Langasek <steve.langasek@ubuntu.com>
 Date: Tue, 30 Oct 2018 15:04:16 -0700
 Subject: If we don't have writable grubenv and we're on EFI, always show the
@@ -26,7 +26,7 @@ Patch-Name: quick-boot-lvm.patch
  1 file changed, 15 insertions(+), 3 deletions(-)
 
 diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
-index 674a76140..b7135b655 100644
+index 674a761402..b7135b655f 100644
 --- a/util/grub.d/00_header.in
 +++ b/util/grub.d/00_header.in
 @@ -115,7 +115,7 @@ EOF
diff --git a/debian/patches/quick-boot.patch b/debian/patches/quick-boot.patch
index 9a0b95d..ad4650d 100644
--- a/debian/patches/quick-boot.patch
+++ b/debian/patches/quick-boot.patch
@@ -1,4 +1,4 @@
-From 20154f1a5e0606fc488df60ac28a4d186cda22bd Mon Sep 17 00:00:00 2001
+From a34a2ebb74968f6a460fd0f90c545f3e847a3411 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:28 +0000
 Subject: Add configure option to bypass boot menu if possible
@@ -29,11 +29,12 @@ Patch-Name: quick-boot.patch
  util/grub-mkconfig.in       |  3 +-
  util/grub.d/00_header.in    | 77 +++++++++++++++++++++++++++++++------
  util/grub.d/10_linux.in     |  4 ++
+ util/grub.d/10_linux_zfs.in |  5 +++
  util/grub.d/30_os-prober.in | 21 ++++++++++
- 7 files changed, 141 insertions(+), 13 deletions(-)
+ 8 files changed, 146 insertions(+), 13 deletions(-)
 
 diff --git a/configure.ac b/configure.ac
-index ea00ccd69..7dda5bb32 100644
+index ea00ccd691..7dda5bb32b 100644
 --- a/configure.ac
 +++ b/configure.ac
 @@ -1868,6 +1868,17 @@ else
@@ -55,7 +56,7 @@ index ea00ccd69..7dda5bb32 100644
  
  AC_SUBST([FONT_SOURCE])
 diff --git a/docs/grub.texi b/docs/grub.texi
-index 87795075a..a835d0ae4 100644
+index 87795075a8..a835d0ae42 100644
 --- a/docs/grub.texi
 +++ b/docs/grub.texi
 @@ -1522,6 +1522,20 @@ This option may be set to a list of GRUB module names separated by spaces.
@@ -80,7 +81,7 @@ index 87795075a..a835d0ae4 100644
  
  The following options are still accepted for compatibility with existing
 diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
-index ebf5a0f10..42c82290d 100644
+index ebf5a0f109..42c82290de 100644
 --- a/grub-core/normal/menu.c
 +++ b/grub-core/normal/menu.c
 @@ -604,6 +604,30 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
@@ -115,7 +116,7 @@ index ebf5a0f10..42c82290d 100644
  	{
  	  pos = grub_term_save_pos ();
 diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
-index d18bf972f..307214310 100644
+index d18bf972f7..3072143105 100644
 --- a/util/grub-mkconfig.in
 +++ b/util/grub-mkconfig.in
 @@ -250,7 +250,8 @@ export GRUB_DEFAULT \
@@ -129,7 +130,7 @@ index d18bf972f..307214310 100644
  if test "x${grub_cfg}" != "x"; then
    rm -f "${grub_cfg}.new"
 diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
-index 93a90233e..674a76140 100644
+index 93a90233ea..674a761402 100644
 --- a/util/grub.d/00_header.in
 +++ b/util/grub.d/00_header.in
 @@ -21,6 +21,8 @@ prefix="@prefix@"
@@ -258,7 +259,7 @@ index 93a90233e..674a76140 100644
  EOF
  }
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index 2e4dff9fb..51cdb5e1d 100644
+index 479a8bf4e5..2be66c7028 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -22,6 +22,7 @@ exec_prefix="@exec_prefix@"
@@ -269,7 +270,7 @@ index 2e4dff9fb..51cdb5e1d 100644
  
  . "$pkgdatadir/grub-mkconfig_lib"
  
-@@ -129,6 +130,9 @@ linux_entry ()
+@@ -133,6 +134,9 @@ linux_entry ()
    else
        echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
    fi      
@@ -279,8 +280,31 @@ index 2e4dff9fb..51cdb5e1d 100644
    if [ x$type != xrecovery ] ; then
        save_default_entry | grub_add_tab
    fi
+diff --git a/util/grub.d/10_linux_zfs.in b/util/grub.d/10_linux_zfs.in
+index 3a0e6d1035..ec4b49d9d7 100755
+--- a/util/grub.d/10_linux_zfs.in
++++ b/util/grub.d/10_linux_zfs.in
+@@ -21,6 +21,7 @@ prefix="@prefix@"
+ datarootdir="@datarootdir@"
+ ubuntu_recovery="@UBUNTU_RECOVERY@"
+ quiet_boot="@QUIET_BOOT@"
++quick_boot="@QUICK_BOOT@"
+ 
+ . "${pkgdatadir}/grub-mkconfig_lib"
+ 
+@@ -755,6 +756,10 @@ zfs_linux_entry () {
+ 
+     echo "${submenu_indentation}menuentry '$(echo "${title}" | grub_quote)' ${CLASS} \${menuentry_id_option} 'gnulinux-${dataset}-${kernel_version}' {"
+ 
++    if [ "${quick_boot}" = 1 ]; then
++        echo "${submenu_indentation}	recordfail"
++    fi
++
+     if [ "${type}" != "recovery" ] ; then
+         GRUB_SAVEDEFAULT=${GRUB_SAVEDEFAULT:-}
+         default_entry="$(save_default_entry)"
 diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
-index 271044f59..da5f28876 100644
+index 271044f592..da5f28876d 100644
 --- a/util/grub.d/30_os-prober.in
 +++ b/util/grub.d/30_os-prober.in
 @@ -20,12 +20,26 @@ set -e
diff --git a/debian/patches/restore-mkdevicemap.patch b/debian/patches/restore-mkdevicemap.patch
index f459634..7236a7b 100644
--- a/debian/patches/restore-mkdevicemap.patch
+++ b/debian/patches/restore-mkdevicemap.patch
@@ -1,4 +1,4 @@
-From 2ecd079ed1078da6a26223333d0645dd53ef181a Mon Sep 17 00:00:00 2001
+From 9e77654bae1ee822ee7ae4e90e5f043105388ee4 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@debian.org>
 Date: Mon, 13 Jan 2014 12:13:01 +0000
 Subject: Restore grub-mkdevicemap
@@ -28,7 +28,7 @@ Patch-Name: restore-mkdevicemap.patch
  create mode 100644 util/grub-mkdevicemap.c
 
 diff --git a/Makefile.util.def b/Makefile.util.def
-index 969d32f00..0029b9000 100644
+index bac85e2840..eec1924b0e 100644
 --- a/Makefile.util.def
 +++ b/Makefile.util.def
 @@ -324,6 +324,23 @@ program = {
@@ -57,7 +57,7 @@ index 969d32f00..0029b9000 100644
    installdir = sbin;
 diff --git a/docs/man/grub-mkdevicemap.h2m b/docs/man/grub-mkdevicemap.h2m
 new file mode 100644
-index 000000000..96cd6ee72
+index 0000000000..96cd6ee723
 --- /dev/null
 +++ b/docs/man/grub-mkdevicemap.h2m
 @@ -0,0 +1,4 @@
@@ -67,7 +67,7 @@ index 000000000..96cd6ee72
 +.BR grub-probe (8)
 diff --git a/include/grub/util/deviceiter.h b/include/grub/util/deviceiter.h
 new file mode 100644
-index 000000000..85374978c
+index 0000000000..85374978c5
 --- /dev/null
 +++ b/include/grub/util/deviceiter.h
 @@ -0,0 +1,14 @@
@@ -87,7 +87,7 @@ index 000000000..85374978c
 +#endif /* ! GRUB_DEVICEITER_MACHINE_UTIL_HEADER */
 diff --git a/util/deviceiter.c b/util/deviceiter.c
 new file mode 100644
-index 000000000..a4971ef42
+index 0000000000..a4971ef429
 --- /dev/null
 +++ b/util/deviceiter.c
 @@ -0,0 +1,1021 @@
@@ -1114,7 +1114,7 @@ index 000000000..a4971ef42
 +}
 diff --git a/util/devicemap.c b/util/devicemap.c
 new file mode 100644
-index 000000000..c61864420
+index 0000000000..c61864420a
 --- /dev/null
 +++ b/util/devicemap.c
 @@ -0,0 +1,13 @@
@@ -1133,7 +1133,7 @@ index 000000000..c61864420
 +}
 diff --git a/util/grub-mkdevicemap.c b/util/grub-mkdevicemap.c
 new file mode 100644
-index 000000000..c4bbdbf69
+index 0000000000..c4bbdbf69c
 --- /dev/null
 +++ b/util/grub-mkdevicemap.c
 @@ -0,0 +1,181 @@
diff --git a/debian/patches/series b/debian/patches/series
index 9a09d27..f6fbf31 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -4,6 +4,7 @@ dpkg-version-comparison.patch
 grub-legacy-0-based-partitions.patch
 disable-floppies.patch
 grub.cfg-400.patch
+ubuntu-zfs-enhance-support.patch
 gfxpayload-keep-default.patch
 install-stage2-confusion.patch
 mkrescue-efi-modules.patch
@@ -20,9 +21,8 @@ default-grub-d.patch
 blacklist-1440x900x32.patch
 uefi-firmware-setup.patch
 mkconfig-ubuntu-distributor.patch
-linuxefi.patch
 mkconfig-signed-kernel.patch
-install-signed.patch
+ubuntu-install-signed.patch
 sleep-shift.patch
 wubi-no-windows.patch
 maybe-quiet.patch
@@ -39,7 +39,7 @@ ieee1275-clear-reset.patch
 ppc64el-disable-vsx.patch
 grub-install-pvxen-paths.patch
 insmod-xzio-and-lzopio-on-xen.patch
-grub-install-extra-removable.patch
+ubuntu-grub-install-extra-removable.patch
 mkconfig-other-inits.patch
 zpool-full-device-name.patch
 net-read-bracketed-ipv6-addr.patch
@@ -48,7 +48,6 @@ efinet-uefi-ipv6-pxe-support.patch
 bootp-process-dhcpack-http-boot.patch
 efinet-set-network-from-uefi-devpath.patch
 efinet-set-dns-from-uefi-proto.patch
-fix-lockdown.patch
 skip-grub_cmd_set_date.patch
 bash-completion-drop-have-checks.patch
 at_keyboard-module-init.patch
@@ -56,4 +55,58 @@ uefi-secure-boot-cryptomount.patch
 vsnprintf-upper-case-hex.patch
 efi-variable-storage-minimise-writes.patch
 no-devicetree-if-secure-boot.patch
-grub-install-removable-shim.patch
+ubuntu-linuxefi.patch
+ubuntu-efi-console-set-text-mode-as-needed.patch
+ubuntu-support-initrd-less-boot.patch
+ubuntu-shorter-version-info.patch
+ubuntu-add-initrd-less-boot-fallback.patch
+ubuntu-mkconfig-leave-breadcrumbs.patch
+ubuntu-fix-lzma-decompressor-objcopy.patch
+ubuntu-temp-keep-auto-nvram.patch
+ubuntu-add-devicetree-command-support.patch
+ubuntu-boot-from-multipath-dependent-symlink.patch
+ubuntu-skip-disk-by-id-lvm-pvm-uuid-entries.patch
+ubuntu-tpm-unknown-error-non-fatal.patch
+ubuntu-efi-allow-loopmount-chainload.patch
+cherrypick-lsefisystab-define-smbios3.patch
+cherrypick-smbios-module.patch
+cherrypick-lsefisystab-show-dtb.patch
+0074-uefi-firmware-rename-fwsetup-menuentry-to-UEFI-Firmw.patch
+0075-smbios-Add-a-linux-argument-to-apply-linux-modalias-.patch
+0076-ubuntu-Make-the-linux-command-in-EFI-grub-always-try.patch
+0077-ubuntu-Update-the-linux-boot-protocol-version-check.patch
+ubuntu-resilient-boot-ignore-alternative-esps.patch
+ubuntu-resilient-boot-boot-order.patch
+ubuntu-speed-zsys-history.patch
+0081-yylex-Make-lexer-fatal-errors-actually-be-fatal.patch
+0082-safemath-Add-some-arithmetic-primitives-that-check-f.patch
+0083-calloc-Make-sure-we-always-have-an-overflow-checking.patch
+0084-calloc-Use-calloc-at-most-places.patch
+0085-malloc-Use-overflow-checking-primitives-where-we-do-.patch
+0086-iso9660-Don-t-leak-memory-on-realloc-failures.patch
+0087-font-Do-not-load-more-than-one-NAME-section.patch
+0088-gfxmenu-Fix-double-free-in-load_image.patch
+0089-lzma-Make-sure-we-don-t-dereference-past-array.patch
+0090-tftp-Do-not-use-priority-queue.patch
+0091-script-Remove-unused-fields-from-grub_script_functio.patch
+0092-script-Avoid-a-use-after-free-when-redefining-a-func.patch
+0093-hfsplus-fix-two-more-overflows.patch
+0094-lvm-fix-two-more-potential-data-dependent-alloc-over.patch
+0095-efi-fix-some-malformed-device-path-arithmetic-errors.patch
+0096-linuxefi-fail-kernel-validation-without-shim-protoco.patch
+0097-Fix-a-regression-caused-by-efi-fix-some-malformed-de.patch
+0098-efi-Fix-use-after-free-in-halt-reboot-path.patch
+0099-chainloader-Avoid-a-double-free-when-validation-fail.patch
+0100-relocator-Protect-grub_relocator_alloc_chunk_addr-in.patch
+0101-relocator-Protect-grub_relocator_alloc_chunk_align-m.patch
+0102-relocator-Fix-grub_relocator_alloc_chunk_align-top-m.patch
+0103-linux-loader-avoid-overflow-on-initrd-size-calculati.patch
+0104-linux-Fix-integer-overflows-in-initrd-size-handling.patch
+0105-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch
+ubuntu-flavour-order.patch
+ubuntu-dont-verify-loopback-images.patch
+ubuntu-recovery-dis_ucode_ldr.patch
+grub-install-backup-and-restore.patch
+ubuntu-linuxefi-arm64.patch
+ubuntu-dejavu-font-path.patch
+ubuntu-add-initrd-less-boot-messages.patch
diff --git a/debian/patches/skip-grub_cmd_set_date.patch b/debian/patches/skip-grub_cmd_set_date.patch
index 6d17b42..6aa97f4 100644
--- a/debian/patches/skip-grub_cmd_set_date.patch
+++ b/debian/patches/skip-grub_cmd_set_date.patch
@@ -1,4 +1,4 @@
-From badf90fb559ecdb1beca8a994995816b00ccbfbb Mon Sep 17 00:00:00 2001
+From 0bd95cc9927bd92aa12a5fa9ba6ffd11ffc8b910 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@debian.org>
 Date: Sun, 28 Oct 2018 19:45:56 +0000
 Subject: Skip flaky grub_cmd_set_date test
@@ -12,7 +12,7 @@ Patch-Name: skip-grub_cmd_set_date.patch
  1 file changed, 3 insertions(+)
 
 diff --git a/tests/grub_cmd_set_date.in b/tests/grub_cmd_set_date.in
-index aac120a6c..1bb5be4ca 100644
+index aac120a6c5..1bb5be4ca7 100644
 --- a/tests/grub_cmd_set_date.in
 +++ b/tests/grub_cmd_set_date.in
 @@ -1,6 +1,9 @@
diff --git a/debian/patches/sleep-shift.patch b/debian/patches/sleep-shift.patch
index b6065a9..9d1aae3 100644
--- a/debian/patches/sleep-shift.patch
+++ b/debian/patches/sleep-shift.patch
@@ -1,4 +1,4 @@
-From 44bedf4e397054ada7cb7f5855f8a73ba5c3ebcb Mon Sep 17 00:00:00 2001
+From e731dba24511ce3c9a06923db223ddd337798719 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:23 +0000
 Subject: Allow Shift to interrupt 'sleep --interruptible'
@@ -17,7 +17,7 @@ Patch-Name: sleep-shift.patch
  2 files changed, 45 insertions(+), 1 deletion(-)
 
 diff --git a/grub-core/commands/sleep.c b/grub-core/commands/sleep.c
-index e77e7900f..3906b1410 100644
+index e77e7900fa..3906b14103 100644
 --- a/grub-core/commands/sleep.c
 +++ b/grub-core/commands/sleep.c
 @@ -46,6 +46,31 @@ do_print (int n)
@@ -62,7 +62,7 @@ index e77e7900f..3906b1410 100644
  
    return 0;
 diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
-index d5e0c79a7..3611ee9ea 100644
+index d5e0c79a70..3611ee9ea7 100644
 --- a/grub-core/normal/menu.c
 +++ b/grub-core/normal/menu.c
 @@ -615,8 +615,27 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
diff --git a/debian/patches/ubuntu-add-devicetree-command-support.patch b/debian/patches/ubuntu-add-devicetree-command-support.patch
new file mode 100644
index 0000000..aa41aba
--- /dev/null
+++ b/debian/patches/ubuntu-add-devicetree-command-support.patch
@@ -0,0 +1,52 @@
+From 56ec016fe65a634c583cd347fc4e90992cb0c111 Mon Sep 17 00:00:00 2001
+From: Dimitri John Ledkov <xnox@ubuntu.com>
+Date: Wed, 22 May 2019 19:57:29 +0100
+Subject: Add devicetree command, if a dtb is present.
+
+Specically support dtb paths as installed by flash-kernel.
+
+Signed-off-by: Dimitri John Ledkov <xnox@ubuntu.com>
+Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=929427
+Bug-Upstream: https://lists.gnu.org/archive/html/grub-devel/2019-05/msg00121.html
+Patch-Name: ubuntu-add-devicetree-command-support.patch
+---
+ util/grub.d/10_linux.in | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index af1e096bd6..bbf5d73e39 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -254,6 +254,17 @@ EOF
+ EOF
+         fi
+     fi
++    if test -n "${dtb}" ; then
++      if [ x"$quiet_boot" = x0 ] || [ x"$type" != xsimple ]; then
++        message="$(gettext_printf "Loading device tree blob...")"
++        sed "s/^/$submenu_indentation/" << EOF
++	echo	'$(echo "$message" | grub_quote)'
++EOF
++      fi
++      sed "s/^/$submenu_indentation/" << EOF
++	devicetree	${rel_dirname}/${dtb}
++EOF
++    fi
+   fi
+   sed "s/^/$submenu_indentation/" << EOF
+ }
+@@ -389,6 +400,14 @@ while [ "x$list" != "x" ] ; do
+     gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
+   fi
+ 
++  dtb=
++  for i in "dtb-${version}" "dtb-${alt_version}" "dtb"; do
++    if test -e "${dirname}/${i}" ; then
++      dtb="$i"
++      break
++    fi
++  done
++
+   config=
+   for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
+     if test -e "${i}" ; then
diff --git a/debian/patches/ubuntu-add-initrd-less-boot-fallback.patch b/debian/patches/ubuntu-add-initrd-less-boot-fallback.patch
new file mode 100644
index 0000000..e734a87
--- /dev/null
+++ b/debian/patches/ubuntu-add-initrd-less-boot-fallback.patch
@@ -0,0 +1,213 @@
+From 978947c3f5d769ee423c73418783ec4ef8f7ab3b Mon Sep 17 00:00:00 2001
+From: Chris Glass <chris.glass@canonical.com>
+Date: Fri, 9 Mar 2018 13:47:07 +0100
+Subject: UBUNTU: Added initrd-less boot capabilities.
+
+In case the kernel fails to boot without an initrd, grub will fallback
+to trying to boot the kernel with an initrd.
+
+Signed-off-by: Steve Langasek <steve.langasek@canonical.com>
+
+Patch-Name: ubuntu-add-initrd-less-boot-fallback.patch
+---
+ Makefile.am                  |  3 ++
+ configure.ac                 | 10 ++++++
+ grub-initrd-fallback.service | 12 +++++++
+ util/grub.d/00_header.in     | 27 ++++++++++++++
+ util/grub.d/10_linux.in      | 68 +++++++++++++++++++++++++++---------
+ 5 files changed, 104 insertions(+), 16 deletions(-)
+ create mode 100644 grub-initrd-fallback.service
+
+diff --git a/Makefile.am b/Makefile.am
+index 1f4bb9b8c5..e6a220711e 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -473,6 +473,9 @@ ChangeLog: FORCE
+ 		touch $@; \
+ 	fi
+ 
++systemdsystemunit_DATA = \
++	grub-initrd-fallback.service
++
+ EXTRA_DIST += ChangeLog ChangeLog-2015
+ 
+ syslinux_test: $(top_builddir)/config.status tests/syslinux/ubuntu10.04_grub.cfg
+diff --git a/configure.ac b/configure.ac
+index 883245553d..1819188f9f 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -305,6 +305,16 @@ AC_SUBST(grubdirname)
+ AC_DEFINE_UNQUOTED(GRUB_DIR_NAME, "$grubdirname",
+     [Default grub directory name])
+ 
++##### systemd unit files
++AC_ARG_WITH([systemdsystemunitdir],
++            AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
++            [],
++            [with_systemdsystemunitdir=/usr/lib/systemd/system],
++            [with_systemdsystemunitdir=no])
++if test "x$with_systemdsystemunitdir" != xno; then
++   AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
++fi
++
+ #
+ # Checks for build programs.
+ #
+diff --git a/grub-initrd-fallback.service b/grub-initrd-fallback.service
+new file mode 100644
+index 0000000000..48778c9f76
+--- /dev/null
++++ b/grub-initrd-fallback.service
+@@ -0,0 +1,12 @@
++[Unit]
++Description=GRUB failed boot detection
++After=local-fs.target
++
++[Service]
++Type=oneshot
++ExecStart=/usr/bin/grub-editenv /boot/grub/grubenv unset initrdfail
++ExecStart=/usr/bin/grub-editenv /boot/grub/grubenv unset prev_entry
++TimeoutSec=0
++
++[Install]
++WantedBy=multi-user.target rescue.target emergency.target
+diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
+index b7135b655f..2642f66c59 100644
+--- a/util/grub.d/00_header.in
++++ b/util/grub.d/00_header.in
+@@ -50,6 +50,18 @@ if [ -s \$prefix/grubenv ]; then
+   load_env
+ fi
+ EOF
++cat <<EOF
++if [ "\${initrdfail}" = 2 ]; then
++   set initrdfail=
++elif [ "\${initrdfail}" = 1 ]; then
++   set next_entry="\${prev_entry}"
++   set prev_entry=
++   save_env prev_entry
++   if [ "\${next_entry}" ]; then
++      set initrdfail=2
++   fi
++fi
++EOF
+ if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ]; then
+     cat <<EOF
+ if cmostest $GRUB_BUTTON_CMOS_ADDRESS ; then
+@@ -101,6 +113,21 @@ function savedefault {
+ }
+ EOF
+ 
++cat <<"EOF"
++function initrdfail {
++    if [ -n "${have_grubenv}" ]; then if [ -n "${partuuid}" ]; then
++      if [ -z "${initrdfail}" ]; then
++        set initrdfail=1
++        if [ -n "${boot_once}" ]; then
++          set prev_entry="${default}"
++          save_env prev_entry
++        fi
++      fi
++      save_env initrdfail
++    fi; fi
++}
++EOF
++
+ if [ "$quick_boot" = 1 ]; then
+     cat <<EOF
+ function recordfail {
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index aa9666e5ad..af1e096bd6 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -118,6 +118,10 @@ if [ "$vt_handoff" = 1 ]; then
+   done
+ fi
+ 
++if [ x"$GRUB_FORCE_PARTUUID" != x ]; then
++   echo "set partuuid=${GRUB_FORCE_PARTUUID}"
++fi
++
+ linux_entry ()
+ {
+   os="$1"
+@@ -193,31 +197,63 @@ EOF
+ 	linux	${rel_dirname}/${basename}.efi.signed root=${linux_root_device_thisversion} ro ${args}
+ EOF
+   else
+-    if [ x"$GRUB_FORCE_PARTUUID" = x ]; then
++    # We have initrd and PARTUUID is set - we try to boot without initrd, and fallback to using it
++    # if it fails.
++    # "panic=-1" means "on panic reboot immediately". "panic=0" disables the reboot behavior.
++    if [ x"$GRUB_FORCE_PARTUUID" != x ]; then
++        linux_root_device_thisversion="PARTUUID=${GRUB_FORCE_PARTUUID}"
++    fi
++    message="$(gettext_printf "Loading initial ramdisk ...")"
++    initrd_path=
++    for i in ${initrd}; do
++        initrd_path="${initrd_path} ${rel_dirname}/${i}"
++    done
++    initrd_path_only_early=
++    for i in ${initrd_early}; do
++        initrd_path_only_early="${initrd_path_only_early} ${rel_dirname}/${i}"
++    done
++    if test -n "${initrd}" && [ x"$GRUB_FORCE_PARTUUID" != x ]; then
++        sed "s/^/$submenu_indentation/" << EOF
++	if [ "\${initrdfail}" = 1 ]; then
++	  linux	${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
++EOF
++        if [ x"$quiet_boot" = x0 ] || [ x"$type" != xsimple ]; then
++          sed "s/^/$submenu_indentation/" << EOF
++	  echo	'$(echo "$message" | grub_quote)'
++EOF
++        fi
+         sed "s/^/$submenu_indentation/" << EOF
+-        linux	${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
++	  initrd	$(echo $initrd_path)
++	else
++	  linux	${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} panic=-1
++EOF
++        if [ -n "$initrd_path_only_early" ]; then
++          sed "s/^/$submenu_indentation/" << EOF
++	  initrd	$(echo $initrd_path_only_early)
++EOF
++        fi
++        sed "s/^/$submenu_indentation/" << EOF
++	fi
++	initrdfail
+ EOF
+     else
++    # We don't have initrd or we don't want to set PARTUUID. Don't try initrd-less boot with fallback.
+         sed "s/^/$submenu_indentation/" << EOF
+-        linux	${rel_dirname}/${basename} root=PARTUUID=${GRUB_FORCE_PARTUUID} ro ${args}
++	linux	${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
+ EOF
+-    fi
+-  fi
+-  if test -n "${initrd}" && [ x"$GRUB_DISABLE_INITRD" != xtrue ]; then
+-    # TRANSLATORS: ramdisk isn't identifier. Should be translated.
+-    if [ x"$quiet_boot" = x0 ] || [ x"$type" != xsimple ]; then
+-      message="$(gettext_printf "Loading initial ramdisk ...")"
+-      sed "s/^/$submenu_indentation/" << EOF
++        if test -n "${initrd}"; then
++            # We do have initrd - let's use it at boot.
++            # TRANSLATORS: ramdisk isn't identifier. Should be translated.
++            if [ x"$quiet_boot" = x0 ] || [ x"$type" != xsimple ]; then
++              sed "s/^/$submenu_indentation/" << EOF
+ 	echo	'$(echo "$message" | grub_quote)'
+ EOF
+-    fi
+-    initrd_path=
+-    for i in ${initrd}; do
+-      initrd_path="${initrd_path} ${rel_dirname}/${i}"
+-    done
+-    sed "s/^/$submenu_indentation/" << EOF
++            fi
++            sed "s/^/$submenu_indentation/" << EOF
+ 	initrd	$(echo $initrd_path)
+ EOF
++        fi
++    fi
+   fi
+   sed "s/^/$submenu_indentation/" << EOF
+ }
diff --git a/debian/patches/ubuntu-add-initrd-less-boot-messages.patch b/debian/patches/ubuntu-add-initrd-less-boot-messages.patch
new file mode 100644
index 0000000..188bb69
--- /dev/null
+++ b/debian/patches/ubuntu-add-initrd-less-boot-messages.patch
@@ -0,0 +1,56 @@
+From 50b137848fd25a580fcd76760802af16e4e961fa Mon Sep 17 00:00:00 2001
+From: Dimitri John Ledkov <xnox@ubuntu.com>
+Date: Mon, 26 Oct 2020 11:38:34 +0000
+Subject: Ubuntu: add initrd-less-boot informational messages
+
+Add additional messages when initrd-less boot is attempted or
+fails. As otherwise it is not obvious why boot seems to panic and
+reboot by default.
+
+Patch-Name: ubuntu-add-initrd-less-boot-messages.patch
+---
+ util/grub.d/10_linux.in | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 49e627228f..47daf51eed 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -160,6 +160,12 @@ if [ "$vt_handoff" = 1 ]; then
+ fi
+ 
+ if [ x"$GRUB_FORCE_PARTUUID" != x ]; then
++    gettext_printf "GRUB_FORCE_PARTUUID is set, will attempt initrdless boot\n" >&2
++    cat << EOF
++#
++# GRUB_FORCE_PARTUUID is set, will attempt initrdless boot
++# Upon panic fallback to booting with initrd
++EOF
+    echo "set partuuid=${GRUB_FORCE_PARTUUID}"
+ fi
+ 
+@@ -245,6 +251,8 @@ EOF
+         linux_root_device_thisversion="PARTUUID=${GRUB_FORCE_PARTUUID}"
+     fi
+     message="$(gettext_printf "Loading initial ramdisk ...")"
++    initrdlessfail_msg="$(gettext_printf "GRUB_FORCE_PARTUUID set, initrdless boot failed. Attempting with initrd.")"
++    initrdlesstry_msg="$(gettext_printf "GRUB_FORCE_PARTUUID set, attempting initrdless boot.")"
+     initrd_path=
+     for i in ${initrd}; do
+         initrd_path="${initrd_path} ${rel_dirname}/${i}"
+@@ -256,6 +264,7 @@ EOF
+     if test -n "${initrd}" && [ x"$GRUB_FORCE_PARTUUID" != x ]; then
+         sed "s/^/$submenu_indentation/" << EOF
+ 	if [ "\${initrdfail}" = 1 ]; then
++	  echo	'$(echo "$initrdlessfail_msg" | grub_quote)'
+ 	  linux	${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
+ EOF
+         if [ x"$quiet_boot" = x0 ] || [ x"$type" != xsimple ]; then
+@@ -266,6 +275,7 @@ EOF
+         sed "s/^/$submenu_indentation/" << EOF
+ 	  initrd	$(echo $initrd_path)
+ 	else
++	  echo	'$(echo "$initrdlesstry_msg" | grub_quote)'
+ 	  linux	${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} panic=-1
+ EOF
+         if [ -n "$initrd_path_only_early" ]; then
diff --git a/debian/patches/ubuntu-boot-from-multipath-dependent-symlink.patch b/debian/patches/ubuntu-boot-from-multipath-dependent-symlink.patch
new file mode 100644
index 0000000..5e19f72
--- /dev/null
+++ b/debian/patches/ubuntu-boot-from-multipath-dependent-symlink.patch
@@ -0,0 +1,69 @@
+From c51cc4664ac67fcd7c3177ea6c6dd0d2c06c43e6 Mon Sep 17 00:00:00 2001
+From: Michael Hudson-Doyle <michael.hudson@canonical.com>
+Date: Tue, 6 Aug 2019 12:31:47 +1200
+Subject: UBUNTU: Boot from multipath-dependent symlink when / is multipathed.
+
+If / is multipathed, there will be multiple paths to the partition, so
+using root=UUID= exposes the boot process to udev races. In addition
+grub-probe --target device / in this case reports /dev/dm-1 or similar
+-- better to use a symlink that depends on the multipath name.
+
+Signed-off-by: Michael Hudson-Doyle <michael.hudson@ubuntu.com>
+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1429327
+Patch-Name: ubuntu-boot-from-multipath-dependent-symlink.patch
+---
+ util/grub.d/10_linux.in | 41 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 41 insertions(+)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index bbf5d73e39..14a89ba13d 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -65,6 +65,47 @@ esac
+ # older kernels.
+ GRUB_DISABLE_LINUX_PARTUUID=${GRUB_DISABLE_LINUX_PARTUUID-true}
+ 
++# get_dm_field_for_dev /dev/dm-0 uuid -> get the device mapper UUID for /dev/dm-0
++# get_dm_field_for_dev /dev/dm-1 name -> get the device mapper name for /dev/dm-1
++# etc
++get_dm_field_for_dev () {
++    dmsetup info -c --noheadings -o $2 $1 2>/dev/null
++}
++
++# Is $1 a multipath device?
++is_multipath () {
++    local dmuuid dmtype
++    dmuuid="$(get_dm_field_for_dev $1 uuid)"
++    if [ $? -ne 0 ]; then
++        # Not a device mapper device -- or dmsetup not installed, and as
++        # multipath depends on kpartx which depends on dmsetup, if there is no
++        # dmsetup then there are not going to be any multipath devices.
++        return 1
++    fi
++    # A device mapper "uuid" is always <type>-<uuid>. If <type> is of the form
++    # part[0-9] then <uuid> is the device the partition is on and we want to
++    # look at that instead. A multipath node always has <type> of mpath.
++    dmtype="${dmuuid%%-*}"
++    if [ "${dmtype#part}" != "$dmtype" ]; then
++        dmuuid="${dmuuid#*-}"
++        dmtype="${dmuuid%%-*}"
++    fi
++    if [ "$dmtype" = "mpath" ]; then
++        return 0
++    else
++        return 1
++    fi
++}
++
++if test -e "${GRUB_DEVICE}" && is_multipath "${GRUB_DEVICE}"; then
++    # If / is multipathed, there will be multiple paths to the partition, so
++    # using root=UUID= exposes the boot process to udev races. In addition
++    # GRUB_DEVICE in this case will be /dev/dm-0 or similar -- better to use a
++    # symlink that depends on the multipath name.
++    GRUB_DEVICE=/dev/mapper/"$(get_dm_field_for_dev $GRUB_DEVICE name)"
++    GRUB_DISABLE_LINUX_UUID=true
++fi
++
+ # 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_DEVICE_PARTUUID}" = "x" ] ) \
diff --git a/debian/patches/ubuntu-dejavu-font-path.patch b/debian/patches/ubuntu-dejavu-font-path.patch
new file mode 100644
index 0000000..1faea8d
--- /dev/null
+++ b/debian/patches/ubuntu-dejavu-font-path.patch
@@ -0,0 +1,25 @@
+From 26335cb229a6b969449f80dc6c5aed949ee1d86c Mon Sep 17 00:00:00 2001
+From: Dimitri John Ledkov <xnox@ubuntu.com>
+Date: Mon, 14 Sep 2020 10:51:32 +0100
+Subject: configure.ac: one more dejavu font search path
+
+Debian/Ubuntu ship dejavu font in a subdir of truetype.
+
+Patch-Name: ubuntu-dejavu-font-path.patch
+---
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/configure.ac b/configure.ac
+index 6a88b9b0c0..fae9171022 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1671,7 +1671,7 @@ fi
+ 
+ if test x"$starfield_excuse" = x; then
+    for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do
+-     for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype; do
++     for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype /usr/share/fonts/truetype/dejavu; do
+         if test -f "$dir/DejaVuSans.$ext"; then
+           DJVU_FONT_SOURCE="$dir/DejaVuSans.$ext"
+           break 2
diff --git a/debian/patches/ubuntu-dont-verify-loopback-images.patch b/debian/patches/ubuntu-dont-verify-loopback-images.patch
new file mode 100644
index 0000000..d5a2a29
--- /dev/null
+++ b/debian/patches/ubuntu-dont-verify-loopback-images.patch
@@ -0,0 +1,37 @@
+From 7cb405298d3729d88b4e4ebc46ca1fc9b644bd6b Mon Sep 17 00:00:00 2001
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Mon, 1 Jun 2020 14:03:37 +0100
+Subject: UBUNTU: disk/loopback: Don't verify loopback images
+
+When a file is verified, the entire contents of the verified file are
+loaded in to memory and retained until the file handle is closed. A
+consequence of this is that opening a loopback image can incur a
+significant memory cost.
+
+As loopback devices are just another disk implementation, don't treat
+loopback images any differently to physical disk images, and skip
+verification of them. Files opened from the filesystem within a loopback
+image will still be passed to verifier modules where required.
+
+Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
+LP: #1878541
+Forwarded: yes, https://lists.gnu.org/archive/html/grub-devel/2020-06/msg00002.html
+Patch-Name: ubuntu-dont-verify-loopback-images.patch
+---
+ grub-core/disk/loopback.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c
+index ccb4b167cc..210201d22d 100644
+--- a/grub-core/disk/loopback.c
++++ b/grub-core/disk/loopback.c
+@@ -86,7 +86,8 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args)
+     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+ 
+   file = grub_file_open (args[1], GRUB_FILE_TYPE_LOOPBACK
+-			 | GRUB_FILE_TYPE_NO_DECOMPRESS);
++			 | GRUB_FILE_TYPE_NO_DECOMPRESS |
++			 GRUB_FILE_TYPE_SKIP_SIGNATURE);
+   if (! file)
+     return grub_errno;
+ 
diff --git a/debian/patches/ubuntu-efi-allow-loopmount-chainload.patch b/debian/patches/ubuntu-efi-allow-loopmount-chainload.patch
new file mode 100644
index 0000000..ecc94e8
--- /dev/null
+++ b/debian/patches/ubuntu-efi-allow-loopmount-chainload.patch
@@ -0,0 +1,127 @@
+From aa08be99df3978b44838e60f571fc965d9d963c4 Mon Sep 17 00:00:00 2001
+From: Dimitri John Ledkov <xnox@ubuntu.com>
+Date: Wed, 27 Nov 2019 23:12:35 +0000
+Subject: UBUNTU: Allow chainloading EFI apps from loop mounts.
+
+Proposed at https://github.com/rhboot/grub2/pull/65.patch
+
+Signed-off-by: Dimitri John Ledkov <xnox@ubuntu.com>
+Patch-Name: ubuntu-efi-allow-loopmount-chainload.patch
+---
+ grub-core/disk/loopback.c          |  9 +--------
+ grub-core/loader/efi/chainloader.c | 17 +++++++++++++++++
+ include/grub/loopback.h            | 30 ++++++++++++++++++++++++++++++
+ 3 files changed, 48 insertions(+), 8 deletions(-)
+ create mode 100644 include/grub/loopback.h
+
+diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c
+index cdf9123fa5..ccb4b167cc 100644
+--- a/grub-core/disk/loopback.c
++++ b/grub-core/disk/loopback.c
+@@ -21,20 +21,13 @@
+ #include <grub/misc.h>
+ #include <grub/file.h>
+ #include <grub/disk.h>
++#include <grub/loopback.h>
+ #include <grub/mm.h>
+ #include <grub/extcmd.h>
+ #include <grub/i18n.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+-struct grub_loopback
+-{
+-  char *devname;
+-  grub_file_t file;
+-  struct grub_loopback *next;
+-  unsigned long id;
+-};
+-
+ static struct grub_loopback *loopback_list;
+ static unsigned long last_id = 0;
+ 
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index ec80f415b8..04e815c052 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -24,6 +24,7 @@
+ #include <grub/err.h>
+ #include <grub/device.h>
+ #include <grub/disk.h>
++#include <grub/loopback.h>
+ #include <grub/misc.h>
+ #include <grub/charset.h>
+ #include <grub/mm.h>
+@@ -889,6 +890,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   grub_efi_status_t status;
+   grub_efi_boot_services_t *b;
+   grub_device_t dev = 0;
++  grub_device_t orig_dev = 0;
+   grub_efi_device_path_t *dp = 0;
+   char *filename;
+   void *boot_image = 0;
+@@ -946,6 +948,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   if (! dev)
+     goto fail;
+ 
++  /* if device is loopback, use underlying dev */
++  if (dev->disk->dev->id == GRUB_DISK_DEVICE_LOOPBACK_ID)
++    {
++      struct grub_loopback *d;
++      orig_dev = dev;
++      d = dev->disk->data;
++      dev = d->file->device;
++    }
++
+   if (dev->disk)
+     dev_handle = grub_efidisk_get_device_handle (dev->disk);
+   else if (dev->net && dev->net->server)
+@@ -1075,6 +1086,12 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   grub_device_close (dev);
+ 
+ fail:
++  if (orig_dev)
++    {
++      dev = orig_dev;
++      orig_dev = 0;
++    }
++
+   if (dev)
+     grub_device_close (dev);
+ 
+diff --git a/include/grub/loopback.h b/include/grub/loopback.h
+new file mode 100644
+index 0000000000..3b9a9e32e8
+--- /dev/null
++++ b/include/grub/loopback.h
+@@ -0,0 +1,30 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2019  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_LOOPBACK_HEADER
++#define GRUB_LOOPBACK_HEADER	1
++
++struct grub_loopback
++{
++  char *devname;
++  grub_file_t file;
++  struct grub_loopback *next;
++  unsigned long id;
++};
++
++#endif /* ! GRUB_LOOPBACK_HEADER */
diff --git a/debian/patches/ubuntu-efi-console-set-text-mode-as-needed.patch b/debian/patches/ubuntu-efi-console-set-text-mode-as-needed.patch
new file mode 100644
index 0000000..7d117b7
--- /dev/null
+++ b/debian/patches/ubuntu-efi-console-set-text-mode-as-needed.patch
@@ -0,0 +1,197 @@
+From a097dd966d2a0073a3f2f30f868fae351b74fda4 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Tue, 6 Mar 2018 17:11:15 +0100
+Subject: UBUNTU: EFI: Do not set text-mode until we actually need it
+
+If we're running with a hidden menu we may never need text mode, so do not
+change the video-mode to text until we actually need it.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+
+Last-Update: 2019-03-06
+Patch-Name: ubuntu-efi-console-set-text-mode-as-needed.patch
+---
+ grub-core/term/efi/console.c | 68 ++++++++++++++++++++++++------------
+ 1 file changed, 45 insertions(+), 23 deletions(-)
+
+diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c
+index 4840cc59d3..b61da7d0d0 100644
+--- a/grub-core/term/efi/console.c
++++ b/grub-core/term/efi/console.c
+@@ -24,6 +24,11 @@
+ #include <grub/efi/api.h>
+ #include <grub/efi/console.h>
+ 
++static grub_err_t grub_prepare_for_text_output(struct grub_term_output *term);
++
++static int text_mode_available = -1;
++static int text_colorstate = -1;
++
+ static grub_uint32_t
+ map_char (grub_uint32_t c)
+ {
+@@ -66,14 +71,14 @@ map_char (grub_uint32_t c)
+ }
+ 
+ static void
+-grub_console_putchar (struct grub_term_output *term __attribute__ ((unused)),
++grub_console_putchar (struct grub_term_output *term,
+ 		      const struct grub_unicode_glyph *c)
+ {
+   grub_efi_char16_t str[2 + 30];
+   grub_efi_simple_text_output_interface_t *o;
+   unsigned i, j;
+ 
+-  if (grub_efi_is_finished)
++  if (grub_prepare_for_text_output (term))
+     return;
+ 
+   o = grub_efi_system_table->con_out;
+@@ -223,14 +228,15 @@ grub_console_getkey (struct grub_term_input *term)
+ }
+ 
+ static struct grub_term_coordinate
+-grub_console_getwh (struct grub_term_output *term __attribute__ ((unused)))
++grub_console_getwh (struct grub_term_output *term)
+ {
+   grub_efi_simple_text_output_interface_t *o;
+   grub_efi_uintn_t columns, rows;
+ 
+   o = grub_efi_system_table->con_out;
+-  if (grub_efi_is_finished || efi_call_4 (o->query_mode, o, o->mode->mode,
+-					  &columns, &rows) != GRUB_EFI_SUCCESS)
++  if (grub_prepare_for_text_output (term) != GRUB_ERR_NONE ||
++      efi_call_4 (o->query_mode, o, o->mode->mode,
++		  &columns, &rows) != GRUB_EFI_SUCCESS)
+     {
+       /* Why does this fail?  */
+       columns = 80;
+@@ -245,7 +251,7 @@ grub_console_getxy (struct grub_term_output *term __attribute__ ((unused)))
+ {
+   grub_efi_simple_text_output_interface_t *o;
+ 
+-  if (grub_efi_is_finished)
++  if (grub_efi_is_finished || text_mode_available != 1)
+     return (struct grub_term_coordinate) { 0, 0 };
+ 
+   o = grub_efi_system_table->con_out;
+@@ -253,12 +259,12 @@ grub_console_getxy (struct grub_term_output *term __attribute__ ((unused)))
+ }
+ 
+ static void
+-grub_console_gotoxy (struct grub_term_output *term __attribute__ ((unused)),
++grub_console_gotoxy (struct grub_term_output *term,
+ 		     struct grub_term_coordinate pos)
+ {
+   grub_efi_simple_text_output_interface_t *o;
+ 
+-  if (grub_efi_is_finished)
++  if (grub_prepare_for_text_output (term))
+     return;
+ 
+   o = grub_efi_system_table->con_out;
+@@ -271,7 +277,7 @@ grub_console_cls (struct grub_term_output *term __attribute__ ((unused)))
+   grub_efi_simple_text_output_interface_t *o;
+   grub_efi_int32_t orig_attr;
+ 
+-  if (grub_efi_is_finished)
++  if (grub_efi_is_finished || text_mode_available != 1)
+     return;
+ 
+   o = grub_efi_system_table->con_out;
+@@ -282,8 +288,7 @@ grub_console_cls (struct grub_term_output *term __attribute__ ((unused)))
+ }
+ 
+ static void
+-grub_console_setcolorstate (struct grub_term_output *term
+-			    __attribute__ ((unused)),
++grub_console_setcolorstate (struct grub_term_output *term __attribute__ ((unused)),
+ 			    grub_term_color_state state)
+ {
+   grub_efi_simple_text_output_interface_t *o;
+@@ -291,6 +296,12 @@ grub_console_setcolorstate (struct grub_term_output *term
+   if (grub_efi_is_finished)
+     return;
+ 
++  if (text_mode_available != 1) {
++    /* Avoid "color_normal" environment writes causing a switch to textmode */
++    text_colorstate = state;
++    return;
++  }
++
+   o = grub_efi_system_table->con_out;
+ 
+   switch (state) {
+@@ -315,7 +326,7 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
+ {
+   grub_efi_simple_text_output_interface_t *o;
+ 
+-  if (grub_efi_is_finished)
++  if (grub_efi_is_finished || text_mode_available != 1)
+     return;
+ 
+   o = grub_efi_system_table->con_out;
+@@ -323,18 +334,38 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
+ }
+ 
+ static grub_err_t
+-grub_efi_console_output_init (struct grub_term_output *term)
++grub_prepare_for_text_output(struct grub_term_output *term)
+ {
+-  grub_efi_set_text_mode (1);
++  if (grub_efi_is_finished)
++    return GRUB_ERR_BAD_DEVICE;
++
++  if (text_mode_available != -1)
++    return text_mode_available ? 0 : GRUB_ERR_BAD_DEVICE;
++
++  if (! grub_efi_set_text_mode (1))
++    {
++      /* This really should never happen */
++      grub_error (GRUB_ERR_BAD_DEVICE, "cannot set text mode");
++      text_mode_available = 0;
++      return GRUB_ERR_BAD_DEVICE;
++    }
++
+   grub_console_setcursor (term, 1);
++  if (text_colorstate != -1)
++    grub_console_setcolorstate (term, text_colorstate);
++  text_mode_available = 1;
+   return 0;
+ }
+ 
+ static grub_err_t
+ grub_efi_console_output_fini (struct grub_term_output *term)
+ {
++  if (text_mode_available != 1)
++    return 0;
++
+   grub_console_setcursor (term, 0);
+   grub_efi_set_text_mode (0);
++  text_mode_available = -1;
+   return 0;
+ }
+ 
+@@ -348,7 +379,6 @@ static struct grub_term_input grub_console_term_input =
+ static struct grub_term_output grub_console_term_output =
+   {
+     .name = "console",
+-    .init = grub_efi_console_output_init,
+     .fini = grub_efi_console_output_fini,
+     .putchar = grub_console_putchar,
+     .getwh = grub_console_getwh,
+@@ -364,14 +394,6 @@ static struct grub_term_output grub_console_term_output =
+ void
+ grub_console_init (void)
+ {
+-  /* FIXME: it is necessary to consider the case where no console control
+-     is present but the default is already in text mode.  */
+-  if (! grub_efi_set_text_mode (1))
+-    {
+-      grub_error (GRUB_ERR_BAD_DEVICE, "cannot set text mode");
+-      return;
+-    }
+-
+   grub_term_register_output ("console", &grub_console_term_output);
+   grub_term_register_input ("console", &grub_console_term_input);
+ }
diff --git a/debian/patches/ubuntu-fix-lzma-decompressor-objcopy.patch b/debian/patches/ubuntu-fix-lzma-decompressor-objcopy.patch
new file mode 100644
index 0000000..66834d3
--- /dev/null
+++ b/debian/patches/ubuntu-fix-lzma-decompressor-objcopy.patch
@@ -0,0 +1,30 @@
+From a0fdddf679ce3ac17b6de7a5c01c99ab598056ce Mon Sep 17 00:00:00 2001
+From: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
+Date: Wed, 3 Jul 2019 15:21:16 -0400
+Subject: UBUNTU: Have the lzma decompressor image only contain the .text
+ section
+
+Previously binutils/objcopy did that correctly, now it seems to be padding to
+an arbitrary size with zeros. Work around this broken by being explicit about
+what we want.
+
+Patch-Name: ubuntu-fix-lzma-decompressor-objcopy.patch
+
+Signed-off-by: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
+---
+ grub-core/Makefile.core.def | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 1731c53f08..33e75021da 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -547,7 +547,7 @@ image = {
+   i386_pc = boot/i386/pc/startup_raw.S;
+   i386_pc_nodist = rs_decoder.h;
+ 
+-  objcopyflags = '-O binary';
++  objcopyflags = '-O binary -j .text';
+   ldflags = '$(TARGET_IMG_LDFLAGS) $(TARGET_IMG_BASE_LDOPT),0x8200';
+   enable = i386_pc;
+ };
diff --git a/debian/patches/ubuntu-flavour-order.patch b/debian/patches/ubuntu-flavour-order.patch
new file mode 100644
index 0000000..30cc2bb
--- /dev/null
+++ b/debian/patches/ubuntu-flavour-order.patch
@@ -0,0 +1,61 @@
+From 8f4642af583c253259e8ca40d8aff776976d8d5d Mon Sep 17 00:00:00 2001
+From: Julian Andres Klode <julian.klode@canonical.com>
+Date: Tue, 9 Jun 2020 11:50:23 +0200
+Subject: UBUNTU: Add GRUB_FLAVOUR_ORDER configuration item
+
+This allows you to specify flavours that will be preferred
+over other ones, and the order in which they are preferred
+- items in the list win over items not in the list, and items
+earlier in the list win over later ones.
+
+We still have to sort out storage of this, as we need to
+inject that from packages or the UA client and similar,
+and we can't just modify /etc/default/grub for that.
+
+LP: #1882663
+Patch-Name: ubuntu-flavour-order.patch
+---
+ util/grub-mkconfig.in     |  3 ++-
+ util/grub-mkconfig_lib.in | 15 +++++++++++++++
+ 2 files changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index 72f1e25a03..6c8988fd60 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -260,7 +260,8 @@ export GRUB_DEFAULT \
+   GRUB_RECORDFAIL_TIMEOUT \
+   GRUB_RECOVERY_TITLE \
+   GRUB_FORCE_PARTUUID \
+-  GRUB_DISABLE_INITRD
++  GRUB_DISABLE_INITRD \
++  GRUB_FLAVOUR_ORDER
+ 
+ if test "x${grub_cfg}" != "x"; then
+   rm -f "${grub_cfg}.new"
+diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
+index fe6319abe0..7e2d1bc214 100644
+--- a/util/grub-mkconfig_lib.in
++++ b/util/grub-mkconfig_lib.in
+@@ -270,6 +270,21 @@ version_test_gt ()
+   if [ "x$version_test_gt_b" = "x" ] ; then
+     return 0
+   fi
++
++  # GRUB_FLAVOUR_ORDER is an ordered list of kernels, in decreasing
++  # priority. Any items in the list take precedence over other kernels,
++  # and earlier flavours are preferred over later ones.
++  for flavour in ${GRUB_FLAVOUR_ORDER:-}; do
++    version_test_gt_a_preferred=$(echo "$version_test_gt_a" | grep --  "-[0-9]*-$flavour\$")
++    version_test_gt_b_preferred=$(echo "$version_test_gt_b" | grep --  "-[0-9]*-$flavour\$")
++
++    if [ -n "$version_test_gt_a_preferred" -a -z "$version_test_gt_b_preferred" ] ; then
++      return 0
++    elif [ -z "$version_test_gt_a_preferred" -a -n "$version_test_gt_b_preferred" ] ; then
++      return 1
++    fi
++  done
++
+   case "$version_test_gt_a:$version_test_gt_b" in
+     *.old:*.old) ;;
+     *.old:*) version_test_gt_a="`echo "$version_test_gt_a" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=gt ;;
diff --git a/debian/patches/grub-install-extra-removable.patch b/debian/patches/ubuntu-grub-install-extra-removable.patch
similarity index 65%
rename from debian/patches/grub-install-extra-removable.patch
rename to debian/patches/ubuntu-grub-install-extra-removable.patch
index ff713cd..d01763e 100644
--- a/debian/patches/grub-install-extra-removable.patch
+++ b/debian/patches/ubuntu-grub-install-extra-removable.patch
@@ -1,35 +1,36 @@
-From 904799066563906ca3650c234b3b0a590b52b1ab Mon Sep 17 00:00:00 2001
+From 42b10df3ba7aff3f58b32cd43a0075a677fa8143 Mon Sep 17 00:00:00 2001
 From: Steve McIntyre <93sam@debian.org>
 Date: Wed, 3 Dec 2014 01:25:12 +0000
-Subject: Add support for forcing EFI installation to the removable media path
+Subject: UBUNTU: Add support for forcing EFI installation to the removable
+ media path
 
-Add an extra option to grub-install "--force-extra-removable". On EFI
-platforms, this will cause an extra copy of the grub-efi image to be
-written to the appropriate removable media patch
-/boot/efi/EFI/BOOT/BOOT$ARCH.EFI as well. This will help with broken
-UEFI implementations where the firmware does not work when configured
-with new boot paths.
+Add an extra option to grub-install "--no-extra-removable". On EFI
+platforms, this will cause the copy of the grub-efi image to not be
+written to the removable media path /boot/efi/EFI/BOOT/BOOT$ARCH.EFI.
+This will help with broken UEFI implementations where you can't install
+to the removable path as a fallback option if Boot Entries get corrupt.
 
 Signed-off-by: Steve McIntyre <93sam@debian.org>
+Signed-off-by: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
 
 Bug-Debian: https://bugs.debian.org/767037 https://bugs.debian.org/773092
 Forwarded: Not yet
 Last-Update: 2014-12-20
 
-Patch-Name: grub-install-extra-removable.patch
+Patch-Name: ubuntu-grub-install-extra-removable.patch
 ---
- util/grub-install.c | 110 +++++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 108 insertions(+), 2 deletions(-)
+ util/grub-install.c | 135 +++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 133 insertions(+), 2 deletions(-)
 
 diff --git a/util/grub-install.c b/util/grub-install.c
-index f511cfc72..5f3217ae4 100644
+index 64c292383f..0304646453 100644
 --- a/util/grub-install.c
 +++ b/util/grub-install.c
 @@ -56,6 +56,7 @@
  
  static char *target;
  static int removable = 0;
-+static int force_extra_removable = 0;
++static int no_extra_removable = 0;
  static int recheck = 0;
  static int update_nvram = 1;
  static char *install_device = NULL;
@@ -39,7 +40,7 @@ index f511cfc72..5f3217ae4 100644
      OPTION_UEFI_SECURE_BOOT,
 -    OPTION_NO_UEFI_SECURE_BOOT
 +    OPTION_NO_UEFI_SECURE_BOOT,
-+    OPTION_FORCE_EXTRA_REMOVABLE
++    OPTION_NO_EXTRA_REMOVABLE
    };
  
  static int fs_probe = 1;
@@ -47,8 +48,8 @@ index f511cfc72..5f3217ae4 100644
        removable = 1;
        return 0;
  
-+    case OPTION_FORCE_EXTRA_REMOVABLE:
-+      force_extra_removable = 1;
++    case OPTION_NO_EXTRA_REMOVABLE:
++      no_extra_removable = 1;
 +      return 0;
 +
      case OPTION_ALLOW_FLOPPY:
@@ -58,13 +59,13 @@ index f511cfc72..5f3217ae4 100644
     N_("do not install an image usable with UEFI Secure Boot, even if the "
        "system was currently started using it. "
        "This option is only available on EFI."), 2},
-+  {"force-extra-removable", OPTION_FORCE_EXTRA_REMOVABLE, 0, 0,
-+   N_("force installation to the removable media path also. "
++  {"no-extra-removable", OPTION_NO_EXTRA_REMOVABLE, 0, 0,
++   N_("Do not install bootloader code to the removable media path. "
 +      "This option is only available on EFI."), 2},
    {0, 0, 0, 0, 0, 0}
  };
  
-@@ -839,6 +848,91 @@ fill_core_services (const char *core_services)
+@@ -839,6 +848,116 @@ fill_core_services (const char *core_services)
    free (sysv_plist);
  }
  
@@ -103,16 +104,25 @@ index f511cfc72..5f3217ae4 100644
 +static void
 +also_install_removable(const char *src,
 +		       const char *base_efidir,
++		       const char *efi_suffix,
 +		       const char *efi_suffix_upper)
 +{
 +  char *efi_file = NULL;
 +  char *dst = NULL;
 +  char *cur = NULL;
 +  char *found = NULL;
++  char *fb_file = NULL;
++  char *mm_file = NULL;
++  char *generic_efidir = NULL;
 +
++  if (!efi_suffix)
++    grub_util_error ("%s", _("efi_suffix not set"));
 +  if (!efi_suffix_upper)
 +    grub_util_error ("%s", _("efi_suffix_upper not set"));
++
 +  efi_file = xasprintf ("BOOT%s.EFI", efi_suffix_upper);
++  fb_file = xasprintf ("fb%s.efi", efi_suffix);
++  mm_file = xasprintf ("mm%s.efi", efi_suffix);
 +
 +  /* We need to install in $base_efidir/EFI/BOOT/$efi_file, but we
 +   * need to cope with case-insensitive stuff here. Build the path one
@@ -134,29 +144,45 @@ index f511cfc72..5f3217ae4 100644
 +  if (found == NULL)
 +    found = xstrdup("BOOT");
 +  dst = grub_util_path_concat (2, cur, found);
-+  cur = xstrdup (dst);
-+  free (dst);
++  free (cur);
 +  free (found);
-+  grub_install_mkdir_p (cur);
++  grub_install_mkdir_p (dst);
++  generic_efidir = xstrdup (dst);
++  free (dst);
 +
 +  /* Now $efi_file */
-+  found = check_component_exists(cur, efi_file);
++  found = check_component_exists(generic_efidir, efi_file);
 +  if (found == NULL)
 +    found = xstrdup(efi_file);
-+  dst = grub_util_path_concat (2, cur, found);
-+  cur = xstrdup (dst);
-+  free (dst);
++  dst = grub_util_path_concat (2, generic_efidir, found);
 +  free (found);
-+  grub_install_copy_file (src, cur, 1);
++  grub_install_copy_file (src, dst, 1);
++  free (efi_file);
++  free (dst);
 +
-+  free (cur);
++  /* Now try to also install fallback */
++  efi_file = grub_util_path_concat (2, "/usr/lib/shim/", fb_file);
++  dst = grub_util_path_concat (2, generic_efidir, fb_file);
++  grub_install_copy_file (efi_file, dst, 0);
++  free (efi_file);
++  free (dst);
++
++  /* Also install MokManager to the removable path */
++  efi_file = grub_util_path_concat (2, "/usr/lib/shim/", mm_file);
++  dst = grub_util_path_concat (2, generic_efidir, mm_file);
++  grub_install_copy_file (efi_file, dst, 0);
 +  free (efi_file);
++  free (dst);
++
++  free (generic_efidir);
++  free (fb_file);
++  free (mm_file);
 +}
 +
  int
  main (int argc, char *argv[])
  {
-@@ -856,6 +950,7 @@ main (int argc, char *argv[])
+@@ -856,6 +975,7 @@ main (int argc, char *argv[])
    char *relative_grubdir;
    char **efidir_device_names = NULL;
    grub_device_t efidir_grub_dev = NULL;
@@ -164,17 +190,17 @@ index f511cfc72..5f3217ae4 100644
    char *efidir_grub_devname;
    int efidir_is_mac = 0;
    int is_prep = 0;
-@@ -888,6 +983,9 @@ main (int argc, char *argv[])
+@@ -888,6 +1008,9 @@ main (int argc, char *argv[])
        bootloader_id = xstrdup ("grub");
      }
  
-+  if (removable && force_extra_removable)
-+    grub_util_error (_("Invalid to use both --removable and --force_extra_removable"));
++  if (removable && no_extra_removable)
++    grub_util_error (_("Invalid to use both --removable and --no_extra_removable"));
 +
    if (!grub_install_source_directory)
      {
        if (!target)
-@@ -1107,6 +1205,8 @@ main (int argc, char *argv[])
+@@ -1107,6 +1230,8 @@ main (int argc, char *argv[])
        if (!efidir_is_mac && grub_strcmp (fs->name, "fat") != 0)
  	grub_util_error (_("%s doesn't look like an EFI partition"), efidir);
  
@@ -183,19 +209,19 @@ index f511cfc72..5f3217ae4 100644
        /* The EFI specification requires that an EFI System Partition must
  	 contain an "EFI" subdirectory, and that OS loaders are stored in
  	 subdirectories below EFI.  Vendors are expected to pick names that do
-@@ -2021,9 +2121,15 @@ main (int argc, char *argv[])
+@@ -2024,9 +2149,15 @@ main (int argc, char *argv[])
  	    fprintf (config_dst_f, "configfile $prefix/grub.cfg\n");
  	    fclose (config_dst_f);
  	    free (config_dst);
-+	    if (force_extra_removable)
-+	      also_install_removable(efi_signed, base_efidir, efi_suffix_upper);
++	    if (!removable && !no_extra_removable)
++	      also_install_removable(efi_signed, base_efidir, efi_suffix, efi_suffix_upper);
  	  }
  	else
 -	  grub_install_copy_file (imgfile, dst, 1);
 +	  {
 +	    grub_install_copy_file (imgfile, dst, 1);
-+	    if (force_extra_removable)
-+	      also_install_removable(imgfile, base_efidir, efi_suffix_upper);
++	    if (!removable && !no_extra_removable)
++	      also_install_removable(imgfile, base_efidir, efi_suffix, efi_suffix_upper);
 +	  }
  	free (dst);
        }
diff --git a/debian/patches/install-signed.patch b/debian/patches/ubuntu-install-signed.patch
similarity index 88%
rename from debian/patches/install-signed.patch
rename to debian/patches/ubuntu-install-signed.patch
index 2b4b9ca..626fedb 100644
--- a/debian/patches/install-signed.patch
+++ b/debian/patches/ubuntu-install-signed.patch
@@ -1,7 +1,7 @@
-From 299b465b171215484818bd98dea6db0913cc062d Mon Sep 17 00:00:00 2001
+From e1cc8a0711a700332db770c6e741d60ca2f9cce8 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:22 +0000
-Subject: Install signed images if UEFI Secure Boot is enabled
+Subject: UBUNTU: Install signed images if UEFI Secure Boot is enabled
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
@@ -13,13 +13,13 @@ Author: Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>
 Forwarded: no
 Last-Update: 2016-11-01
 
-Patch-Name: install-signed.patch
+Patch-Name: ubuntu-install-signed.patch
 ---
- util/grub-install.c | 212 ++++++++++++++++++++++++++++++++------------
- 1 file changed, 153 insertions(+), 59 deletions(-)
+ util/grub-install.c | 215 ++++++++++++++++++++++++++++++++------------
+ 1 file changed, 156 insertions(+), 59 deletions(-)
 
 diff --git a/util/grub-install.c b/util/grub-install.c
-index 3b4606eef..b0c7c7c37 100644
+index 3b4606eef1..e1e40cf2b5 100644
 --- a/util/grub-install.c
 +++ b/util/grub-install.c
 @@ -80,6 +80,7 @@ static char *label_color;
@@ -236,7 +236,7 @@ index 3b4606eef..b0c7c7c37 100644
  	{
  	  char *uuid = NULL;
  	  /*  generic method (used on coreboot and ata mod).  */
-@@ -1916,7 +1946,71 @@ main (int argc, char *argv[])
+@@ -1916,7 +1946,74 @@ main (int argc, char *argv[])
      case GRUB_INSTALL_PLATFORM_IA64_EFI:
        {
  	char *dst = grub_util_path_concat (2, efidir, efi_file);
@@ -244,21 +244,28 @@ index 3b4606eef..b0c7c7c37 100644
 +	if (uefi_secure_boot)
 +	  {
 +	    char *shim_signed = NULL;
-+	    char *mok_signed = NULL, *mok_file = NULL;
-+	    char *fb_signed = NULL, *fb_file = NULL;
++	    char *mok_file = NULL;
++	    char *bootcsv = NULL;
 +	    char *config_dst;
 +	    FILE *config_dst_f;
 +
 +	    shim_signed = xasprintf ("/usr/lib/shim/shim%s.efi.signed", efi_suffix);
-+	    mok_signed = xasprintf ("mm%s.efi.signed", efi_suffix);
 +	    mok_file = xasprintf ("mm%s.efi", efi_suffix);
-+	    fb_signed = xasprintf ("fb%s.efi.signed", efi_suffix);
-+	    fb_file = xasprintf ("fb%s.efi", efi_suffix);
++	    bootcsv = xasprintf ("BOOT%s.CSV", efi_suffix_upper);
 +
 +	    if (grub_util_is_regular (shim_signed))
 +	      {
 +		char *chained_base, *chained_dst;
-+		char *mok_src, *mok_dst, *fb_src, *fb_dst;
++		char *mok_src, *mok_dst, *bootcsv_src, *bootcsv_dst;
++
++		/* Install grub as our chained bootloader */
++		chained_base = xasprintf ("grub%s.efi", efi_suffix);
++		chained_dst = grub_util_path_concat (2, efidir, chained_base);
++		grub_install_copy_file (efi_signed, chained_dst, 1);
++		free (chained_dst);
++		free (chained_base);
++
++		/* Now handle shim, and make this our new "default" loader. */
 +		if (!removable)
 +		  {
 +		    free (efi_file);
@@ -267,17 +274,14 @@ index 3b4606eef..b0c7c7c37 100644
 +		    dst = grub_util_path_concat (2, efidir, efi_file);
 +		  }
 +		grub_install_copy_file (shim_signed, dst, 1);
-+		chained_base = xasprintf ("grub%s.efi", efi_suffix);
-+		chained_dst = grub_util_path_concat (2, efidir, chained_base);
-+		grub_install_copy_file (efi_signed, chained_dst, 1);
-+		free (chained_dst);
-+		free (chained_base);
++		free (efi_signed);
++		efi_signed = xstrdup (shim_signed);
 +
-+		/* Not critical, so not an error if they are not present (as it
-+		   won't be for older releases); but if we have them, make
-+		   sure they are installed.  */
++		/* Not critical, so not an error if it is not present (as it
++		   won't be for older releases); but if we have MokManager,
++		   make sure it gets installed.  */
 +		mok_src = grub_util_path_concat (2, "/usr/lib/shim/",
-+						    mok_signed);
++						    mok_file);
 +		mok_dst = grub_util_path_concat (2, efidir,
 +						    mok_file);
 +		grub_install_copy_file (mok_src,
@@ -285,14 +289,13 @@ index 3b4606eef..b0c7c7c37 100644
 +		free (mok_src);
 +		free (mok_dst);
 +
-+		fb_src = grub_util_path_concat (2, "/usr/lib/shim/",
-+						    fb_signed);
-+		fb_dst = grub_util_path_concat (2, efidir,
-+						    fb_file);
-+		grub_install_copy_file (fb_src,
-+					fb_dst, 0);
-+		free (fb_src);
-+		free (fb_dst);
++		/* Also try to install boot.csv for fallback */
++		bootcsv_src = grub_util_path_concat (2, "/usr/lib/shim/",
++						     bootcsv);
++		bootcsv_dst = grub_util_path_concat (2, efidir, bootcsv);
++		grub_install_copy_file (bootcsv_src, bootcsv_dst, 0);
++		free (bootcsv_src);
++		free (bootcsv_dst);
 +	      }
 +	    else
 +	      grub_install_copy_file (efi_signed, dst, 1);
diff --git a/debian/patches/ubuntu-linuxefi-arm64.patch b/debian/patches/ubuntu-linuxefi-arm64.patch
new file mode 100644
index 0000000..dd7c9e9
--- /dev/null
+++ b/debian/patches/ubuntu-linuxefi-arm64.patch
@@ -0,0 +1,185 @@
+From f38282a2ced47589ab05b2184a57d87cbbd7db40 Mon Sep 17 00:00:00 2001
+From: Julian Andres Klode <julian.klode@canonical.com>
+Date: Fri, 11 Sep 2020 11:28:08 +0200
+Subject: Cherry-pick back parts of "Load arm with SB enabled."
+
+These parts got lost in our 2.04 rebase, let's add them back.
+
+Pick (grub_efi_physical_address_t)(grub_efi_uintn_t) cast from
+fedora-34 instead, it seems to cause compilation error on armhf
+to not do the (grub_efi_uintn_t) cast first.
+
+Bug-Ubuntu: https://bugs.launchpad.net/1862279
+Origin: vendor, https://github.com/rhboot/grub2/commit/2786ab864cf00c15123320671f653e9a36ba12b4
+Patch-Name: ubuntu-linuxefi-arm64.patch
+---
+ grub-core/loader/arm64/linux.c | 106 +++++++++++++++++----------------
+ 1 file changed, 56 insertions(+), 50 deletions(-)
+
+diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
+index 3f5496fc55..130e9c09b4 100644
+--- a/grub-core/loader/arm64/linux.c
++++ b/grub-core/loader/arm64/linux.c
+@@ -43,6 +43,8 @@ static int loaded;
+ 
+ static void *kernel_addr;
+ static grub_uint64_t kernel_size;
++static grub_uint32_t handover_offset;
++
+ 
+ static char *linux_args;
+ static grub_uint32_t cmdline_size;
+@@ -76,7 +78,8 @@ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
+ static grub_err_t
+ finalize_params_linux (void)
+ {
+-  int node, retval;
++  grub_efi_loaded_image_t *loaded_image = NULL;
++  int node, retval, len;
+ 
+   void *fdt;
+ 
+@@ -111,6 +114,27 @@ finalize_params_linux (void)
+   if (grub_fdt_install() != GRUB_ERR_NONE)
+     goto failure;
+ 
++
++  grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
++		fdt);
++
++  /* Convert command line to UCS-2 */
++  loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
++  if (!loaded_image)
++    goto failure;
++
++  loaded_image->load_options_size = len =
++    (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t);
++  loaded_image->load_options =
++    grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
++  if (!loaded_image->load_options)
++    return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters");
++
++  loaded_image->load_options_size =
++    2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
++			    (grub_uint8_t *) linux_args, len, NULL);
++
++
+   return GRUB_ERR_NONE;
+ 
+ failure:
+@@ -118,70 +142,48 @@ failure:
+   return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
+ }
+ 
++static void
++free_params (void)
++{
++  grub_efi_loaded_image_t *loaded_image = NULL;
++  loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
++  if (loaded_image)
++    {
++      if (loaded_image->load_options)
++      grub_efi_free_pages ((grub_efi_physical_address_t)(grub_efi_uintn_t)
++			      loaded_image->load_options,
++			     GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
++      loaded_image->load_options = NULL;
++      loaded_image->load_options_size = 0;
++    }
++}
++
+ grub_err_t
+ grub_arch_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;
+-  grub_efi_boot_services_t *b;
+-  grub_efi_status_t status;
+-  grub_efi_loaded_image_t *loaded_image;
+-  int len;
+-
+-  mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t));
+-  if (!mempath)
+-    return grub_errno;
+-
+-  mempath[0].header.type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE;
+-  mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE;
+-  mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath));
+-  mempath[0].memory_type = GRUB_EFI_LOADER_DATA;
+-  mempath[0].start_address = addr;
+-  mempath[0].end_address = addr + size;
++  grub_err_t retval;
+ 
+-  mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+-  mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+-  mempath[1].header.length = sizeof (grub_efi_device_path_t);
+-
+-  b = grub_efi_system_table->boot_services;
+-  status = b->load_image (0, grub_efi_image_handle,
+-			  (grub_efi_device_path_t *) mempath,
+-			  (void *) addr, size, &image_handle);
+-  if (status != GRUB_EFI_SUCCESS)
+-    return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
++  retval = finalize_params_linux ();
++  if (retval != GRUB_ERR_NONE)
++    return grub_errno;
+ 
+   grub_dprintf ("linux", "linux command line: '%s'\n", args);
+ 
+-  /* Convert command line to UCS-2 */
+-  loaded_image = grub_efi_get_loaded_image (image_handle);
+-  loaded_image->load_options_size = len =
+-    (grub_strlen (args) + 1) * sizeof (grub_efi_char16_t);
+-  loaded_image->load_options =
+-    grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+-  if (!loaded_image->load_options)
+-    return grub_errno;
+-
+-  loaded_image->load_options_size =
+-    2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
+-			    (grub_uint8_t *) args, len, NULL);
++  (void) addr;
++  (void) size;
+ 
+-  grub_dprintf ("linux", "starting image %p\n", image_handle);
+-  status = b->start_image (image_handle, 0, NULL);
+ 
+-  /* When successful, not reached */
+-  b->unload_image (image_handle);
+-  grub_efi_free_pages ((grub_addr_t) loaded_image->load_options,
+-		       GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
++  retval = grub_efi_linux_boot ((char *)kernel_addr, handover_offset,
++				kernel_addr);
+ 
+-  return grub_errno;
++  /* Never reached... */
++  free_params();
++  return retval;
+ }
+ 
+ static grub_err_t
+ grub_linux_boot (void)
+ {
+-  if (finalize_params_linux () != GRUB_ERR_NONE)
+-    return grub_errno;
+-
+   return (grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr,
+                                           kernel_size, linux_args));
+ }
+@@ -297,6 +299,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ {
+   grub_file_t file = 0;
+   struct linux_arch_kernel_header lh;
++  struct grub_arm64_linux_pe_header *pe;
+   grub_err_t err;
+   int rc;
+ 
+@@ -354,6 +357,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+         }
+     }
+ 
++  pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
++  handover_offset = pe->opt.entry_addr;
++
+   cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
+   linux_args = grub_malloc (cmdline_size);
+   if (!linux_args)
diff --git a/debian/patches/ubuntu-linuxefi.patch b/debian/patches/ubuntu-linuxefi.patch
new file mode 100644
index 0000000..750cda6
--- /dev/null
+++ b/debian/patches/ubuntu-linuxefi.patch
@@ -0,0 +1,2795 @@
+From 5d037853169fac31b3c0cfe7a6b6c4eb267879d3 Mon Sep 17 00:00:00 2001
+From: Matthew Garrett <mjg@redhat.com>
+Date: Wed, 27 Feb 2019 12:20:48 -0500
+Subject: UBUNTU: Add support for linuxefi
+
+Last-Update: 2019-02-27
+Patch-Name: ubuntu-linuxefi.patch
+Origin: vendor, https://github.com/rhboot/grub2/commit/c81a5cc77110c919da5bce565854fc38ab49303b
+Forwarded: no
+
+Load arm with SB enabled.
+
+Make sure we actually try to validate secure boot on this platform (even
+though we're not shipping it enabled by default.)
+
+This means giving the kernel grub's loaded image as the vehicle for the
+kernel command line, because we can't call systab->bs->LoadImage() if SB
+is enabled.
+
+Origin: vendor, https://github.com/rhboot/grub2/commit/2786ab864cf00c15123320671f653e9a36ba12b4
+Forwarded: no
+Last-Update: 2019-02-27
+
+Fix race in EFI validation
+
+Origin: vendor, https://github.com/rhboot/grub2/commit/57414c73c4e80baedcb96ff35be9306fb0599a09
+Forwarded: no
+Last-Update: 2019-02-27
+
+Use device part of chainloader target, if present.
+
+Otherwise chainloading is restricted to '$root', which might not even
+be readable by EFI!
+
+v1. use grub_file_get_device_name() to get device name
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+Origin: vendor, https://github.com/rhboot/grub2/commit/f8e5b67d99449b8cb9cc45237adb839406f2db97
+Forwarded: no
+Last-Update: 2019-02-27
+
+Add secureboot support on efi chainloader
+
+Expand the chainloader to be able to verify the image by means of shim
+lock protocol. The PE/COFF image is loaded and relocated by the
+chainloader instead of calling LoadImage and StartImage UEFI boot
+Service as they require positive verification result from keys enrolled
+in KEK or DB. The shim will use MOK in addition to firmware enrolled
+keys to verify the image.
+
+The chainloader module could be used to load other UEFI bootloaders,
+such as xen.efi, and could be signed by any of MOK, KEK or DB.
+
+Based on https://build.opensuse.org/package/view_file/openSUSE:Factory/grub2/grub2-secureboot-chainloader.patch
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+Origin: vendor, https://github.com/rhboot/grub2/commit/a00fc9f578d2c310438ced8d4be07f5fa4005873
+Forwarded: no
+Last-Update: 2019-02-27
+
+Make any of the loaders that link in efi mode honor secure boot.
+
+And in this case "honor" means "even if somebody does link this in, they
+won't register commands if SB is enabled."
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+Origin: vendor, https://github.com/rhboot/grub2/commit/3056bfc5044e976fa97f76b81b6a680731005095
+Forwarded: no
+Last-Update: 2019-02-27
+
+Rework linux command
+
+We want a single buffer that contains the entire kernel image in order to
+perform a TPM measurement. Allocate one and copy the entire kernel into it
+before pulling out the individual blocks later on.
+
+Origin: vendor, https://github.com/rhboot/grub2/commit/97c97a2e9a95a29c42569952c8be7b