diff -pruN 2.06-2/debian/build-efi-images 2.06-2ubuntu16/debian/build-efi-images
--- 2.06-2/debian/build-efi-images	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/build-efi-images	2022-12-09 16:11:44.000000000 +0000
@@ -52,7 +52,8 @@ workdir="$(mktemp -d build-efi-images.XX
 echo 'normal (memdisk)/grub.cfg' >"$workdir/grub-bootstrap.cfg"
 
 # Skeleton configuration file which finds the real boot disk.
-cat >"$workdir/grub.cfg" <<EOF
+mkdir "$workdir/memdisk-cd"
+cat >"$workdir/memdisk-cd/grub.cfg" <<EOF
 if [ -z "\$prefix" -o ! -e "\$prefix" ]; then
 	if ! search --file --set=root /.disk/info; then
 		search --file --set=root /.disk/mini-info
@@ -68,19 +69,27 @@ else
 fi
 EOF
 
-cat >"$workdir/grub-netboot.cfg" <<EOF
+mkdir "$workdir/memdisk-netboot"
+cat >"$workdir/memdisk-netboot/grub.cfg" <<EOF
 if [ -e \$prefix/$platform/grub.cfg ]; then
 	source \$prefix/$platform/grub.cfg
+elif [ -e \$prefix/grub.cfg-$deb_arch ]; then
+	source \$prefix/grub.cfg-default-$deb_arch
 else
 	source \$prefix/grub.cfg
 fi
 EOF
 
-mkfs.msdos -C "$workdir/memdisk.fat" 64
-mcopy -i "$workdir/memdisk.fat" "$workdir/grub.cfg" ::grub.cfg
+mkdir -p "$workdir/memdisk/fonts"
 
-mkfs.msdos -C "$workdir/memdisk-netboot.fat" 64
-mcopy -i "$workdir/memdisk-netboot.fat" "$workdir/grub-netboot.cfg" ::grub.cfg
+for name in "memdisk" "memdisk-cd" "memdisk-netboot"; do
+        mkdir -p "$workdir/$name/fonts"
+        cp "$grub_core/../unicode.pf2" "$workdir/$name/fonts"
+done
+
+mksquashfs "$workdir/memdisk-cd" "$workdir/memdisk-cd.squashfs" -comp xz
+mksquashfs "$workdir/memdisk-netboot" "$workdir/memdisk-netboot.squashfs" -comp xz
+mksquashfs "$workdir/memdisk" "$workdir/memdisk.squashfs" -comp xz
 
 CD_MODULES="
 	all_video
@@ -95,7 +104,6 @@ CD_MODULES="
 	ext2
 	fat
 	font
-	f2fs
 	gettext
 	gfxmenu
 	gfxterm
@@ -105,7 +113,6 @@ CD_MODULES="
 	help
 	hfsplus
 	iso9660
-	jfs
 	jpeg
 	keystatus
 	loadenv
@@ -133,6 +140,7 @@ CD_MODULES="
 	search_fs_file
 	search_label
 	sleep
+	smbios
 	squash4
 	test
 	true
@@ -187,6 +195,7 @@ GRUB_MODULES="$CD_MODULES
 	raid6rec
 	"
 NET_MODULES="$CD_MODULES
+	http
 	tftp
 	"
 
@@ -194,7 +203,7 @@ NET_MODULES="$CD_MODULES
 echo "Including modules $CD_MODULES in $outdir/gcd$efi_name.efi"
 "$grub_mkimage" -O "$platform" -o "$outdir/gcd$efi_name.efi" \
 	-d "$grub_core" \
-	-c "$workdir/grub-bootstrap.cfg" -m "$workdir/memdisk.fat" \
+	-c "$workdir/grub-bootstrap.cfg" -m "$workdir/memdisk-cd.squashfs" \
 	-p /boot/grub \
 	--sbat "$sbat_csv" \
 	$CD_MODULES
@@ -202,15 +211,15 @@ echo "Including modules $CD_MODULES in $
 # Normal disk boot image
 echo "Including modules $GRUB_MODULES in $outdir/grub$efi_name.efi"
 "$grub_mkimage" -O "$platform" -o "$outdir/grub$efi_name.efi" \
-	-d "$grub_core" -p "/EFI/$efi_vendor" \
-	--sbat "$sbat_csv" \
+	-d "$grub_core" -m "$workdir/memdisk.squashfs" \
+        -p "/EFI/$efi_vendor" --sbat "$sbat_csv" \
 	$GRUB_MODULES
 
 # Normal network boot image
 echo "Including modules $NET_MODULES in $outdir/grubnet$efi_name.efi"
 "$grub_mkimage" -O "$platform" -o "$outdir/grubnet$efi_name.efi" \
 	-d "$grub_core" -c "$workdir/grub-bootstrap.cfg" \
-	-m "$workdir/memdisk-netboot.fat" \
+	-m "$workdir/memdisk-netboot.squashfs" \
 	-p /grub \
 	--sbat "$sbat_csv" \
 	$NET_MODULES
@@ -218,12 +227,15 @@ echo "Including modules $NET_MODULES in
 # 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
-echo "Including modules $NET_MODULES in $outdir/grubnet$efi_name-installer.efi"
-"$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" \
-	--sbat "$sbat_csv" \
-	$NET_MODULES
+#
+# but not on Ubuntu LP: #1863994
+#
+#echo "Including modules $NET_MODULES in $outdir/grubnet$efi_name-installer.efi"
+#"$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" \
+#	--sbat "$sbat_csv" \
+#	$NET_MODULES
 
 exit 0
diff -pruN 2.06-2/debian/canonical-uefi-ca.crt 2.06-2ubuntu16/debian/canonical-uefi-ca.crt
--- 2.06-2/debian/canonical-uefi-ca.crt	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/canonical-uefi-ca.crt	2022-12-09 16:11:44.000000000 +0000
@@ -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 -pruN 2.06-2/debian/changelog 2.06-2ubuntu16/debian/changelog
--- 2.06-2/debian/changelog	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/changelog	2022-12-09 16:11:44.000000000 +0000
@@ -1,3 +1,368 @@
+grub2 (2.06-2ubuntu16) lunar; urgency=medium
+
+  * Cherry-pick all memory patches from rhboot
+    - Allocate initrd > 4 GB (LP: #1842320)
+    - Allocate kernels as code, not data (needed for newer firmware)
+  * ubuntu: Fix casts on i386-efi target
+  * Cherry-pick all the 2.12 memory management changes (LP: #1842320)
+  * Allocate executables as CODE, not DATA in chainloader and arm64
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Fri, 09 Dec 2022 17:11:44 +0100
+
+grub2 (2.06-2ubuntu15) lunar; urgency=medium
+
+  * grub-multi-install: Reset partition type between partitions (LP: #1997795)
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Thu, 01 Dec 2022 16:30:53 +0100
+
+grub2 (2.06-2ubuntu14) kinetic; urgency=medium
+
+  * SECURITY UPDATE: Fix out of bounds writes due specially crafted fonts.
+    - add debian/patches/font-Fix-several-integer-overflows-in-grub_font_construct.patch
+    - add debian/patches/font-Fix-an-integer-underflow-in-blit_comb.patch
+    - CVE-2022-2601, CVE-2022-3775
+    - LP: #1996950
+  * Fix various issues as a result of fuzzing, static analysis and code
+    review:
+    - add debian/patches/font-Reject-glyphs-exceeds-font-max_glyph_width-or-font-m.patch
+    - add debian/patches/font-Fix-size-overflow-in-grub_font_get_glyph_internal.patch
+    - add debian/patchces/font-Remove-grub_font_dup_glyph.patch
+    - add debian/patches/font-Fix-integer-overflow-in-ensure_comb_space.patch
+    - add debian/patches/font-Fix-integer-overflow-in-BMP-index.patch
+    - add debian/patches/font-Fix-integer-underflow-in-binary-search-of-char-index.patch
+    - add debian/patches/fbutil-Fix-integer-overflow.patch
+    - add debian/patches/font-Harden-grub_font_blit_glyph-and-grub_font_blit_glyph.patch
+    - add debian/patches/font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch
+    - add debian/patches/normal-charset-Fix-an-integer-overflow-in-grub_unicode_ag.patch
+  * Enforce verification of fonts when secure boot is enabled:
+    - add debian/patches/kern-efi-sb-Enforce-verification-of-font-files.patch
+  * Bundle unicode.pf2 in a squashfs memdisk attached to the signed EFI binary
+    - update debian/control
+    - update debian/build-efi-image
+    - add debian/patches/font-Try-opening-fonts-from-the-bundled-memdisk.patch
+  * Fix LP: #1997006 - add support for performing measurements to RTMRs
+    - add debian/patches/commands-efi-tpm-Refine-the-status-of-log-event.patch
+    - add debian/patches/commands-efi-tpm-Use-grub_strcpy-instead-of-grub_memcpy.patch
+    - add debian/patches/efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch
+  * Fix the squashfs tests during the build
+    - remove debian/patches/ubuntu-fix-reproducible-squashfs-test.patch
+    - add debian/patches/tests-Explicitly-unset-SOURCE_DATE_EPOCH-before-running-f.patch
+  * Bump SBAT generation:
+    - update debian/sbat.ubuntu.csv.in
+
+ -- Chris Coulson <chris.coulson@canonical.com>  Wed, 16 Nov 2022 14:40:42 +0000
+
+grub2 (2.06-2ubuntu13) kinetic; urgency=medium
+
+  * Try to pick better locations for kernel and initrd (LP: #1989446)
+  * x86-efi: Use bounce buffers for reading to addresses > 4GB (enhances
+    firmware compatibility of previous change)
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Thu, 20 Oct 2022 21:18:25 +0200
+
+grub2 (2.06-2ubuntu12) kinetic; urgency=medium
+
+  * ubuntu-zfs-enhance-support.patch: Fix missing lines (LP: #1990143)
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Mon, 19 Sep 2022 16:00:47 +0200
+
+grub2 (2.06-2ubuntu11) kinetic; urgency=medium
+
+  [ Mauricio Faria de Oliveira ]
+  * linux_xen: Properly handle multiple initrd files (LP: #1987567)
+    - d/p/linux_xen-Properly-load-multiple-initrd-files.patch
+    - d/p/linux_xen-Properly-order-multiple-initrd-files.patch
+  * Fix for ZFS snapshots without etc directory.
+    Thanks to Adam R Bell <a_0x07@protonmail.ch> (LP: #1965983)
+
+  [ Heinrich Schuchardt ]
+  * efi/peimage: fix typos in code comments
+
+  [ dann frazier ]
+  * linuxefi: Invalidate i-cache before starting the kernel (LP: #1987924)
+    - d/p/linuxefi-Invalidate-i-cache-before-starting-the-kern.patch
+
+ -- dann frazier <dannf@ubuntu.com>  Wed, 14 Sep 2022 12:35:29 -0600
+
+grub2 (2.06-2ubuntu10) kinetic; urgency=medium
+
+  [ Chris Coulson ]
+  * SECURITY UPDATE: Crafted PNG grayscale images may lead to out-of-bounds
+    write in heap.
+    - 0139-video-readers-png-Drop-greyscale-support-to-fix-heap.patch:
+      video/readers/png: Drop greyscale support to fix heap out-of-bounds write
+    - CVE-2021-3695
+  * SECURITY UPDATE: Crafted PNG image may lead to out-of-bound write during
+    huffman table handling.
+    - 0140-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch:
+      video/readers/png: Avoid heap OOB R/W inserting huff table items
+    - CVE-2021-3696
+  * SECURITY UPDATE: Crafted JPEG image can lead to buffer underflow write in
+    the heap.
+    - 0145-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch:
+      video/readers/jpeg: Block int underflow -> wild pointer write
+    - CVE-2021-3697
+  * SECURITY UPDATE: Integer underflow in grub_net_recv_ip4_packets
+    - 0148-net-ip-Do-IP-fragment-maths-safely.patch: net/ip: Do IP fragment
+      maths safely
+    - CVE-2022-28733
+  * SECURITY UPDATE: Out-of-bounds write when handling split HTTP headers
+    - 0154-net-http-Fix-OOB-write-for-split-http-headers.patch: net/http: Fix
+      OOB write for split http headers
+    - CVE-2022-28734
+  * SECURITY UPDATE: shim_lock verifier allows non-kernel files to be loaded
+    - 0135-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch:
+      kern/efi/sb: Reject non-kernel files in the shim_lock verifier
+    - CVE-2022-28735
+  * SECURITY UPDATE: use-after-free in grub_cmd_chainloader()
+    - 0130-loader-efi-chainloader-simplify-the-loader-state.patch:
+      loader/efi/chainloader: simplify the loader state
+    - 0131-commands-boot-Add-API-to-pass-context-to-loader.patch: commands/boot:
+      Add API to pass context to loader
+    - 0132-loader-efi-chainloader-Use-grub_loader_set_ex.patch:
+      loader/efi/chainloader: Use grub_loader_set_ex
+    - 0133-loader-i386-efi-linux-Use-grub_loader_set_ex.patch:
+      loader/i386/efi/linux: Use grub_loader_set_ex
+  * Various fixes as a result of fuzzing and static analysis:
+    - 0129-loader-efi-chainloader-grub_load_and_start_image-doe.patch:
+      loader/efi/chainloader: grub_load_and_start_image doesn't load and start
+    - 0134-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch:
+      loader/i386/efi/linux: Fix a memory leak in the initrd command
+    - 0136-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch:
+      kern/file: Do not leak device_name on error in grub_file_open()
+    - 0137-video-readers-png-Abort-sooner-if-a-read-operation-f.patch:
+      video/readers/png: Abort sooner if a read operation fails
+    - 0138-video-readers-png-Refuse-to-handle-multiple-image-he.patch:
+      video/readers/png: Refuse to handle multiple image headers
+    - 0141-video-readers-png-Sanity-check-some-huffman-codes.patch:
+      video/readers/png: Sanity check some huffman codes
+    - 0142-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch:
+      video/readers/jpeg: Abort sooner if a read operation fails
+    - 0143-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch:
+      video/readers/jpeg: Do not reallocate a given huff table
+    - 0144-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch:
+      video/readers/jpeg: Refuse to handle multiple start of streams
+    - 0146-normal-charset-Fix-array-out-of-bounds-formatting-un.patch:
+      normal/charset: Fix array out-of-bounds formatting unicode for display
+    - 0147-net-netbuff-Block-overly-large-netbuff-allocs.patch:
+      net/netbuff: Block overly large netbuff allocs
+    - 0149-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch:
+      net/dns: Fix double-free addresses on corrupt DNS response
+    - 0150-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch:
+      net/dns: Don't read past the end of the string we're checking against
+    - 0151-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch:
+      net/tftp: Prevent a UAF and double-free from a failed seek
+    - 0152-net-tftp-Avoid-a-trivial-UAF.patch: net/tftp: Avoid a trivial UAF
+    - 0153-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch:
+      net/http: Do not tear down socket if it's already been torn down
+    - 0155-net-http-Error-out-on-headers-with-LF-without-CR.patch:
+      net/http: Error out on headers with LF without CR
+    - 0156-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch:
+      fs/f2fs: Do not read past the end of nat journal entries
+    - 0157-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch:
+      fs/f2fs: Do not read past the end of nat bitmap
+    - 0158-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch:
+      fs/f2fs: Do not copy file names that are too long
+    - 0159-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch:
+      fs/btrfs: Fix several fuzz issues with invalid dir item sizing
+    - 0160-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch:
+      fs/btrfs: Fix more ASAN and SEGV issues found with fuzzing
+    - 0161-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch:
+      fs/btrfs: Fix more fuzz issues related to chunks
+  * Bump SBAT generation:
+    - update debian/sbat.ubuntu.csv.in
+  * Make the grub2/no_efi_extra_removable setting work correctly
+    - update debian/postinst.in
+  * Build grub2-unsigned packages with xz compression for compatibility
+    with xenial dpkg
+    - update debian/rules
+
+  [ Steve Langasek ]
+  * Bump versioned dependency on grub2-common to 2.02~beta2-36ubuntu3.32 for
+    necessary arm relocation support.  LP: #1926748.
+  * debian/postinst.in: Unconditionally call grub-install with
+    --force-extra-removable on xenial and bionic, so that the \EFI\BOOT
+    removable path as used in cloud images receives the updates.  LP: #1930742.
+
+ -- Chris Coulson <chris.coulson@canonical.com>  Tue, 07 Jun 2022 17:36:27 +0100
+
+grub2 (2.06-2ubuntu7) jammy; urgency=medium
+
+  [ Heinrich Schuchardt ]
+  * Disable LOAD FILE2 protocol for initrd on ARM (LP: #1967562)
+
+ -- dann frazier <dannf@ubuntu.com>  Fri, 15 Apr 2022 15:50:11 -0600
+
+grub2 (2.06-2ubuntu6) jammy; urgency=medium
+
+  [ Heinrich Schuchardt ]
+  * efivar: check that efivarfs is writeable (LP: #1965288)
+
+  [ Dimitri John Ledkov ]
+  * Do not validate kernels twice. (LP: #1964943)
+
+  [ Heinrich Schuchardt ]
+  * efi: EFI Device Tree Fixup Protocol (LP: #1965796)
+  * fdt: add debug output to devicetree command
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Fri, 25 Mar 2022 16:03:11 +0100
+
+grub2 (2.06-2ubuntu5) jammy; urgency=medium
+
+  [ Julian Andres Klode ]
+  * Free correct size when freeing params, rather than 16 Ki (LP: #1958623)
+  * Build with FUSE3 (LP: #1935659)
+  * Only run os-prober on first run and if it previously found other OS
+    (LP: #1955109)
+
+  [ Heinrich Schuchardt ]
+  * Rename grub-core/loader/efi/linux.c
+  * Add patches for GRUB on RISC-V
+  * fat: fix listing the root directory
+  * Enable building for RISC-V (LP: #1876620)
+
+  [ Julian Andres Klode ]
+  * Re-enable peimage code on other archs outside secure boot; this
+    fixes LP: #1947046 when not booting in secure boot mode (secure
+    boot pending security review of the code)
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Fri, 18 Feb 2022 17:21:16 +0100
+
+grub2 (2.06-2ubuntu4) jammy; urgency=medium
+
+  * UBUNTU: Move verifiers after decompressors (LP: #1954683)
+  * grub-check-signatures: Support gzip compressed kernels (LP: #1954683)
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Mon, 10 Jan 2022 14:52:04 +0100
+
+grub2 (2.06-2ubuntu3) jammy; urgency=medium
+
+  * Cherry-pick the missing hunk back that changes parameter loading
+    in grub-core/loader/i386/linux.c, this should fix booting on
+    BIOS systems.
+  * Fix the fallback for kernel addresses on amd64 EFI, if the kernel
+    could not be allocated at the preferred address, reset errno such
+    that if the 2nd allocation succeeds, we do not fail erroneously.
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Mon, 13 Dec 2021 14:27:53 +0100
+
+grub2 (2.06-2ubuntu2) jammy; urgency=medium
+
+  * Restore still relevant patches lost in rebase.
+    They got lost in a first rebase, when we did not include
+    ubuntu-linuxefi.patch as they modify code in there.
+    - no-devicetree-if-secure-boot.patch
+    - 0077-ubuntu-Update-the-linux-boot-protocol-version-check.patch
+    - 0096-linuxefi-fail-kernel-validation-without-shim-protoco.patch
+    - 0099-chainloader-Avoid-a-double-free-when-validation-fail.patch
+    - 0105-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Wed, 08 Dec 2021 17:14:50 +0100
+
+grub2 (2.06-2ubuntu1) jammy; urgency=medium
+
+  * Merge from Debian unstable; remaining changes:
+    - Build without lto
+    - Add Ubuntu sbat data
+    - Make prebuilt netboot image look for MAAS grub.cfg
+    - build-efi-images: add smbios module to the prebuilt signed EFI images
+      (LP: 1856424)
+    - build-efi-images: do not produce -installer.efi.signed. LP: 1863994
+    - build-efi-images: Add http to netboot images
+    - grub-common: Install canonical-uefi-ca.crt
+    - Check signatures
+    - minilzo: built using the distribution's minilzo
+    - Support installing to multiple ESP (LP: 1871821)
+    - Disable various bits on i386
+    - Split out unsigned artefacts into grub2-unsigned
+    - Vcs-Git: Point to ubuntu packaging branch
+    - Relax dependencies on grub-common and grub2-common
+    - grub-pc: Avoid the possibility of breaking grub on SRU update due
+      to ABI change
+    - UBUNTU: Default timeout changes
+    - Disable os-prober for ppc64el on the PowerNV platform (for Petitboot)
+    - dirs.in: create var/lib/grub/ucf in grub-efi-amd64 (and similar)
+    - Link grub-efi-{amd64,arm64}-bin docs directory
+    - grub-common.service: port init.d script to systemd unit. Add warning
+      message, when initrdless boot fails triggering fallback. LP: 1901553
+    - Removed patches:
+      - grub-install-extra-removable.patch
+      - grub-install-removable-shim.patch
+    - Added patches:
+      + ubuntu-grub-install-extra-removable.patch
+      + ubuntu-zfs-enhance-support.patch
+      + ubuntu-zfs-gfxpayload-keep-default.patch
+      + ubuntu-zfs-mkconfig-ubuntu-distributor.patch
+      + ubuntu-zfs-mkconfig-signed-kernel.patch
+      + ubuntu-zfs-maybe-quiet.patch
+      + ubuntu-zfs-quick-boot.patch
+      + ubuntu-zfs-gfxpayload-dynamic.patch
+      + ubuntu-zfs-vt-handoff.patch
+      + ubuntu-zfs-mkconfig-recovery-title.patch
+      + ubuntu-zfs-insmod-xzio-and-lzopio-on-xen.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-efi-allow-loopmount-chainload.patch
+      + 0076-ubuntu-Make-the-linux-command-in-EFI-grub-always-try.patch
+      + ubuntu-resilient-boot-ignore-alternative-esps.patch
+      + ubuntu-resilient-boot-boot-order.patch
+      + ubuntu-speed-zsys-history.patch
+      + ubuntu-flavour-order.patch
+      + ubuntu-dont-verify-loopback-images.patch
+      + ubuntu-recovery-dis_ucode_ldr.patch
+      + ubuntu-linuxefi-arm64.patch
+      + ubuntu-add-initrd-less-boot-messages.patch
+      + ubuntu-fix-reproducible-squashfs-test.patch
+      + rhboot-f34-make-exit-take-a-return-code.patch
+      + rhboot-f34-dont-use-int-for-efi-status.patch
+      + rhboot-f34-make-pmtimer-tsc-calibration-fast.patch
+      + suse-add-support-for-UEFI-network-protocols.patch
+      + suse-AUDIT-0-http-boot-tracker-bug.patch
+      + rhboot-f34-efinet-also-use-the-firmware-acceleration-for-http.patch
+      + 0241-Call-hwmatch-only-on-the-grub-pc-platform.patch
+  * Dropped changes:
+    - Remove obsolete dependencies on dh-autoreconf and automake
+    - Remove explicit --with systemd in debhelper invocation
+    - Remove debian/gettext-patches; they do not seem to be necessary anymore
+    - Remove inadvertent change to debian/signing-template.json.in, we do not
+      use that file anyway.
+    - Merged upstream:
+      + merged: 0074-uefi-firmware-rename-fwsetup-menuentry-to-UEFI-Firmw.patch
+      + merged: 0075-smbios-Add-a-linux-argument-to-apply-linux-modalias-.patch
+      + merged security patches 0081-0105, and 0128-0240
+      + various cherry picks: cherry-* and cherrypick-*.patch
+      + grub-install-backup-and-restore.patch
+      + uefi-firmware-setup.patch
+      + sleep-shift.patch
+      + vsnprintf-upper-case-hex.patch
+      + rhboot-f34-update-info-with-grub.cfg-netboot-selection-order.patch
+      + suse-search-for-specific-config-files-for-netboot.patch
+      + tftp-rollover-block-counter.patch
+      + ubuntu-efi-console-set-text-mode-as-needed.patch
+    - Merged in Debian:
+      + install-efi-ubuntu-flavours.patch
+      + ubuntu-dejavu-font-path.patch
+      + ubuntu-tpm-unknown-error-non-fatal.patch
+    - Not applicable:
+      + 0077-ubuntu-Update-the-linux-boot-protocol-version-check.patch: The
+        check has been removed.
+  * Fix zstd build on s390x
+  * Cherry-pick two upstream fixes to fix closing of SNP protocol in EFI
+    networking stack
+  * Build with -O1 on s390x to avoid build failure due to gcc optimization
+    failure causing it to wrongly assume variables as uninitialized.
+  * Revert integration of jfs and f2fs modules into signed images, we do not
+    support these file systems on /boot.
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Tue, 07 Dec 2021 13:40:32 +0100
+
 grub2 (2.06-2) unstable; urgency=medium
 
   * Update to minilzo-2.10, fixing build failures on armel, mips64el,
@@ -420,6 +785,705 @@ grub2 (2.04-2) unstable; urgency=medium
 
  -- Colin Watson <cjwatson@debian.org>  Sat, 03 Aug 2019 13:42:49 +0100
 
+grub2 (2.04-1ubuntu48) jammy; urgency=medium
+
+  * d/p/0241-Call-hwmatch-only-on-the-grub-pc-platform.patch:
+    Fix "error: can't find command `hwmatch'." on non-i386/pc
+    platforms such as x86_64/efi. (LP: #1840560)
+
+ -- Mauricio Faria de Oliveira <mfo@canonical.com>  Thu, 04 Nov 2021 10:48:06 -0300
+
+grub2 (2.04-1ubuntu47) impish; urgency=medium
+
+  * Drop grub.cfg-400.patch (LP: #1933826)
+
+ -- Julian Andres Klode <juliank@ubuntu.com>  Thu, 02 Sep 2021 14:37:43 +0200
+
+grub2 (2.04-1ubuntu46) impish; urgency=medium
+
+  * debian/grub-common.service: change type to oneshot, add wantedby
+    sleep.target, after sleep.target. The service will now start after
+    resume from hybernation. LP: #1929860
+  * grub-initrd-fallback.service: add wantedby sleep.target, after
+    sleep.target. The service will now start after resume from
+    hybernation. LP: #1929860
+  * cherrypick upstream fix to make armhf efi boot work. LP: #1788940
+  * debian/rules: disable LTO. LP: #1922005
+  * grub-initrd-fallback.service, debian/grub-common.service: only start
+    units when booted with grub. Use presence of /boot/grub/grub.cfg as
+    proxy. LP: #1925507
+  * tests: patch qemu command to use ide-hd instead of the removed
+    ide-drive.
+
+ -- Dimitri John Ledkov <dimitri.ledkov@canonical.com>  Fri, 16 Jul 2021 14:01:31 +0100
+
+grub2 (2.04-1ubuntu45) hirsute; urgency=medium
+
+  * Unapply all patches.
+  * Stop using git-dpm.
+  * Start using gbp pq import|export --no-patch-numbers, this brings grub2
+    packaging closer to other non-debian distributions.
+  * It would be nice to separate patches into topic subdirs -
+    i.e. reverts, upstream cherry picks, debian, ubuntu, rhel, security,
+    etc.
+  * Drop redundant dh-systemd build-dependency.
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Tue, 30 Mar 2021 11:55:05 +0100
+
+grub2 (2.04-1ubuntu44) hirsute; urgency=medium
+
+  * Compile grub-efi-amd64 installable i386 platform on hirsute, to make
+    it available in bionic and earlier as part of onegrub builds.
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Wed, 03 Mar 2021 11:42:28 +0000
+
+grub2 (2.04-1ubuntu42) hirsute; urgency=medium
+
+  * SECURITY UPDATE: acpi command allows privilleged user to load crafted
+    ACPI tables when secure boot is enabled.
+    - 0126-acpi-Don-t-register-the-acpi-command-when-locked-dow.patch: Don't
+      register the acpi command when secure boot is enabled.
+    - CVE-2020-14372
+  * SECURITY UPDATE: use-after-free in rmmod command
+    - 0128-dl-Only-allow-unloading-modules-that-are-not-depende.patch: Don't
+      allow rmmod to unload modules that are dependencies of other modules.
+    - CVE-2020-25632
+  * SECURITY UPDATE: out-of-bound write in grub_usb_device_initialize()
+    - 0129-usb-Avoid-possible-out-of-bound-accesses-caused-by-m.patch
+    - CVE-2020-25647
+  * SECURITY UPDATE: Stack buffer overflow in grub_parser_split_cmdline
+    - 0206-kern-parser-Introduce-process_char-helper.patch,
+      0207-kern-parser-Introduce-terminate_arg-helper.patch,
+      0208-kern-parser-Refactor-grub_parser_split_cmdline-clean.patch,
+      0209-kern-buffer-Add-variable-sized-heap-buffer.patch,
+      0210-kern-parser-Fix-a-stack-buffer-overflow.patch: Add a variable
+      sized heap buffer type and use this.
+    - CVE-2020-27749
+  * SECURITY UPDATE: cutmem command allows privileged user to remove memory
+    regions when Secure Boot is enabled.
+    - 0127-mmap-Don-t-register-cutmem-and-badram-commands-when-.patch:
+      Don't register cutmem and badram commands when secure boot is enabled.
+    - CVE-2020-27779
+  * SECURITY UPDATE: heap out-of-bounds write in short form option parser.
+    - 0173-lib-arg-Block-repeated-short-options-that-require-an.patch:
+      Block repeated short options that require an argument.
+    - CVE-2021-20225
+  * SECURITY UPDATE: heap out-of-bound write due to mis-calculation of space
+    required for quoting.
+    - 0175-commands-menuentry-Fix-quoting-in-setparams_prefix.patch: Fix
+      quoting in setparams_prefix()
+    - CVE-2021-20233
+  * Partially backport the lockdown framework to restrict certain features
+    when secure boot is enabled.
+  * Backport various fixes for Coverity defects.
+  * Add SBAT metadata to the grub EFI binary.
+    - Backport patches to support adding SBAT metadata with grub-mkimage:
+      + 0212-util-mkimage-Remove-unused-code-to-add-BSS-section.patch
+      + 0213-util-mkimage-Use-grub_host_to_target32-instead-of-gr.patch
+      + 0214-util-mkimage-Always-use-grub_host_to_target32-to-ini.patch
+      + 0215-util-mkimage-Unify-more-of-the-PE32-and-PE32-header-.patch
+      + 0216-util-mkimage-Reorder-PE-optional-header-fields-set-u.patch
+      + 0217-util-mkimage-Improve-data_size-value-calculation.patch
+      + 0218-util-mkimage-Refactor-section-setup-to-use-a-helper.patch
+      + 0219-util-mkimage-Add-an-option-to-import-SBAT-metadata-i.patch
+    - Add debian/sbat.csv.in
+    - Update debian/build-efi-image and debian/rules
+
+  [ Dimitri John Ledkov & Steve Langasek LP: #1915536 ]
+  * Allow grub-efi-amd64|arm64 & -bin & -dbg be built by
+    src:grub2-unsigned (potentially of a higher version number).
+  * Add debian/rules generate-grub2-unsigned target to quickly build
+    src:grub2-unsigned for binary-copy backports.
+  * postinst: allow postinst to with with or without grub-multi-install
+    binary.
+  * postinst: allow using various grub-install options to achieve
+    --no-extra-removable.
+  * postinst: only call grub-check-signatures if it exists.
+  * control: relax dependency on grub2-common, as maintainer script got
+    fixed up to work with grub2-common/grub-common as far back as trusty.
+  * control: allow higher version depdencies from grub-efi package.
+  * dirs.in: create var/lib/grub/ucf in grub-efi-amd64 (and similar) as
+    postinst script uses that directory, and yet relies on grub-common to
+    create/ship it, which is not true in older releases. Also make sure
+    dh_installdirs runs after the .dirs files are generated.
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Tue, 23 Feb 2021 16:23:39 +0000
+
+grub2 (2.04-1ubuntu41) hirsute; urgency=medium
+
+  * No-change rebuild to drop the udeb package.
+
+ -- Matthias Klose <doko@ubuntu.com>  Mon, 22 Feb 2021 10:33:38 +0100
+
+grub2 (2.04-1ubuntu40) hirsute; urgency=medium
+
+  * Revert: rhboot-f34-tcp-add-window-scaling-support.patch,
+    rhboot-f34-support-non-ethernet.patch,
+    ubuntu-fixup-rhboot-f34-support-non-ethernet.patch,
+    ubuntu-fixup-rhboot-f34-support-non-ethernet-2.patch: these break MAAS
+    LXD KVM pod deployments. LP: #1915288
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Fri, 12 Feb 2021 20:29:16 +0000
+
+grub2 (2.04-1ubuntu39) hirsute; urgency=medium
+
+  * Cherrypick a bunch of patches:
+    - fix crash in http LP: #1915288
+    - add bootp6 documentation
+    - add support for UEFI boot protocols
+    - use UEFI protocols for http & https networking
+    - make netboot search for by-mac/by-uuid/by-ip for grub.cfg
+    - update documentation for netboot search paths of grub.cfg
+  * Make prebuilt netboot image look for MAAS grub.cfg
+  * Fix grub-initrd-fallback.service thanks to JawnSmith LP: #1910815
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Fri, 12 Feb 2021 00:42:07 +0000
+
+grub2 (2.04-1ubuntu38) hirsute; urgency=medium
+
+  [ Jean-Baptiste Lallement ]
+  [ Didier Roche ]
+  * Fix warnings during grub menu generation.  Thanks wdoekes for the patch
+    (LP: #1898177)
+    - Fix warnings when bpool doesn't exist.
+    - Fix warnings when snapshot name contains dashes.
+  * Do not fail to generate grub menu when name of the snapshot contains
+    spaces. (LP: #1903524)
+
+ -- Jean-Baptiste Lallement <jean-baptiste.lallement@ubuntu.com>  Mon, 08 Feb 2021 10:50:21 +0100
+
+grub2 (2.04-1ubuntu37) hirsute; urgency=medium
+
+  * debian/patches/grub-install-backup-and-restore.patch: Fix-up the patch
+    to correctly initialyze the names of the modules to restore. LP:
+    #1907085
+  * 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
+  * debian/rules: undo po/ directory patching in
+    override_dh_autoreconf_clean.
+  * minilzo: built using the distribution's minilzo
+  * ubuntu-fix-reproducible-squashfs-test.patch: fix squashfs-test with
+    new squashfs-tools in hirsute.
+  * rhboot-f34-make-exit-take-a-return-code.patch,
+    rhboot-f34-dont-use-int-for-efi-status.patch: allow grub to exit
+    non-zero under EFI, this should allow falling back to the next
+    BootOrder BootEntry.
+  * rhboot-f34-tcp-add-window-scaling-support.patch: speed up netboot
+    transfer speed.
+  * rhboot-f34-support-non-ethernet.patch,
+    ubuntu-fixup-rhboot-f34-support-non-ethernet.patch,
+    ubuntu-fixup-rhboot-f34-support-non-ethernet-2.patch:
+    add support for link layer addresses of up to 32-bytes.
+  * rhboot-f34-make-pmtimer-tsc-calibration-fast.patch:
+    speed up calibration time, especially when booting VMs.
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com>  Sat, 12 Dec 2020 00:50:47 +0000
+
+grub2 (2.04-1ubuntu36) hirsute; urgency=medium
+
+  * Avoid "EFI stub: FIRMWARE BUG" message when booting >= 5.7 kernels
+    on arm64 by setting the image base address before jumping to the
+    PE/COFF entry point LP: #1900774
+  * Fix tftp timeouts when fetch large files. LP: #1900773
+
+ -- dann frazier <dannf@ubuntu.com>  Wed, 11 Nov 2020 07:17:49 -0700
+
+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-1) unstable; urgency=medium
 
   * New upstream release.
@@ -553,6 +1617,112 @@ grub2 (2.02+dfsg1-13) unstable; urgency=
 
  -- 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 ]
@@ -697,6 +1867,175 @@ grub2 (2.02+dfsg1-6) unstable; urgency=m
 
  -- 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 ]
@@ -793,6 +2132,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.
@@ -829,6 +2333,92 @@ grub2 (2.02~beta3-5) unstable; urgency=m
 
  -- 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 -pruN 2.06-2/debian/control 2.06-2ubuntu16/debian/control
--- 2.06-2/debian/control	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/control	2022-12-09 16:11:44.000000000 +0000
@@ -1,7 +1,8 @@
 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>, Steve McIntyre <93sam@debian.org>
 Build-Depends: debhelper-compat (= 10),
  patchutils,
@@ -19,26 +20,27 @@ Build-Depends: debhelper-compat (= 10),
  libdevmapper-dev [linux-any],
  libgeom-dev (>= 8.2+ds1-1~) [kfreebsd-any] | libgeom-dev (<< 8.2) [kfreebsd-any],
  libsdl1.2-dev [!hurd-any],
- xorriso,
- qemu-system [i386 kfreebsd-i386 kopensolaris-i386 any-amd64],
+ xorriso [!i386],
+ qemu-system [kfreebsd-i386 kopensolaris-i386 any-amd64],
  cpio [i386 kopensolaris-i386 amd64 x32],
  parted [!hurd-any],
- libfuse-dev (>= 2.8.4-1.4) [linux-any kfreebsd-any],
+ libfuse3-dev [linux-any kfreebsd-any],
  fonts-dejavu-core,
  liblzma-dev,
- dosfstools [any-i386 any-amd64 any-arm64],
- mtools [any-i386 any-amd64 any-arm64],
+ liblzo2-dev,
+ dosfstools [any-amd64 any-arm64],
+ squashfs-tools [any-amd64 any-arm64],
  wamerican,
  libparted-dev [any-powerpc any-ppc64 any-ppc64el],
  pkg-config,
  bash-completion,
- libefiboot-dev [i386 amd64 ia64 x32 armel armhf arm64],
- libefivar-dev [i386 amd64 ia64 x32 armel armhf arm64],
+ libefiboot-dev [i386 amd64 ia64 x32 armel armhf arm64 riscv64],
+ libefivar-dev [i386 amd64 ia64 x32 armel armhf arm64 riscv64],
 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
@@ -61,9 +63,9 @@ Description: GRand Unified Bootloader, v
  This is a dummy transitional package that depends on grub-coreboot.
 
 Package: grub-efi
-Architecture: any-i386 any-amd64 any-arm64 any-ia64 any-arm
+Architecture: any-i386 any-amd64 any-arm64 any-ia64 any-arm any-riscv64
 Pre-Depends: ${misc:Pre-Depends}
-Depends: ${misc:Depends}, grub-efi-ia32 (= ${binary:Version}) [any-i386], grub-efi-amd64 (= ${binary:Version}) [any-amd64], grub-efi-arm64 (= ${binary:Version}) [any-arm64], grub-efi-ia64 (= ${binary:Version}) [any-ia64], grub-efi-arm (= ${binary:Version}) [any-arm]
+Depends: ${misc:Depends}, grub-efi-ia32 (= ${binary:Version}) [any-i386], grub-efi-amd64 (>= ${binary:Version}) [any-amd64], grub-efi-arm64 (>= ${binary:Version}) [any-arm64], grub-efi-ia64 (= ${binary:Version}) [any-ia64], grub-efi-arm (= ${binary:Version}) [any-arm], grub-efi-riscv64 (= ${binary:Version}) [any-riscv64]
 Multi-Arch: foreign
 Description: GRand Unified Bootloader, version 2 (dummy package)
  This is a dummy package that depends on the grub-efi-$ARCH package most likely
@@ -71,10 +73,11 @@ Description: GRand Unified Bootloader, v
 
 Package: grub-common
 Architecture: any
+Built-Using: ${Built-Using}
 Depends: ${shlibs:Depends}, ${misc:Depends}, gettext-base, ${lsb-base-depends}
 Replaces: grub-pc (<< 2.00-4), grub-ieee1275 (<< 2.00-4), grub-efi (<< 1.99-1), grub-coreboot (<< 2.00-4), grub-linuxbios (<< 1.96+20080831-1), grub-efi-ia32 (<< 2.00-4), grub-efi-amd64 (<< 2.00-4), grub-efi-ia64 (<< 2.00-4), grub-yeeloong (<< 2.00-4), init-select
 Recommends: os-prober (>= 1.33)
-Suggests: multiboot-doc, grub-emu [any-i386 any-amd64 any-powerpc], mtools [any-i386 any-amd64 any-ia64 any-arm any-arm64], xorriso (>= 0.5.6.pl00), desktop-base (>= 4.0.6), console-setup
+Suggests: multiboot-doc, grub-emu [any-i386 any-amd64 any-powerpc], mtools [any-i386 any-amd64 any-ia64 any-arm any-arm64 riscv64], xorriso (>= 0.5.6.pl00), desktop-base (>= 4.0.6), console-setup
 Conflicts: init-select
 # mdadm: See bugs #435983 and #455746
 Breaks: mdadm (<< 2.6.7-2), lupin-support (<< 0.55), friendly-recovery (<< 0.2.13), apport (<< 2.1.1)
@@ -91,7 +94,7 @@ Package: grub2-common
 # Not Architecture: any because this package contains some things which are
 # only built when there is a real platform (e.g. grub-install), and the rest
 # of the package is not very useful in a utilities-only build.
-Architecture: any-i386 any-amd64 any-powerpc any-ppc64 any-ppc64el any-sparc any-sparc64 any-mipsel any-ia64 any-arm any-arm64
+Architecture: any-i386 any-amd64 any-powerpc any-ppc64 any-ppc64el any-sparc any-sparc64 any-mipsel any-ia64 any-arm any-arm64 any-riscv64
 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
@@ -308,7 +311,7 @@ Description: GRand Unified Bootloader, v
 
 Package: grub-efi-amd64-bin
 Architecture: i386 kopensolaris-i386 any-amd64
-Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (>= 2.02~beta2-9)
 Recommends: grub-efi-amd64-signed [amd64], efibootmgr [linux-any]
 Replaces: grub2 (<< ${source:Version}), grub-common (<= 1.97~beta2-1), grub-efi-amd64 (<< 1.99-1)
 Multi-Arch: foreign
@@ -333,7 +336,7 @@ Description: GRand Unified Bootloader, v
 Package: grub-efi-amd64-dbg
 Section: debug
 Architecture: i386 kopensolaris-i386 any-amd64
-Depends: ${misc:Depends}, grub-efi-amd64-bin (= ${binary:Version}), grub-common (= ${binary:Version})
+Depends: ${misc:Depends}, grub-efi-amd64-bin (= ${binary:Version})
 Multi-Arch: foreign
 Description: GRand Unified Bootloader, version 2 (EFI-AMD64 debug files)
  This package contains debugging files for grub-efi-amd64-bin.  You only
@@ -342,7 +345,7 @@ Description: GRand Unified Bootloader, v
 Package: grub-efi-amd64
 Architecture: i386 kopensolaris-i386 any-amd64
 Pre-Depends: ${misc:Pre-Depends}
-Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (= ${binary:Version}), grub-efi-amd64-bin (= ${binary:Version}), ucf
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (>= 2.02~beta2-9), grub-efi-amd64-bin (= ${binary:Version}), ucf
 Replaces: grub, grub-legacy, grub2 (<< ${source:Version}), grub-common (<= 1.97~beta2-1), grub-pc, grub-efi-ia32, grub-coreboot, grub-ieee1275
 Conflicts: grub, grub-legacy, grub-efi-ia32, grub-pc, grub-coreboot, grub-ieee1275, grub-xen, elilo
 Multi-Arch: foreign
@@ -469,7 +472,7 @@ Description: GRand Unified Bootloader, v
 
 Package: grub-efi-arm64-bin
 Architecture: any-arm64
-Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (>= 2.02~beta2-9)
 Recommends: grub-efi-arm64-signed [arm64], efibootmgr [linux-any]
 Multi-Arch: foreign
 XB-Efi-Vendor: ${efi:Vendor}
@@ -492,7 +495,7 @@ Description: GRand Unified Bootloader, v
 Package: grub-efi-arm64-dbg
 Section: debug
 Architecture: any-arm64
-Depends: ${misc:Depends}, grub-efi-arm64-bin (= ${binary:Version}), grub-common (= ${binary:Version})
+Depends: ${misc:Depends}, grub-efi-arm64-bin (= ${binary:Version})
 Multi-Arch: foreign
 Description: GRand Unified Bootloader, version 2 (ARM64 UEFI debug files)
  This package contains debugging files for grub-efi-arm64-bin.  You only
@@ -501,7 +504,7 @@ Description: GRand Unified Bootloader, v
 Package: grub-efi-arm64
 Architecture: any-arm64
 Pre-Depends: ${misc:Pre-Depends}
-Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (= ${binary:Version}), grub-efi-arm64-bin (= ${binary:Version}), ucf
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (>= 2.02~beta2-36ubuntu3.32), grub-efi-arm64-bin (= ${binary:Version}), ucf
 Multi-Arch: foreign
 Description: GRand Unified Bootloader, version 2 (ARM64 UEFI version)
  GRUB is a portable, powerful bootloader.  This version of GRUB is based on a
@@ -523,6 +526,56 @@ Description: GRand Unified Bootloader, v
  This package contains template files for grub-efi-arm64-signed.
  This is only needed for Secure Boot signing.
 
+Package: grub-efi-riscv64-bin
+Architecture: any-riscv64
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (>= 2.02~beta2-9)
+Recommends: efibootmgr [linux-any]
+Multi-Arch: foreign
+XB-Efi-Vendor: ${efi:Vendor}
+Description: GRand Unified Bootloader, version 2 (riscv64 UEFI modules)
+ GRUB is a portable, powerful bootloader.  This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+  - Scripting in grub.cfg using BASH-like syntax.
+  - Support for modern partition maps such as GPT.
+  - Modular generation of grub.cfg via update-grub.  Packages providing GRUB
+    add-ons can plug in their own script rules and trigger updates by invoking
+    update-grub.
+ .
+ This package contains GRUB modules that have been built for use on riscv64
+ systems with UEFI.  It can be installed in parallel with other flavours,
+ but will not automatically install GRUB as the active boot loader nor
+ automatically update grub.cfg on upgrade unless grub-efi-riscv64 is also
+ installed.
+
+Package: grub-efi-riscv64-dbg
+Section: debug
+Architecture: any-riscv64
+Depends: ${misc:Depends}, grub-efi-riscv64-bin (= ${binary:Version})
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (riscv64 UEFI debug files)
+ This package contains debugging files for grub-efi-riscv64-bin.  You only
+ need these if you are trying to debug GRUB using its GDB stub.
+
+Package: grub-efi-riscv64
+Architecture: any-riscv64
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}, grub2-common (>= 2.02~beta2-9), grub-efi-riscv64-bin (= ${binary:Version}), ucf
+Multi-Arch: foreign
+Description: GRand Unified Bootloader, version 2 (riscv64 UEFI version)
+ GRUB is a portable, powerful bootloader.  This version of GRUB is based on a
+ cleaner design than its predecessors, and provides the following new features:
+ .
+  - Scripting in grub.cfg using BASH-like syntax.
+  - Support for modern partition maps such as GPT.
+  - Modular generation of grub.cfg via update-grub.  Packages providing GRUB
+    add-ons can plug in their own script rules and trigger updates by invoking
+    update-grub.
+ .
+ This is a dependency package for a version of GRUB that has been built for
+ use on RISC-V 64-bit systems with UEFI.  Installing this package indicates that
+ this version of GRUB should be the active boot loader.
+
 Package: grub-ieee1275-bin
 Architecture: any-i386 any-amd64 any-powerpc any-ppc64 any-ppc64el any-sparc any-sparc64
 Depends: ${shlibs:Depends}, ${misc:Depends}, grub-common (= ${binary:Version})
@@ -762,7 +815,7 @@ Description: GRand Unified Bootloader, v
 Package: grub-theme-starfield
 # Could be Architecture: any, but in practice this package is useless in a
 # utilities-only build.
-Architecture: any-i386 any-amd64 any-powerpc any-ppc64 any-ppc64el any-sparc any-sparc64 any-mipsel any-ia64 any-arm any-arm64
+Architecture: any-i386 any-amd64 any-powerpc any-ppc64 any-ppc64el any-sparc any-sparc64 any-mipsel any-ia64 any-arm any-arm64 any-riscv64
 Depends: ${misc:Depends}, grub-common (= ${binary:Version})
 Multi-Arch: foreign
 Description: GRand Unified Bootloader, version 2 (starfield theme)
diff -pruN 2.06-2/debian/dirs.in 2.06-2ubuntu16/debian/dirs.in
--- 2.06-2/debian/dirs.in	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/dirs.in	2022-12-09 16:11:44.000000000 +0000
@@ -1,3 +1,4 @@
 usr/bin
 usr/sbin
 usr/share/grub
+var/lib/grub/ucf
diff -pruN 2.06-2/debian/.git-dpm 2.06-2ubuntu16/debian/.git-dpm
--- 2.06-2/debian/.git-dpm	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/.git-dpm	1970-01-01 00:00:00.000000000 +0000
@@ -1,9 +0,0 @@
-# see git-dpm(1) from git-dpm package
-dbcbb3e5b9fac665b92d630eb24de7bd8c43652e
-dbcbb3e5b9fac665b92d630eb24de7bd8c43652e
-21f954425ffe2a934b6b26c0c948d340c91a16bb
-21f954425ffe2a934b6b26c0c948d340c91a16bb
-grub2_2.06.orig.tar.xz
-c9f93f1e195ec7a5a21d36a13b469788c0b29f0f
-6581924
-signature:910db38472f2d654a4816a0c3b7b83415502850f:833:grub2_2.06.orig.tar.xz.asc
diff -pruN 2.06-2/debian/.gitignore 2.06-2ubuntu16/debian/.gitignore
--- 2.06-2/debian/.gitignore	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/.gitignore	1970-01-01 00:00:00.000000000 +0000
@@ -1,110 +0,0 @@
-*.bash-completion
-*.config
-*.debhelper*
-*.postinst
-*.postrm
-*.preinst
-*.templates
-files
-grub-common
-grub-common.maintscript
-grub-coreboot
-grub-coreboot*.dirs
-grub-coreboot*.install
-grub-coreboot*.links
-grub-coreboot*.maintscript
-grub-coreboot-bin
-grub-coreboot-dbg
-grub-efi
-grub-efi-amd64
-grub-efi-amd64*.dirs
-grub-efi-amd64*.install
-grub-efi-amd64*.links
-grub-efi-amd64*.maintscript
-grub-efi-amd64-bin
-grub-efi-amd64-dbg
-grub-efi-amd64-signed-template
-grub-efi-arm
-grub-efi-arm*.dirs
-grub-efi-arm*.install
-grub-efi-arm*.links
-grub-efi-arm*.maintscript
-grub-efi-arm-bin
-grub-efi-arm-dbg
-grub-efi-arm64
-grub-efi-arm64*.dirs
-grub-efi-arm64*.install
-grub-efi-arm64*.links
-grub-efi-arm64*.maintscript
-grub-efi-arm64-bin
-grub-efi-arm64-dbg
-grub-efi-arm64-signed-template
-grub-efi-ia32
-grub-efi-ia32*.dirs
-grub-efi-ia32*.install
-grub-efi-ia32*.links
-grub-efi-ia32*.maintscript
-grub-efi-ia32-bin
-grub-efi-ia32-dbg
-grub-efi-ia32-signed-template
-grub-efi-ia64
-grub-efi-ia64*.dirs
-grub-efi-ia64*.install
-grub-efi-ia64*.links
-grub-efi-ia64*.maintscript
-grub-efi-ia64-bin
-grub-efi-ia64-dbg
-grub-emu
-grub-emu*.dirs
-grub-emu*.install
-grub-emu*.links
-grub-emu*.maintscript
-grub-emu-dbg
-grub-extras-enabled
-grub-extras/*/conf/*.mk
-grub-firmware-qemu
-grub-ieee1275
-grub-ieee1275*.dirs
-grub-ieee1275*.install
-grub-ieee1275*.links
-grub-ieee1275*.maintscript
-grub-ieee1275-bin
-grub-ieee1275-dbg
-grub-linuxbios
-grub-mount-udeb
-grub-pc
-grub-pc*.dirs
-grub-pc*.install
-grub-pc*.links
-grub-pc*.maintscript
-grub-pc-bin
-grub-pc-dbg
-grub-rescue-pc
-grub-theme-starfield
-grub-uboot
-grub-uboot*.dirs
-grub-uboot*.install
-grub-uboot*.links
-grub-uboot*.maintscript
-grub-uboot-bin
-grub-uboot-dbg
-grub-xen
-grub-xen*.dirs
-grub-xen*.install
-grub-xen*.links
-grub-xen*.maintscript
-grub-xen-bin
-grub-xen-dbg
-grub-xen-host
-grub-yeeloong
-grub-yeeloong*.dirs
-grub-yeeloong*.install
-grub-yeeloong*.links
-grub-yeeloong*.maintscript
-grub-yeeloong-bin
-grub-yeeloong-dbg
-grub2
-grub2-common
-prep-bootdev
-stamps
-tmp-*
diff -pruN 2.06-2/debian/grub-check-signatures 2.06-2ubuntu16/debian/grub-check-signatures
--- 2.06-2/debian/grub-check-signatures	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/grub-check-signatures	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,136 @@
+#!/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() {
+	kernel=$1
+	tmp=$(mktemp)
+	kernel_tmp=$(mktemp)
+	if zcat $kernel > $kernel_tmp 2>/dev/null; then
+		kernel=$kernel_tmp
+	fi
+	sbattach --detach $tmp $kernel >/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 $kernel >/dev/null 2>/dev/null
+			result=$?
+			if [ $result -eq 0 ]; then
+				rm "$kernel_tmp"
+				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
+	rm "$kernel_tmp"
+	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 -pruN 2.06-2/debian/grub-common.dirs 2.06-2ubuntu16/debian/grub-common.dirs
--- 2.06-2/debian/grub-common.dirs	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/grub-common.dirs	2022-12-09 16:11:44.000000000 +0000
@@ -1,2 +1,3 @@
 usr/sbin
 var/lib/grub/ucf
+var/lib/grub/esp
diff -pruN 2.06-2/debian/grub-common.install.in 2.06-2ubuntu16/debian/grub-common.install.in
--- 2.06-2/debian/grub-common.install.in	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/grub-common.install.in	2022-12-09 16:11:44.000000000 +0000
@@ -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 -pruN 2.06-2/debian/grub-common.service 2.06-2ubuntu16/debian/grub-common.service
--- 2.06-2/debian/grub-common.service	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/grub-common.service	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,15 @@
+[Unit]
+Description=Record successful boot for GRUB
+After=sleep.target
+ConditionPathExists=/boot/grub/grub.cfg
+
+[Service]
+Type=oneshot
+Restart=no
+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 "grub: GRUB_FORCE_PARTUUID set, initrdless boot paniced, fallback triggered."; fi'
+StandardOutput=kmsg
+
+[Install]
+WantedBy=multi-user.target sleep.target
diff -pruN 2.06-2/debian/grub-common.templates 2.06-2ubuntu16/debian/grub-common.templates
--- 2.06-2/debian/grub-common.templates	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/grub-common.templates	2022-12-09 16:11:44.000000000 +0000
@@ -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 -pruN 2.06-2/debian/grub-efi-amd64-bin.maintscript.in 2.06-2ubuntu16/debian/grub-efi-amd64-bin.maintscript.in
--- 2.06-2/debian/grub-efi-amd64-bin.maintscript.in	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/grub-efi-amd64-bin.maintscript.in	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1 @@
+symlink_to_dir /usr/share/doc/@PACKAGE@ grub-common 2.04-1ubuntu42~
diff -pruN 2.06-2/debian/grub-efi-arm64-bin.maintscript.in 2.06-2ubuntu16/debian/grub-efi-arm64-bin.maintscript.in
--- 2.06-2/debian/grub-efi-arm64-bin.maintscript.in	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/grub-efi-arm64-bin.maintscript.in	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1 @@
+symlink_to_dir /usr/share/doc/@PACKAGE@ grub-common 2.04-1ubuntu42~
diff -pruN 2.06-2/debian/grub-extras/915resolution/.gitignore 2.06-2ubuntu16/debian/grub-extras/915resolution/.gitignore
--- 2.06-2/debian/grub-extras/915resolution/.gitignore	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/grub-extras/915resolution/.gitignore	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-.deps-core
-.dirstamp
-/Makefile.core.am
diff -pruN 2.06-2/debian/grub-extras/disabled/gpxe/.gitignore 2.06-2ubuntu16/debian/grub-extras/disabled/gpxe/.gitignore
--- 2.06-2/debian/grub-extras/disabled/gpxe/.gitignore	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/grub-extras/disabled/gpxe/.gitignore	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-.deps-core
-.dirstamp
-/Makefile.core.am
diff -pruN 2.06-2/debian/grub-extras/disabled/zfs/.gitignore 2.06-2ubuntu16/debian/grub-extras/disabled/zfs/.gitignore
--- 2.06-2/debian/grub-extras/disabled/zfs/.gitignore	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/grub-extras/disabled/zfs/.gitignore	1970-01-01 00:00:00.000000000 +0000
@@ -1,5 +0,0 @@
-.deps-core
-.deps-util
-.dirstamp
-/Makefile.core.am
-/Makefile.util.am
diff -pruN 2.06-2/debian/grub-extras/lua/.gitignore 2.06-2ubuntu16/debian/grub-extras/lua/.gitignore
--- 2.06-2/debian/grub-extras/lua/.gitignore	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/grub-extras/lua/.gitignore	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-.deps-core
-.dirstamp
-/Makefile.core.am
diff -pruN 2.06-2/debian/grub-extras/ntldr-img/.gitignore 2.06-2ubuntu16/debian/grub-extras/ntldr-img/.gitignore
--- 2.06-2/debian/grub-extras/ntldr-img/.gitignore	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/grub-extras/ntldr-img/.gitignore	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-.deps-core
-.dirstamp
-/Makefile.core.am
diff -pruN 2.06-2/debian/grub-multi-install 2.06-2ubuntu16/debian/grub-multi-install
--- 2.06-2/debian/grub-multi-install	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/grub-multi-install	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,419 @@
+#!/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
+    ID_PART_ENTRY_TYPE=""
+    ID_PART_ENTRY_SCHEME=""
+    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 -pruN 2.06-2/debian/patches/0076-ubuntu-Make-the-linux-command-in-EFI-grub-always-try.patch 2.06-2ubuntu16/debian/patches/0076-ubuntu-Make-the-linux-command-in-EFI-grub-always-try.patch
--- 2.06-2/debian/patches/0076-ubuntu-Make-the-linux-command-in-EFI-grub-always-try.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0076-ubuntu-Make-the-linux-command-in-EFI-grub-always-try.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,117 @@
+From: Julian Andres Klode <julian.klode@canonical.com>
+Date: Thu, 2 Dec 2021 12:25:37 +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 382ff52..9241fed 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_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+     {
+-      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 b6c13d7..e764e2a 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -665,35 +665,40 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+ #ifdef GRUB_MACHINE_EFI
+   using_linuxefi = 0;
+-  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+-    {
+-      /* 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_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+ 	    {
+-	      (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_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    {
++      grub_dprintf("linux", "Unable to hand off to linuxefi and secure boot is enabled\n");
++      goto fail;
++    }
+ #endif
+ 
+   if (argc == 0)
diff -pruN 2.06-2/debian/patches/0077-ubuntu-Update-the-linux-boot-protocol-version-check.patch 2.06-2ubuntu16/debian/patches/0077-ubuntu-Update-the-linux-boot-protocol-version-check.patch
--- 2.06-2/debian/patches/0077-ubuntu-Update-the-linux-boot-protocol-version-check.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0077-ubuntu-Update-the-linux-boot-protocol-version-check.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,24 @@
+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 9241fed..c7dc08b 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 -pruN 2.06-2/debian/patches/0096-linuxefi-fail-kernel-validation-without-shim-protoco.patch 2.06-2ubuntu16/debian/patches/0096-linuxefi-fail-kernel-validation-without-shim-protoco.patch
--- 2.06-2/debian/patches/0096-linuxefi-fail-kernel-validation-without-shim-protoco.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0096-linuxefi-fail-kernel-validation-without-shim-protoco.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,89 @@
+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/efi/chainloader.c |  1 +
+ grub-core/loader/efi/linux.c       | 13 +++++++++----
+ grub-core/loader/efi/linux_sb.c    |  1 +
+ grub-core/loader/i386/efi/linux.c  |  2 +-
+ 4 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 2b74d79..9042603 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -1097,6 +1097,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 93e4cfc..56d6745 100644
+--- a/grub-core/loader/efi/linux.c
++++ b/grub-core/loader/efi/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+");
+ 
+@@ -455,11 +456,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_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+     {
+-      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;
++        }
+     }
+ 
+   pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
+diff --git a/grub-core/loader/efi/linux_sb.c b/grub-core/loader/efi/linux_sb.c
+index 73a7196..a09479c 100644
+--- a/grub-core/loader/efi/linux_sb.c
++++ b/grub-core/loader/efi/linux_sb.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 c7dc08b..262d357 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_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+     {
+       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 -pruN 2.06-2/debian/patches/0099-chainloader-Avoid-a-double-free-when-validation-fail.patch 2.06-2ubuntu16/debian/patches/0099-chainloader-Avoid-a-double-free-when-validation-fail.patch
--- 2.06-2/debian/patches/0099-chainloader-Avoid-a-double-free-when-validation-fail.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0099-chainloader-Avoid-a-double-free-when-validation-fail.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,41 @@
+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 9042603..4a85f41 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 -pruN 2.06-2/debian/patches/0105-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch 2.06-2ubuntu16/debian/patches/0105-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch
--- 2.06-2/debian/patches/0105-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0105-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,49 @@
+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 262d357..6a90743 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 -pruN 2.06-2/debian/patches/0129-loader-efi-chainloader-grub_load_and_start_image-doe.patch 2.06-2ubuntu16/debian/patches/0129-loader-efi-chainloader-grub_load_and_start_image-doe.patch
--- 2.06-2/debian/patches/0129-loader-efi-chainloader-grub_load_and_start_image-doe.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0129-loader-efi-chainloader-grub_load_and_start_image-doe.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,68 @@
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Thu, 28 Apr 2022 21:53:36 +0100
+Subject: loader/efi/chainloader: grub_load_and_start_image doesn't load and
+ start
+
+grub_load_and_start_image only loads an image - it still requires the
+caller to start it. This renames it to grub_load_image.
+
+It's called from 2 places:
+- grub_cmd_chainloader when not using the shim protocol.
+- grub_secureboot_chainloader_boot if handle_image returns an error.
+In this case, the image is loaded and then nothing else happens which
+seems strange. I assume the intention is that it falls back to LoadImage
+and StartImage if handle_image fails, so I've made it do that.
+
+Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
+(cherry picked from commit b4d70820a65c00561045856b7b8355461a9545f6)
+---
+ grub-core/loader/efi/chainloader.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index c6ae2fc..7ff2c5b 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -845,7 +845,7 @@ grub_secureboot_chainloader_unload (void)
+ }
+ 
+ static grub_err_t
+-grub_load_and_start_image(void *boot_image)
++grub_load_image(void *boot_image)
+ {
+   grub_efi_boot_services_t *b;
+   grub_efi_status_t status;
+@@ -887,13 +887,23 @@ grub_load_and_start_image(void *boot_image)
+ static grub_err_t
+ grub_secureboot_chainloader_boot (void)
+ {
++  grub_efi_boot_services_t *b;
+   int rc;
++
+   rc = handle_image ((void *)((grub_addr_t) address), fsize);
+   if (rc == 0)
+     {
+-      grub_load_and_start_image((void *)((grub_addr_t) address));
++      /* We weren't able to attempt to execute the image, so fall back
++       * to LoadImage / StartImage.
++       */
++      rc = grub_load_image((void *)(unsigned long)address);
++      if (rc == 0)
++        grub_chainloader_boot ();
+     }
+ 
++  b = grub_efi_system_table->boot_services;
++  efi_call_1 (b->unload_image, image_handle);
++
+   grub_loader_unset ();
+   return grub_errno;
+ }
+@@ -1091,7 +1101,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+     }
+   else
+     {
+-      grub_load_and_start_image(boot_image);
++      grub_load_image(boot_image);
+       grub_file_close (file);
+       if (orig_dev)
+ 	dev = orig_dev;
diff -pruN 2.06-2/debian/patches/0130-loader-efi-chainloader-simplify-the-loader-state.patch 2.06-2ubuntu16/debian/patches/0130-loader-efi-chainloader-simplify-the-loader-state.patch
--- 2.06-2/debian/patches/0130-loader-efi-chainloader-simplify-the-loader-state.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0130-loader-efi-chainloader-simplify-the-loader-state.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,334 @@
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Fri, 29 Apr 2022 21:13:08 +0100
+Subject: loader/efi/chainloader: simplify the loader state
+
+When not using the shim lock protocol, the chainloader command retains
+the source buffer and device path passed to LoadImage, requiring the
+unload hook passed to grub_loader_set to free them. It isn't required
+to retain this state though - they aren't required by StartImage or
+anything else in the boot hook, so clean them up before
+grub_cmd_chainloader finishes.
+
+This also wraps the loader state when using the shim lock protocol
+inside a struct.
+
+Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
+(cherry picked from commit fa39862933b3be1553a580a3a5c28073257d8046)
+---
+ grub-core/loader/efi/chainloader.c | 161 +++++++++++++++++++++++--------------
+ 1 file changed, 101 insertions(+), 60 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 7ff2c5b..232b296 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -48,38 +48,21 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+ static grub_dl_t my_mod;
+ 
+-static grub_efi_physical_address_t address;
+-static grub_efi_uintn_t pages;
+-static grub_ssize_t fsize;
+-static grub_efi_device_path_t *file_path;
+ static grub_efi_handle_t image_handle;
+-static grub_efi_char16_t *cmdline;
+-static grub_ssize_t cmdline_len;
+-static grub_efi_handle_t dev_handle;
+ 
+-static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table);
+-
+-static grub_err_t
+-grub_chainloader_unload (void)
+-{
+-  grub_efi_boot_services_t *b;
+-
+-  b = grub_efi_system_table->boot_services;
+-  efi_call_1 (b->unload_image, image_handle);
+-  efi_call_2 (b->free_pages, address, pages);
+-
+-  grub_free (file_path);
+-  grub_free (cmdline);
+-  cmdline = 0;
+-  file_path = 0;
+-  dev_handle = 0;
+-
+-  grub_dl_unref (my_mod);
+-  return GRUB_ERR_NONE;
+-}
++struct grub_secureboot_chainloader_context {
++  grub_efi_physical_address_t address;
++  grub_efi_uintn_t pages;
++  grub_ssize_t fsize;
++  grub_efi_device_path_t *file_path;
++  grub_efi_char16_t *cmdline;
++  grub_ssize_t cmdline_len;
++  grub_efi_handle_t dev_handle;
++};
++static struct grub_secureboot_chainloader_context *sb_context;
+ 
+ static grub_err_t
+-grub_chainloader_boot (void)
++grub_start_image (grub_efi_handle_t handle)
+ {
+   grub_efi_boot_services_t *b;
+   grub_efi_status_t status;
+@@ -87,7 +70,7 @@ grub_chainloader_boot (void)
+   grub_efi_char16_t *exit_data = NULL;
+ 
+   b = grub_efi_system_table->boot_services;
+-  status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data);
++  status = efi_call_3 (b->start_image, handle, &exit_data_size, &exit_data);
+   if (status != GRUB_EFI_SUCCESS)
+     {
+       if (exit_data)
+@@ -111,11 +94,37 @@ grub_chainloader_boot (void)
+   if (exit_data)
+     efi_call_1 (b->free_pool, exit_data);
+ 
+-  grub_loader_unset ();
+-
+   return grub_errno;
+ }
+ 
++static grub_err_t
++grub_chainloader_unload (void)
++{
++  grub_efi_loaded_image_t *loaded_image;
++  grub_efi_boot_services_t *b;
++
++  loaded_image = grub_efi_get_loaded_image (image_handle);
++  if (loaded_image != NULL)
++    grub_free (loaded_image->load_options);
++
++  b = grub_efi_system_table->boot_services;
++  efi_call_1 (b->unload_image, image_handle);
++
++  grub_dl_unref (my_mod);
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_chainloader_boot (void)
++{
++  grub_err_t err;
++
++  err = grub_start_image (image_handle);
++
++  grub_loader_unset ();
++  return err;
++}
++
+ static grub_err_t
+ copy_file_path (grub_efi_file_path_device_path_t *fp,
+ 		const char *str, grub_efi_uint16_t len)
+@@ -150,7 +159,7 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
+   char *dir_start;
+   char *dir_end;
+   grub_size_t size;
+-  grub_efi_device_path_t *d;
++  grub_efi_device_path_t *d, *file_path;
+ 
+   dir_start = grub_strchr (filename, ')');
+   if (! dir_start)
+@@ -525,11 +534,13 @@ grub_efi_get_media_file_path (grub_efi_device_path_t *dp)
+ }
+ 
+ static grub_efi_boolean_t
+-handle_image (void *data, grub_efi_uint32_t datasize)
++handle_image (struct grub_secureboot_chainloader_context *load_context)
+ {
+   grub_efi_boot_services_t *b;
+   grub_efi_loaded_image_t *li, li_bak;
+   int efi_status;
++  void *data = (void *)(unsigned long)load_context->address;
++  grub_efi_uint32_t datasize = load_context->fsize;
+   char *buffer = NULL;
+   char *buffer_aligned = NULL;
+   grub_efi_uint32_t i;
+@@ -540,6 +551,7 @@ handle_image (void *data, grub_efi_uint32_t datasize)
+   grub_uint32_t buffer_size;
+   int found_entry_point = 0;
+   int rc;
++  grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table);
+ 
+   b = grub_efi_system_table->boot_services;
+ 
+@@ -799,10 +811,10 @@ handle_image (void *data, grub_efi_uint32_t datasize)
+   grub_memcpy (&li_bak, li, sizeof (grub_efi_loaded_image_t));
+   li->image_base = buffer_aligned;
+   li->image_size = context.image_size;
+-  li->load_options = cmdline;
+-  li->load_options_size = cmdline_len;
+-  li->file_path = grub_efi_get_media_file_path (file_path);
+-  li->device_handle = dev_handle;
++  li->load_options = load_context->cmdline;
++  li->load_options_size = load_context->cmdline_len;
++  li->file_path = grub_efi_get_media_file_path (load_context->file_path);
++  li->device_handle = load_context->dev_handle;
+   if (!li->file_path)
+     {
+       grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found");
+@@ -830,22 +842,22 @@ error_exit:
+ static grub_err_t
+ grub_secureboot_chainloader_unload (void)
+ {
+-  grub_efi_boot_services_t *b;
++  grub_efi_free_pages (sb_context->address, sb_context->pages);
++  grub_free (sb_context->file_path);
++  grub_free (sb_context->cmdline);
++  grub_free (sb_context);
+ 
+-  b = grub_efi_system_table->boot_services;
+-  efi_call_2 (b->free_pages, address, pages);
+-  grub_free (file_path);
+-  grub_free (cmdline);
+-  cmdline = 0;
+-  file_path = 0;
+-  dev_handle = 0;
++  sb_context = 0;
+ 
+   grub_dl_unref (my_mod);
+   return GRUB_ERR_NONE;
+ }
+ 
+ static grub_err_t
+-grub_load_image(void *boot_image)
++grub_load_image(grub_efi_device_path_t *file_path, void *boot_image,
++		grub_efi_uintn_t image_size, grub_efi_handle_t dev_handle,
++		grub_efi_char16_t *cmdline, grub_ssize_t cmdline_len,
++		grub_efi_handle_t *image_handle_out)
+ {
+   grub_efi_boot_services_t *b;
+   grub_efi_status_t status;
+@@ -854,7 +866,7 @@ grub_load_image(void *boot_image)
+   b = grub_efi_system_table->boot_services;
+ 
+   status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
+-		       boot_image, fsize, &image_handle);
++		       boot_image, image_size, image_handle_out);
+   if (status != GRUB_EFI_SUCCESS)
+     {
+       if (status == GRUB_EFI_OUT_OF_RESOURCES)
+@@ -867,7 +879,7 @@ grub_load_image(void *boot_image)
+   /* LoadImage does not set a device handler when the image is
+      loaded from memory, so it is necessary to set it explicitly here.
+      This is a mess.  */
+-  loaded_image = grub_efi_get_loaded_image (image_handle);
++  loaded_image = grub_efi_get_loaded_image (*image_handle_out);
+   if (! loaded_image)
+     {
+       grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
+@@ -889,20 +901,25 @@ grub_secureboot_chainloader_boot (void)
+ {
+   grub_efi_boot_services_t *b;
+   int rc;
++  grub_efi_handle_t handle = 0;
+ 
+-  rc = handle_image ((void *)((grub_addr_t) address), fsize);
++  rc = handle_image (sb_context);
+   if (rc == 0)
+     {
+       /* We weren't able to attempt to execute the image, so fall back
+        * to LoadImage / StartImage.
+        */
+-      rc = grub_load_image((void *)(unsigned long)address);
++      rc = grub_load_image(sb_context->file_path,
++			   (void *)(unsigned long)sb_context->address,
++			   sb_context->fsize, sb_context->dev_handle,
++			   sb_context->cmdline, sb_context->cmdline_len,
++			   &handle);
+       if (rc == 0)
+-        grub_chainloader_boot ();
++	grub_start_image (handle);
+     }
+ 
+   b = grub_efi_system_table->boot_services;
+-  efi_call_1 (b->unload_image, image_handle);
++  efi_call_1 (b->unload_image, handle);
+ 
+   grub_loader_unset ();
+   return grub_errno;
+@@ -917,9 +934,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   grub_efi_boot_services_t *b;
+   grub_device_t dev = 0;
+   grub_device_t orig_dev = 0;
+-  grub_efi_device_path_t *dp = 0;
++  grub_efi_device_path_t *dp = 0, *file_path = 0;
+   char *filename;
+   void *boot_image = 0;
++  grub_efi_physical_address_t address = 0;
++  grub_ssize_t fsize;
++  grub_efi_uintn_t pages = 0;
++  grub_efi_char16_t *cmdline = 0;
++  grub_ssize_t cmdline_len = 0;
++  grub_efi_handle_t dev_handle = 0;
+ 
+   if (argc == 0)
+     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+@@ -927,12 +950,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ 
+   grub_dl_ref (my_mod);
+ 
+-  /* Initialize some global variables.  */
+-  address = 0;
+-  image_handle = 0;
+-  file_path = 0;
+-  dev_handle = 0;
+-
+   b = grub_efi_system_table->boot_services;
+ 
+   if (argc > 1)
+@@ -1091,21 +1108,39 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ 
+   if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+     {
++      sb_context = grub_malloc (sizeof (*sb_context));
++      if (sb_context == NULL)
++        goto fail;
++      sb_context->address = address;
++      sb_context->fsize = fsize;
++      sb_context->pages = pages;
++      sb_context->file_path = file_path;
++      sb_context->cmdline = cmdline;
++      sb_context->cmdline_len = cmdline_len;
++      sb_context->dev_handle = dev_handle;
++
+       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;
+     }
+   else
+     {
+-      grub_load_image(boot_image);
++      grub_load_image(file_path, boot_image, fsize, dev_handle, cmdline,
++		      cmdline_len, &image_handle);
+       grub_file_close (file);
+       if (orig_dev)
+ 	dev = orig_dev;
+       grub_device_close (dev);
++
++      /* We're finished with the source image buffer and file path now */
++      efi_call_2 (b->free_pages, address, pages);
++      grub_free (file_path);
++
+       grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
+ 
+       return 0;
+@@ -1132,6 +1167,12 @@ fail:
+   if (cmdline)
+     grub_free (cmdline);
+ 
++  if (image_handle != 0)
++    {
++      efi_call_1 (b->unload_image, image_handle);
++      image_handle = 0;
++    }
++
+   grub_dl_unref (my_mod);
+ 
+   return grub_errno;
diff -pruN 2.06-2/debian/patches/0131-commands-boot-Add-API-to-pass-context-to-loader.patch 2.06-2ubuntu16/debian/patches/0131-commands-boot-Add-API-to-pass-context-to-loader.patch
--- 2.06-2/debian/patches/0131-commands-boot-Add-API-to-pass-context-to-loader.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0131-commands-boot-Add-API-to-pass-context-to-loader.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,157 @@
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Fri, 29 Apr 2022 21:16:02 +0100
+Subject: commands/boot: Add API to pass context to loader
+
+Loaders rely on global variables for saving context which is consumed
+in the boot hook and freed in the unload hook. In the case where a loader
+command is executed twice, calling grub_loader_set a second time executes
+the unload hook, but in some cases this runs when the loader's global
+context has already been updated, resulting in the updated context being
+freed and potential use-after-free bugs when the boot hook is subsequently
+called.
+
+This adds a new API (grub_loader_set_ex) which allows a loader to specify
+context that is passed to its boot and unload hooks. This is an alternative
+to requiring that loaders call grub_loader_unset before mutating their
+global context.
+
+Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
+(cherry picked from commit 4322a64dde7e8fedb58e50b79408667129d45dd3)
+---
+ grub-core/commands/boot.c | 66 +++++++++++++++++++++++++++++++++++++++++------
+ include/grub/loader.h     |  5 ++++
+ 2 files changed, 63 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c
+index bbca81e..53691a6 100644
+--- a/grub-core/commands/boot.c
++++ b/grub-core/commands/boot.c
+@@ -27,10 +27,20 @@
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+-static grub_err_t (*grub_loader_boot_func) (void);
+-static grub_err_t (*grub_loader_unload_func) (void);
++static grub_err_t (*grub_loader_boot_func) (void *);
++static grub_err_t (*grub_loader_unload_func) (void *);
++static void *grub_loader_context;
+ static int grub_loader_flags;
+ 
++struct grub_simple_loader_hooks
++{
++  grub_err_t (*boot) (void);
++  grub_err_t (*unload) (void);
++};
++
++/* Don't heap allocate this to avoid making grub_loader_set fallible. */
++static struct grub_simple_loader_hooks simple_loader_hooks;
++
+ struct grub_preboot
+ {
+   grub_err_t (*preboot_func) (int);
+@@ -44,6 +54,29 @@ static int grub_loader_loaded;
+ static struct grub_preboot *preboots_head = 0,
+   *preboots_tail = 0;
+ 
++static grub_err_t
++grub_simple_boot_hook (void *context)
++{
++  struct grub_simple_loader_hooks *hooks;
++
++  hooks = (struct grub_simple_loader_hooks *) context;
++  return hooks->boot ();
++}
++
++static grub_err_t
++grub_simple_unload_hook (void *context)
++{
++  struct grub_simple_loader_hooks *hooks;
++  grub_err_t ret;
++
++  hooks = (struct grub_simple_loader_hooks *) context;
++
++  ret = hooks->unload ();
++  grub_memset (hooks, 0, sizeof (*hooks));
++
++  return ret;
++}
++
+ int
+ grub_loader_is_loaded (void)
+ {
+@@ -110,28 +143,45 @@ grub_loader_unregister_preboot_hook (struct grub_preboot *hnd)
+ }
+ 
+ void
+-grub_loader_set (grub_err_t (*boot) (void),
+-		 grub_err_t (*unload) (void),
+-		 int flags)
++grub_loader_set_ex (grub_err_t (*boot) (void *),
++		    grub_err_t (*unload) (void *),
++		    void *context,
++		    int flags)
+ {
+   if (grub_loader_loaded && grub_loader_unload_func)
+-    grub_loader_unload_func ();
++    grub_loader_unload_func (grub_loader_context);
+ 
+   grub_loader_boot_func = boot;
+   grub_loader_unload_func = unload;
++  grub_loader_context = context;
+   grub_loader_flags = flags;
+ 
+   grub_loader_loaded = 1;
+ }
+ 
++void
++grub_loader_set (grub_err_t (*boot) (void),
++		 grub_err_t (*unload) (void),
++		 int flags)
++{
++  grub_loader_set_ex (grub_simple_boot_hook,
++		      grub_simple_unload_hook,
++		      &simple_loader_hooks,
++		      flags);
++
++  simple_loader_hooks.boot = boot;
++  simple_loader_hooks.unload = unload;
++}
++
+ void
+ grub_loader_unset(void)
+ {
+   if (grub_loader_loaded && grub_loader_unload_func)
+-    grub_loader_unload_func ();
++    grub_loader_unload_func (grub_loader_context);
+ 
+   grub_loader_boot_func = 0;
+   grub_loader_unload_func = 0;
++  grub_loader_context = 0;
+ 
+   grub_loader_loaded = 0;
+ }
+@@ -158,7 +208,7 @@ grub_loader_boot (void)
+ 	  return err;
+ 	}
+     }
+-  err = (grub_loader_boot_func) ();
++  err = (grub_loader_boot_func) (grub_loader_context);
+ 
+   for (cur = preboots_tail; cur; cur = cur->prev)
+     if (! err)
+diff --git a/include/grub/loader.h b/include/grub/loader.h
+index b208642..1846fa6 100644
+--- a/include/grub/loader.h
++++ b/include/grub/loader.h
+@@ -40,6 +40,11 @@ void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void),
+ 				    grub_err_t (*unload) (void),
+ 				    int flags);
+ 
++void EXPORT_FUNC (grub_loader_set_ex) (grub_err_t (*boot) (void *),
++				       grub_err_t (*unload) (void *),
++				       void *context,
++				       int flags);
++
+ /* Unset current loader, if any.  */
+ void EXPORT_FUNC (grub_loader_unset) (void);
+ 
diff -pruN 2.06-2/debian/patches/0132-loader-efi-chainloader-Use-grub_loader_set_ex.patch 2.06-2ubuntu16/debian/patches/0132-loader-efi-chainloader-Use-grub_loader_set_ex.patch
--- 2.06-2/debian/patches/0132-loader-efi-chainloader-Use-grub_loader_set_ex.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0132-loader-efi-chainloader-Use-grub_loader_set_ex.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,144 @@
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Fri, 29 Apr 2022 21:30:56 +0100
+Subject: loader/efi/chainloader: Use grub_loader_set_ex
+
+This ports the EFI chainloader to use grub_loader_set_ex in order to fix
+a use-after-free bug that occurs when grub_cmd_chainloader is executed
+more than once before a boot attempt is performed.
+
+Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
+(cherry picked from commit 4b7f0402b7cb0f67a93be736f2b75b818d7f44c9)
+---
+ grub-core/loader/efi/chainloader.c | 38 ++++++++++++++++++++++----------------
+ 1 file changed, 22 insertions(+), 16 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 232b296..fbd14eb 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -48,8 +48,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+ static grub_dl_t my_mod;
+ 
+-static grub_efi_handle_t image_handle;
+-
+ struct grub_secureboot_chainloader_context {
+   grub_efi_physical_address_t address;
+   grub_efi_uintn_t pages;
+@@ -59,7 +57,6 @@ struct grub_secureboot_chainloader_context {
+   grub_ssize_t cmdline_len;
+   grub_efi_handle_t dev_handle;
+ };
+-static struct grub_secureboot_chainloader_context *sb_context;
+ 
+ static grub_err_t
+ grub_start_image (grub_efi_handle_t handle)
+@@ -98,11 +95,14 @@ grub_start_image (grub_efi_handle_t handle)
+ }
+ 
+ static grub_err_t
+-grub_chainloader_unload (void)
++grub_chainloader_unload (void *context)
+ {
++  grub_efi_handle_t image_handle;
+   grub_efi_loaded_image_t *loaded_image;
+   grub_efi_boot_services_t *b;
+ 
++  image_handle = (grub_efi_handle_t) context;
++
+   loaded_image = grub_efi_get_loaded_image (image_handle);
+   if (loaded_image != NULL)
+     grub_free (loaded_image->load_options);
+@@ -115,10 +115,12 @@ grub_chainloader_unload (void)
+ }
+ 
+ static grub_err_t
+-grub_chainloader_boot (void)
++grub_chainloader_boot (void *context)
+ {
++  grub_efi_handle_t image_handle;
+   grub_err_t err;
+ 
++  image_handle = (grub_efi_handle_t) context;
+   err = grub_start_image (image_handle);
+ 
+   grub_loader_unset ();
+@@ -840,15 +842,17 @@ error_exit:
+ }
+ 
+ static grub_err_t
+-grub_secureboot_chainloader_unload (void)
++grub_secureboot_chainloader_unload (void *context)
+ {
++  struct grub_secureboot_chainloader_context *sb_context;
++
++  sb_context = (struct grub_secureboot_chainloader_context *) context;
++
+   grub_efi_free_pages (sb_context->address, sb_context->pages);
+   grub_free (sb_context->file_path);
+   grub_free (sb_context->cmdline);
+   grub_free (sb_context);
+ 
+-  sb_context = 0;
+-
+   grub_dl_unref (my_mod);
+   return GRUB_ERR_NONE;
+ }
+@@ -897,12 +901,15 @@ grub_load_image(grub_efi_device_path_t *file_path, void *boot_image,
+ }
+ 
+ static grub_err_t
+-grub_secureboot_chainloader_boot (void)
++grub_secureboot_chainloader_boot (void *context)
+ {
++  struct grub_secureboot_chainloader_context *sb_context;
+   grub_efi_boot_services_t *b;
+   int rc;
+   grub_efi_handle_t handle = 0;
+ 
++  sb_context = (struct grub_secureboot_chainloader_context *) context;
++
+   rc = handle_image (sb_context);
+   if (rc == 0)
+     {
+@@ -943,6 +950,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   grub_efi_char16_t *cmdline = 0;
+   grub_ssize_t cmdline_len = 0;
+   grub_efi_handle_t dev_handle = 0;
++  grub_efi_handle_t image_handle = 0;
++  struct grub_secureboot_chainloader_context *sb_context = 0;
+ 
+   if (argc == 0)
+     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+@@ -1124,8 +1133,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ 	dev = orig_dev;
+       grub_device_close (dev);
+ 
+-      grub_loader_set (grub_secureboot_chainloader_boot,
+-		       grub_secureboot_chainloader_unload, 0);
++      grub_loader_set_ex (grub_secureboot_chainloader_boot,
++			  grub_secureboot_chainloader_unload, sb_context, 0);
+       return 0;
+     }
+   else
+@@ -1141,7 +1150,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+       efi_call_2 (b->free_pages, address, pages);
+       grub_free (file_path);
+ 
+-      grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
++      grub_loader_set_ex (grub_chainloader_boot, grub_chainloader_unload, image_handle, 0);
+ 
+       return 0;
+     }
+@@ -1168,10 +1177,7 @@ fail:
+     grub_free (cmdline);
+ 
+   if (image_handle != 0)
+-    {
+-      efi_call_1 (b->unload_image, image_handle);
+-      image_handle = 0;
+-    }
++    efi_call_1 (b->unload_image, image_handle);
+ 
+   grub_dl_unref (my_mod);
+ 
diff -pruN 2.06-2/debian/patches/0133-loader-i386-efi-linux-Use-grub_loader_set_ex.patch 2.06-2ubuntu16/debian/patches/0133-loader-i386-efi-linux-Use-grub_loader_set_ex.patch
--- 2.06-2/debian/patches/0133-loader-i386-efi-linux-Use-grub_loader_set_ex.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0133-loader-i386-efi-linux-Use-grub_loader_set_ex.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,306 @@
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Mon, 2 May 2022 17:04:23 +0200
+Subject: loader/i386/efi/linux: Use grub_loader_set_ex
+
+This ports the linuxefi loader to use grub_loader_set_ex in order to fix
+a use-after-fre bug that occurs when grub_cmd_linux is executed more than
+once before a boot attempt is performed.
+
+This is more complicated than for the chainloader command, as the initrd
+command needs access to the loader state. To solve this, the linuxefi
+module registers a dummy initrd command at startup that returns an error.
+The linuxefi command then registers a proper initrd command with a higher
+priority that is passed the loader state.
+
+Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
+(cherry picked from commit 7cf736436b4c934df5ddfa6f44b46a7e07d99fdc)
+[rharwood/pjones: set kernel_size in context]
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ grub-core/loader/i386/efi/linux.c | 142 +++++++++++++++++++++++---------------
+ 1 file changed, 87 insertions(+), 55 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index cbd313a..cfe1096 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -32,55 +32,69 @@
+ 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;
++
++static grub_command_t cmd_linux, cmd_initrd;
++
++struct grub_linuxefi_context {
++  void *kernel_mem;
++  grub_uint64_t kernel_size;
++  grub_uint32_t handover_offset;
++  struct linux_kernel_params *params;
++  char *cmdline;
++
++  void *initrd_mem;
++};
+ 
+ #define BYTES_TO_PAGES(bytes)   (((bytes) + 0xfff) >> 12)
+ 
+ static grub_err_t
+-grub_linuxefi_boot (void)
++grub_linuxefi_boot (void *data)
+ {
++  struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) data;
++
+   asm volatile ("cli");
+ 
+-  return grub_efi_linux_boot ((char *)kernel_mem,
+-			      handover_offset,
+-			      params);
++  return grub_efi_linux_boot ((char *)context->kernel_mem,
++			      context->handover_offset,
++			      context->params);
+ }
+ 
+ static grub_err_t
+-grub_linuxefi_unload (void)
++grub_linuxefi_unload (void *data)
+ {
++  struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) data;
++  struct linux_kernel_params *params = context->params;
++
+   grub_dl_unref (my_mod);
+-  loaded = 0;
+-  if (initrd_mem)
+-    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem,
++
++  if (context->initrd_mem)
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->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,
++  if (context->cmdline)
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->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 (context->kernel_mem)
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->kernel_mem,
++			 BYTES_TO_PAGES(context->kernel_size));
+   if (params)
+     grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params,
+ 			 BYTES_TO_PAGES(16384));
++
++  cmd_initrd->data = 0;
++  grub_free (context);
++
+   return GRUB_ERR_NONE;
+ }
+ 
+ static grub_err_t
+-grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+-                 int argc, char *argv[])
++grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+ {
+   grub_file_t *files = 0;
+   int i, nfiles = 0;
+   grub_size_t size = 0;
+   grub_uint8_t *ptr;
++  struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) cmd->data;
++  struct linux_kernel_params *params;
+ 
+   if (argc == 0)
+     {
+@@ -88,12 +102,14 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-  if (!loaded)
++  if (!context)
+     {
+       grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
+       goto fail;
+     }
+ 
++  params = context->params;
++
+   files = grub_calloc (argc, sizeof (files[0]));
+   if (!files)
+     goto fail;
+@@ -111,20 +127,20 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ 	}
+     }
+ 
+-  initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
++  context->initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
+ 
+-  if (!initrd_mem)
++  if (context->initrd_mem == NULL)
+     {
+       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);
++  grub_dprintf ("linuxefi", "initrd_mem = %lx\n", (unsigned long) context->initrd_mem);
+ 
+   params->ramdisk_size = size;
+-  params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem;
++  params->ramdisk_image = (grub_uint32_t)(grub_addr_t) context->initrd_mem;
+ 
+-  ptr = initrd_mem;
++  ptr = context->initrd_mem;
+ 
+   for (i = 0; i < nfiles; i++)
+     {
+@@ -148,8 +164,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+     grub_file_close (files[i]);
+   grub_free (files);
+ 
+-  if (initrd_mem && grub_errno)
+-    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem,
++  if (context->initrd_mem && grub_errno)
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->initrd_mem,
+ 			 BYTES_TO_PAGES(size));
+ 
+   return grub_errno;
+@@ -169,6 +185,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_ssize_t start, filelen;
+   void *kernel = NULL;
+   int setup_header_end_offset;
++  void *kernel_mem = 0;
++  grub_uint64_t kernel_size = 0;
++  grub_uint32_t handover_offset;
++  struct linux_kernel_params *params = 0;
++  char *cmdline = 0;
++  struct grub_linuxefi_context *context = 0;
+ 
+   grub_dl_ref (my_mod);
+ 
+@@ -270,39 +292,39 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ #endif
+ 
+   grub_dprintf ("linuxefi", "setting up cmdline\n");
+-  linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
+-					 BYTES_TO_PAGES(lh->cmdline_size + 1));
+-  if (!linux_cmdline)
++  cmdline = grub_efi_allocate_pages_max(0x3fffffff,
++					BYTES_TO_PAGES(lh->cmdline_size + 1));
++  if (!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_dprintf ("linuxefi", "cmdline = %lx\n", (unsigned long)cmdline);
+ 
+-  grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
++  grub_memcpy (cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
+   grub_create_loader_cmdline (argc, argv,
+-                              linux_cmdline + sizeof (LINUX_IMAGE) - 1,
++                              cmdline + sizeof (LINUX_IMAGE) - 1,
+ 			      lh->cmdline_size - (sizeof (LINUX_IMAGE) - 1),
+ 			      GRUB_VERIFY_KERNEL_CMDLINE);
+ 
+   grub_dprintf ("linuxefi", "setting lh->cmd_line_ptr\n");
+-  lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
++  lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)cmdline;
+ 
+   grub_dprintf ("linuxefi", "computing handover offset\n");
+   handover_offset = lh->handover_offset;
+ 
+   start = (lh->setup_sects + 1) * 512;
+ 
++  kernel_size = lh->init_size;
+   kernel_mem = grub_efi_allocate_fixed(lh->pref_address,
+-				       BYTES_TO_PAGES(lh->init_size));
++				       BYTES_TO_PAGES(kernel_size));
+ 
+   if (!kernel_mem)
+     {
+       grub_error_pop();
+       kernel_mem = grub_efi_allocate_pages_max (
+-          0x3fffffff, BYTES_TO_PAGES (lh->init_size));
++          0x3fffffff, BYTES_TO_PAGES (kernel_size));
+     }
+ 
+   if (!kernel_mem)
+@@ -313,8 +335,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+   grub_dprintf ("linuxefi", "kernel_mem = %lx\n", (unsigned long) kernel_mem);
+ 
+-  grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
+-  loaded=1;
+   grub_dprintf ("linuxefi", "setting lh->code32_start to %p\n", kernel_mem);
+   lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
+ 
+@@ -329,6 +349,23 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_dprintf("linuxefi", "kernel_mem: %p handover_offset: %08x\n",
+ 	       kernel_mem, handover_offset);
+ 
++  context = grub_zalloc (sizeof (*context));
++  if (!context)
++    goto fail;
++  context->kernel_mem = kernel_mem;
++  context->kernel_size = kernel_size;
++  context->handover_offset = handover_offset;
++  context->params = params;
++  context->cmdline = cmdline;
++
++  grub_loader_set_ex (grub_linuxefi_boot, grub_linuxefi_unload, context, 0);
++
++  cmd_initrd->data = context;
++
++  grub_file_close (file);
++  grub_free (kernel);
++  return 0;
++
+  fail:
+   if (file)
+     grub_file_close (file);
+@@ -336,30 +373,25 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   if (kernel)
+     grub_free (kernel);
+ 
+-  if (grub_errno != GRUB_ERR_NONE)
+-    {
+-      grub_dl_unref (my_mod);
+-      loaded = 0;
+-    }
++  grub_dl_unref (my_mod);
+ 
+-  if (linux_cmdline && lh && !loaded)
+-    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
+-			 linux_cmdline,
++  if (cmdline && lh)
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)cmdline,
+ 			 BYTES_TO_PAGES(lh->cmdline_size + 1));
+ 
+-  if (kernel_mem && !loaded)
++  if (kernel_mem)
+     grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem,
+ 			 BYTES_TO_PAGES(kernel_size));
+ 
+-  if (params && !loaded)
++  if (params)
+     grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params,
+ 			 sizeof(*params));
+ 
++  grub_free (context);
++
+   return grub_errno;
+ }
+ 
+-static grub_command_t cmd_linux, cmd_initrd;
+-
+ GRUB_MOD_INIT(linuxefi)
+ {
+   cmd_linux =
diff -pruN 2.06-2/debian/patches/0134-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch 2.06-2ubuntu16/debian/patches/0134-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch
--- 2.06-2/debian/patches/0134-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0134-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,72 @@
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Tue, 3 May 2022 09:47:35 +0200
+Subject: loader/i386/efi/linux: Fix a memory leak in the initrd command
+
+Subsequent invocations of the initrd command result in the previous
+initrd being leaked, so fix that.
+
+Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
+(cherry picked from commit d98af31ce1e31bb22163960d53f5eb28c66582a0)
+---
+ grub-core/loader/i386/efi/linux.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index cfe1096..639e84a 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -95,6 +95,7 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+   grub_uint8_t *ptr;
+   struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) cmd->data;
+   struct linux_kernel_params *params;
++  void *initrd_mem = 0;
+ 
+   if (argc == 0)
+     {
+@@ -127,9 +128,9 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+ 	}
+     }
+ 
+-  context->initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
++  initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
+ 
+-  if (context->initrd_mem == NULL)
++  if (initrd_mem == NULL)
+     {
+       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
+       goto fail;
+@@ -138,9 +139,9 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+   grub_dprintf ("linuxefi", "initrd_mem = %lx\n", (unsigned long) context->initrd_mem);
+ 
+   params->ramdisk_size = size;
+-  params->ramdisk_image = (grub_uint32_t)(grub_addr_t) context->initrd_mem;
++  params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem;
+ 
+-  ptr = context->initrd_mem;
++  ptr = initrd_mem;
+ 
+   for (i = 0; i < nfiles; i++)
+     {
+@@ -157,6 +158,11 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+       ptr += ALIGN_UP_OVERHEAD (cursize, 4);
+     }
+ 
++  if (context->initrd_mem)
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->initrd_mem,
++			 BYTES_TO_PAGES(params->ramdisk_size));
++
++  context->initrd_mem = initrd_mem;
+   params->ramdisk_size = size;
+ 
+  fail:
+@@ -164,8 +170,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+     grub_file_close (files[i]);
+   grub_free (files);
+ 
+-  if (context->initrd_mem && grub_errno)
+-    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->initrd_mem,
++  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;
diff -pruN 2.06-2/debian/patches/0135-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch 2.06-2ubuntu16/debian/patches/0135-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
--- 2.06-2/debian/patches/0135-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0135-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,98 @@
+From: Julian Andres Klode <julian.klode@canonical.com>
+Date: Thu, 2 Dec 2021 15:03:53 +0100
+Subject: kern/efi/sb: Reject non-kernel files in the shim_lock verifier
+
+We must not allow other verifiers to pass things like the GRUB modules.
+Instead of maintaining a blocklist, maintain an allowlist of things
+that we do not care about.
+
+This allowlist really should be made reusable, and shared by the
+lockdown verifier, but this is the minimal patch addressing
+security concerns where the TPM verifier was able to mark modules
+as verified (or the OpenPGP verifier for that matter), when it
+should not do so on shim-powered secure boot systems.
+
+Fixes: CVE-2022-28735
+
+Signed-off-by: Julian Andres Klode <julian.klode@canonical.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/kern/efi/sb.c | 39 ++++++++++++++++++++++++++++++++++++---
+ include/grub/verify.h   |  1 +
+ 2 files changed, 37 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
+index c52ec62..89c4bb3 100644
+--- a/grub-core/kern/efi/sb.c
++++ b/grub-core/kern/efi/sb.c
+@@ -119,10 +119,11 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
+ 			 void **context __attribute__ ((unused)),
+ 			 enum grub_verify_flags *flags)
+ {
+-  *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
++  *flags = GRUB_VERIFY_FLAGS_NONE;
+ 
+   switch (type & GRUB_FILE_TYPE_MASK)
+     {
++    /* Files we check. */
+     case GRUB_FILE_TYPE_LINUX_KERNEL:
+     case GRUB_FILE_TYPE_MULTIBOOT_KERNEL:
+     case GRUB_FILE_TYPE_BSD_KERNEL:
+@@ -130,11 +131,43 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
+     case GRUB_FILE_TYPE_PLAN9_KERNEL:
+     case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE:
+       *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
++      return GRUB_ERR_NONE;
+ 
+-      /* Fall through. */
++    /* Files that do not affect secureboot state. */
++    case GRUB_FILE_TYPE_NONE:
++    case GRUB_FILE_TYPE_LOOPBACK:
++    case GRUB_FILE_TYPE_LINUX_INITRD:
++    case GRUB_FILE_TYPE_OPENBSD_RAMDISK:
++    case GRUB_FILE_TYPE_XNU_RAMDISK:
++    case GRUB_FILE_TYPE_SIGNATURE:
++    case GRUB_FILE_TYPE_PUBLIC_KEY:
++    case GRUB_FILE_TYPE_PUBLIC_KEY_TRUST:
++    case GRUB_FILE_TYPE_PRINT_BLOCKLIST:
++    case GRUB_FILE_TYPE_TESTLOAD:
++    case GRUB_FILE_TYPE_GET_SIZE:
++    case GRUB_FILE_TYPE_FONT:
++    case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY:
++    case GRUB_FILE_TYPE_CAT:
++    case GRUB_FILE_TYPE_HEXCAT:
++    case GRUB_FILE_TYPE_CMP:
++    case GRUB_FILE_TYPE_HASHLIST:
++    case GRUB_FILE_TYPE_TO_HASH:
++    case GRUB_FILE_TYPE_KEYBOARD_LAYOUT:
++    case GRUB_FILE_TYPE_PIXMAP:
++    case GRUB_FILE_TYPE_GRUB_MODULE_LIST:
++    case GRUB_FILE_TYPE_CONFIG:
++    case GRUB_FILE_TYPE_THEME:
++    case GRUB_FILE_TYPE_GETTEXT_CATALOG:
++    case GRUB_FILE_TYPE_FS_SEARCH:
++    case GRUB_FILE_TYPE_LOADENV:
++    case GRUB_FILE_TYPE_SAVEENV:
++    case GRUB_FILE_TYPE_VERIFY_SIGNATURE:
++      *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
++      return GRUB_ERR_NONE;
+ 
++    /* Other files. */
+     default:
+-      return GRUB_ERR_NONE;
++      return grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited by secure boot policy"));
+     }
+ }
+ 
+diff --git a/include/grub/verify.h b/include/grub/verify.h
+index 6fde244..6744816 100644
+--- a/include/grub/verify.h
++++ b/include/grub/verify.h
+@@ -24,6 +24,7 @@
+ 
+ enum grub_verify_flags
+   {
++    GRUB_VERIFY_FLAGS_NONE		= 0,
+     GRUB_VERIFY_FLAGS_SKIP_VERIFICATION	= 1,
+     GRUB_VERIFY_FLAGS_SINGLE_CHUNK	= 2,
+     /* Defer verification to another authority. */
diff -pruN 2.06-2/debian/patches/0136-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch 2.06-2ubuntu16/debian/patches/0136-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch
--- 2.06-2/debian/patches/0136-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0136-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,36 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Fri, 25 Jun 2021 02:19:05 +1000
+Subject: kern/file: Do not leak device_name on error in grub_file_open()
+
+If we have an error in grub_file_open() before we free device_name, we
+will leak it.
+
+Free device_name in the error path and null out the pointer in the good
+path once we free it there.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/kern/file.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
+index 5845445..ffdcaba 100644
+--- a/grub-core/kern/file.c
++++ b/grub-core/kern/file.c
+@@ -79,6 +79,7 @@ grub_file_open (const char *name, enum grub_file_type type)
+ 
+   device = grub_device_open (device_name);
+   grub_free (device_name);
++  device_name = NULL;
+   if (! device)
+     goto fail;
+ 
+@@ -131,6 +132,7 @@ grub_file_open (const char *name, enum grub_file_type type)
+   return file;
+ 
+  fail:
++  grub_free (device_name);
+   if (device)
+     grub_device_close (device);
+ 
diff -pruN 2.06-2/debian/patches/0137-video-readers-png-Abort-sooner-if-a-read-operation-f.patch 2.06-2ubuntu16/debian/patches/0137-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
--- 2.06-2/debian/patches/0137-video-readers-png-Abort-sooner-if-a-read-operation-f.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0137-video-readers-png-Abort-sooner-if-a-read-operation-f.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,196 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 6 Jul 2021 14:02:55 +1000
+Subject: video/readers/png: Abort sooner if a read operation fails
+
+Fuzzing revealed some inputs that were taking a long time, potentially
+forever, because they did not bail quickly upon encountering an I/O error.
+
+Try to catch I/O errors sooner and bail out.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/png.c | 55 ++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 47 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
+index 0157ff7..e2a6b1c 100644
+--- a/grub-core/video/readers/png.c
++++ b/grub-core/video/readers/png.c
+@@ -142,6 +142,7 @@ static grub_uint8_t
+ grub_png_get_byte (struct grub_png_data *data)
+ {
+   grub_uint8_t r;
++  grub_ssize_t bytes_read = 0;
+ 
+   if ((data->inside_idat) && (data->idat_remain == 0))
+     {
+@@ -175,7 +176,14 @@ grub_png_get_byte (struct grub_png_data *data)
+     }
+ 
+   r = 0;
+-  grub_file_read (data->file, &r, 1);
++  bytes_read = grub_file_read (data->file, &r, 1);
++
++  if (bytes_read != 1)
++    {
++      grub_error (GRUB_ERR_BAD_FILE_TYPE,
++		  "png: unexpected end of data");
++      return 0;
++    }
+ 
+   if (data->inside_idat)
+     data->idat_remain--;
+@@ -231,15 +239,16 @@ grub_png_decode_image_palette (struct grub_png_data *data,
+   if (len == 0)
+     return GRUB_ERR_NONE;
+ 
+-  for (i = 0; 3 * i < len && i < 256; i++)
++  grub_errno = GRUB_ERR_NONE;
++  for (i = 0; 3 * i < len && i < 256 && grub_errno == GRUB_ERR_NONE; i++)
+     for (j = 0; j < 3; j++)
+       data->palette[i][j] = grub_png_get_byte (data);
+-  for (i *= 3; i < len; i++)
++  for (i *= 3; i < len && grub_errno == GRUB_ERR_NONE; i++)
+     grub_png_get_byte (data);
+ 
+   grub_png_get_dword (data);
+ 
+-  return GRUB_ERR_NONE;
++  return grub_errno;
+ }
+ 
+ static grub_err_t
+@@ -256,9 +265,13 @@ grub_png_decode_image_header (struct grub_png_data *data)
+     return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid image size");
+ 
+   color_bits = grub_png_get_byte (data);
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
+   data->is_16bit = (color_bits == 16);
+ 
+   color_type = grub_png_get_byte (data);
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
+ 
+   /* According to PNG spec, no other types are valid.  */
+   if ((color_type & ~(PNG_COLOR_MASK_ALPHA | PNG_COLOR_MASK_COLOR))
+@@ -340,14 +353,20 @@ grub_png_decode_image_header (struct grub_png_data *data)
+   if (grub_png_get_byte (data) != PNG_COMPRESSION_BASE)
+     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ 		       "png: compression method not supported");
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
+ 
+   if (grub_png_get_byte (data) != PNG_FILTER_TYPE_BASE)
+     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ 		       "png: filter method not supported");
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
+ 
+   if (grub_png_get_byte (data) != PNG_INTERLACE_NONE)
+     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ 		       "png: interlace method not supported");
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
+ 
+   /* Skip crc checksum.  */
+   grub_png_get_dword (data);
+@@ -449,7 +468,7 @@ grub_png_get_huff_code (struct grub_png_data *data, struct huff_table *ht)
+   int code, i;
+ 
+   code = 0;
+-  for (i = 0; i < ht->max_length; i++)
++  for (i = 0; i < ht->max_length && grub_errno == GRUB_ERR_NONE; i++)
+     {
+       code = (code << 1) + grub_png_get_bits (data, 1);
+       if (code < ht->maxval[i])
+@@ -504,8 +523,14 @@ grub_png_init_dynamic_block (struct grub_png_data *data)
+   grub_uint8_t lens[DEFLATE_HCLEN_MAX];
+ 
+   nl = DEFLATE_HLIT_BASE + grub_png_get_bits (data, 5);
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
+   nd = DEFLATE_HDIST_BASE + grub_png_get_bits (data, 5);
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
+   nb = DEFLATE_HCLEN_BASE + grub_png_get_bits (data, 4);
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
+ 
+   if ((nl > DEFLATE_HLIT_MAX) || (nd > DEFLATE_HDIST_MAX) ||
+       (nb > DEFLATE_HCLEN_MAX))
+@@ -533,7 +558,7 @@ grub_png_init_dynamic_block (struct grub_png_data *data)
+ 			    data->dist_offset);
+ 
+   prev = 0;
+-  for (i = 0; i < nl + nd; i++)
++  for (i = 0; i < nl + nd && grub_errno == GRUB_ERR_NONE; i++)
+     {
+       int n, code;
+       struct huff_table *ht;
+@@ -721,17 +746,21 @@ grub_png_read_dynamic_block (struct grub_png_data *data)
+ 	  len = cplens[n];
+ 	  if (cplext[n])
+ 	    len += grub_png_get_bits (data, cplext[n]);
++	  if (grub_errno != GRUB_ERR_NONE)
++	    return grub_errno;
+ 
+ 	  n = grub_png_get_huff_code (data, &data->dist_table);
+ 	  dist = cpdist[n];
+ 	  if (cpdext[n])
+ 	    dist += grub_png_get_bits (data, cpdext[n]);
++	  if (grub_errno != GRUB_ERR_NONE)
++	    return grub_errno;
+ 
+ 	  pos = data->wp - dist;
+ 	  if (pos < 0)
+ 	    pos += WSIZE;
+ 
+-	  while (len > 0)
++	  while (len > 0 && grub_errno == GRUB_ERR_NONE)
+ 	    {
+ 	      data->slide[data->wp] = data->slide[pos];
+ 	      grub_png_output_byte (data, data->slide[data->wp]);
+@@ -759,7 +788,11 @@ grub_png_decode_image_data (struct grub_png_data *data)
+   int final;
+ 
+   cmf = grub_png_get_byte (data);
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
+   flg = grub_png_get_byte (data);
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
+ 
+   if ((cmf & 0xF) != Z_DEFLATED)
+     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+@@ -774,7 +807,11 @@ grub_png_decode_image_data (struct grub_png_data *data)
+       int block_type;
+ 
+       final = grub_png_get_bits (data, 1);
++      if (grub_errno != GRUB_ERR_NONE)
++	return grub_errno;
+       block_type = grub_png_get_bits (data, 2);
++      if (grub_errno != GRUB_ERR_NONE)
++	return grub_errno;
+ 
+       switch (block_type)
+ 	{
+@@ -790,7 +827,7 @@ grub_png_decode_image_data (struct grub_png_data *data)
+ 	    grub_png_get_byte (data);
+ 	    grub_png_get_byte (data);
+ 
+-	    for (i = 0; i < len; i++)
++	    for (i = 0; i < len && grub_errno == GRUB_ERR_NONE; i++)
+ 	      grub_png_output_byte (data, grub_png_get_byte (data));
+ 
+ 	    break;
+@@ -1045,6 +1082,8 @@ grub_png_decode_png (struct grub_png_data *data)
+ 
+       len = grub_png_get_dword (data);
+       type = grub_png_get_dword (data);
++      if (grub_errno != GRUB_ERR_NONE)
++	break;
+       data->next_offset = data->file->offset + len + 4;
+ 
+       switch (type)
diff -pruN 2.06-2/debian/patches/0138-video-readers-png-Refuse-to-handle-multiple-image-he.patch 2.06-2ubuntu16/debian/patches/0138-video-readers-png-Refuse-to-handle-multiple-image-he.patch
--- 2.06-2/debian/patches/0138-video-readers-png-Refuse-to-handle-multiple-image-he.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0138-video-readers-png-Refuse-to-handle-multiple-image-he.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,26 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 6 Jul 2021 14:13:40 +1000
+Subject: video/readers/png: Refuse to handle multiple image headers
+
+This causes the bitmap to be leaked. Do not permit multiple image headers.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/png.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
+index e2a6b1c..8955b8e 100644
+--- a/grub-core/video/readers/png.c
++++ b/grub-core/video/readers/png.c
+@@ -258,6 +258,9 @@ grub_png_decode_image_header (struct grub_png_data *data)
+   int color_bits;
+   enum grub_video_blit_format blt;
+ 
++  if (data->image_width || data->image_height)
++    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: two image headers found");
++
+   data->image_width = grub_png_get_dword (data);
+   data->image_height = grub_png_get_dword (data);
+ 
diff -pruN 2.06-2/debian/patches/0139-video-readers-png-Drop-greyscale-support-to-fix-heap.patch 2.06-2ubuntu16/debian/patches/0139-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
--- 2.06-2/debian/patches/0139-video-readers-png-Drop-greyscale-support-to-fix-heap.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0139-video-readers-png-Drop-greyscale-support-to-fix-heap.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,167 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 6 Jul 2021 18:51:35 +1000
+Subject: video/readers/png: Drop greyscale support to fix heap out-of-bounds
+ write
+
+A 16-bit greyscale PNG without alpha is processed in the following loop:
+
+      for (i = 0; i < (data->image_width * data->image_height);
+	   i++, d1 += 4, d2 += 2)
+	{
+	  d1[R3] = d2[1];
+	  d1[G3] = d2[1];
+	  d1[B3] = d2[1];
+	}
+
+The increment of d1 is wrong. d1 is incremented by 4 bytes per iteration,
+but there are only 3 bytes allocated for storage. This means that image
+data will overwrite somewhat-attacker-controlled parts of memory - 3 bytes
+out of every 4 following the end of the image.
+
+This has existed since greyscale support was added in 2013 in commit
+3ccf16dff98f (grub-core/video/readers/png.c: Support grayscale).
+
+Saving starfield.png as a 16-bit greyscale image without alpha in the gimp
+and attempting to load it causes grub-emu to crash - I don't think this code
+has ever worked.
+
+Delete all PNG greyscale support.
+
+Fixes: CVE-2021-3695
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/png.c | 87 ++++---------------------------------------
+ 1 file changed, 7 insertions(+), 80 deletions(-)
+
+diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
+index 8955b8e..a3161e2 100644
+--- a/grub-core/video/readers/png.c
++++ b/grub-core/video/readers/png.c
+@@ -100,7 +100,7 @@ struct grub_png_data
+ 
+   unsigned image_width, image_height;
+   int bpp, is_16bit;
+-  int raw_bytes, is_gray, is_alpha, is_palette;
++  int raw_bytes, is_alpha, is_palette;
+   int row_bytes, color_bits;
+   grub_uint8_t *image_data;
+ 
+@@ -296,13 +296,13 @@ grub_png_decode_image_header (struct grub_png_data *data)
+     data->bpp = 3;
+   else
+     {
+-      data->is_gray = 1;
+-      data->bpp = 1;
++      return grub_error (GRUB_ERR_BAD_FILE_TYPE,
++			 "png: color type not supported");
+     }
+ 
+   if ((color_bits != 8) && (color_bits != 16)
+       && (color_bits != 4
+-	  || !(data->is_gray || data->is_palette)))
++	  || !data->is_palette))
+     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                        "png: bit depth must be 8 or 16");
+ 
+@@ -331,7 +331,7 @@ grub_png_decode_image_header (struct grub_png_data *data)
+     }
+ 
+ #ifndef GRUB_CPU_WORDS_BIGENDIAN
+-  if (data->is_16bit || data->is_gray || data->is_palette)
++  if (data->is_16bit || data->is_palette)
+ #endif
+     {
+       data->image_data = grub_calloc (data->image_height, data->row_bytes);
+@@ -899,27 +899,8 @@ grub_png_convert_image (struct grub_png_data *data)
+       int shift;
+       int mask = (1 << data->color_bits) - 1;
+       unsigned j;
+-      if (data->is_gray)
+-	{
+-	  /* Generic formula is
+-	     (0xff * i) / ((1U << data->color_bits) - 1)
+-	     but for allowed bit depth of 1, 2 and for it's
+-	     equivalent to
+-	     (0xff / ((1U << data->color_bits) - 1)) * i
+-	     Precompute the multipliers to avoid division.
+-	  */
+-
+-	  const grub_uint8_t multipliers[5] = { 0xff, 0xff, 0x55, 0x24, 0x11 };
+-	  for (i = 0; i < (1U << data->color_bits); i++)
+-	    {
+-	      grub_uint8_t col = multipliers[data->color_bits] * i;
+-	      palette[i][0] = col;
+-	      palette[i][1] = col;
+-	      palette[i][2] = col;
+-	    }
+-	}
+-      else
+-	grub_memcpy (palette, data->palette, 3 << data->color_bits);
++
++      grub_memcpy (palette, data->palette, 3 << data->color_bits);
+       d1c = d1;
+       d2c = d2;
+       for (j = 0; j < data->image_height; j++, d1c += data->image_width * 3,
+@@ -956,60 +937,6 @@ grub_png_convert_image (struct grub_png_data *data)
+ 	}
+       return;
+     }
+-  
+-  if (data->is_gray)
+-    {
+-      switch (data->bpp)
+-	{
+-	case 4:
+-	  /* 16-bit gray with alpha.  */
+-	  for (i = 0; i < (data->image_width * data->image_height);
+-	       i++, d1 += 4, d2 += 4)
+-	    {
+-	      d1[R4] = d2[3];
+-	      d1[G4] = d2[3];
+-	      d1[B4] = d2[3];
+-	      d1[A4] = d2[1];
+-	    }
+-	  break;
+-	case 2:
+-	  if (data->is_16bit)
+-	    /* 16-bit gray without alpha.  */
+-	    {
+-	      for (i = 0; i < (data->image_width * data->image_height);
+-		   i++, d1 += 4, d2 += 2)
+-		{
+-		  d1[R3] = d2[1];
+-		  d1[G3] = d2[1];
+-		  d1[B3] = d2[1];
+-		}
+-	    }
+-	  else
+-	    /* 8-bit gray with alpha.  */
+-	    {
+-	      for (i = 0; i < (data->image_width * data->image_height);
+-		   i++, d1 += 4, d2 += 2)
+-		{
+-		  d1[R4] = d2[1];
+-		  d1[G4] = d2[1];
+-		  d1[B4] = d2[1];
+-		  d1[A4] = d2[0];
+-		}
+-	    }
+-	  break;
+-	  /* 8-bit gray without alpha.  */
+-	case 1:
+-	  for (i = 0; i < (data->image_width * data->image_height);
+-	       i++, d1 += 3, d2++)
+-	    {
+-	      d1[R3] = d2[0];
+-	      d1[G3] = d2[0];
+-	      d1[B3] = d2[0];
+-	    }
+-	  break;
+-	}
+-      return;
+-    }
+ 
+     {
+   /* Only copy the upper 8 bit.  */
diff -pruN 2.06-2/debian/patches/0140-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch 2.06-2ubuntu16/debian/patches/0140-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch
--- 2.06-2/debian/patches/0140-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0140-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,37 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 6 Jul 2021 23:25:07 +1000
+Subject: video/readers/png: Avoid heap OOB R/W inserting huff table items
+
+In fuzzing we observed crashes where a code would attempt to be inserted
+into a huffman table before the start, leading to a set of heap OOB reads
+and writes as table entries with negative indices were shifted around and
+the new code written in.
+
+Catch the case where we would underflow the array and bail.
+
+Fixes: CVE-2021-3696
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/png.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
+index a3161e2..d7ed5aa 100644
+--- a/grub-core/video/readers/png.c
++++ b/grub-core/video/readers/png.c
+@@ -438,6 +438,13 @@ grub_png_insert_huff_item (struct huff_table *ht, int code, int len)
+   for (i = len; i < ht->max_length; i++)
+     n += ht->maxval[i];
+ 
++  if (n > ht->num_values)
++    {
++      grub_error (GRUB_ERR_BAD_FILE_TYPE,
++		  "png: out of range inserting huffman table item");
++      return;
++    }
++
+   for (i = 0; i < n; i++)
+     ht->values[ht->num_values - i] = ht->values[ht->num_values - i - 1];
+ 
diff -pruN 2.06-2/debian/patches/0141-video-readers-png-Sanity-check-some-huffman-codes.patch 2.06-2ubuntu16/debian/patches/0141-video-readers-png-Sanity-check-some-huffman-codes.patch
--- 2.06-2/debian/patches/0141-video-readers-png-Sanity-check-some-huffman-codes.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0141-video-readers-png-Sanity-check-some-huffman-codes.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,38 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 6 Jul 2021 19:19:11 +1000
+Subject: video/readers/png: Sanity check some huffman codes
+
+ASAN picked up two OOB global reads: we weren't checking if some code
+values fit within the cplens or cpdext arrays. Check and throw an error
+if not.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/png.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
+index d7ed5aa..7f2ba78 100644
+--- a/grub-core/video/readers/png.c
++++ b/grub-core/video/readers/png.c
+@@ -753,6 +753,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data)
+ 	  int len, dist, pos;
+ 
+ 	  n -= 257;
++	  if (((unsigned int) n) >= ARRAY_SIZE (cplens))
++	    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
++			       "png: invalid huff code");
+ 	  len = cplens[n];
+ 	  if (cplext[n])
+ 	    len += grub_png_get_bits (data, cplext[n]);
+@@ -760,6 +763,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data)
+ 	    return grub_errno;
+ 
+ 	  n = grub_png_get_huff_code (data, &data->dist_table);
++	  if (((unsigned int) n) >= ARRAY_SIZE (cpdist))
++	    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
++			       "png: invalid huff code");
+ 	  dist = cpdist[n];
+ 	  if (cpdext[n])
+ 	    dist += grub_png_get_bits (data, cpdext[n]);
diff -pruN 2.06-2/debian/patches/0142-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch 2.06-2ubuntu16/debian/patches/0142-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
--- 2.06-2/debian/patches/0142-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0142-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,253 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Mon, 28 Jun 2021 14:16:14 +1000
+Subject: video/readers/jpeg: Abort sooner if a read operation fails
+
+Fuzzing revealed some inputs that were taking a long time, potentially
+forever, because they did not bail quickly upon encountering an I/O error.
+
+Try to catch I/O errors sooner and bail out.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/jpeg.c | 86 ++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 70 insertions(+), 16 deletions(-)
+
+diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
+index e31602f..10225ab 100644
+--- a/grub-core/video/readers/jpeg.c
++++ b/grub-core/video/readers/jpeg.c
+@@ -109,9 +109,17 @@ static grub_uint8_t
+ grub_jpeg_get_byte (struct grub_jpeg_data *data)
+ {
+   grub_uint8_t r;
++  grub_ssize_t bytes_read;
+ 
+   r = 0;
+-  grub_file_read (data->file, &r, 1);
++  bytes_read = grub_file_read (data->file, &r, 1);
++
++  if (bytes_read != 1)
++    {
++      grub_error (GRUB_ERR_BAD_FILE_TYPE,
++		  "jpeg: unexpected end of data");
++      return 0;
++    }
+ 
+   return r;
+ }
+@@ -120,9 +128,17 @@ static grub_uint16_t
+ grub_jpeg_get_word (struct grub_jpeg_data *data)
+ {
+   grub_uint16_t r;
++  grub_ssize_t bytes_read;
+ 
+   r = 0;
+-  grub_file_read (data->file, &r, sizeof (grub_uint16_t));
++  bytes_read = grub_file_read (data->file, &r, sizeof (grub_uint16_t));
++
++  if (bytes_read != sizeof (grub_uint16_t))
++    {
++      grub_error (GRUB_ERR_BAD_FILE_TYPE,
++		  "jpeg: unexpected end of data");
++      return 0;
++    }
+ 
+   return grub_be_to_cpu16 (r);
+ }
+@@ -135,6 +151,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data)
+   if (data->bit_mask == 0)
+     {
+       data->bit_save = grub_jpeg_get_byte (data);
++      if (grub_errno != GRUB_ERR_NONE) {
++	grub_error (GRUB_ERR_BAD_FILE_TYPE,
++		    "jpeg: file read error");
++	return 0;
++      }
+       if (data->bit_save == JPEG_ESC_CHAR)
+ 	{
+ 	  if (grub_jpeg_get_byte (data) != 0)
+@@ -143,6 +164,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data)
+ 			  "jpeg: invalid 0xFF in data stream");
+ 	      return 0;
+ 	    }
++	  if (grub_errno != GRUB_ERR_NONE)
++	    {
++	      grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: file read error");
++	      return 0;
++	    }
+ 	}
+       data->bit_mask = 0x80;
+     }
+@@ -161,7 +187,7 @@ grub_jpeg_get_number (struct grub_jpeg_data *data, int num)
+     return 0;
+ 
+   msb = value = grub_jpeg_get_bit (data);
+-  for (i = 1; i < num; i++)
++  for (i = 1; i < num && grub_errno == GRUB_ERR_NONE; i++)
+     value = (value << 1) + (grub_jpeg_get_bit (data) != 0);
+   if (!msb)
+     value += 1 - (1 << num);
+@@ -202,6 +228,8 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data)
+   while (data->file->offset + sizeof (count) + 1 <= next_marker)
+     {
+       id = grub_jpeg_get_byte (data);
++      if (grub_errno != GRUB_ERR_NONE)
++	return grub_errno;
+       ac = (id >> 4) & 1;
+       id &= 0xF;
+       if (id > 1)
+@@ -252,6 +280,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
+ 
+   next_marker = data->file->offset;
+   next_marker += grub_jpeg_get_word (data);
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
+ 
+   if (next_marker > data->file->size)
+     {
+@@ -263,6 +293,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
+ 	 <= next_marker)
+     {
+       id = grub_jpeg_get_byte (data);
++      if (grub_errno != GRUB_ERR_NONE)
++        return grub_errno;
+       if (id >= 0x10)		/* Upper 4-bit is precision.  */
+ 	return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ 			   "jpeg: only 8-bit precision is supported");
+@@ -294,6 +326,9 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
+   next_marker = data->file->offset;
+   next_marker += grub_jpeg_get_word (data);
+ 
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
++
+   if (grub_jpeg_get_byte (data) != 8)
+     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ 		       "jpeg: only 8-bit precision is supported");
+@@ -319,6 +354,8 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
+ 	return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
+ 
+       ss = grub_jpeg_get_byte (data);	/* Sampling factor.  */
++      if (grub_errno != GRUB_ERR_NONE)
++	return grub_errno;
+       if (!id)
+ 	{
+ 	  grub_uint8_t vs, hs;
+@@ -498,7 +535,7 @@ grub_jpeg_idct_transform (jpeg_data_unit_t du)
+     }
+ }
+ 
+-static void
++static grub_err_t
+ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
+ {
+   int h1, h2, qt;
+@@ -513,6 +550,9 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
+   data->dc_value[id] +=
+     grub_jpeg_get_number (data, grub_jpeg_get_huff_code (data, h1));
+ 
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
++
+   du[0] = data->dc_value[id] * (int) data->quan_table[qt][0];
+   pos = 1;
+   while (pos < ARRAY_SIZE (data->quan_table[qt]))
+@@ -527,11 +567,13 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
+       num >>= 4;
+       pos += num;
+ 
++      if (grub_errno != GRUB_ERR_NONE)
++        return grub_errno;
++
+       if (pos >= ARRAY_SIZE (jpeg_zigzag_order))
+ 	{
+-	  grub_error (GRUB_ERR_BAD_FILE_TYPE,
+-		      "jpeg: invalid position in zigzag order!?");
+-	  return;
++	  return grub_error (GRUB_ERR_BAD_FILE_TYPE,
++			     "jpeg: invalid position in zigzag order!?");
+ 	}
+ 
+       du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos];
+@@ -539,6 +581,7 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
+     }
+ 
+   grub_jpeg_idct_transform (du);
++  return GRUB_ERR_NONE;
+ }
+ 
+ static void
+@@ -597,7 +640,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
+   data_offset += grub_jpeg_get_word (data);
+ 
+   cc = grub_jpeg_get_byte (data);
+-
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
+   if (cc != 3 && cc != 1)
+     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ 		       "jpeg: component count must be 1 or 3");
+@@ -610,7 +654,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
+       id = grub_jpeg_get_byte (data) - 1;
+       if ((id < 0) || (id >= 3))
+ 	return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
+-
++      if (grub_errno != GRUB_ERR_NONE)
++	return grub_errno;
+       ht = grub_jpeg_get_byte (data);
+       data->comp_index[id][1] = (ht >> 4);
+       data->comp_index[id][2] = (ht & 0xF) + 2;
+@@ -618,11 +663,14 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
+       if ((data->comp_index[id][1] < 0) || (data->comp_index[id][1] > 3) ||
+ 	  (data->comp_index[id][2] < 0) || (data->comp_index[id][2] > 3))
+ 	return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid hufftable index");
++      if (grub_errno != GRUB_ERR_NONE)
++	return grub_errno;
+     }
+ 
+   grub_jpeg_get_byte (data);	/* Skip 3 unused bytes.  */
+   grub_jpeg_get_word (data);
+-
++  if (grub_errno != GRUB_ERR_NONE)
++    return grub_errno;
+   if (data->file->offset != data_offset)
+     return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos");
+ 
+@@ -640,6 +688,7 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
+ {
+   unsigned c1, vb, hb, nr1, nc1;
+   int rst = data->dri;
++  grub_err_t err = GRUB_ERR_NONE;
+ 
+   vb = 8 << data->log_vs;
+   hb = 8 << data->log_hs;
+@@ -660,17 +709,22 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
+ 
+ 	for (r2 = 0; r2 < (1U << data->log_vs); r2++)
+ 	  for (c2 = 0; c2 < (1U << data->log_hs); c2++)
+-	    grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]);
++            {
++              err = grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]);
++              if (err != GRUB_ERR_NONE)
++                return err;
++            }
+ 
+ 	if (data->color_components >= 3)
+ 	  {
+-	    grub_jpeg_decode_du (data, 1, data->cbdu);
+-	    grub_jpeg_decode_du (data, 2, data->crdu);
++	    err = grub_jpeg_decode_du (data, 1, data->cbdu);
++	    if (err != GRUB_ERR_NONE)
++	      return err;
++	    err = grub_jpeg_decode_du (data, 2, data->crdu);
++	    if (err != GRUB_ERR_NONE)
++	      return err;
+ 	  }
+ 
+-	if (grub_errno)
+-	  return grub_errno;
+-
+ 	nr2 = (data->r1 == nr1 - 1) ? (data->image_height - data->r1 * vb) : vb;
+ 	nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb;
+ 
diff -pruN 2.06-2/debian/patches/0143-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch 2.06-2ubuntu16/debian/patches/0143-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch
--- 2.06-2/debian/patches/0143-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0143-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,27 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Mon, 28 Jun 2021 14:16:58 +1000
+Subject: video/readers/jpeg: Do not reallocate a given huff table
+
+Fix a memory leak where an invalid file could cause us to reallocate
+memory for a huffman table we had already allocated memory for.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/jpeg.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
+index 10225ab..caa211f 100644
+--- a/grub-core/video/readers/jpeg.c
++++ b/grub-core/video/readers/jpeg.c
+@@ -245,6 +245,9 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data)
+ 	n += count[i];
+ 
+       id += ac * 2;
++      if (data->huff_value[id] != NULL)
++	return grub_error (GRUB_ERR_BAD_FILE_TYPE,
++			   "jpeg: attempt to reallocate huffman table");
+       data->huff_value[id] = grub_malloc (n);
+       if (grub_errno)
+ 	return grub_errno;
diff -pruN 2.06-2/debian/patches/0144-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch 2.06-2ubuntu16/debian/patches/0144-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch
--- 2.06-2/debian/patches/0144-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0144-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,41 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Mon, 28 Jun 2021 14:25:17 +1000
+Subject: video/readers/jpeg: Refuse to handle multiple start of streams
+
+An invalid file could contain multiple start of stream blocks, which
+would cause us to reallocate and leak our bitmap. Refuse to handle
+multiple start of streams.
+
+Additionally, fix a grub_error() call formatting.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/jpeg.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
+index caa211f..1df1171 100644
+--- a/grub-core/video/readers/jpeg.c
++++ b/grub-core/video/readers/jpeg.c
+@@ -677,6 +677,9 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
+   if (data->file->offset != data_offset)
+     return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos");
+ 
++  if (*data->bitmap)
++    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: too many start of scan blocks");
++
+   if (grub_video_bitmap_create (data->bitmap, data->image_width,
+ 				data->image_height,
+ 				GRUB_VIDEO_BLIT_FORMAT_RGB_888))
+@@ -699,8 +702,8 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
+   nc1 = (data->image_width + hb - 1)  >> (3 + data->log_hs);
+ 
+   if (data->bitmap_ptr == NULL)
+-    return grub_error(GRUB_ERR_BAD_FILE_TYPE,
+-		      "jpeg: attempted to decode data before start of stream");
++    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
++		       "jpeg: attempted to decode data before start of stream");
+ 
+   for (; data->r1 < nr1 && (!data->dri || rst);
+        data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
diff -pruN 2.06-2/debian/patches/0145-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch 2.06-2ubuntu16/debian/patches/0145-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch
--- 2.06-2/debian/patches/0145-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0145-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,72 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Wed, 7 Jul 2021 15:38:19 +1000
+Subject: video/readers/jpeg: Block int underflow -> wild pointer write
+
+Certain 1 px wide images caused a wild pointer write in
+grub_jpeg_ycrcb_to_rgb(). This was caused because in grub_jpeg_decode_data(),
+we have the following loop:
+
+for (; data->r1 < nr1 && (!data->dri || rst);
+     data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
+
+We did not check if vb * width >= hb * nc1.
+
+On a 64-bit platform, if that turns out to be negative, it will underflow,
+be interpreted as unsigned 64-bit, then be added to the 64-bit pointer, so
+we see data->bitmap_ptr jump, e.g.:
+
+0x6180_0000_0480 to
+0x6181_0000_0498
+     ^
+     ~--- carry has occurred and this pointer is now far away from
+          any object.
+
+On a 32-bit platform, it will decrement the pointer, creating a pointer
+that won't crash but will overwrite random data.
+
+Catch the underflow and error out.
+
+Fixes: CVE-2021-3697
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/readers/jpeg.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
+index 1df1171..97a533b 100644
+--- a/grub-core/video/readers/jpeg.c
++++ b/grub-core/video/readers/jpeg.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+");
+ 
+@@ -693,6 +694,7 @@ static grub_err_t
+ grub_jpeg_decode_data (struct grub_jpeg_data *data)
+ {
+   unsigned c1, vb, hb, nr1, nc1;
++  unsigned stride_a, stride_b, stride;
+   int rst = data->dri;
+   grub_err_t err = GRUB_ERR_NONE;
+ 
+@@ -705,8 +707,14 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
+     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ 		       "jpeg: attempted to decode data before start of stream");
+ 
++  if (grub_mul(vb, data->image_width, &stride_a) ||
++      grub_mul(hb, nc1, &stride_b) ||
++      grub_sub(stride_a, stride_b, &stride))
++    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
++		       "jpeg: cannot decode image with these dimensions");
++
+   for (; data->r1 < nr1 && (!data->dri || rst);
+-       data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
++       data->r1++, data->bitmap_ptr += stride * 3)
+     for (c1 = 0;  c1 < nc1 && (!data->dri || rst);
+ 	c1++, rst--, data->bitmap_ptr += hb * 3)
+       {
diff -pruN 2.06-2/debian/patches/0146-normal-charset-Fix-array-out-of-bounds-formatting-un.patch 2.06-2ubuntu16/debian/patches/0146-normal-charset-Fix-array-out-of-bounds-formatting-un.patch
--- 2.06-2/debian/patches/0146-normal-charset-Fix-array-out-of-bounds-formatting-un.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0146-normal-charset-Fix-array-out-of-bounds-formatting-un.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,32 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 13 Jul 2021 13:24:38 +1000
+Subject: normal/charset: Fix array out-of-bounds formatting unicode for
+ display
+
+In some cases attempting to display arbitrary binary strings leads
+to ASAN splats reading the widthspec array out of bounds.
+
+Check the index. If it would be out of bounds, return a width of 1.
+I don't know if that's strictly correct, but we're not really expecting
+great display of arbitrary binary data, and it's certainly not worse than
+an OOB read.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/normal/charset.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c
+index 4dfcc31..7a5a7c1 100644
+--- a/grub-core/normal/charset.c
++++ b/grub-core/normal/charset.c
+@@ -395,6 +395,8 @@ grub_unicode_estimate_width (const struct grub_unicode_glyph *c)
+ {
+   if (grub_unicode_get_comb_type (c->base))
+     return 0;
++  if (((unsigned long) (c->base >> 3)) >= ARRAY_SIZE (widthspec))
++    return 1;
+   if (widthspec[c->base >> 3] & (1 << (c->base & 7)))
+     return 2;
+   else
diff -pruN 2.06-2/debian/patches/0147-net-netbuff-Block-overly-large-netbuff-allocs.patch 2.06-2ubuntu16/debian/patches/0147-net-netbuff-Block-overly-large-netbuff-allocs.patch
--- 2.06-2/debian/patches/0147-net-netbuff-Block-overly-large-netbuff-allocs.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0147-net-netbuff-Block-overly-large-netbuff-allocs.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,44 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 8 Mar 2022 23:47:46 +1100
+Subject: net/netbuff: Block overly large netbuff allocs
+
+A netbuff shouldn't be too huge. It's bounded by MTU and TCP segment
+reassembly.
+
+This helps avoid some bugs (and provides a spot to instrument to catch
+them at their source).
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/netbuff.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c
+index dbeeefe..d5e9e9a 100644
+--- a/grub-core/net/netbuff.c
++++ b/grub-core/net/netbuff.c
+@@ -79,10 +79,23 @@ grub_netbuff_alloc (grub_size_t len)
+ 
+   COMPILE_TIME_ASSERT (NETBUFF_ALIGN % sizeof (grub_properly_aligned_t) == 0);
+ 
++  /*
++   * The largest size of a TCP packet is 64 KiB, and everything else
++   * should be a lot smaller - most MTUs are 1500 or less. Cap data
++   * size at 64 KiB + a buffer.
++   */
++  if (len > 0xffffUL + 0x1000UL)
++    {
++      grub_error (GRUB_ERR_BUG,
++                  "attempted to allocate a packet that is too big");
++      return NULL;
++    }
++
+   if (len < NETBUFFMINLEN)
+     len = NETBUFFMINLEN;
+ 
+   len = ALIGN_UP (len, NETBUFF_ALIGN);
++
+ #ifdef GRUB_MACHINE_EMU
+   data = grub_malloc (len + sizeof (*nb));
+ #else
diff -pruN 2.06-2/debian/patches/0148-net-ip-Do-IP-fragment-maths-safely.patch 2.06-2ubuntu16/debian/patches/0148-net-ip-Do-IP-fragment-maths-safely.patch
--- 2.06-2/debian/patches/0148-net-ip-Do-IP-fragment-maths-safely.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0148-net-ip-Do-IP-fragment-maths-safely.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,42 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Mon, 20 Dec 2021 19:41:21 +1100
+Subject: net/ip: Do IP fragment maths safely
+
+This avoids an underflow and subsequent unpleasantness.
+
+Fixes: CVE-2022-28733
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/ip.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
+index 0141079..937be87 100644
+--- a/grub-core/net/ip.c
++++ b/grub-core/net/ip.c
+@@ -25,6 +25,7 @@
+ #include <grub/net/netbuff.h>
+ #include <grub/mm.h>
+ #include <grub/priority_queue.h>
++#include <grub/safemath.h>
+ #include <grub/time.h>
+ 
+ struct iphdr {
+@@ -551,7 +552,14 @@ grub_net_recv_ip4_packets (struct grub_net_buff *nb,
+     {
+       rsm->total_len = (8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK)
+ 			+ (nb->tail - nb->data));
+-      rsm->total_len -= ((iph->verhdrlen & 0xf) * sizeof (grub_uint32_t));
++
++      if (grub_sub (rsm->total_len, (iph->verhdrlen & 0xf) * sizeof (grub_uint32_t),
++		    &rsm->total_len))
++	{
++	  grub_dprintf ("net", "IP reassembly size underflow\n");
++	  return GRUB_ERR_NONE;
++	}
++
+       rsm->asm_netbuff = grub_netbuff_alloc (rsm->total_len);
+       if (!rsm->asm_netbuff)
+ 	{
diff -pruN 2.06-2/debian/patches/0149-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch 2.06-2ubuntu16/debian/patches/0149-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch
--- 2.06-2/debian/patches/0149-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0149-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,54 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Thu, 16 Sep 2021 01:29:54 +1000
+Subject: net/dns: Fix double-free addresses on corrupt DNS response
+
+grub_net_dns_lookup() takes as inputs a pointer to an array of addresses
+("addresses") for the given name, and pointer to a number of addresses
+("naddresses"). grub_net_dns_lookup() is responsible for allocating
+"addresses", and the caller is responsible for freeing it if
+"naddresses" > 0.
+
+The DNS recv_hook will sometimes set and free the addresses array,
+for example if the packet is too short:
+
+      if (ptr + 10 >= nb->tail)
+	{
+	  if (!*data->naddresses)
+	    grub_free (*data->addresses);
+	  grub_netbuff_free (nb);
+	  return GRUB_ERR_NONE;
+	}
+
+Later on the nslookup command code unconditionally frees the "addresses"
+array. Normally this is fine: the array is either populated with valid
+data or is NULL. But in these sorts of error cases it is neither NULL
+nor valid and we get a double-free.
+
+Only free "addresses" if "naddresses" > 0.
+
+It looks like the other use of grub_net_dns_lookup() is not affected.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/dns.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
+index 906ec7d..135faac 100644
+--- a/grub-core/net/dns.c
++++ b/grub-core/net/dns.c
+@@ -667,9 +667,11 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
+       grub_net_addr_to_str (&addresses[i], buf);
+       grub_printf ("%s\n", buf);
+     }
+-  grub_free (addresses);
+   if (naddresses)
+-    return GRUB_ERR_NONE;
++    {
++      grub_free (addresses);
++      return GRUB_ERR_NONE;
++    }
+   return grub_error (GRUB_ERR_NET_NO_DOMAIN, N_("no DNS record found"));
+ }
+ 
diff -pruN 2.06-2/debian/patches/0150-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch 2.06-2ubuntu16/debian/patches/0150-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch
--- 2.06-2/debian/patches/0150-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0150-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,69 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Mon, 20 Dec 2021 21:55:43 +1100
+Subject: net/dns: Don't read past the end of the string we're checking
+ against
+
+I don't really understand what's going on here but fuzzing found
+a bug where we read past the end of check_with. That's a C string,
+so use grub_strlen() to make sure we don't overread it.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/dns.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
+index 135faac..17961a9 100644
+--- a/grub-core/net/dns.c
++++ b/grub-core/net/dns.c
+@@ -146,11 +146,18 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
+ 		 int *length, char *set)
+ {
+   const char *readable_ptr = check_with;
++  int readable_len;
+   const grub_uint8_t *ptr;
+   char *optr = set;
+   int bytes_processed = 0;
+   if (length)
+     *length = 0;
++
++  if (readable_ptr != NULL)
++    readable_len = grub_strlen (readable_ptr);
++  else
++    readable_len = 0;
++
+   for (ptr = name_at; ptr < tail && bytes_processed < tail - head + 2; )
+     {
+       /* End marker.  */
+@@ -172,13 +179,16 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
+ 	  ptr = head + (((ptr[0] & 0x3f) << 8) | ptr[1]);
+ 	  continue;
+ 	}
+-      if (readable_ptr && grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0)
++      if (readable_ptr != NULL && (*ptr > readable_len || grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0))
+ 	return 0;
+       if (grub_memchr (ptr + 1, 0, *ptr) 
+ 	  || grub_memchr (ptr + 1, '.', *ptr))
+ 	return 0;
+       if (readable_ptr)
+-	readable_ptr += *ptr;
++	{
++	  readable_ptr += *ptr;
++	  readable_len -= *ptr;
++	}
+       if (readable_ptr && *readable_ptr != '.' && *readable_ptr != 0)
+ 	return 0;
+       bytes_processed += *ptr + 1;
+@@ -192,7 +202,10 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
+       if (optr)
+ 	*optr++ = '.';
+       if (readable_ptr && *readable_ptr)
+-	readable_ptr++;
++	{
++	  readable_ptr++;
++	  readable_len--;
++	}
+       ptr += *ptr + 1;
+     }
+   return 0;
diff -pruN 2.06-2/debian/patches/0151-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch 2.06-2ubuntu16/debian/patches/0151-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
--- 2.06-2/debian/patches/0151-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0151-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,110 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Mon, 20 Sep 2021 01:12:24 +1000
+Subject: net/tftp: Prevent a UAF and double-free from a failed seek
+
+A malicious tftp server can cause UAFs and a double free.
+
+An attempt to read from a network file is handled by grub_net_fs_read(). If
+the read is at an offset other than the current offset, grub_net_seek_real()
+is invoked.
+
+In grub_net_seek_real(), if a backwards seek cannot be satisfied from the
+currently received packets, and the underlying transport does not provide
+a seek method, then grub_net_seek_real() will close and reopen the network
+protocol layer.
+
+For tftp, the ->close() call goes to tftp_close() and frees the tftp_data_t
+file->data. The file->data pointer is not nulled out after the free.
+
+If the ->open() call fails, the file->data will not be reallocated and will
+continue point to a freed memory block. This could happen from a server
+refusing to send the requisite ack to the new tftp request, for example.
+
+The seek and the read will then fail, but the grub_file continues to exist:
+the failed seek does not necessarily cause the entire file to be thrown
+away (e.g. where the file is checked to see if it is gzipped/lzio/xz/etc.,
+a read failure is interpreted as a decompressor passing on the file, not as
+an invalidation of the entire grub_file_t structure).
+
+This means subsequent attempts to read or seek the file will use the old
+file->data after free. Eventually, the file will be close()d again and
+file->data will be freed again.
+
+Mark a net_fs file that doesn't reopen as broken. Do not permit read() or
+close() on a broken file (seek is not exposed directly to the file API -
+it is only called as part of read, so this blocks seeks as well).
+
+As an additional defence, null out the ->data pointer if tftp_open() fails.
+That would have lead to a simple null pointer dereference rather than
+a mess of UAFs.
+
+This may affect other protocols, I haven't checked.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/net.c  | 11 +++++++++--
+ grub-core/net/tftp.c |  1 +
+ include/grub/net.h   |  1 +
+ 3 files changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index 34bf04f..4785f33 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -1551,7 +1551,8 @@ grub_net_fs_close (grub_file_t file)
+       grub_netbuff_free (file->device->net->packs.first->nb);
+       grub_net_remove_packet (file->device->net->packs.first);
+     }
+-  file->device->net->protocol->close (file);
++  if (!file->device->net->broken)
++    file->device->net->protocol->close (file);
+   grub_free (file->device->net->name);
+   return GRUB_ERR_NONE;
+ }
+@@ -1773,7 +1774,10 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset)
+     file->device->net->stall = 0;
+     err = file->device->net->protocol->open (file, file->device->net->name);
+     if (err)
+-      return err;
++      {
++	file->device->net->broken = 1;
++	return err;
++      }
+     grub_net_fs_read_real (file, NULL, offset);
+     return grub_errno;
+   }
+@@ -1782,6 +1786,9 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset)
+ static grub_ssize_t
+ grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
+ {
++  if (file->device->net->broken)
++    return -1;
++
+   if (file->offset != file->device->net->offset)
+     {
+       grub_err_t err;
+diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
+index f3e7879..d1afa25 100644
+--- a/grub-core/net/tftp.c
++++ b/grub-core/net/tftp.c
+@@ -404,6 +404,7 @@ tftp_open (struct grub_file *file, const char *filename)
+     {
+       grub_net_udp_close (data->sock);
+       grub_free (data);
++      file->data = NULL;
+       return grub_errno;
+     }
+ 
+diff --git a/include/grub/net.h b/include/grub/net.h
+index cbcae79..8d71ca6 100644
+--- a/include/grub/net.h
++++ b/include/grub/net.h
+@@ -277,6 +277,7 @@ typedef struct grub_net
+   grub_fs_t fs;
+   int eof;
+   int stall;
++  int broken;
+ } *grub_net_t;
+ 
+ extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name);
diff -pruN 2.06-2/debian/patches/0152-net-tftp-Avoid-a-trivial-UAF.patch 2.06-2ubuntu16/debian/patches/0152-net-tftp-Avoid-a-trivial-UAF.patch
--- 2.06-2/debian/patches/0152-net-tftp-Avoid-a-trivial-UAF.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0152-net-tftp-Avoid-a-trivial-UAF.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,33 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 18 Jan 2022 14:29:20 +1100
+Subject: net/tftp: Avoid a trivial UAF
+
+Under tftp errors, we print a tftp error message from the tftp header.
+However, the tftph pointer is a pointer inside nb, the netbuff. Previously,
+we were freeing the nb and then dereferencing it. Don't do that, use it
+and then free it later.
+
+This isn't really _bad_ per se, especially as we're single-threaded, but
+it trips up fuzzers.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/tftp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
+index d1afa25..4222d93 100644
+--- a/grub-core/net/tftp.c
++++ b/grub-core/net/tftp.c
+@@ -251,9 +251,9 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
+       return GRUB_ERR_NONE;
+     case TFTP_ERROR:
+       data->have_oack = 1;
+-      grub_netbuff_free (nb);
+       grub_error (GRUB_ERR_IO, "%s", tftph->u.err.errmsg);
+       grub_error_save (&data->save_err);
++      grub_netbuff_free (nb);
+       return GRUB_ERR_NONE;
+     default:
+       grub_netbuff_free (nb);
diff -pruN 2.06-2/debian/patches/0153-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch 2.06-2ubuntu16/debian/patches/0153-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch
--- 2.06-2/debian/patches/0153-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0153-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,39 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 1 Mar 2022 23:14:15 +1100
+Subject: net/http: Do not tear down socket if it's already been torn down
+
+It's possible for data->sock to get torn down in tcp error handling.
+If we unconditionally tear it down again we will end up doing writes
+to an offset of the NULL pointer when we go to tear it down again.
+
+Detect if it has been torn down and don't do it again.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/http.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/net/http.c b/grub-core/net/http.c
+index bf83866..a77bc4e 100644
+--- a/grub-core/net/http.c
++++ b/grub-core/net/http.c
+@@ -425,7 +425,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
+       return err;
+     }
+ 
+-  for (i = 0; !data->headers_recv && i < 100; i++)
++  for (i = 0; data->sock && !data->headers_recv && i < 100; i++)
+     {
+       grub_net_tcp_retransmit ();
+       grub_net_poll_cards (300, &data->headers_recv);
+@@ -433,7 +433,8 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
+ 
+   if (!data->headers_recv)
+     {
+-      grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
++      if (data->sock)
++        grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
+       if (data->err)
+ 	{
+ 	  char *str = data->errmsg;
diff -pruN 2.06-2/debian/patches/0154-net-http-Fix-OOB-write-for-split-http-headers.patch 2.06-2ubuntu16/debian/patches/0154-net-http-Fix-OOB-write-for-split-http-headers.patch
--- 2.06-2/debian/patches/0154-net-http-Fix-OOB-write-for-split-http-headers.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0154-net-http-Fix-OOB-write-for-split-http-headers.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,44 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 8 Mar 2022 18:17:03 +1100
+Subject: net/http: Fix OOB write for split http headers
+
+GRUB has special code for handling an http header that is split
+across two packets.
+
+The code tracks the end of line by looking for a "\n" byte. The
+code for split headers has always advanced the pointer just past the
+end of the line, whereas the code that handles unsplit headers does
+not advance the pointer. This extra advance causes the length to be
+one greater, which breaks an assumption in parse_line(), leading to
+it writing a NUL byte one byte past the end of the buffer where we
+reconstruct the line from the two packets.
+
+It's conceivable that an attacker controlled set of packets could
+cause this to zero out the first byte of the "next" pointer of the
+grub_mm_region structure following the current_line buffer.
+
+Do not advance the pointer in the split header case.
+
+Fixes: CVE-2022-28734
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/http.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/grub-core/net/http.c b/grub-core/net/http.c
+index a77bc4e..d9d2ade 100644
+--- a/grub-core/net/http.c
++++ b/grub-core/net/http.c
+@@ -193,9 +193,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
+ 	  int have_line = 1;
+ 	  char *t;
+ 	  ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data);
+-	  if (ptr)
+-	    ptr++;
+-	  else
++	  if (ptr == NULL)
+ 	    {
+ 	      have_line = 0;
+ 	      ptr = (char *) nb->tail;
diff -pruN 2.06-2/debian/patches/0155-net-http-Error-out-on-headers-with-LF-without-CR.patch 2.06-2ubuntu16/debian/patches/0155-net-http-Error-out-on-headers-with-LF-without-CR.patch
--- 2.06-2/debian/patches/0155-net-http-Error-out-on-headers-with-LF-without-CR.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0155-net-http-Error-out-on-headers-with-LF-without-CR.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,46 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 8 Mar 2022 19:04:40 +1100
+Subject: net/http: Error out on headers with LF without CR
+
+In a similar vein to the previous patch, parse_line() would write
+a NUL byte past the end of the buffer if there was an HTTP header
+with a LF rather than a CRLF.
+
+RFC-2616 says:
+
+  Many HTTP/1.1 header field values consist of words separated by LWS
+  or special characters. These special characters MUST be in a quoted
+  string to be used within a parameter value (as defined in section 3.6).
+
+We don't support quoted sections or continuation lines, etc.
+
+If we see an LF that's not part of a CRLF, bail out.
+
+Fixes: CVE-2022-28734
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/net/http.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/grub-core/net/http.c b/grub-core/net/http.c
+index d9d2ade..0472645 100644
+--- a/grub-core/net/http.c
++++ b/grub-core/net/http.c
+@@ -69,7 +69,15 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len)
+   char *end = ptr + len;
+   while (end > ptr && *(end - 1) == '\r')
+     end--;
++
++  /* LF without CR. */
++  if (end == ptr + len)
++    {
++      data->errmsg = grub_strdup (_("invalid HTTP header - LF without CR"));
++      return GRUB_ERR_NONE;
++    }
+   *end = 0;
++
+   /* Trailing CRLF.  */
+   if (data->in_chunk_len == 1)
+     {
diff -pruN 2.06-2/debian/patches/0156-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch 2.06-2ubuntu16/debian/patches/0156-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch
--- 2.06-2/debian/patches/0156-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0156-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,70 @@
+From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Date: Wed, 6 Apr 2022 18:03:37 +0530
+Subject: fs/f2fs: Do not read past the end of nat journal entries
+
+A corrupt f2fs file system could specify a nat journal entry count
+that is beyond the maximum NAT_JOURNAL_ENTRIES.
+
+Check if the specified nat journal entry count before accessing the
+array, and throw an error if it is too large.
+
+Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/f2fs.c | 21 ++++++++++++++-------
+ 1 file changed, 14 insertions(+), 7 deletions(-)
+
+diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
+index 8a9992c..6370221 100644
+--- a/grub-core/fs/f2fs.c
++++ b/grub-core/fs/f2fs.c
+@@ -632,23 +632,27 @@ get_nat_journal (struct grub_f2fs_data *data)
+   return err;
+ }
+ 
+-static grub_uint32_t
+-get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid)
++static grub_err_t
++get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid,
++                              grub_uint32_t *blkaddr)
+ {
+   grub_uint16_t n = grub_le_to_cpu16 (data->nat_j.n_nats);
+-  grub_uint32_t blkaddr = 0;
+   grub_uint16_t i;
+ 
++  if (n >= NAT_JOURNAL_ENTRIES)
++    return grub_error (GRUB_ERR_BAD_FS,
++                       "invalid number of nat journal entries");
++
+   for (i = 0; i < n; i++)
+     {
+       if (grub_le_to_cpu32 (data->nat_j.entries[i].nid) == nid)
+         {
+-          blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr);
++          *blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr);
+           break;
+         }
+     }
+ 
+-  return blkaddr;
++  return GRUB_ERR_NONE;
+ }
+ 
+ static grub_uint32_t
+@@ -656,10 +660,13 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid)
+ {
+   struct grub_f2fs_nat_block *nat_block;
+   grub_uint32_t seg_off, block_off, entry_off, block_addr;
+-  grub_uint32_t blkaddr;
++  grub_uint32_t blkaddr = 0;
+   grub_err_t err;
+ 
+-  blkaddr = get_blkaddr_from_nat_journal (data, nid);
++  err = get_blkaddr_from_nat_journal (data, nid, &blkaddr);
++  if (err != GRUB_ERR_NONE)
++    return 0;
++
+   if (blkaddr)
+     return blkaddr;
+ 
diff -pruN 2.06-2/debian/patches/0157-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch 2.06-2ubuntu16/debian/patches/0157-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
--- 2.06-2/debian/patches/0157-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0157-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,130 @@
+From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Date: Wed, 6 Apr 2022 18:49:09 +0530
+Subject: fs/f2fs: Do not read past the end of nat bitmap
+
+A corrupt f2fs filesystem could have a block offset or a bitmap
+offset that would cause us to read beyond the bounds of the nat
+bitmap.
+
+Introduce the nat_bitmap_size member in grub_f2fs_data which holds
+the size of nat bitmap.
+
+Set the size when loading the nat bitmap in nat_bitmap_ptr(), and
+catch when an invalid offset would create a pointer past the end of
+the allocated space.
+
+Check against the bitmap size in grub_f2fs_test_bit() test bit to avoid
+reading past the end of the nat bitmap.
+
+Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/f2fs.c | 33 +++++++++++++++++++++++++++------
+ 1 file changed, 27 insertions(+), 6 deletions(-)
+
+diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
+index 6370221..8898b23 100644
+--- a/grub-core/fs/f2fs.c
++++ b/grub-core/fs/f2fs.c
+@@ -122,6 +122,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ #define F2FS_INLINE_DOTS          0x10  /* File having implicit dot dentries. */
+ 
+ #define MAX_VOLUME_NAME           512
++#define MAX_NAT_BITMAP_SIZE       3900
+ 
+ enum FILE_TYPE
+ {
+@@ -183,7 +184,7 @@ struct grub_f2fs_checkpoint
+   grub_uint32_t                   checksum_offset;
+   grub_uint64_t                   elapsed_time;
+   grub_uint8_t                    alloc_type[MAX_ACTIVE_LOGS];
+-  grub_uint8_t                    sit_nat_version_bitmap[3900];
++  grub_uint8_t                    sit_nat_version_bitmap[MAX_NAT_BITMAP_SIZE];
+   grub_uint32_t                   checksum;
+ } GRUB_PACKED;
+ 
+@@ -302,6 +303,7 @@ struct grub_f2fs_data
+ 
+   struct grub_f2fs_nat_journal    nat_j;
+   char                            *nat_bitmap;
++  grub_uint32_t                   nat_bitmap_size;
+ 
+   grub_disk_t                     disk;
+   struct grub_f2fs_node           *inode;
+@@ -377,15 +379,20 @@ sum_blk_addr (struct grub_f2fs_data *data, int base, int type)
+ }
+ 
+ static void *
+-nat_bitmap_ptr (struct grub_f2fs_data *data)
++nat_bitmap_ptr (struct grub_f2fs_data *data, grub_uint32_t *nat_bitmap_size)
+ {
+   struct grub_f2fs_checkpoint *ckpt = &data->ckpt;
+   grub_uint32_t offset;
++  *nat_bitmap_size = MAX_NAT_BITMAP_SIZE;
+ 
+   if (grub_le_to_cpu32 (data->sblock.cp_payload) > 0)
+     return ckpt->sit_nat_version_bitmap;
+ 
+   offset = grub_le_to_cpu32 (ckpt->sit_ver_bitmap_bytesize);
++  if (offset >= MAX_NAT_BITMAP_SIZE)
++     return NULL;
++
++  *nat_bitmap_size = *nat_bitmap_size - offset;
+ 
+   return ckpt->sit_nat_version_bitmap + offset;
+ }
+@@ -438,11 +445,15 @@ grub_f2fs_crc_valid (grub_uint32_t blk_crc, void *buf, const grub_uint32_t len)
+ }
+ 
+ static int
+-grub_f2fs_test_bit (grub_uint32_t nr, const char *p)
++grub_f2fs_test_bit (grub_uint32_t nr, const char *p, grub_uint32_t len)
+ {
+   int mask;
++  grub_uint32_t shifted_nr = (nr >> 3);
++
++  if (shifted_nr >= len)
++    return -1;
+ 
+-  p += (nr >> 3);
++  p += shifted_nr;
+   mask = 1 << (7 - (nr & 0x07));
+ 
+   return mask & *p;
+@@ -662,6 +673,7 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid)
+   grub_uint32_t seg_off, block_off, entry_off, block_addr;
+   grub_uint32_t blkaddr = 0;
+   grub_err_t err;
++  int result_bit;
+ 
+   err = get_blkaddr_from_nat_journal (data, nid, &blkaddr);
+   if (err != GRUB_ERR_NONE)
+@@ -682,8 +694,15 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid)
+         ((seg_off * data->blocks_per_seg) << 1) +
+         (block_off & (data->blocks_per_seg - 1));
+ 
+-  if (grub_f2fs_test_bit (block_off, data->nat_bitmap))
++  result_bit = grub_f2fs_test_bit (block_off, data->nat_bitmap,
++                                   data->nat_bitmap_size);
++  if (result_bit > 0)
+     block_addr += data->blocks_per_seg;
++  else if (result_bit == -1)
++    {
++      grub_free (nat_block);
++      return 0;
++    }
+ 
+   err = grub_f2fs_block_read (data, block_addr, nat_block);
+   if (err)
+@@ -833,7 +852,9 @@ grub_f2fs_mount (grub_disk_t disk)
+   if (err)
+     goto fail;
+ 
+-  data->nat_bitmap = nat_bitmap_ptr (data);
++  data->nat_bitmap = nat_bitmap_ptr (data, &data->nat_bitmap_size);
++  if (data->nat_bitmap == NULL)
++    goto fail;
+ 
+   err = get_nat_journal (data);
+   if (err)
diff -pruN 2.06-2/debian/patches/0158-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch 2.06-2ubuntu16/debian/patches/0158-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
--- 2.06-2/debian/patches/0158-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0158-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,36 @@
+From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Date: Wed, 6 Apr 2022 18:17:43 +0530
+Subject: fs/f2fs: Do not copy file names that are too long
+
+A corrupt f2fs file system might specify a name length which is greater
+than the maximum name length supported by the GRUB f2fs driver.
+
+We will allocate enough memory to store the overly long name, but there
+are only F2FS_NAME_LEN bytes in the source, so we would read past the end
+of the source.
+
+While checking directory entries, do not copy a file name with an invalid
+length.
+
+Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/f2fs.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
+index 8898b23..df6beb5 100644
+--- a/grub-core/fs/f2fs.c
++++ b/grub-core/fs/f2fs.c
+@@ -1003,6 +1003,10 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx)
+ 
+       ftype = ctx->dentry[i].file_type;
+       name_len = grub_le_to_cpu16 (ctx->dentry[i].name_len);
++
++      if (name_len >= F2FS_NAME_LEN)
++        return 0;
++
+       filename = grub_malloc (name_len + 1);
+       if (!filename)
+         return 0;
diff -pruN 2.06-2/debian/patches/0159-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch 2.06-2ubuntu16/debian/patches/0159-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch
--- 2.06-2/debian/patches/0159-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0159-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,74 @@
+From: Darren Kenny <darren.kenny@oracle.com>
+Date: Tue, 29 Mar 2022 10:49:56 +0000
+Subject: fs/btrfs: Fix several fuzz issues with invalid dir item sizing
+
+According to the btrfs code in Linux, the structure of a directory item
+leaf should be of the form:
+
+  |struct btrfs_dir_item|name|data|
+
+in GRUB the name len and data len are in the grub_btrfs_dir_item
+structure's n and m fields respectively.
+
+The combined size of the structure, name and data should be less than
+the allocated memory, a difference to the Linux kernel's struct
+btrfs_dir_item is that the grub_btrfs_dir_item has an extra field for
+where the name is stored, so we adjust for that too.
+
+Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/btrfs.c | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
+index 6320303..eb9857d 100644
+--- a/grub-core/fs/btrfs.c
++++ b/grub-core/fs/btrfs.c
+@@ -1961,6 +1961,7 @@ grub_btrfs_dir (grub_device_t device, const char *path,
+   int r = 0;
+   grub_uint64_t tree;
+   grub_uint8_t type;
++  grub_size_t est_size = 0;
+ 
+   if (!data)
+     return grub_errno;
+@@ -2019,6 +2020,18 @@ grub_btrfs_dir (grub_device_t device, const char *path,
+ 	  break;
+ 	}
+ 
++      if (direl == NULL ||
++	  grub_add (grub_le_to_cpu16 (direl->n),
++		    grub_le_to_cpu16 (direl->m), &est_size) ||
++	  grub_add (est_size, sizeof (*direl), &est_size) ||
++	  grub_sub (est_size, sizeof (direl->name), &est_size) ||
++	  est_size > allocated)
++       {
++         grub_errno = GRUB_ERR_OUT_OF_RANGE;
++         r = -grub_errno;
++         goto out;
++       }
++
+       for (cdirel = direl;
+ 	   (grub_uint8_t *) cdirel - (grub_uint8_t *) direl
+ 	   < (grub_ssize_t) elemsize;
+@@ -2029,6 +2042,19 @@ grub_btrfs_dir (grub_device_t device, const char *path,
+ 	  char c;
+ 	  struct grub_btrfs_inode inode;
+ 	  struct grub_dirhook_info info;
++
++	  if (cdirel == NULL ||
++	      grub_add (grub_le_to_cpu16 (cdirel->n),
++			grub_le_to_cpu16 (cdirel->m), &est_size) ||
++	      grub_add (est_size, sizeof (*cdirel), &est_size) ||
++	      grub_sub (est_size, sizeof (cdirel->name), &est_size) ||
++	      est_size > allocated)
++	   {
++	     grub_errno = GRUB_ERR_OUT_OF_RANGE;
++	     r = -grub_errno;
++	     goto out;
++	   }
++
+ 	  err = grub_btrfs_read_inode (data, &inode, cdirel->key.object_id,
+ 				       tree);
+ 	  grub_memset (&info, 0, sizeof (info));
diff -pruN 2.06-2/debian/patches/0160-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch 2.06-2ubuntu16/debian/patches/0160-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
--- 2.06-2/debian/patches/0160-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0160-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,132 @@
+From: Darren Kenny <darren.kenny@oracle.com>
+Date: Tue, 29 Mar 2022 15:52:46 +0000
+Subject: fs/btrfs: Fix more ASAN and SEGV issues found with fuzzing
+
+The fuzzer is generating btrfs file systems that have chunks with
+invalid combinations of stripes and substripes for the given RAID
+configurations.
+
+After examining the Linux kernel fs/btrfs/tree-checker.c code, it
+appears that sub-stripes should only be applied to RAID10, and in that
+case there should only ever be 2 of them.
+
+Similarly, RAID single should only have 1 stripe, and RAID1/1C3/1C4
+should have 2. 3 or 4 stripes respectively, which is what redundancy
+corresponds.
+
+Some of the chunks ended up with a size of 0, which grub_malloc() still
+returned memory for and in turn generated ASAN errors later when
+accessed.
+
+While it would be possible to specifically limit the number of stripes,
+a more correct test was on the combination of the chunk item, and the
+number of stripes by the size of the chunk stripe structure in
+comparison to the size of the chunk itself.
+
+Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/btrfs.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 55 insertions(+)
+
+diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
+index eb9857d..b3d71cd 100644
+--- a/grub-core/fs/btrfs.c
++++ b/grub-core/fs/btrfs.c
+@@ -912,6 +912,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ 	return grub_error (GRUB_ERR_BAD_FS,
+ 			   "couldn't find the chunk descriptor");
+ 
++      if (!chsize)
++	{
++	  grub_dprintf ("btrfs", "zero-size chunk\n");
++	  return grub_error (GRUB_ERR_BAD_FS,
++			     "got an invalid zero-size chunk");
++	}
+       chunk = grub_malloc (chsize);
+       if (!chunk)
+ 	return grub_errno;
+@@ -970,6 +976,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ 	      stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size),
+ 					     nstripes,
+ 					     NULL);
++
++	      /* For single, there should be exactly 1 stripe. */
++	      if (grub_le_to_cpu16 (chunk->nstripes) != 1)
++		{
++		  grub_dprintf ("btrfs", "invalid RAID_SINGLE: nstripes != 1 (%u)\n",
++				grub_le_to_cpu16 (chunk->nstripes));
++		  return grub_error (GRUB_ERR_BAD_FS,
++				     "invalid RAID_SINGLE: nstripes != 1 (%u)",
++				      grub_le_to_cpu16 (chunk->nstripes));
++		}
+ 	      if (stripe_length == 0)
+ 		stripe_length = 512;
+ 	      stripen = grub_divmod64 (off, stripe_length, &stripe_offset);
+@@ -989,6 +1005,19 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ 	      stripen = 0;
+ 	      stripe_offset = off;
+ 	      csize = grub_le_to_cpu64 (chunk->size) - off;
++
++             /*
++	      * Redundancy, and substripes only apply to RAID10, and there
++	      * should be exactly 2 sub-stripes.
++	      */
++	     if (grub_le_to_cpu16 (chunk->nstripes) != redundancy)
++               {
++                 grub_dprintf ("btrfs", "invalid RAID1: nstripes != %u (%u)\n",
++                               redundancy, grub_le_to_cpu16 (chunk->nstripes));
++                 return grub_error (GRUB_ERR_BAD_FS,
++                                    "invalid RAID1: nstripes != %u (%u)",
++                                    redundancy, grub_le_to_cpu16 (chunk->nstripes));
++               }
+ 	      break;
+ 	    }
+ 	  case GRUB_BTRFS_CHUNK_TYPE_RAID0:
+@@ -1025,6 +1054,20 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ 	      stripe_offset = low + chunk_stripe_length
+ 		* high;
+ 	      csize = chunk_stripe_length - low;
++
++	      /*
++	       * Substripes only apply to RAID10, and there
++	       * should be exactly 2 sub-stripes.
++	       */
++	      if (grub_le_to_cpu16 (chunk->nsubstripes) != 2)
++		{
++		  grub_dprintf ("btrfs", "invalid RAID10: nsubstripes != 2 (%u)",
++				grub_le_to_cpu16 (chunk->nsubstripes));
++		  return grub_error (GRUB_ERR_BAD_FS,
++				     "invalid RAID10: nsubstripes != 2 (%u)",
++				     grub_le_to_cpu16 (chunk->nsubstripes));
++		}
++
+ 	      break;
+ 	    }
+ 	  case GRUB_BTRFS_CHUNK_TYPE_RAID5:
+@@ -1124,6 +1167,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ 
+ 	for (j = 0; j < 2; j++)
+ 	  {
++	    grub_size_t est_chunk_alloc = 0;
++
+ 	    grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
+ 			  "+0x%" PRIxGRUB_UINT64_T
+ 			  " (%d stripes (%d substripes) of %"
+@@ -1136,6 +1181,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ 	    grub_dprintf ("btrfs", "reading laddr 0x%" PRIxGRUB_UINT64_T "\n",
+ 			  addr);
+ 
++	    if (grub_mul (sizeof (struct grub_btrfs_chunk_stripe),
++			  grub_le_to_cpu16 (chunk->nstripes), &est_chunk_alloc) ||
++		grub_add (est_chunk_alloc,
++			  sizeof (struct grub_btrfs_chunk_item), &est_chunk_alloc) ||
++		est_chunk_alloc > chunk->size)
++	      {
++		err = GRUB_ERR_BAD_FS;
++		break;
++	      }
++
+ 	    if (is_raid56)
+ 	      {
+ 		err = btrfs_read_from_chunk (data, chunk, stripen,
diff -pruN 2.06-2/debian/patches/0161-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch 2.06-2ubuntu16/debian/patches/0161-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
--- 2.06-2/debian/patches/0161-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0161-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,74 @@
+From: Darren Kenny <darren.kenny@oracle.com>
+Date: Thu, 7 Apr 2022 15:18:12 +0000
+Subject: fs/btrfs: Fix more fuzz issues related to chunks
+
+The corpus was generating issues in grub_btrfs_read_logical() when
+attempting to iterate over stripe entries in the superblock's
+bootmapping.
+
+In most cases the reason for the failure was that the number of stripes
+in chunk->nstripes exceeded the possible space statically allocated in
+superblock bootmapping space. Each stripe entry in the bootmapping block
+consists of a grub_btrfs_key followed by a grub_btrfs_chunk_stripe.
+
+Another issue that came up was that while calculating the chunk size,
+in an earlier piece of code in that function, depending on the data
+provided in the btrfs file system, it would end up calculating a size
+that was too small to contain even 1 grub_btrfs_chunk_item, which is
+obviously invalid too.
+
+Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/btrfs.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
+index b3d71cd..54a46b8 100644
+--- a/grub-core/fs/btrfs.c
++++ b/grub-core/fs/btrfs.c
+@@ -918,6 +918,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ 	  return grub_error (GRUB_ERR_BAD_FS,
+ 			     "got an invalid zero-size chunk");
+ 	}
++
++      /*
++       * The space being allocated for a chunk should at least be able to
++       * contain one chunk item.
++       */
++      if (chsize < sizeof (struct grub_btrfs_chunk_item))
++       {
++         grub_dprintf ("btrfs", "chunk-size too small\n");
++         return grub_error (GRUB_ERR_BAD_FS,
++                            "got an invalid chunk size");
++       }
+       chunk = grub_malloc (chsize);
+       if (!chunk)
+ 	return grub_errno;
+@@ -1165,6 +1176,13 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ 	if (csize > (grub_uint64_t) size)
+ 	  csize = size;
+ 
++	/*
++	 * The space for a chunk stripe is limited to the space provide in the super-block's
++	 * bootstrap mapping with an initial btrfs key at the start of each chunk.
++	 */
++	grub_size_t avail_stripes = sizeof (data->sblock.bootstrap_mapping) /
++	  (sizeof (struct grub_btrfs_key) + sizeof (struct grub_btrfs_chunk_stripe));
++
+ 	for (j = 0; j < 2; j++)
+ 	  {
+ 	    grub_size_t est_chunk_alloc = 0;
+@@ -1191,6 +1209,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
+ 		break;
+ 	      }
+ 
++	   if (grub_le_to_cpu16 (chunk->nstripes) > avail_stripes)
++             {
++               err = GRUB_ERR_BAD_FS;
++               break;
++             }
++
+ 	    if (is_raid56)
+ 	      {
+ 		err = btrfs_read_from_chunk (data, chunk, stripen,
diff -pruN 2.06-2/debian/patches/0241-Call-hwmatch-only-on-the-grub-pc-platform.patch 2.06-2ubuntu16/debian/patches/0241-Call-hwmatch-only-on-the-grub-pc-platform.patch
--- 2.06-2/debian/patches/0241-Call-hwmatch-only-on-the-grub-pc-platform.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/0241-Call-hwmatch-only-on-the-grub-pc-platform.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,47 @@
+From: Mauricio Faria de Oliveira <mfo@canonical.com>
+Date: Fri, 20 Aug 2021 10:15:06 -0300
+Subject: Call hwmatch only on the grub-pc platform
+
+Call hwmatch only on i386/pc as it is only available there.
+This avoids "error: can't find command `hwmatch'." on e.g., x86_64/efi.
+
+The equivalent behavior is linux_gfx_mode=keep because grub is special:
+the `if hwmatch` clause is true on that error and `$match = 0` is true
+too, as it is undefined (confirmed in grub shell.) A quick fix for now.
+
+Before and After:
+
+    grub> hwmatch
+    error: can't find command `hwmatch'.
+
+    grub> echo $grub_platform
+    efi
+
+    grub> echo $linux_gfx_mode
+    keep
+
+Signed-off-by: Mauricio Faria de Oliveira <mfo@canonical.com>
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1840560
+Bug-Debian: https://bugs.debian.org/990836
+Forwarded: no
+Last-Update: 2020-08-20
+---
+ util/grub.d/10_linux.in | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 8f2cf82..6668b21 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -378,7 +378,9 @@ else
+   cat << EOF
+ if [ "\${recordfail}" != 1 ]; then
+   if [ -e \${prefix}/gfxblacklist.txt ]; then
+-    if hwmatch \${prefix}/gfxblacklist.txt 3; then
++    if [ \${grub_platform} != pc ]; then
++      set linux_gfx_mode=keep
++    elif hwmatch \${prefix}/gfxblacklist.txt 3; then
+       if [ \${match} = 0 ]; then
+         set linux_gfx_mode=keep
+       else
diff -pruN 2.06-2/debian/patches/2.12-mm/0194-mm-Clarify-grub_real_malloc.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0194-mm-Clarify-grub_real_malloc.patch
--- 2.06-2/debian/patches/2.12-mm/0194-mm-Clarify-grub_real_malloc.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0194-mm-Clarify-grub_real_malloc.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,181 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Thu, 25 Nov 2021 02:22:46 +1100
+Subject: mm: Clarify grub_real_malloc()
+
+When iterating through the singly linked list of free blocks,
+grub_real_malloc() uses p and q for the current and previous blocks
+respectively. This isn't super clear, so swap to using prev and cur.
+
+This makes another quirk more obvious. The comment at the top of
+grub_real_malloc() might lead you to believe that the function will
+allocate from *first if there is space in that block.
+
+It actually doesn't do that, and it can't do that with the current
+data structures. If we used up all of *first, we would need to change
+the ->next of the previous block to point to *first->next, but we
+can't do that because it's a singly linked list and we don't have
+access to *first's previous block.
+
+What grub_real_malloc() actually does is set *first to the initial
+previous block, and *first->next is the block we try to allocate
+from. That allows us to keep all the data structures consistent.
+
+Document that.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/kern/mm.c | 76 +++++++++++++++++++++++++++++------------------------
+ 1 file changed, 41 insertions(+), 35 deletions(-)
+
+diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
+index c070afc..6efabe9 100644
+--- a/grub-core/kern/mm.c
++++ b/grub-core/kern/mm.c
+@@ -178,13 +178,20 @@ grub_mm_init_region (void *addr, grub_size_t size)
+ }
+ 
+ /* Allocate the number of units N with the alignment ALIGN from the ring
+-   buffer starting from *FIRST.  ALIGN must be a power of two. Both N and
+-   ALIGN are in units of GRUB_MM_ALIGN.  Return a non-NULL if successful,
+-   otherwise return NULL.  */
++ * buffer given in *FIRST.  ALIGN must be a power of two. Both N and
++ * ALIGN are in units of GRUB_MM_ALIGN.  Return a non-NULL if successful,
++ * otherwise return NULL.
++ *
++ * Note: because in certain circumstances we need to adjust the ->next
++ * pointer of the previous block, we iterate over the singly linked
++ * list with the pair (prev, cur). *FIRST is our initial previous, and
++ * *FIRST->next is our initial current pointer. So we will actually
++ * allocate from *FIRST->next first and *FIRST itself last.
++ */
+ static void *
+ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
+ {
+-  grub_mm_header_t p, q;
++  grub_mm_header_t cur, prev;
+ 
+   /* When everything is allocated side effect is that *first will have alloc
+      magic marked, meaning that there is no room in this region.  */
+@@ -192,24 +199,24 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
+     return 0;
+ 
+   /* Try to search free slot for allocation in this memory region.  */
+-  for (q = *first, p = q->next; ; q = p, p = p->next)
++  for (prev = *first, cur = prev->next; ; prev = cur, cur = cur->next)
+     {
+       grub_off_t extra;
+ 
+-      extra = ((grub_addr_t) (p + 1) >> GRUB_MM_ALIGN_LOG2) & (align - 1);
++      extra = ((grub_addr_t) (cur + 1) >> GRUB_MM_ALIGN_LOG2) & (align - 1);
+       if (extra)
+ 	extra = align - extra;
+ 
+-      if (! p)
++      if (! cur)
+ 	grub_fatal ("null in the ring");
+ 
+-      if (p->magic != GRUB_MM_FREE_MAGIC)
+-	grub_fatal ("free magic is broken at %p: 0x%x", p, p->magic);
++      if (cur->magic != GRUB_MM_FREE_MAGIC)
++	grub_fatal ("free magic is broken at %p: 0x%x", cur, cur->magic);
+ 
+-      if (p->size >= n + extra)
++      if (cur->size >= n + extra)
+ 	{
+-	  extra += (p->size - extra - n) & (~(align - 1));
+-	  if (extra == 0 && p->size == n)
++	  extra += (cur->size - extra - n) & (~(align - 1));
++	  if (extra == 0 && cur->size == n)
+ 	    {
+ 	      /* There is no special alignment requirement and memory block
+ 	         is complete match.
+@@ -222,9 +229,9 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
+ 	         | alloc, size=n |          |
+ 	         +---------------+          v
+ 	       */
+-	      q->next = p->next;
++	      prev->next = cur->next;
+ 	    }
+-	  else if (align == 1 || p->size == n + extra)
++	  else if (align == 1 || cur->size == n + extra)
+ 	    {
+ 	      /* There might be alignment requirement, when taking it into
+ 	         account memory block fits in.
+@@ -241,23 +248,22 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
+ 	         | alloc, size=n |        |
+ 	         +---------------+        v
+ 	       */
+-
+-	      p->size -= n;
+-	      p += p->size;
++	      cur->size -= n;
++	      cur += cur->size;
+ 	    }
+ 	  else if (extra == 0)
+ 	    {
+ 	      grub_mm_header_t r;
+ 	      
+-	      r = p + extra + n;
++	      r = cur + extra + n;
+ 	      r->magic = GRUB_MM_FREE_MAGIC;
+-	      r->size = p->size - extra - n;
+-	      r->next = p->next;
+-	      q->next = r;
++	      r->size = cur->size - extra - n;
++	      r->next = cur->next;
++	      prev->next = r;
+ 
+-	      if (q == p)
++	      if (prev == cur)
+ 		{
+-		  q = r;
++		  prev = r;
+ 		  r->next = r;
+ 		}
+ 	    }
+@@ -284,32 +290,32 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
+ 	       */
+ 	      grub_mm_header_t r;
+ 
+-	      r = p + extra + n;
++	      r = cur + extra + n;
+ 	      r->magic = GRUB_MM_FREE_MAGIC;
+-	      r->size = p->size - extra - n;
+-	      r->next = p;
++	      r->size = cur->size - extra - n;
++	      r->next = cur;
+ 
+-	      p->size = extra;
+-	      q->next = r;
+-	      p += extra;
++	      cur->size = extra;
++	      prev->next = r;
++	      cur += extra;
+ 	    }
+ 
+-	  p->magic = GRUB_MM_ALLOC_MAGIC;
+-	  p->size = n;
++	  cur->magic = GRUB_MM_ALLOC_MAGIC;
++	  cur->size = n;
+ 
+ 	  /* Mark find as a start marker for next allocation to fasten it.
+ 	     This will have side effect of fragmenting memory as small
+ 	     pieces before this will be un-used.  */
+ 	  /* So do it only for chunks under 64K.  */
+ 	  if (n < (0x8000 >> GRUB_MM_ALIGN_LOG2)
+-	      || *first == p)
+-	    *first = q;
++	      || *first == cur)
++	    *first = prev;
+ 
+-	  return p + 1;
++	  return cur + 1;
+ 	}
+ 
+       /* Search was completed without result.  */
+-      if (p == *first)
++      if (cur == *first)
+ 	break;
+     }
+ 
diff -pruN 2.06-2/debian/patches/2.12-mm/0195-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0195-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch
--- 2.06-2/debian/patches/2.12-mm/0195-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0195-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,30 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Thu, 25 Nov 2021 02:22:47 +1100
+Subject: mm: grub_real_malloc(): Make small allocs comment match code
+
+Small allocations move the region's *first pointer. The comment
+says that this happens for allocations under 64K. The code says
+it's for allocations under 32K. Commit 45bf8b3a7549 changed the
+code intentionally: make the comment match.
+
+Fixes: 45bf8b3a7549 (* grub-core/kern/mm.c (grub_real_malloc): Decrease cut-off of moving the)
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/kern/mm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
+index 6efabe9..ac41cf4 100644
+--- a/grub-core/kern/mm.c
++++ b/grub-core/kern/mm.c
+@@ -306,7 +306,7 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
+ 	  /* Mark find as a start marker for next allocation to fasten it.
+ 	     This will have side effect of fragmenting memory as small
+ 	     pieces before this will be un-used.  */
+-	  /* So do it only for chunks under 64K.  */
++	  /* So do it only for chunks under 32K.  */
+ 	  if (n < (0x8000 >> GRUB_MM_ALIGN_LOG2)
+ 	      || *first == cur)
+ 	    *first = prev;
diff -pruN 2.06-2/debian/patches/2.12-mm/0196-mm-Document-grub_free.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0196-mm-Document-grub_free.patch
--- 2.06-2/debian/patches/2.12-mm/0196-mm-Document-grub_free.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0196-mm-Document-grub_free.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,118 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Thu, 25 Nov 2021 02:22:48 +1100
+Subject: mm: Document grub_free()
+
+The grub_free() possesses a surprising number of quirks, and also
+uses single-letter variable names confusingly to iterate through
+the free list.
+
+Document what's going on.
+
+Use prev and cur to iterate over the free list.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/kern/mm.c | 63 ++++++++++++++++++++++++++++++++++-------------------
+ 1 file changed, 41 insertions(+), 22 deletions(-)
+
+diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
+index ac41cf4..bec960c 100644
+--- a/grub-core/kern/mm.c
++++ b/grub-core/kern/mm.c
+@@ -446,54 +446,73 @@ grub_free (void *ptr)
+     }
+   else
+     {
+-      grub_mm_header_t q, s;
++      grub_mm_header_t cur, prev;
+ 
+ #if 0
+-      q = r->first;
++      cur = r->first;
+       do
+ 	{
+ 	  grub_printf ("%s:%d: q=%p, q->size=0x%x, q->magic=0x%x\n",
+-		       GRUB_FILE, __LINE__, q, q->size, q->magic);
+-	  q = q->next;
++		       GRUB_FILE, __LINE__, cur, cur->size, cur->magic);
++	  cur = cur->next;
+ 	}
+-      while (q != r->first);
++      while (cur != r->first);
+ #endif
+-
+-      for (s = r->first, q = s->next; q <= p || q->next >= p; s = q, q = s->next)
++      /* Iterate over all blocks in the free ring.
++       *
++       * The free ring is arranged from high addresses to low
++       * addresses, modulo wraparound.
++       *
++       * We are looking for a block with a higher address than p or
++       * whose next address is lower than p.
++       */
++      for (prev = r->first, cur = prev->next; cur <= p || cur->next >= p;
++	   prev = cur, cur = prev->next)
+ 	{
+-	  if (q->magic != GRUB_MM_FREE_MAGIC)
+-	    grub_fatal ("free magic is broken at %p: 0x%x", q, q->magic);
++	  if (cur->magic != GRUB_MM_FREE_MAGIC)
++	    grub_fatal ("free magic is broken at %p: 0x%x", cur, cur->magic);
+ 
+-	  if (q <= q->next && (q > p || q->next < p))
++	  /* Deal with wrap-around */
++	  if (cur <= cur->next && (cur > p || cur->next < p))
+ 	    break;
+ 	}
+ 
++      /* mark p as free and insert it between cur and cur->next */
+       p->magic = GRUB_MM_FREE_MAGIC;
+-      p->next = q->next;
+-      q->next = p;
++      p->next = cur->next;
++      cur->next = p;
+ 
++      /*
++       * If the block we are freeing can be merged with the next
++       * free block, do that.
++       */
+       if (p->next + p->next->size == p)
+ 	{
+ 	  p->magic = 0;
+ 
+ 	  p->next->size += p->size;
+-	  q->next = p->next;
++	  cur->next = p->next;
+ 	  p = p->next;
+ 	}
+ 
+-      r->first = q;
++      r->first = cur;
+ 
+-      if (q == p + p->size)
++      /* Likewise if can be merged with the preceeding free block */
++      if (cur == p + p->size)
+ 	{
+-	  q->magic = 0;
+-	  p->size += q->size;
+-	  if (q == s)
+-	    s = p;
+-	  s->next = p;
+-	  q = s;
++	  cur->magic = 0;
++	  p->size += cur->size;
++	  if (cur == prev)
++	    prev = p;
++	  prev->next = p;
++	  cur = prev;
+ 	}
+ 
+-      r->first = q;
++      /*
++       * Set r->first such that the just free()d block is tried first.
++       * (An allocation is tried from *first->next, and cur->next == p.)
++       */
++      r->first = cur;
+     }
+ }
+ 
diff -pruN 2.06-2/debian/patches/2.12-mm/0197-mm-Document-grub_mm_init_region.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0197-mm-Document-grub_mm_init_region.patch
--- 2.06-2/debian/patches/2.12-mm/0197-mm-Document-grub_mm_init_region.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0197-mm-Document-grub_mm_init_region.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,71 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Thu, 25 Nov 2021 02:22:49 +1100
+Subject: mm: Document grub_mm_init_region()
+
+The grub_mm_init_region() does some things that seem magical, especially
+around region merging. Make it a bit clearer.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/kern/mm.c | 31 ++++++++++++++++++++++++++++++-
+ 1 file changed, 30 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
+index bec960c..c686917 100644
+--- a/grub-core/kern/mm.c
++++ b/grub-core/kern/mm.c
+@@ -128,23 +128,52 @@ grub_mm_init_region (void *addr, grub_size_t size)
+   if (((grub_addr_t) addr + 0x1000) > ~(grub_addr_t) size)
+     size = ((grub_addr_t) -0x1000) - (grub_addr_t) addr;
+ 
++  /* Attempt to merge this region with every existing region */
+   for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p)
++    /*
++     * Is the new region immediately below an existing region? That
++     * is, is the address of the memory we're adding now (addr) + size
++     * of the memory we're adding (size) + the bytes we couldn't use
++     * at the start of the region we're considering (q->pre_size)
++     * equal to the address of q? In other words, does the memory
++     * looks like this?
++     *
++     * addr                          q
++     *   |----size-----|-q->pre_size-|<q region>|
++     */
+     if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q)
+       {
++	/*
++	 * Yes, we can merge the memory starting at addr into the
++	 * existing region from below. Align up addr to GRUB_MM_ALIGN
++	 * so that our new region has proper alignment.
++	 */
+ 	r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN);
++	/* Copy the region data across */
+ 	*r = *q;
++	/* Consider all the new size as pre-size */
+ 	r->pre_size += size;
+-	
++
++	/*
++	 * If we have enough pre-size to create a block, create a
++	 * block with it. Mark it as allocated and pass it to
++	 * grub_free (), which will sort out getting it into the free
++	 * list.
++	 */
+ 	if (r->pre_size >> GRUB_MM_ALIGN_LOG2)
+ 	  {
+ 	    h = (grub_mm_header_t) (r + 1);
++	    /* block size is pre-size converted to cells */
+ 	    h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2);
+ 	    h->magic = GRUB_MM_ALLOC_MAGIC;
++	    /* region size grows by block size converted back to bytes */
+ 	    r->size += h->size << GRUB_MM_ALIGN_LOG2;
++	    /* adjust pre_size to be accurate */
+ 	    r->pre_size &= (GRUB_MM_ALIGN - 1);
+ 	    *p = r;
+ 	    grub_free (h + 1);
+ 	  }
++	/* Replace the old region with the new region */
+ 	*p = r;
+ 	return;
+       }
diff -pruN 2.06-2/debian/patches/2.12-mm/0198-kern-Remove-trailing-whitespaces.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0198-kern-Remove-trailing-whitespaces.patch
--- 2.06-2/debian/patches/2.12-mm/0198-kern-Remove-trailing-whitespaces.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0198-kern-Remove-trailing-whitespaces.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,674 @@
+From: Elyes Haouas <ehaouas@noos.fr>
+Date: Fri, 4 Mar 2022 07:42:03 +0100
+Subject: kern: Remove trailing whitespaces
+
+Signed-off-by: Elyes Haouas <ehaouas@noos.fr>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/kern/acpi.c                | 2 +-
+ grub-core/kern/arm/efi/init.c        | 2 +-
+ grub-core/kern/arm64/dl.c            | 2 +-
+ grub-core/kern/arm64/dl_helper.c     | 4 ++--
+ grub-core/kern/command.c             | 2 +-
+ grub-core/kern/coreboot/cbtable.c    | 2 +-
+ grub-core/kern/device.c              | 2 +-
+ grub-core/kern/disk.c                | 6 +++---
+ grub-core/kern/dl.c                  | 2 +-
+ grub-core/kern/efi/efi.c             | 2 +-
+ grub-core/kern/efi/init.c            | 2 +-
+ grub-core/kern/efi/mm.c              | 2 +-
+ grub-core/kern/emu/hostdisk.c        | 2 +-
+ grub-core/kern/emu/hostfs.c          | 2 +-
+ grub-core/kern/emu/main.c            | 2 +-
+ grub-core/kern/emu/misc.c            | 8 ++++----
+ grub-core/kern/env.c                 | 4 ++--
+ grub-core/kern/file.c                | 4 ++--
+ grub-core/kern/i386/coreboot/init.c  | 2 +-
+ grub-core/kern/i386/pc/mmap.c        | 8 ++++----
+ grub-core/kern/i386/qemu/init.c      | 4 ++--
+ grub-core/kern/ia64/dl_helper.c      | 6 +++---
+ grub-core/kern/ieee1275/ieee1275.c   | 2 +-
+ grub-core/kern/ieee1275/init.c       | 6 +++---
+ grub-core/kern/ieee1275/openfw.c     | 2 +-
+ grub-core/kern/main.c                | 4 ++--
+ grub-core/kern/mips/dl.c             | 8 ++++----
+ grub-core/kern/mips/loongson/init.c  | 6 +++---
+ grub-core/kern/mips/qemu_mips/init.c | 4 ++--
+ grub-core/kern/misc.c                | 4 ++--
+ grub-core/kern/mm.c                  | 4 ++--
+ grub-core/kern/partition.c           | 2 +-
+ grub-core/kern/powerpc/dl.c          | 8 ++++----
+ 33 files changed, 61 insertions(+), 61 deletions(-)
+
+diff --git a/grub-core/kern/acpi.c b/grub-core/kern/acpi.c
+index 5746ac0..70898dd 100644
+--- a/grub-core/kern/acpi.c
++++ b/grub-core/kern/acpi.c
+@@ -1,4 +1,4 @@
+-/* 
++/*
+  *  GRUB  --  GRand Unified Bootloader
+  *  Copyright (C) 2012  Free Software Foundation, Inc.
+  *
+diff --git a/grub-core/kern/arm/efi/init.c b/grub-core/kern/arm/efi/init.c
+index 40c3b46..7fcf91b 100644
+--- a/grub-core/kern/arm/efi/init.c
++++ b/grub-core/kern/arm/efi/init.c
+@@ -34,7 +34,7 @@ grub_efi_get_time_ms (void)
+   return tmr;
+ }
+ 
+-static void 
++static void
+ increment_timer (grub_efi_event_t event __attribute__ ((unused)),
+ 		 void *context __attribute__ ((unused)))
+ {
+diff --git a/grub-core/kern/arm64/dl.c b/grub-core/kern/arm64/dl.c
+index 512e5a8..a2b5789 100644
+--- a/grub-core/kern/arm64/dl.c
++++ b/grub-core/kern/arm64/dl.c
+@@ -49,7 +49,7 @@ grub_arch_dl_check_header (void *ehdr)
+ #pragma GCC diagnostic ignored "-Wcast-align"
+ 
+ /*
+- * Unified function for both REL and RELA 
++ * Unified function for both REL and RELA
+  */
+ grub_err_t
+ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
+diff --git a/grub-core/kern/arm64/dl_helper.c b/grub-core/kern/arm64/dl_helper.c
+index e00c198..cf7d432 100644
+--- a/grub-core/kern/arm64/dl_helper.c
++++ b/grub-core/kern/arm64/dl_helper.c
+@@ -69,9 +69,9 @@ grub_arm64_set_hi21 (grub_uint32_t *place, grub_int64_t offset)
+   grub_uint32_t val;
+ 
+   offset >>= 12;
+-  
++
+   val = ((offset & 3) << 29) | (((offset >> 2) & 0x7ffff) << 5);
+-  
++
+   *place &= insmask;
+   *place |= grub_cpu_to_le32 (val) & ~insmask;
+ }
+diff --git a/grub-core/kern/command.c b/grub-core/kern/command.c
+index 4aabcd4..5812e13 100644
+--- a/grub-core/kern/command.c
++++ b/grub-core/kern/command.c
+@@ -46,7 +46,7 @@ grub_register_command_prio (const char *name,
+ 
+   cmd->flags = 0;
+   cmd->prio = prio;
+-    
++
+   for (p = &grub_command_list, q = *p; q; p = &(q->next), q = q->next)
+     {
+       int r;
+diff --git a/grub-core/kern/coreboot/cbtable.c b/grub-core/kern/coreboot/cbtable.c
+index aec63db..b6d0801 100644
+--- a/grub-core/kern/coreboot/cbtable.c
++++ b/grub-core/kern/coreboot/cbtable.c
+@@ -62,7 +62,7 @@ signature_found:
+        {
+          table_header = (grub_linuxbios_table_header_t) (grub_addr_t)
+            *(grub_uint64_t *) (table_item + 1);
+-         goto signature_found;   
++         goto signature_found;
+        }
+       if (hook (table_item, hook_data))
+        return 1;
+diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c
+index 73b8ecc..92ce8a7 100644
+--- a/grub-core/kern/device.c
++++ b/grub-core/kern/device.c
+@@ -56,7 +56,7 @@ grub_device_open (const char *name)
+   if (grub_net_open && grub_errno == GRUB_ERR_UNKNOWN_DEVICE)
+     {
+       grub_errno = GRUB_ERR_NONE;
+-      dev->net = grub_net_open (name); 
++      dev->net = grub_net_open (name);
+     }
+ 
+   if (dev->net)
+diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c
+index e1b0e07..3a42c00 100644
+--- a/grub-core/kern/disk.c
++++ b/grub-core/kern/disk.c
+@@ -376,7 +376,7 @@ grub_disk_read_small_real (grub_disk_t disk, grub_disk_addr_t sector,
+     tmp_buf = grub_malloc (num << disk->log_sector_size);
+     if (!tmp_buf)
+       return grub_errno;
+-    
++
+     if ((disk->dev->disk_read) (disk, transform_sector (disk, aligned_sector),
+ 				num, tmp_buf))
+       {
+@@ -490,7 +490,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
+ 					buf);
+ 	  if (err)
+ 	    return err;
+-	  
++
+ 	  for (i = 0; i < agglomerate; i ++)
+ 	    grub_disk_cache_store (disk->dev->id, disk->id,
+ 				   sector + (i << GRUB_DISK_CACHE_BITS),
+@@ -505,7 +505,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
+ 
+ 	  sector += agglomerate << GRUB_DISK_CACHE_BITS;
+ 	  size -= agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS);
+-	  buf = (char *) buf 
++	  buf = (char *) buf
+ 	    + (agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS));
+ 	}
+ 
+diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
+index 1fea604..b3e93c3 100644
+--- a/grub-core/kern/dl.c
++++ b/grub-core/kern/dl.c
+@@ -480,7 +480,7 @@ grub_dl_resolve_name (grub_dl_t mod, Elf_Ehdr *e)
+   s = grub_dl_find_section (e, ".modname");
+   if (!s)
+     return grub_error (GRUB_ERR_BAD_MODULE, "no module name found");
+-  
++
+   mod->name = grub_strdup ((char *) e + s->sh_offset);
+   if (! mod->name)
+     return grub_errno;
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index 69c283d..4795fe9 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -228,7 +228,7 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid,
+ 
+   r = grub_efi_system_table->runtime_services;
+ 
+-  status = efi_call_5 (r->set_variable, var16, guid, 
++  status = efi_call_5 (r->set_variable, var16, guid,
+ 		       (GRUB_EFI_VARIABLE_NON_VOLATILE
+ 			| GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS
+ 			| GRUB_EFI_VARIABLE_RUNTIME_ACCESS),
+diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
+index 7facacf..26ed07b 100644
+--- a/grub-core/kern/efi/init.c
++++ b/grub-core/kern/efi/init.c
+@@ -111,7 +111,7 @@ grub_efi_init (void)
+   grub_efidisk_init ();
+ }
+ 
+-void (*grub_efi_net_config) (grub_efi_handle_t hnd, 
++void (*grub_efi_net_config) (grub_efi_handle_t hnd,
+ 			     char **device,
+ 			     char **path);
+ 
+diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
+index 7741d66..dac9c58 100644
+--- a/grub-core/kern/efi/mm.c
++++ b/grub-core/kern/efi/mm.c
+@@ -554,7 +554,7 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
+ 
+       addr = grub_efi_allocate_pages_real (start, pages,
+ 					   GRUB_EFI_ALLOCATE_ADDRESS,
+-					   GRUB_EFI_LOADER_CODE);      
++					   GRUB_EFI_LOADER_CODE);
+       if (! addr)
+ 	grub_fatal ("cannot allocate conventional memory %p with %u pages",
+ 		    (void *) ((grub_addr_t) start),
+diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c
+index f90b6c9..3e39fc6 100644
+--- a/grub-core/kern/emu/hostdisk.c
++++ b/grub-core/kern/emu/hostdisk.c
+@@ -550,7 +550,7 @@ read_device_map (const char *dev_map)
+       map[drive].device = grub_canonicalize_file_name (p);
+       if (! map[drive].device)
+ 	map[drive].device = xstrdup (p);
+-      
++
+       if (!map[drive].drive)
+ 	{
+ 	  char c;
+diff --git a/grub-core/kern/emu/hostfs.c b/grub-core/kern/emu/hostfs.c
+index cb53210..ccbe13f 100644
+--- a/grub-core/kern/emu/hostfs.c
++++ b/grub-core/kern/emu/hostfs.c
+@@ -122,7 +122,7 @@ grub_hostfs_open (struct grub_file *file, const char *name)
+       return grub_errno;
+     }
+ 
+-  data->f = f;  
++  data->f = f;
+ 
+   file->data = data;
+ 
+diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c
+index 55ea5a1..65d5ea6 100644
+--- a/grub-core/kern/emu/main.c
++++ b/grub-core/kern/emu/main.c
+@@ -194,7 +194,7 @@ int
+ main (int argc, char *argv[])
+ {
+   struct arguments arguments =
+-    { 
++    {
+       .dev_map = DEFAULT_DEVICE_MAP,
+       .hold = 0,
+       .mem_disk = 0,
+diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c
+index 0ff13bc..45cd270 100644
+--- a/grub-core/kern/emu/misc.c
++++ b/grub-core/kern/emu/misc.c
+@@ -135,16 +135,16 @@ xstrdup (const char *str)
+ #if !defined (GRUB_MKFONT) && !defined (GRUB_BUILD)
+ char *
+ xasprintf (const char *fmt, ...)
+-{ 
++{
+   va_list ap;
+   char *result;
+-  
++
+   va_start (ap, fmt);
+   result = grub_xvasprintf (fmt, ap);
+   va_end (ap);
+   if (!result)
+     grub_util_error ("%s", _("out of memory"));
+-  
++
+   return result;
+ }
+ #endif
+@@ -181,7 +181,7 @@ grub_util_get_image_size (const char *path)
+     grub_util_error (_("cannot open `%s': %s"), path, strerror (errno));
+ 
+   fseeko (f, 0, SEEK_END);
+-  
++
+   sz = ftello (f);
+   if (sz < 0)
+     grub_util_error (_("cannot open `%s': %s"), path, strerror (errno));
+diff --git a/grub-core/kern/env.c b/grub-core/kern/env.c
+index c408626..10e08ad 100644
+--- a/grub-core/kern/env.c
++++ b/grub-core/kern/env.c
+@@ -226,12 +226,12 @@ grub_env_export (const char *name)
+   if (! var)
+     {
+       grub_err_t err;
+-      
++
+       err = grub_env_set (name, "");
+       if (err)
+ 	return err;
+       var = grub_env_find (name);
+-    }    
++    }
+   var->global = 1;
+ 
+   return GRUB_ERR_NONE;
+diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
+index ffdcaba..8d48fd5 100644
+--- a/grub-core/kern/file.c
++++ b/grub-core/kern/file.c
+@@ -212,9 +212,9 @@ grub_file_seek (grub_file_t file, grub_off_t offset)
+ 		  N_("attempt to seek outside of the file"));
+       return -1;
+     }
+-  
++
+   old = file->offset;
+   file->offset = offset;
+-    
++
+   return old;
+ }
+diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c
+index 36f9134..feaf929 100644
+--- a/grub-core/kern/i386/coreboot/init.c
++++ b/grub-core/kern/i386/coreboot/init.c
+@@ -77,7 +77,7 @@ heap_init (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
+ 
+   if (modend && begin < modend)
+     begin = modend;
+-  
++
+   if (end <= begin)
+     return 0;
+ 
+diff --git a/grub-core/kern/i386/pc/mmap.c b/grub-core/kern/i386/pc/mmap.c
+index c0c3c35..ef2faa2 100644
+--- a/grub-core/kern/i386/pc/mmap.c
++++ b/grub-core/kern/i386/pc/mmap.c
+@@ -73,9 +73,9 @@ grub_get_ext_memsize (void)
+    in 1KB parts, and upper 16 bits are above 16MB in 64KB parts. If error, return zero.
+    BIOS call "INT 15H, AH=E801H" to get EISA memory map,
+      AX = memory between 1M and 16M in 1K parts.
+-     BX = memory above 16M in 64K parts. 
++     BX = memory above 16M in 64K parts.
+ */
+- 
++
+ static inline grub_uint32_t
+ grub_get_eisa_mmap (void)
+ {
+@@ -114,7 +114,7 @@ grub_get_mmap_entry (struct grub_machine_mmap_entry *entry,
+   /* place address (+4) in ES:DI */
+   regs.es = ((grub_addr_t) &entry->addr) >> 4;
+   regs.edi = ((grub_addr_t) &entry->addr) & 0xf;
+-	
++
+   /* set continuation value */
+   regs.ebx = cont;
+ 
+@@ -127,7 +127,7 @@ grub_get_mmap_entry (struct grub_machine_mmap_entry *entry,
+   regs.eax = 0xe820;
+   grub_bios_interrupt (0x15, &regs);
+ 
+-  /* write length of buffer (zero if error) into ADDR */	
++  /* write length of buffer (zero if error) into ADDR */
+   if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) || regs.eax != 0x534d4150
+       || regs.ecx < 0x14 || regs.ecx > 0x400)
+     entry->size = 0;
+diff --git a/grub-core/kern/i386/qemu/init.c b/grub-core/kern/i386/qemu/init.c
+index 9fafe98..d8b48ef 100644
+--- a/grub-core/kern/i386/qemu/init.c
++++ b/grub-core/kern/i386/qemu/init.c
+@@ -174,7 +174,7 @@ enable_cards (grub_pci_device_t dev,
+ 
+   if (class == GRUB_PCI_CLASS_SUBCLASS_USB)
+     return 0;
+-  
++
+   addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
+   grub_pci_write (addr, cmd);
+ 
+@@ -237,7 +237,7 @@ grub_pci_assign_addresses (void)
+ 					      + 4 * resources[i].bar + 4);
+ 		grub_pci_write (addr, 0);
+ 	      }
+-	  }	  
++	  }
+       }
+     grub_pci_iterate (enable_cards, NULL);
+   }
+diff --git a/grub-core/kern/ia64/dl_helper.c b/grub-core/kern/ia64/dl_helper.c
+index c601595..05a0a68 100644
+--- a/grub-core/kern/ia64/dl_helper.c
++++ b/grub-core/kern/ia64/dl_helper.c
+@@ -73,7 +73,7 @@ grub_ia64_add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value)
+     case 0:
+       val = grub_le_to_cpu32 (grub_get_unaligned32 (((grub_uint8_t *)
+ 						     (addr & MASK3) + 2)));
+-      val = (((((val & MASK20) + value) & MASK20) << 2) 
++      val = (((((val & MASK20) + value) & MASK20) << 2)
+ 	    | (val & ~(MASK20 << 2)));
+       grub_set_unaligned32 (((grub_uint8_t *) (addr & MASK3) + 2),
+ 			    grub_cpu_to_le32 (val));
+@@ -161,9 +161,9 @@ static grub_uint8_t jump[0x20] =
+     /* 	[MIB]       ld8 r1=[r15] */
+     0x11, 0x08, 0x00, 0x1e, 0x18, 0x10,
+     /* mov b6=r16 */
+-    0x60, 0x80, 0x04, 0x80, 0x03, 0x00, 
++    0x60, 0x80, 0x04, 0x80, 0x03, 0x00,
+     /* br.few b6;; */
+-    0x60, 0x00, 0x80, 0x00       	            
++    0x60, 0x00, 0x80, 0x00
+   };
+ #else
+ static const grub_uint8_t jump[0x20] =
+diff --git a/grub-core/kern/ieee1275/ieee1275.c b/grub-core/kern/ieee1275/ieee1275.c
+index 86f81a3..4fe72a5 100644
+--- a/grub-core/kern/ieee1275/ieee1275.c
++++ b/grub-core/kern/ieee1275/ieee1275.c
+@@ -306,7 +306,7 @@ grub_ieee1275_seek (grub_ieee1275_ihandle_t ihandle, grub_disk_addr_t pos,
+   args.pos_lo = pos;
+ #else
+   args.pos_hi = (grub_ieee1275_cell_t) (pos >> (8 * GRUB_IEEE1275_CELL_SIZEOF));
+-  args.pos_lo = (grub_ieee1275_cell_t) 
++  args.pos_lo = (grub_ieee1275_cell_t)
+     (pos & ((1ULL << (8 * GRUB_IEEE1275_CELL_SIZEOF)) - 1));
+ #endif
+ 
+diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
+index 085a6a3..d1e1862 100644
+--- a/grub-core/kern/ieee1275/init.c
++++ b/grub-core/kern/ieee1275/init.c
+@@ -160,7 +160,7 @@ grub_machine_get_bootlocation (char **device, char **path)
+ 
+ /* Claim some available memory in the first /memory node. */
+ #ifdef __sparc__
+-static void 
++static void
+ grub_claim_heap (void)
+ {
+   grub_mm_init_region ((void *) (grub_modules_get_end ()
+@@ -228,7 +228,7 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
+   return 0;
+ }
+ 
+-static void 
++static void
+ grub_claim_heap (void)
+ {
+   unsigned long total = 0;
+@@ -286,7 +286,7 @@ grub_addr_t grub_modbase;
+ void
+ grub_machine_init (void)
+ {
+-  grub_modbase = ALIGN_UP((grub_addr_t) _end 
++  grub_modbase = ALIGN_UP((grub_addr_t) _end
+ 			  + GRUB_KERNEL_MACHINE_MOD_GAP,
+ 			  GRUB_KERNEL_MACHINE_MOD_ALIGN);
+   grub_ieee1275_init ();
+diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
+index 4d493ab..11b2beb 100644
+--- a/grub-core/kern/ieee1275/openfw.c
++++ b/grub-core/kern/ieee1275/openfw.c
+@@ -404,7 +404,7 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype)
+ 	if (comma)
+ 	  {
+ 	    char *filepath = comma + 1;
+-	    
++
+ 	    /* Make sure filepath has leading backslash.  */
+ 	    if (filepath[0] != '\\')
+ 	      ret = grub_xasprintf ("\\%s", filepath);
+diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
+index c6fb668..40ab83d 100644
+--- a/grub-core/kern/main.c
++++ b/grub-core/kern/main.c
+@@ -210,7 +210,7 @@ grub_set_prefix_and_root (void)
+   if (device)
+     {
+       char *prefix_set;
+-    
++
+       prefix_set = grub_xasprintf ("(%s)%s", device, path ? : "");
+       if (prefix_set)
+ 	{
+@@ -300,7 +300,7 @@ grub_main (void)
+   grub_register_exported_symbols ();
+ #ifdef GRUB_LINKER_HAVE_INIT
+   grub_arch_dl_init_linker ();
+-#endif  
++#endif
+   grub_load_modules ();
+ 
+   grub_boot_time ("After loading embedded modules.");
+diff --git a/grub-core/kern/mips/dl.c b/grub-core/kern/mips/dl.c
+index 5d7d299..5b02f97 100644
+--- a/grub-core/kern/mips/dl.c
++++ b/grub-core/kern/mips/dl.c
+@@ -164,7 +164,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
+ #endif
+ 
+ 	    /* Handle partner lo16 relocation. Lower part is
+-	       treated as signed. Hence add 0x8000 to compensate. 
++	       treated as signed. Hence add 0x8000 to compensate.
+ 	    */
+ 	    value = (*(grub_uint16_t *) addr << 16)
+ 	      + sym_value + 0x8000;
+@@ -206,8 +206,8 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
+ 	    value = raw << 2;
+ 	    value += sym_value;
+ 	    raw = (value >> 2) & 0x3ffffff;
+-			
+-	    *(grub_uint32_t *) addr = 
++
++	    *(grub_uint32_t *) addr =
+ 	      raw | ((*(grub_uint32_t *) addr) & 0xfc000000);
+ 	  }
+ 	  break;
+@@ -265,7 +265,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
+   return GRUB_ERR_NONE;
+ }
+ 
+-void 
++void
+ grub_arch_dl_init_linker (void)
+ {
+   grub_dl_register_symbol ("__gnu_local_gp", &__gnu_local_gp_dummy, 0, 0);
+diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c
+index dff598c..97b09b0 100644
+--- a/grub-core/kern/mips/loongson/init.c
++++ b/grub-core/kern/mips/loongson/init.c
+@@ -107,10 +107,10 @@ init_pci (void)
+ 
+   *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER
+ 				+ GRUB_PCI_REG_CACHELINE)) = 0xff;
+-  *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER 
++  *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER
+ 				+ GRUB_PCI_REG_ADDRESS_REG0))
+     = 0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 | GRUB_PCI_ADDR_MEM_PREFETCH;
+-  *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER 
++  *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER
+ 				+ GRUB_PCI_REG_ADDRESS_REG1)) = 0;
+ 
+   grub_pci_iterate (set_card, NULL);
+@@ -183,7 +183,7 @@ grub_machine_init (void)
+       else
+ 	totalmem = ((spd.ddr2.num_of_ranks
+ 		     & GRUB_SMBUS_SPD_MEMORY_NUM_OF_RANKS_MASK) + 1) << (i + 2);
+-      
++
+       if (totalmem >= 256)
+ 	{
+ 	  grub_arch_memsize = 256;
+diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c
+index 8b6c55f..69488a3 100644
+--- a/grub-core/kern/mips/qemu_mips/init.c
++++ b/grub-core/kern/mips/qemu_mips/init.c
+@@ -41,7 +41,7 @@ grub_machine_init (void)
+   if (grub_arch_memsize == 0)
+     {
+       int i;
+-      
++
+       for (i = 27; i >= 0; i--)
+ 	if (probe_mem (grub_arch_memsize | (1 << i)))
+ 	  grub_arch_memsize |= (1 << i);
+@@ -87,7 +87,7 @@ grub_halt (void)
+   while (1);
+ }
+ 
+-grub_err_t 
++grub_err_t
+ grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
+ {
+   hook (0, grub_arch_memsize, GRUB_MEMORY_AVAILABLE, hook_data);
+diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
+index 63b586d..35972de 100644
+--- a/grub-core/kern/misc.c
++++ b/grub-core/kern/misc.c
+@@ -1200,7 +1200,7 @@ static void __attribute__ ((noreturn))
+ grub_abort (void)
+ {
+   grub_printf ("\nAborted.");
+-  
++
+ #ifndef GRUB_UTIL
+   if (grub_term_inputs)
+ #endif
+@@ -1264,7 +1264,7 @@ grub_real_boot_time (const char *file,
+   n->next = 0;
+ 
+   va_start (args, fmt);
+-  n->msg = grub_xvasprintf (fmt, args);    
++  n->msg = grub_xvasprintf (fmt, args);
+   va_end (args);
+ 
+   *boot_time_last = n;
+diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
+index c686917..079c28d 100644
+--- a/grub-core/kern/mm.c
++++ b/grub-core/kern/mm.c
+@@ -283,7 +283,7 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
+ 	  else if (extra == 0)
+ 	    {
+ 	      grub_mm_header_t r;
+-	      
++
+ 	      r = cur + extra + n;
+ 	      r->magic = GRUB_MM_FREE_MAGIC;
+ 	      r->size = cur->size - extra - n;
+@@ -707,7 +707,7 @@ grub_debug_memalign (const char *file, int line, grub_size_t align,
+   void *ptr;
+ 
+   if (grub_mm_debug)
+-    grub_printf ("%s:%d: memalign (0x%" PRIxGRUB_SIZE  ", 0x%" PRIxGRUB_SIZE  
++    grub_printf ("%s:%d: memalign (0x%" PRIxGRUB_SIZE  ", 0x%" PRIxGRUB_SIZE
+ 		 ") = ", file, line, align, size);
+   ptr = grub_memalign (align, size);
+   if (grub_mm_debug)
+diff --git a/grub-core/kern/partition.c b/grub-core/kern/partition.c
+index 3068c4d..edad9f9 100644
+--- a/grub-core/kern/partition.c
++++ b/grub-core/kern/partition.c
+@@ -128,7 +128,7 @@ grub_partition_probe (struct grub_disk *disk, const char *str)
+       partname = ptr;
+       while (*ptr && grub_isalpha (*ptr))
+ 	ptr++;
+-      partname_end = ptr; 
++      partname_end = ptr;
+       num = grub_strtoul (ptr, &ptr, 0) - 1;
+ 
+       curpart = 0;
+diff --git a/grub-core/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c
+index cdd61b3..7b6418e 100644
+--- a/grub-core/kern/powerpc/dl.c
++++ b/grub-core/kern/powerpc/dl.c
+@@ -47,7 +47,7 @@ struct trampoline
+   grub_uint32_t bctr;
+ };
+ 
+-static const struct trampoline trampoline_template = 
++static const struct trampoline trampoline_template =
+   {
+     0x3d800000,
+     0x618c0000,
+@@ -74,7 +74,7 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
+     if (s->sh_type == SHT_RELA)
+       {
+ 	const Elf_Rela *rel, *max;
+-	
++
+ 	for (rel = (const Elf_Rela *) ((const char *) e + s->sh_offset),
+ 	       max = rel + s->sh_size / s->sh_entsize;
+ 	     rel < max;
+@@ -82,7 +82,7 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
+ 	  if (ELF_R_TYPE (rel->r_info) == GRUB_ELF_R_PPC_REL24
+ 	      || ELF_R_TYPE (rel->r_info) == GRUB_ELF_R_PPC_PLTREL24)
+ 	    (*tramp)++;
+-	
++
+       }
+ 
+   *tramp *= sizeof (struct trampoline);
+@@ -138,7 +138,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
+ 		tptr->ori |= ((value) & 0xffff);
+ 		mod->trampptr = tptr + 1;
+ 	      }
+-			
++
+ 	    if (delta << 6 >> 6 != delta)
+ 	      return grub_error (GRUB_ERR_BAD_MODULE,
+ 				 "relocation overflow");
diff -pruN 2.06-2/debian/patches/2.12-mm/0199-mm-Document-GRUB-internal-memory-management-structur.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0199-mm-Document-GRUB-internal-memory-management-structur.patch
--- 2.06-2/debian/patches/2.12-mm/0199-mm-Document-GRUB-internal-memory-management-structur.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0199-mm-Document-GRUB-internal-memory-management-structur.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,76 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Thu, 25 Nov 2021 02:22:45 +1100
+Subject: mm: Document GRUB internal memory management structures
+
+I spent more than a trivial quantity of time figuring out pre_size and
+whether a memory region's size contains the header cell or not.
+
+Document the meanings of all the properties. Hopefully now no-one else
+has to figure it out!
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ include/grub/mm_private.h | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h
+index c2c4cb1..203533c 100644
+--- a/include/grub/mm_private.h
++++ b/include/grub/mm_private.h
+@@ -21,15 +21,27 @@
+ 
+ #include <grub/mm.h>
+ 
++/* For context, see kern/mm.c */
++
+ /* Magic words.  */
+ #define GRUB_MM_FREE_MAGIC	0x2d3c2808
+ #define GRUB_MM_ALLOC_MAGIC	0x6db08fa4
+ 
++/* A header describing a block of memory - either allocated or free */
+ typedef struct grub_mm_header
+ {
++  /*
++   * The 'next' free block in this region's circular free list.
++   * Only meaningful if the block is free.
++   */
+   struct grub_mm_header *next;
++  /* The block size, not in bytes but the number of cells of
++   * GRUB_MM_ALIGN bytes. Includes the header cell.
++   */
+   grub_size_t size;
++  /* either free or alloc magic, depending on the block type. */
+   grub_size_t magic;
++  /* pad to cell size: see the top of kern/mm.c. */
+ #if GRUB_CPU_SIZEOF_VOID_P == 4
+   char padding[4];
+ #elif GRUB_CPU_SIZEOF_VOID_P == 8
+@@ -48,11 +60,27 @@ typedef struct grub_mm_header
+ 
+ #define GRUB_MM_ALIGN	(1 << GRUB_MM_ALIGN_LOG2)
+ 
++/* A region from which we can make allocations. */
+ typedef struct grub_mm_region
+ {
++  /* The first free block in this region. */
+   struct grub_mm_header *first;
++
++  /*
++   * The next region in the linked list of regions. Regions are initially
++   * sorted in order of increasing size, but can grow, in which case the
++   * ordering may not be preserved.
++   */
+   struct grub_mm_region *next;
++
++  /*
++   * A grub_mm_region will always be aligned to cell size. The pre-size is
++   * the number of bytes we were given but had to skip in order to get that
++   * alignment.
++   */
+   grub_size_t pre_size;
++
++  /* How many bytes are in this region? (free and allocated) */
+   grub_size_t size;
+ }
+ *grub_mm_region_t;
diff -pruN 2.06-2/debian/patches/2.12-mm/0200-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0200-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch
--- 2.06-2/debian/patches/2.12-mm/0200-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0200-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,54 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Thu, 21 Apr 2022 15:24:14 +1000
+Subject: mm: Assert that we preserve header vs region alignment
+
+grub_mm_region_init() does:
+
+  h = (grub_mm_header_t) (r + 1);
+
+where h is a grub_mm_header_t and r is a grub_mm_region_t.
+
+Cells are supposed to be GRUB_MM_ALIGN aligned, but while grub_mm_dump
+ensures this vs the region header, grub_mm_region_init() does not.
+
+It's better to be explicit than implicit here: rather than changing
+grub_mm_region_init() to ALIGN_UP(), require that the struct is
+explicitly a multiple of the header size.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Tested-by: Patrick Steinhardt <ps@pks.im>
+---
+ include/grub/mm_private.h | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h
+index 203533c..a688b92 100644
+--- a/include/grub/mm_private.h
++++ b/include/grub/mm_private.h
+@@ -20,6 +20,7 @@
+ #define GRUB_MM_PRIVATE_H	1
+ 
+ #include <grub/mm.h>
++#include <grub/misc.h>
+ 
+ /* For context, see kern/mm.c */
+ 
+@@ -89,4 +90,17 @@ typedef struct grub_mm_region
+ extern grub_mm_region_t EXPORT_VAR (grub_mm_base);
+ #endif
+ 
++static inline void
++grub_mm_size_sanity_check (void) {
++  /* Ensure we preserve alignment when doing h = (grub_mm_header_t) (r + 1). */
++  COMPILE_TIME_ASSERT ((sizeof (struct grub_mm_region) %
++		        sizeof (struct grub_mm_header)) == 0);
++
++  /*
++   * GRUB_MM_ALIGN is supposed to represent cell size, and a mm_header is
++   * supposed to be 1 cell.
++   */
++  COMPILE_TIME_ASSERT (sizeof (struct grub_mm_header) == GRUB_MM_ALIGN);
++}
++
+ #endif
diff -pruN 2.06-2/debian/patches/2.12-mm/0201-mm-When-adding-a-region-merge-with-region-after-as-w.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0201-mm-When-adding-a-region-merge-with-region-after-as-w.patch
--- 2.06-2/debian/patches/2.12-mm/0201-mm-When-adding-a-region-merge-with-region-after-as-w.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0201-mm-When-adding-a-region-merge-with-region-after-as-w.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,201 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Thu, 21 Apr 2022 15:24:15 +1000
+Subject: mm: When adding a region, merge with region after as well as before
+
+On x86_64-efi (at least) regions seem to be added from top down. The mm
+code will merge a new region with an existing region that comes
+immediately before the new region. This allows larger allocations to be
+satisfied that would otherwise be the case.
+
+On powerpc-ieee1275, however, regions are added from bottom up. So if
+we add 3x 32MB regions, we can still only satisfy a 32MB allocation,
+rather than the 96MB allocation we might otherwise be able to satisfy.
+
+  * Define 'post_size' as being bytes lost to the end of an allocation
+    due to being given weird sizes from firmware that are not multiples
+    of GRUB_MM_ALIGN.
+
+  * Allow merging of regions immediately _after_ existing regions, not
+    just before. As with the other approach, we create an allocated
+    block to represent the new space and the pass it to grub_free() to
+    get the metadata right.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Tested-by: Stefan Berger <stefanb@linux.ibm.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Tested-by: Patrick Steinhardt <ps@pks.im>
+---
+ grub-core/kern/mm.c       | 130 +++++++++++++++++++++++++++++-----------------
+ include/grub/mm_private.h |   9 ++++
+ 2 files changed, 92 insertions(+), 47 deletions(-)
+
+diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
+index 079c28d..b406906 100644
+--- a/grub-core/kern/mm.c
++++ b/grub-core/kern/mm.c
+@@ -130,53 +130,88 @@ grub_mm_init_region (void *addr, grub_size_t size)
+ 
+   /* Attempt to merge this region with every existing region */
+   for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p)
+-    /*
+-     * Is the new region immediately below an existing region? That
+-     * is, is the address of the memory we're adding now (addr) + size
+-     * of the memory we're adding (size) + the bytes we couldn't use
+-     * at the start of the region we're considering (q->pre_size)
+-     * equal to the address of q? In other words, does the memory
+-     * looks like this?
+-     *
+-     * addr                          q
+-     *   |----size-----|-q->pre_size-|<q region>|
+-     */
+-    if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q)
+-      {
+-	/*
+-	 * Yes, we can merge the memory starting at addr into the
+-	 * existing region from below. Align up addr to GRUB_MM_ALIGN
+-	 * so that our new region has proper alignment.
+-	 */
+-	r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN);
+-	/* Copy the region data across */
+-	*r = *q;
+-	/* Consider all the new size as pre-size */
+-	r->pre_size += size;
+-
+-	/*
+-	 * If we have enough pre-size to create a block, create a
+-	 * block with it. Mark it as allocated and pass it to
+-	 * grub_free (), which will sort out getting it into the free
+-	 * list.
+-	 */
+-	if (r->pre_size >> GRUB_MM_ALIGN_LOG2)
+-	  {
+-	    h = (grub_mm_header_t) (r + 1);
+-	    /* block size is pre-size converted to cells */
+-	    h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2);
+-	    h->magic = GRUB_MM_ALLOC_MAGIC;
+-	    /* region size grows by block size converted back to bytes */
+-	    r->size += h->size << GRUB_MM_ALIGN_LOG2;
+-	    /* adjust pre_size to be accurate */
+-	    r->pre_size &= (GRUB_MM_ALIGN - 1);
+-	    *p = r;
+-	    grub_free (h + 1);
+-	  }
+-	/* Replace the old region with the new region */
+-	*p = r;
+-	return;
+-      }
++    {
++      /*
++       * Is the new region immediately below an existing region? That
++       * is, is the address of the memory we're adding now (addr) + size
++       * of the memory we're adding (size) + the bytes we couldn't use
++       * at the start of the region we're considering (q->pre_size)
++       * equal to the address of q? In other words, does the memory
++       * looks like this?
++       *
++       * addr                          q
++       *   |----size-----|-q->pre_size-|<q region>|
++       */
++      if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q)
++        {
++          /*
++           * Yes, we can merge the memory starting at addr into the
++           * existing region from below. Align up addr to GRUB_MM_ALIGN
++           * so that our new region has proper alignment.
++           */
++          r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN);
++          /* Copy the region data across */
++          *r = *q;
++          /* Consider all the new size as pre-size */
++          r->pre_size += size;
++
++          /*
++           * If we have enough pre-size to create a block, create a
++           * block with it. Mark it as allocated and pass it to
++           * grub_free (), which will sort out getting it into the free
++           * list.
++           */
++          if (r->pre_size >> GRUB_MM_ALIGN_LOG2)
++            {
++              h = (grub_mm_header_t) (r + 1);
++              /* block size is pre-size converted to cells */
++              h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2);
++              h->magic = GRUB_MM_ALLOC_MAGIC;
++              /* region size grows by block size converted back to bytes */
++              r->size += h->size << GRUB_MM_ALIGN_LOG2;
++              /* adjust pre_size to be accurate */
++              r->pre_size &= (GRUB_MM_ALIGN - 1);
++              *p = r;
++              grub_free (h + 1);
++            }
++          /* Replace the old region with the new region */
++          *p = r;
++          return;
++        }
++
++      /*
++       * Is the new region immediately above an existing region? That
++       * is:
++       *   q                       addr
++       *   |<q region>|-q->post_size-|----size-----|
++       */
++      if ((grub_uint8_t *) q + sizeof (*q) + q->size + q->post_size ==
++	  (grub_uint8_t *) addr)
++	{
++	  /*
++	   * Yes! Follow a similar pattern to above, but simpler.
++	   * Our header starts at address - post_size, which should align us
++	   * to a cell boundary.
++	   *
++	   * Cast to (void *) first to avoid the following build error:
++	   *   kern/mm.c: In function ‘grub_mm_init_region’:
++	   *   kern/mm.c:211:15: error: cast increases required alignment of target type [-Werror=cast-align]
++	   *     211 |           h = (grub_mm_header_t) ((grub_uint8_t *) addr - q->post_size);
++	   *         |               ^
++	   * It is safe to do that because proper alignment is enforced in grub_mm_size_sanity_check().
++	   */
++	  h = (grub_mm_header_t)(void *) ((grub_uint8_t *) addr - q->post_size);
++	  /* our size is the allocated size plus post_size, in cells */
++	  h->size = (size + q->post_size) >> GRUB_MM_ALIGN_LOG2;
++	  h->magic = GRUB_MM_ALLOC_MAGIC;
++	  /* region size grows by block size converted back to bytes */
++	  q->size += h->size << GRUB_MM_ALIGN_LOG2;
++	  /* adjust new post_size to be accurate */
++	  q->post_size = (q->post_size + size) & (GRUB_MM_ALIGN - 1);
++	  grub_free (h + 1);
++	  return;
++	}
++    }
+ 
+   /* Allocate a region from the head.  */
+   r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN);
+@@ -195,6 +230,7 @@ grub_mm_init_region (void *addr, grub_size_t size)
+   r->first = h;
+   r->pre_size = (grub_addr_t) r - (grub_addr_t) addr;
+   r->size = (h->size << GRUB_MM_ALIGN_LOG2);
++  r->post_size = size - r->size;
+ 
+   /* Find where to insert this region. Put a smaller one before bigger ones,
+      to prevent fragmentation.  */
+diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h
+index a688b92..96c2d81 100644
+--- a/include/grub/mm_private.h
++++ b/include/grub/mm_private.h
+@@ -81,8 +81,17 @@ typedef struct grub_mm_region
+    */
+   grub_size_t pre_size;
+ 
++  /*
++   * Likewise, the post-size is the number of bytes we wasted at the end
++   * of the allocation because it wasn't a multiple of GRUB_MM_ALIGN
++   */
++  grub_size_t post_size;
++
+   /* How many bytes are in this region? (free and allocated) */
+   grub_size_t size;
++
++  /* pad to a multiple of cell size */
++  char padding[3 * GRUB_CPU_SIZEOF_VOID_P];
+ }
+ *grub_mm_region_t;
+ 
diff -pruN 2.06-2/debian/patches/2.12-mm/0202-mm-Debug-support-for-region-operations.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0202-mm-Debug-support-for-region-operations.patch
--- 2.06-2/debian/patches/2.12-mm/0202-mm-Debug-support-for-region-operations.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0202-mm-Debug-support-for-region-operations.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,69 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Thu, 21 Apr 2022 15:24:16 +1000
+Subject: mm: Debug support for region operations
+
+This is handy for debugging. Enable with "set debug=regions".
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Tested-by: Patrick Steinhardt <ps@pks.im>
+---
+ grub-core/kern/mm.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
+index b406906..43d4e60 100644
+--- a/grub-core/kern/mm.c
++++ b/grub-core/kern/mm.c
+@@ -115,9 +115,8 @@ grub_mm_init_region (void *addr, grub_size_t size)
+   grub_mm_header_t h;
+   grub_mm_region_t r, *p, q;
+ 
+-#if 0
+-  grub_printf ("Using memory for heap: start=%p, end=%p\n", addr, addr + (unsigned int) size);
+-#endif
++  grub_dprintf ("regions", "Using memory for heap: start=%p, end=%p\n",
++                addr, (char *) addr + (unsigned int) size);
+ 
+   /* Exclude last 4K to avoid overflows. */
+   /* If addr + 0x1000 overflows then whole region is in excluded zone.  */
+@@ -142,8 +141,14 @@ grub_mm_init_region (void *addr, grub_size_t size)
+        * addr                          q
+        *   |----size-----|-q->pre_size-|<q region>|
+        */
++      grub_dprintf ("regions", "Can we extend into region above?"
++		    " %p + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " ?=? %p\n",
++		    (grub_uint8_t *) addr, size, q->pre_size, (grub_uint8_t *) q);
+       if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q)
+         {
++	  grub_dprintf ("regions", "Yes: extending a region: (%p -> %p) -> (%p -> %p)\n",
++			q, (grub_uint8_t *) q + sizeof (*q) + q->size,
++			addr, (grub_uint8_t *) q + sizeof (*q) + q->size);
+           /*
+            * Yes, we can merge the memory starting at addr into the
+            * existing region from below. Align up addr to GRUB_MM_ALIGN
+@@ -185,9 +190,15 @@ grub_mm_init_region (void *addr, grub_size_t size)
+        *   q                       addr
+        *   |<q region>|-q->post_size-|----size-----|
+        */
++      grub_dprintf ("regions", "Can we extend into region below?"
++                    " %p + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " ?=? %p\n",
++                    (grub_uint8_t *) q, sizeof(*q), q->size, q->post_size, (grub_uint8_t *) addr);
+       if ((grub_uint8_t *) q + sizeof (*q) + q->size + q->post_size ==
+ 	  (grub_uint8_t *) addr)
+ 	{
++	  grub_dprintf ("regions", "Yes: extending a region: (%p -> %p) -> (%p -> %p)\n",
++			q, (grub_uint8_t *) q + sizeof (*q) + q->size,
++			q, (grub_uint8_t *) addr + size);
+ 	  /*
+ 	   * Yes! Follow a similar pattern to above, but simpler.
+ 	   * Our header starts at address - post_size, which should align us
+@@ -213,6 +224,8 @@ grub_mm_init_region (void *addr, grub_size_t size)
+ 	}
+     }
+ 
++  grub_dprintf ("regions", "No: considering a new region at %p of size %" PRIxGRUB_SIZE "\n",
++		addr, size);
+   /* Allocate a region from the head.  */
+   r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN);
+ 
diff -pruN 2.06-2/debian/patches/2.12-mm/0203-mm-Drop-unused-unloading-of-modules-on-OOM.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0203-mm-Drop-unused-unloading-of-modules-on-OOM.patch
--- 2.06-2/debian/patches/2.12-mm/0203-mm-Drop-unused-unloading-of-modules-on-OOM.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0203-mm-Drop-unused-unloading-of-modules-on-OOM.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,78 @@
+From: Patrick Steinhardt <ps@pks.im>
+Date: Thu, 21 Apr 2022 15:24:17 +1000
+Subject: mm: Drop unused unloading of modules on OOM
+
+In grub_memalign(), there's a commented section which would allow for
+unloading of unneeded modules in case where there is not enough free
+memory available to satisfy a request. Given that this code is never
+compiled in, let's remove it together with grub_dl_unload_unneeded().
+
+Signed-off-by: Patrick Steinhardt <ps@pks.im>
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Tested-by: Patrick Steinhardt <ps@pks.im>
+---
+ grub-core/kern/dl.c | 20 --------------------
+ grub-core/kern/mm.c |  8 --------
+ include/grub/dl.h   |  1 -
+ 3 files changed, 29 deletions(-)
+
+diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
+index b3e93c3..eecab8f 100644
+--- a/grub-core/kern/dl.c
++++ b/grub-core/kern/dl.c
+@@ -817,23 +817,3 @@ grub_dl_unload (grub_dl_t mod)
+   grub_free (mod);
+   return 1;
+ }
+-
+-/* Unload unneeded modules.  */
+-void
+-grub_dl_unload_unneeded (void)
+-{
+-  /* Because grub_dl_remove modifies the list of modules, this
+-     implementation is tricky.  */
+-  grub_dl_t p = grub_dl_head;
+-
+-  while (p)
+-    {
+-      if (grub_dl_unload (p))
+-	{
+-	  p = grub_dl_head;
+-	  continue;
+-	}
+-
+-      p = p->next;
+-    }
+-}
+diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
+index 43d4e60..e859772 100644
+--- a/grub-core/kern/mm.c
++++ b/grub-core/kern/mm.c
+@@ -444,14 +444,6 @@ grub_memalign (grub_size_t align, grub_size_t size)
+       count++;
+       goto again;
+ 
+-#if 0
+-    case 1:
+-      /* Unload unneeded modules.  */
+-      grub_dl_unload_unneeded ();
+-      count++;
+-      goto again;
+-#endif
+-
+     default:
+       break;
+     }
+diff --git a/include/grub/dl.h b/include/grub/dl.h
+index b3753c9..5367177 100644
+--- a/include/grub/dl.h
++++ b/include/grub/dl.h
+@@ -203,7 +203,6 @@ grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name);
+ grub_dl_t grub_dl_load_core (void *addr, grub_size_t size);
+ grub_dl_t EXPORT_FUNC(grub_dl_load_core_noinit) (void *addr, grub_size_t size);
+ int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod);
+-extern void grub_dl_unload_unneeded (void);
+ extern int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod);
+ extern int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod);
+ extern int EXPORT_FUNC(grub_dl_ref_count) (grub_dl_t mod);
diff -pruN 2.06-2/debian/patches/2.12-mm/0204-mm-Allow-dynamically-requesting-additional-memory-re.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0204-mm-Allow-dynamically-requesting-additional-memory-re.patch
--- 2.06-2/debian/patches/2.12-mm/0204-mm-Allow-dynamically-requesting-additional-memory-re.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0204-mm-Allow-dynamically-requesting-additional-memory-re.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,128 @@
+From: Patrick Steinhardt <ps@pks.im>
+Date: Thu, 21 Apr 2022 15:24:18 +1000
+Subject: mm: Allow dynamically requesting additional memory regions
+
+Currently, all platforms will set up their heap on initialization of the
+platform code. While this works mostly fine, it poses some limitations
+on memory management on us. Most notably, allocating big chunks of
+memory in the gigabyte range would require us to pre-request this many
+bytes from the firmware and add it to the heap from the beginning on
+some platforms like EFI. As this isn't needed for most configurations,
+it is inefficient and may even negatively impact some usecases when,
+e.g., chainloading. Nonetheless, allocating big chunks of memory is
+required sometimes, where one example is the upcoming support for the
+Argon2 key derival function in LUKS2.
+
+In order to avoid pre-allocating big chunks of memory, this commit
+implements a runtime mechanism to add more pages to the system. When
+a given allocation cannot be currently satisfied, we'll call a given
+callback set up by the platform's own memory management subsystem,
+asking it to add a memory area with at least "n" bytes. If this
+succeeds, we retry searching for a valid memory region, which should
+now succeed.
+
+If this fails, we try asking for "n" bytes, possibly spread across
+multiple regions, in hopes that region merging means that we end up
+with enough memory for things to work out.
+
+Signed-off-by: Patrick Steinhardt <ps@pks.im>
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Tested-by: Stefan Berger <stefanb@linux.ibm.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Tested-by: Patrick Steinhardt <ps@pks.im>
+---
+ grub-core/kern/mm.c | 30 ++++++++++++++++++++++++++++++
+ include/grub/mm.h   | 18 ++++++++++++++++++
+ 2 files changed, 48 insertions(+)
+
+diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
+index e859772..75f6eac 100644
+--- a/grub-core/kern/mm.c
++++ b/grub-core/kern/mm.c
+@@ -28,6 +28,9 @@
+   - multiple regions may be used as free space. They may not be
+   contiguous.
+ 
++  - if existing regions are insufficient to satisfy an allocation, a new
++  region can be requested from firmware.
++
+   Regions are managed by a singly linked list, and the meta information is
+   stored in the beginning of each region. Space after the meta information
+   is used to allocate memory.
+@@ -81,6 +84,7 @@
+ 
+ 
+ grub_mm_region_t grub_mm_base;
++grub_mm_add_region_func_t grub_mm_add_region_fn;
+ 
+ /* Get a header from the pointer PTR, and set *P and *R to a pointer
+    to the header and a pointer to its region, respectively. PTR must
+@@ -444,6 +448,32 @@ grub_memalign (grub_size_t align, grub_size_t size)
+       count++;
+       goto again;
+ 
++    case 1:
++      /* Request additional pages, contiguous */
++      count++;
++
++      if (grub_mm_add_region_fn != NULL &&
++          grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE)
++	goto again;
++
++      /* fallthrough  */
++
++    case 2:
++      /* Request additional pages, anything at all */
++      count++;
++
++      if (grub_mm_add_region_fn != NULL)
++        {
++          /*
++           * Try again even if this fails, in case it was able to partially
++           * satisfy the request
++           */
++          grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_NONE);
++          goto again;
++        }
++
++      /* fallthrough */
++
+     default:
+       break;
+     }
+diff --git a/include/grub/mm.h b/include/grub/mm.h
+index 9c38dd3..d2d6fce 100644
+--- a/include/grub/mm.h
++++ b/include/grub/mm.h
+@@ -20,6 +20,7 @@
+ #ifndef GRUB_MM_H
+ #define GRUB_MM_H	1
+ 
++#include <grub/err.h>
+ #include <grub/types.h>
+ #include <grub/symbol.h>
+ #include <config.h>
+@@ -28,6 +29,23 @@
+ # define NULL	((void *) 0)
+ #endif
+ 
++#define GRUB_MM_ADD_REGION_NONE        0
++#define GRUB_MM_ADD_REGION_CONSECUTIVE (1 << 0)
++
++/*
++ * Function used to request memory regions of `grub_size_t` bytes. The second
++ * parameter is a bitfield of `GRUB_MM_ADD_REGION` flags.
++ */
++typedef grub_err_t (*grub_mm_add_region_func_t) (grub_size_t, unsigned int);
++
++/*
++ * Set this function pointer to enable adding memory-regions at runtime in case
++ * a memory allocation cannot be satisfied with existing regions.
++ */
++#ifndef GRUB_MACHINE_EMU
++extern grub_mm_add_region_func_t EXPORT_VAR(grub_mm_add_region_fn);
++#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);
diff -pruN 2.06-2/debian/patches/2.12-mm/0205-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0205-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch
--- 2.06-2/debian/patches/2.12-mm/0205-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0205-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,101 @@
+From: Patrick Steinhardt <ps@pks.im>
+Date: Thu, 21 Apr 2022 15:24:19 +1000
+Subject: kern/efi/mm: Always request a fixed number of pages on init
+
+When initializing the EFI memory subsystem, we will by default request
+a quarter of the available memory, bounded by a minimum/maximum value.
+Given that we're about to extend the EFI memory system to dynamically
+request additional pages from the firmware as required, this scaling of
+requested memory based on available memory will not make a lot of sense
+anymore.
+
+Remove this logic as a preparatory patch such that we'll instead defer
+to the runtime memory allocator. Note that ideally, we'd want to change
+this after dynamic requesting of pages has been implemented for the EFI
+platform. But because we'll need to split up initialization of the
+memory subsystem and the request of pages from the firmware, we'd have
+to duplicate quite some logic at first only to remove it afterwards
+again. This seems quite pointless, so we instead have patches slightly
+out of order.
+
+Signed-off-by: Patrick Steinhardt <ps@pks.im>
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Tested-by: Patrick Steinhardt <ps@pks.im>
+---
+ grub-core/kern/efi/mm.c | 35 +++--------------------------------
+ 1 file changed, 3 insertions(+), 32 deletions(-)
+
+diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
+index dac9c58..e4f90ad 100644
+--- a/grub-core/kern/efi/mm.c
++++ b/grub-core/kern/efi/mm.c
+@@ -38,9 +38,8 @@
+    a multiplier of 4KB.  */
+ #define MEMORY_MAP_SIZE	0x3000
+ 
+-/* The minimum and maximum heap size for GRUB itself.  */
+-#define MIN_HEAP_SIZE	0x100000
+-#define MAX_HEAP_SIZE	(1600 * 0x100000)
++/* The default heap size for GRUB itself in bytes.  */
++#define DEFAULT_HEAP_SIZE	0x100000
+ 
+ static void *finish_mmap_buf = 0;
+ static grub_efi_uintn_t finish_mmap_size = 0;
+@@ -510,23 +509,6 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
+   return filtered_desc;
+ }
+ 
+-/* Return the total number of pages.  */
+-static grub_efi_uint64_t
+-get_total_pages (grub_efi_memory_descriptor_t *memory_map,
+-		 grub_efi_uintn_t desc_size,
+-		 grub_efi_memory_descriptor_t *memory_map_end)
+-{
+-  grub_efi_memory_descriptor_t *desc;
+-  grub_efi_uint64_t total = 0;
+-
+-  for (desc = memory_map;
+-       desc < memory_map_end;
+-       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+-    total += desc->num_pages;
+-
+-  return total;
+-}
+-
+ /* Add memory regions.  */
+ static void
+ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
+@@ -615,8 +597,6 @@ grub_efi_mm_init (void)
+   grub_efi_memory_descriptor_t *filtered_memory_map_end;
+   grub_efi_uintn_t map_size;
+   grub_efi_uintn_t desc_size;
+-  grub_efi_uint64_t total_pages;
+-  grub_efi_uint64_t required_pages;
+   int mm_status;
+ 
+   /* Prepare a memory region to store two memory maps.  */
+@@ -656,22 +636,13 @@ grub_efi_mm_init (void)
+   filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map,
+ 					       desc_size, memory_map_end);
+ 
+-  /* By default, request a quarter of the available memory.  */
+-  total_pages = get_total_pages (filtered_memory_map, desc_size,
+-				 filtered_memory_map_end);
+-  required_pages = (total_pages >> 2);
+-  if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE))
+-    required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE);
+-  else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE))
+-    required_pages = BYTES_TO_PAGES (MAX_HEAP_SIZE);
+-
+   /* Sort the filtered descriptors, so that GRUB can allocate pages
+      from smaller regions.  */
+   sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end);
+ 
+   /* Allocate memory regions for GRUB's memory management.  */
+   add_memory_regions (filtered_memory_map, desc_size,
+-		      filtered_memory_map_end, required_pages);
++		      filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE));
+ 
+ #if 0
+   /* For debug.  */
diff -pruN 2.06-2/debian/patches/2.12-mm/0206-kern-efi-mm-Extract-function-to-add-memory-regions.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0206-kern-efi-mm-Extract-function-to-add-memory-regions.patch
--- 2.06-2/debian/patches/2.12-mm/0206-kern-efi-mm-Extract-function-to-add-memory-regions.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0206-kern-efi-mm-Extract-function-to-add-memory-regions.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,82 @@
+From: Patrick Steinhardt <ps@pks.im>
+Date: Thu, 21 Apr 2022 15:24:20 +1000
+Subject: kern/efi/mm: Extract function to add memory regions
+
+In preparation of support for runtime-allocating additional memory
+region, this patch extracts the function to retrieve the EFI memory
+map and add a subset of it to GRUB's own memory regions.
+
+Signed-off-by: Patrick Steinhardt <ps@pks.im>
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Tested-by: Patrick Steinhardt <ps@pks.im>
+---
+ grub-core/kern/efi/mm.c | 21 +++++++++++++++------
+ 1 file changed, 15 insertions(+), 6 deletions(-)
+
+diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
+index e4f90ad..b1e1b75 100644
+--- a/grub-core/kern/efi/mm.c
++++ b/grub-core/kern/efi/mm.c
+@@ -588,8 +588,8 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map,
+ }
+ #endif
+ 
+-void
+-grub_efi_mm_init (void)
++static grub_err_t
++grub_efi_mm_add_regions (grub_size_t required_bytes)
+ {
+   grub_efi_memory_descriptor_t *memory_map;
+   grub_efi_memory_descriptor_t *memory_map_end;
+@@ -602,7 +602,7 @@ grub_efi_mm_init (void)
+   /* Prepare a memory region to store two memory maps.  */
+   memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
+   if (! memory_map)
+-    grub_fatal ("cannot allocate memory");
++    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for memory map");
+ 
+   /* Obtain descriptors for available memory.  */
+   map_size = MEMORY_MAP_SIZE;
+@@ -620,14 +620,14 @@ grub_efi_mm_init (void)
+ 
+       memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size));
+       if (! memory_map)
+-	grub_fatal ("cannot allocate memory");
++	return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for new memory map");
+ 
+       mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0,
+ 					   &desc_size, 0);
+     }
+ 
+   if (mm_status < 0)
+-    grub_fatal ("cannot get memory map");
++    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "error fetching memory map from EFI");
+ 
+   memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size);
+ 
+@@ -642,7 +642,7 @@ grub_efi_mm_init (void)
+ 
+   /* Allocate memory regions for GRUB's memory management.  */
+   add_memory_regions (filtered_memory_map, desc_size,
+-		      filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE));
++		      filtered_memory_map_end, BYTES_TO_PAGES (required_bytes));
+ 
+ #if 0
+   /* For debug.  */
+@@ -660,6 +660,15 @@ grub_efi_mm_init (void)
+   /* Release the memory maps.  */
+   grub_efi_free_pages ((grub_addr_t) memory_map,
+ 		       2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
++
++  return GRUB_ERR_NONE;
++}
++
++void
++grub_efi_mm_init (void)
++{
++  if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE)
++    grub_fatal ("%s", grub_errmsg);
+ }
+ 
+ #if defined (__aarch64__) || defined (__arm__) || defined (__riscv)
diff -pruN 2.06-2/debian/patches/2.12-mm/0207-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0207-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch
--- 2.06-2/debian/patches/2.12-mm/0207-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0207-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,85 @@
+From: Patrick Steinhardt <ps@pks.im>
+Date: Thu, 21 Apr 2022 15:24:21 +1000
+Subject: kern/efi/mm: Pass up errors from add_memory_regions()
+
+The function add_memory_regions() is currently only called on system
+initialization to allocate a fixed amount of pages. As such, it didn't
+need to return any errors: in case it failed, we cannot proceed anyway.
+This will change with the upcoming support for requesting more memory
+from the firmware at runtime, where it doesn't make sense anymore to
+fail hard.
+
+Refactor the function to return an error to prepare for this. Note that
+this does not change the behaviour when initializing the memory system
+because grub_efi_mm_init() knows to call grub_fatal() in case
+grub_efi_mm_add_regions() returns an error.
+
+Signed-off-by: Patrick Steinhardt <ps@pks.im>
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Tested-by: Patrick Steinhardt <ps@pks.im>
+---
+ grub-core/kern/efi/mm.c | 22 +++++++++++++++-------
+ 1 file changed, 15 insertions(+), 7 deletions(-)
+
+diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
+index b1e1b75..ac232f5 100644
+--- a/grub-core/kern/efi/mm.c
++++ b/grub-core/kern/efi/mm.c
+@@ -510,7 +510,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
+ }
+ 
+ /* Add memory regions.  */
+-static void
++static grub_err_t
+ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
+ 		    grub_efi_uintn_t desc_size,
+ 		    grub_efi_memory_descriptor_t *memory_map_end,
+@@ -538,9 +538,9 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
+ 					   GRUB_EFI_ALLOCATE_ADDRESS,
+ 					   GRUB_EFI_LOADER_CODE);
+       if (! addr)
+-	grub_fatal ("cannot allocate conventional memory %p with %u pages",
+-		    (void *) ((grub_addr_t) start),
+-		    (unsigned) pages);
++	return grub_error (GRUB_ERR_OUT_OF_MEMORY,
++			    "Memory starting at %p (%u pages) marked as free, but EFI would not allocate",
++			    (void *) ((grub_addr_t) start), (unsigned) pages);
+ 
+       grub_mm_init_region (addr, PAGES_TO_BYTES (pages));
+ 
+@@ -550,7 +550,11 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
+     }
+ 
+   if (required_pages > 0)
+-    grub_fatal ("too little memory");
++    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
++                       "could not allocate all requested memory: %" PRIuGRUB_UINT64_T " pages still required after iterating EFI memory map",
++                       required_pages);
++
++  return GRUB_ERR_NONE;
+ }
+ 
+ void
+@@ -597,6 +601,7 @@ grub_efi_mm_add_regions (grub_size_t required_bytes)
+   grub_efi_memory_descriptor_t *filtered_memory_map_end;
+   grub_efi_uintn_t map_size;
+   grub_efi_uintn_t desc_size;
++  grub_err_t err;
+   int mm_status;
+ 
+   /* Prepare a memory region to store two memory maps.  */
+@@ -641,8 +646,11 @@ grub_efi_mm_add_regions (grub_size_t required_bytes)
+   sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end);
+ 
+   /* Allocate memory regions for GRUB's memory management.  */
+-  add_memory_regions (filtered_memory_map, desc_size,
+-		      filtered_memory_map_end, BYTES_TO_PAGES (required_bytes));
++  err = add_memory_regions (filtered_memory_map, desc_size,
++			    filtered_memory_map_end,
++			    BYTES_TO_PAGES (required_bytes));
++  if (err != GRUB_ERR_NONE)
++    return err;
+ 
+ #if 0
+   /* For debug.  */
diff -pruN 2.06-2/debian/patches/2.12-mm/0208-kern-efi-mm-Implement-runtime-addition-of-pages.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0208-kern-efi-mm-Implement-runtime-addition-of-pages.patch
--- 2.06-2/debian/patches/2.12-mm/0208-kern-efi-mm-Implement-runtime-addition-of-pages.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0208-kern-efi-mm-Implement-runtime-addition-of-pages.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,73 @@
+From: Patrick Steinhardt <ps@pks.im>
+Date: Thu, 21 Apr 2022 15:24:22 +1000
+Subject: kern/efi/mm: Implement runtime addition of pages
+
+Adjust the interface of grub_efi_mm_add_regions() to take a set of
+GRUB_MM_ADD_REGION_* flags, which most notably is currently only the
+GRUB_MM_ADD_REGION_CONSECUTIVE flag. This allows us to set the function
+up as callback for the memory subsystem and have it call out to us in
+case there's not enough pages available in the current heap.
+
+Signed-off-by: Patrick Steinhardt <ps@pks.im>
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Tested-by: Patrick Steinhardt <ps@pks.im>
+---
+ grub-core/kern/efi/mm.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
+index ac232f5..290d832 100644
+--- a/grub-core/kern/efi/mm.c
++++ b/grub-core/kern/efi/mm.c
+@@ -514,7 +514,8 @@ static grub_err_t
+ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
+ 		    grub_efi_uintn_t desc_size,
+ 		    grub_efi_memory_descriptor_t *memory_map_end,
+-		    grub_efi_uint64_t required_pages)
++		    grub_efi_uint64_t required_pages,
++		    unsigned int flags)
+ {
+   grub_efi_memory_descriptor_t *desc;
+ 
+@@ -528,6 +529,10 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
+ 
+       start = desc->physical_start;
+       pages = desc->num_pages;
++
++      if (pages < required_pages && (flags & GRUB_MM_ADD_REGION_CONSECUTIVE))
++	continue;
++
+       if (pages > required_pages)
+ 	{
+ 	  start += PAGES_TO_BYTES (pages - required_pages);
+@@ -593,7 +598,7 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map,
+ #endif
+ 
+ static grub_err_t
+-grub_efi_mm_add_regions (grub_size_t required_bytes)
++grub_efi_mm_add_regions (grub_size_t required_bytes, unsigned int flags)
+ {
+   grub_efi_memory_descriptor_t *memory_map;
+   grub_efi_memory_descriptor_t *memory_map_end;
+@@ -648,7 +653,8 @@ grub_efi_mm_add_regions (grub_size_t required_bytes)
+   /* Allocate memory regions for GRUB's memory management.  */
+   err = add_memory_regions (filtered_memory_map, desc_size,
+ 			    filtered_memory_map_end,
+-			    BYTES_TO_PAGES (required_bytes));
++			    BYTES_TO_PAGES (required_bytes),
++			    flags);
+   if (err != GRUB_ERR_NONE)
+     return err;
+ 
+@@ -675,8 +681,9 @@ grub_efi_mm_add_regions (grub_size_t required_bytes)
+ void
+ grub_efi_mm_init (void)
+ {
+-  if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE)
++  if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE, GRUB_MM_ADD_REGION_NONE) != GRUB_ERR_NONE)
+     grub_fatal ("%s", grub_errmsg);
++  grub_mm_add_region_fn = grub_efi_mm_add_regions;
+ }
+ 
+ #if defined (__aarch64__) || defined (__arm__) || defined (__riscv)
diff -pruN 2.06-2/debian/patches/2.12-mm/0209-efi-Increase-default-memory-allocation-to-32-MiB.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0209-efi-Increase-default-memory-allocation-to-32-MiB.patch
--- 2.06-2/debian/patches/2.12-mm/0209-efi-Increase-default-memory-allocation-to-32-MiB.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0209-efi-Increase-default-memory-allocation-to-32-MiB.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,29 @@
+From: Daniel Axtens <dja@axtens.net>
+Date: Tue, 20 Sep 2022 00:30:30 +1000
+Subject: efi: Increase default memory allocation to 32 MiB
+
+We have multiple reports of things being slower with a 1 MiB initial static
+allocation, and a report (more difficult to nail down) of a boot failure
+as a result of the smaller initial allocation.
+
+Make the initial memory allocation 32 MiB.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/kern/efi/mm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
+index 290d832..eb3b33d 100644
+--- a/grub-core/kern/efi/mm.c
++++ b/grub-core/kern/efi/mm.c
+@@ -39,7 +39,7 @@
+ #define MEMORY_MAP_SIZE	0x3000
+ 
+ /* The default heap size for GRUB itself in bytes.  */
+-#define DEFAULT_HEAP_SIZE	0x100000
++#define DEFAULT_HEAP_SIZE	0x2000000
+ 
+ static void *finish_mmap_buf = 0;
+ static grub_efi_uintn_t finish_mmap_size = 0;
diff -pruN 2.06-2/debian/patches/2.12-mm/0210-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch 2.06-2ubuntu16/debian/patches/2.12-mm/0210-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch
--- 2.06-2/debian/patches/2.12-mm/0210-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/2.12-mm/0210-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,55 @@
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Sat, 15 Oct 2022 22:15:11 +0800
+Subject: mm: Try invalidate disk caches last when out of memory
+
+Every heap grow will cause all disk caches invalidated which decreases
+performance severely. This patch moves disk cache invalidation code to
+the last of memory squeezing measures. So, disk caches are released only
+when there are no other ways to get free memory.
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Reviewed-by: Patrick Steinhardt <ps@pks.im>
+---
+ grub-core/kern/mm.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
+index 75f6eac..ae22791 100644
+--- a/grub-core/kern/mm.c
++++ b/grub-core/kern/mm.c
+@@ -443,12 +443,6 @@ grub_memalign (grub_size_t align, grub_size_t size)
+   switch (count)
+     {
+     case 0:
+-      /* Invalidate disk caches.  */
+-      grub_disk_cache_invalidate_all ();
+-      count++;
+-      goto again;
+-
+-    case 1:
+       /* Request additional pages, contiguous */
+       count++;
+ 
+@@ -458,7 +452,7 @@ grub_memalign (grub_size_t align, grub_size_t size)
+ 
+       /* fallthrough  */
+ 
+-    case 2:
++    case 1:
+       /* Request additional pages, anything at all */
+       count++;
+ 
+@@ -474,6 +468,12 @@ grub_memalign (grub_size_t align, grub_size_t size)
+ 
+       /* fallthrough */
+ 
++    case 2:
++      /* Invalidate disk caches.  */
++      grub_disk_cache_invalidate_all ();
++      count++;
++      goto again;
++
+     default:
+       break;
+     }
diff -pruN 2.06-2/debian/patches/at_keyboard-module-init.patch 2.06-2ubuntu16/debian/patches/at_keyboard-module-init.patch
--- 2.06-2/debian/patches/at_keyboard-module-init.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/at_keyboard-module-init.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From e619f11201a4d93ce36d384221c899f88f7618c9 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 +15,7 @@ Patch-Name: at_keyboard-module-init.patc
  1 file changed, 9 insertions(+)
 
 diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c
-index 597111077..beb007002 100644
+index 5971110..beb0070 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 -pruN 2.06-2/debian/patches/bash-completion-drop-have-checks.patch 2.06-2ubuntu16/debian/patches/bash-completion-drop-have-checks.patch
--- 2.06-2/debian/patches/bash-completion-drop-have-checks.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/bash-completion-drop-have-checks.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From c543561137513e37ae17879366ebf4e10348daa2 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
@@ -12,11 +11,11 @@ Last-Update: 2018-11-16
 
 Patch-Name: bash-completion-drop-have-checks.patch
 ---
- .../bash-completion.d/grub-completion.bash.in | 39 +++++++------------
+ util/bash-completion.d/grub-completion.bash.in | 39 +++++++++-----------------
  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 44bf135..d4235e7 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 -pruN 2.06-2/debian/patches/blacklist-1440x900x32.patch 2.06-2ubuntu16/debian/patches/blacklist-1440x900x32.patch
--- 2.06-2/debian/patches/blacklist-1440x900x32.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/blacklist-1440x900x32.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From ee6cee995e403b3fa81798cddb5247be6de3205b 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 +12,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 b7f9119..4b1bd7d 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 -pruN 2.06-2/debian/patches/bootp-new-net_bootp6-command.patch 2.06-2ubuntu16/debian/patches/bootp-new-net_bootp6-command.patch
--- 2.06-2/debian/patches/bootp-new-net_bootp6-command.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/bootp-new-net_bootp6-command.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 2ce72d9b58e2166f47603851fb9b66acb314cca1 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
@@ -13,13 +12,13 @@ Last-Update: 2021-09-24
 
 Patch-Name: bootp-new-net_bootp6-command.patch
 ---
- grub-core/net/bootp.c | 908 +++++++++++++++++++++++++++++++++++++++++-
- grub-core/net/ip.c    |  39 ++
+ grub-core/net/bootp.c | 908 +++++++++++++++++++++++++++++++++++++++++++++++++-
+ grub-core/net/ip.c    |  39 +++
  include/grub/net.h    |  72 ++++
  3 files changed, 1018 insertions(+), 1 deletion(-)
 
 diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
-index 6fb562702..00c11af39 100644
+index 6fb5627..00c11af 100644
 --- a/grub-core/net/bootp.c
 +++ b/grub-core/net/bootp.c
 @@ -24,6 +24,98 @@
@@ -971,7 +970,7 @@ index 6fb562702..00c11af39 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 ea5edf8..0141079 100644
 --- a/grub-core/net/ip.c
 +++ b/grub-core/net/ip.c
 @@ -239,6 +239,45 @@ handle_dgram (struct grub_net_buff *nb,
@@ -1021,7 +1020,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 69bfe0947..1cb05627e 100644
+index 69bfe09..1cb0562 100644
 --- a/include/grub/net.h
 +++ b/include/grub/net.h
 @@ -448,6 +448,66 @@ struct grub_net_bootp_packet
diff -pruN 2.06-2/debian/patches/bootp-process-dhcpack-http-boot.patch 2.06-2ubuntu16/debian/patches/bootp-process-dhcpack-http-boot.patch
--- 2.06-2/debian/patches/bootp-process-dhcpack-http-boot.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/bootp-process-dhcpack-http-boot.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From cd78a54e5fa8d4a6f9223b7ddbb7db86ca0dd993 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
@@ -21,12 +20,12 @@ Last-Update: 2021-09-24
 
 Patch-Name: bootp-process-dhcpack-http-boot.patch
 ---
- grub-core/net/bootp.c | 60 ++++++++++++++++++++++++++++++++++++++++++-
+ grub-core/net/bootp.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++-
  include/grub/net.h    |  1 +
  2 files changed, 60 insertions(+), 1 deletion(-)
 
 diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
-index 00c11af39..f35d582b8 100644
+index 00c11af..f35d582 100644
 --- a/grub-core/net/bootp.c
 +++ b/grub-core/net/bootp.c
 @@ -154,7 +154,7 @@ struct grub_dhcp_request_options
@@ -111,7 +110,7 @@ index 00c11af39..f35d582b8 100644
        },
        GRUB_NET_BOOTP_END,
 diff --git a/include/grub/net.h b/include/grub/net.h
-index 1cb05627e..cbcae79b1 100644
+index 1cb0562..cbcae79 100644
 --- a/include/grub/net.h
 +++ b/include/grub/net.h
 @@ -528,6 +528,7 @@ enum
diff -pruN 2.06-2/debian/patches/cherrypick-efi-grub_efi_close_protocol.patch 2.06-2ubuntu16/debian/patches/cherrypick-efi-grub_efi_close_protocol.patch
--- 2.06-2/debian/patches/cherrypick-efi-grub_efi_close_protocol.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/cherrypick-efi-grub_efi_close_protocol.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,79 @@
+From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+Date: Mon, 29 Nov 2021 16:00:29 +0100
+Subject: efi: library function grub_efi_close_protocol()
+
+Create a library function for CloseProtocol() and use it for the SNP
+driver.
+
+Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+
+Origin: upstream
+---
+ grub-core/kern/efi/efi.c           | 12 ++++++++++++
+ grub-core/net/drivers/efi/efinet.c |  8 ++------
+ include/grub/efi/efi.h             |  3 +++
+ 3 files changed, 17 insertions(+), 6 deletions(-)
+
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index a3cae1e..69c283d 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -117,6 +117,18 @@ grub_efi_open_protocol (grub_efi_handle_t handle,
+   return interface;
+ }
+ 
++grub_efi_status_t
++grub_efi_close_protocol (grub_efi_handle_t handle, grub_efi_guid_t *protocol)
++{
++  grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
++  grub_efi_status_t status;
++
++  status = efi_call_4 (b->close_protocol, handle, protocol,
++		       grub_efi_image_handle, NULL);
++
++  return status;
++}
++
+ int
+ grub_efi_set_text_mode (int on)
+ {
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 9273bb7..a5d0539 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -160,9 +160,7 @@ open_card (struct grub_net_card *dev)
+ 
+   if (dev->efi_net != NULL)
+     {
+-      efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
+-		  dev->efi_handle, &net_io_guid,
+-		  grub_efi_image_handle, NULL);
++      grub_efi_close_protocol (dev->efi_handle, &net_io_guid);
+       dev->efi_net = NULL;
+     }
+   /*
+@@ -224,9 +222,7 @@ close_card (struct grub_net_card *dev)
+ {
+   efi_call_1 (dev->efi_net->shutdown, dev->efi_net);
+   efi_call_1 (dev->efi_net->stop, dev->efi_net);
+-  efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
+-	      dev->efi_handle, &net_io_guid,
+-	      grub_efi_image_handle, 0);
++  grub_efi_close_protocol (dev->efi_handle, &net_io_guid);
+ }
+ 
+ static struct grub_net_card_driver efidriver =
+diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
+index 08f6ee0..58ac621 100644
+--- a/include/grub/efi/efi.h
++++ b/include/grub/efi/efi.h
+@@ -35,6 +35,9 @@ EXPORT_FUNC(grub_efi_locate_handle) (grub_efi_locate_search_type_t search_type,
+ void *EXPORT_FUNC(grub_efi_open_protocol) (grub_efi_handle_t handle,
+ 					   grub_efi_guid_t *protocol,
+ 					   grub_efi_uint32_t attributes);
++grub_efi_status_t
++EXPORT_FUNC(grub_efi_close_protocol) (grub_efi_handle_t handle,
++				      grub_efi_guid_t *protocol);
+ int EXPORT_FUNC(grub_efi_set_text_mode) (int on);
+ void EXPORT_FUNC(grub_efi_stall) (grub_efi_uintn_t microseconds);
+ void *
diff -pruN 2.06-2/debian/patches/cherrypick-efinet-correct-closing-snp-protocol.patch 2.06-2ubuntu16/debian/patches/cherrypick-efinet-correct-closing-snp-protocol.patch
--- 2.06-2/debian/patches/cherrypick-efinet-correct-closing-snp-protocol.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/cherrypick-efinet-correct-closing-snp-protocol.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,106 @@
+From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+Date: Mon, 29 Nov 2021 16:00:28 +0100
+Subject: efinet: correct closing of SNP protocol
+
+In the context of the implementation of the EFI_LOAD_FILE2_PROTOCOL for
+the initial ramdisk it was observed that opening the SNP protocol failed.
+https://lists.gnu.org/archive/html/grub-devel/2021-10/msg00020.html
+This is due to an incorrect call to CloseProtocol().
+
+The first parameter of CloseProtocol() is the handle, not the interface.
+
+We call OpenProtocol() with ControllerHandle = NULL. Hence we must also
+call CloseProtcol with ControllerHandel = NULL.
+
+Each call of OpenProtocol() for the same network card handle is expected to
+return the same interface pointer. If we want to close the protocol which
+we opened non-exclusively when searching for a card, we have to do this
+before opening the protocol exclusively.
+
+As there is no guarantee that we successfully open the protocol add checks
+in the transmit and receive functions.
+
+Reported-by: Andreas Schwab <schwab@linux-m68k.org>
+Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+
+Origin: upstream
+---
+ grub-core/net/drivers/efi/efinet.c | 31 ++++++++++++++++++++++---------
+ 1 file changed, 22 insertions(+), 9 deletions(-)
+
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index f189209..9273bb7 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -43,6 +43,9 @@ send_card_buffer (struct grub_net_card *dev,
+   grub_uint64_t limit_time = grub_get_time_ms () + 4000;
+   void *txbuf;
+ 
++  if (net == NULL)
++    return grub_error (GRUB_ERR_IO,
++		       N_("network protocol not available, can't send packet"));
+   if (dev->txbusy)
+     while (1)
+       {
+@@ -105,6 +108,9 @@ get_card_packet (struct grub_net_card *dev)
+   struct grub_net_buff *nb;
+   int i;
+ 
++  if (net == NULL)
++    return NULL;
++
+   for (i = 0; i < 2; i++)
+     {
+       if (!dev->rcvbuf)
+@@ -152,12 +158,20 @@ open_card (struct grub_net_card *dev)
+ {
+   grub_efi_simple_network_t *net;
+ 
+-  /* Try to reopen SNP exlusively to close any active MNP protocol instance
+-     that may compete for packet polling
++  if (dev->efi_net != NULL)
++    {
++      efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
++		  dev->efi_handle, &net_io_guid,
++		  grub_efi_image_handle, NULL);
++      dev->efi_net = NULL;
++    }
++  /*
++   * Try to reopen SNP exlusively to close any active MNP protocol instance
++   * that may compete for packet polling
+    */
+   net = grub_efi_open_protocol (dev->efi_handle, &net_io_guid,
+ 				GRUB_EFI_OPEN_PROTOCOL_BY_EXCLUSIVE);
+-  if (net)
++  if (net != NULL)
+     {
+       if (net->mode->state == GRUB_EFI_NETWORK_STOPPED
+ 	  && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS)
+@@ -196,13 +210,12 @@ open_card (struct grub_net_card *dev)
+ 	  efi_call_6 (net->receive_filters, net, filters, 0, 0, 0, NULL);
+ 	}
+ 
+-      efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
+-		  dev->efi_net, &net_io_guid,
+-		  grub_efi_image_handle, dev->efi_handle);
+       dev->efi_net = net;
++    } else {
++      return grub_error (GRUB_ERR_NET_NO_CARD, "%s: can't open protocol",
++			 dev->name);
+     }
+ 
+-  /* If it failed we just try to run as best as we can */
+   return GRUB_ERR_NONE;
+ }
+ 
+@@ -212,8 +225,8 @@ close_card (struct grub_net_card *dev)
+   efi_call_1 (dev->efi_net->shutdown, dev->efi_net);
+   efi_call_1 (dev->efi_net->stop, dev->efi_net);
+   efi_call_4 (grub_efi_system_table->boot_services->close_protocol,
+-	      dev->efi_net, &net_io_guid,
+-	      grub_efi_image_handle, dev->efi_handle);
++	      dev->efi_handle, &net_io_guid,
++	      grub_efi_image_handle, 0);
+ }
+ 
+ static struct grub_net_card_driver efidriver =
diff -pruN 2.06-2/debian/patches/commands-efi-tpm-Refine-the-status-of-log-event.patch 2.06-2ubuntu16/debian/patches/commands-efi-tpm-Refine-the-status-of-log-event.patch
--- 2.06-2/debian/patches/commands-efi-tpm-Refine-the-status-of-log-event.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/commands-efi-tpm-Refine-the-status-of-log-event.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,41 @@
+From: Lu Ken <ken.lu@intel.com>
+Date: Wed, 13 Jul 2022 10:06:10 +0800
+Subject: commands/efi/tpm: Refine the status of log event
+
+1. Use macro GRUB_ERR_NONE instead of hard code 0.
+2. Keep lowercase of the first char for the status string of log event.
+
+Signed-off-by: Lu Ken <ken.lu@intel.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/commands/efi/tpm.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c
+index e73bd55..08ce919 100644
+--- a/grub-core/commands/efi/tpm.c
++++ b/grub-core/commands/efi/tpm.c
+@@ -135,18 +135,18 @@ grub_efi_log_event_status (grub_efi_status_t status)
+   switch (status)
+     {
+     case GRUB_EFI_SUCCESS:
+-      return 0;
++      return GRUB_ERR_NONE;
+     case GRUB_EFI_DEVICE_ERROR:
+-      return grub_error (GRUB_ERR_IO, N_("Command failed"));
++      return grub_error (GRUB_ERR_IO, N_("command failed"));
+     case GRUB_EFI_INVALID_PARAMETER:
+-      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter"));
++      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid parameter"));
+     case GRUB_EFI_BUFFER_TOO_SMALL:
+-      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Output buffer too small"));
++      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("output buffer too small"));
+     case GRUB_EFI_NOT_FOUND:
+       return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable"));
+     default:
+       grub_dprintf ("tpm", "Unknown TPM error: %" PRIdGRUB_SSIZE, status);
+-      return 0;
++      return GRUB_ERR_NONE;
+     }
+ }
+ 
diff -pruN 2.06-2/debian/patches/commands-efi-tpm-Use-grub_strcpy-instead-of-grub_memcpy.patch 2.06-2ubuntu16/debian/patches/commands-efi-tpm-Use-grub_strcpy-instead-of-grub_memcpy.patch
--- 2.06-2/debian/patches/commands-efi-tpm-Use-grub_strcpy-instead-of-grub_memcpy.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/commands-efi-tpm-Use-grub_strcpy-instead-of-grub_memcpy.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,35 @@
+From: Lu Ken <ken.lu@intel.com>
+Date: Wed, 13 Jul 2022 10:06:11 +0800
+Subject: commands/efi/tpm: Use grub_strcpy() instead of grub_memcpy()
+
+The event description is a string, so using grub_strcpy() is cleaner than
+using grub_memcpy().
+
+Signed-off-by: Lu Ken <ken.lu@intel.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/commands/efi/tpm.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c
+index 08ce919..2286368 100644
+--- a/grub-core/commands/efi/tpm.c
++++ b/grub-core/commands/efi/tpm.c
+@@ -176,7 +176,7 @@ grub_tpm1_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf,
+   event->PCRIndex = pcr;
+   event->EventType = EV_IPL;
+   event->EventSize = grub_strlen (description) + 1;
+-  grub_memcpy (event->Event, description, event->EventSize);
++  grub_strcpy ((char *) event->Event, description);
+ 
+   algorithm = TCG_ALG_SHA;
+   status = efi_call_7 (tpm->log_extend_event, tpm, (grub_addr_t) buf, (grub_uint64_t) size,
+@@ -213,7 +213,7 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf,
+   event->Header.EventType = EV_IPL;
+   event->Size =
+     sizeof (*event) - sizeof (event->Event) + grub_strlen (description) + 1;
+-  grub_memcpy (event->Event, description, grub_strlen (description) + 1);
++  grub_strcpy ((char *) event->Event, description);
+ 
+   status = efi_call_5 (tpm->hash_log_extend_event, tpm, 0, (grub_addr_t) buf,
+ 		       (grub_uint64_t) size, event);
diff -pruN 2.06-2/debian/patches/core-in-fs.patch 2.06-2ubuntu16/debian/patches/core-in-fs.patch
--- 2.06-2/debian/patches/core-in-fs.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/core-in-fs.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From bd289b232f3e9ddaa378d02f0f0040c2171078a4 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@debian.org>
 Date: Mon, 13 Jan 2014 12:12:51 +0000
 Subject: Write marker if core.img was written to filesystem
@@ -11,7 +10,7 @@ Patch-Name: core-in-fs.patch
  1 file changed, 8 insertions(+)
 
 diff --git a/util/setup.c b/util/setup.c
-index da5f2c07f..d1902656e 100644
+index da5f2c0..d190265 100644
 --- a/util/setup.c
 +++ b/util/setup.c
 @@ -58,6 +58,8 @@
diff -pruN 2.06-2/debian/patches/debug_verifiers.patch 2.06-2ubuntu16/debian/patches/debug_verifiers.patch
--- 2.06-2/debian/patches/debug_verifiers.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/debug_verifiers.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 55796e3e90a55d54aff94f2dfeb6e02055e08e30 Mon Sep 17 00:00:00 2001
 From: Steve McIntyre <93sam@debian.org>
 Date: Sat, 17 Apr 2021 22:05:47 +0100
 Subject: Add debug to display what's going on with verifiers
@@ -9,7 +8,7 @@ Patch-Name: debug_verifiers.patch
  1 file changed, 2 insertions(+)
 
 diff --git a/grub-core/kern/verifiers.c b/grub-core/kern/verifiers.c
-index 1245d0d9e..5242a723f 100644
+index 1245d0d..5242a72 100644
 --- a/grub-core/kern/verifiers.c
 +++ b/grub-core/kern/verifiers.c
 @@ -100,11 +100,13 @@ grub_verifiers_open (grub_file_t io, enum grub_file_type type)
diff -pruN 2.06-2/debian/patches/default-grub-d.patch 2.06-2ubuntu16/debian/patches/default-grub-d.patch
--- 2.06-2/debian/patches/default-grub-d.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/default-grub-d.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 4dff7f7df2853c519c4b0f59ff224c0b31f8223e 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
@@ -9,12 +8,12 @@ Last-Update: 2021-09-24
 
 Patch-Name: default-grub-d.patch
 ---
- grub-core/osdep/unix/config.c | 128 ++++++++++++++++++++++++++++------
+ grub-core/osdep/unix/config.c | 128 +++++++++++++++++++++++++++++++++++-------
  util/grub-mkconfig.in         |   5 ++
  2 files changed, 112 insertions(+), 21 deletions(-)
 
 diff --git a/grub-core/osdep/unix/config.c b/grub-core/osdep/unix/config.c
-index 7d6325138..545d64b4c 100644
+index 7d63251..545d64b 100644
 --- a/grub-core/osdep/unix/config.c
 +++ b/grub-core/osdep/unix/config.c
 @@ -24,6 +24,9 @@
@@ -192,7 +191,7 @@ index 7d6325138..545d64b4c 100644
 +  free (cfgdir);
  }
 diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
-index 0fd618e35..0265a5a66 100644
+index 0fd618e..0265a5a 100644
 --- a/util/grub-mkconfig.in
 +++ b/util/grub-mkconfig.in
 @@ -160,6 +160,11 @@ fi
diff -pruN 2.06-2/debian/patches/dejavu-font-path.patch 2.06-2ubuntu16/debian/patches/dejavu-font-path.patch
--- 2.06-2/debian/patches/dejavu-font-path.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/dejavu-font-path.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 973e040bdeddcf366a7a45bb5d9f77e06f4784c7 Mon Sep 17 00:00:00 2001
 From: Fabian Greffrath <fabian@greffrath.com>
 Date: Tue, 19 May 2020 12:19:26 +0200
 Subject: add /u/s/fonts/truetype/dejavu to the DejaVu fonts search paths
@@ -9,10 +8,10 @@ Patch-Name: dejavu-font-path.patch
  1 file changed, 1 insertion(+), 1 deletion(-)
 
 diff --git a/configure.ac b/configure.ac
-index b3fb7437e..22c6cf7ac 100644
+index d422626..a29beb9 100644
 --- a/configure.ac
 +++ b/configure.ac
-@@ -1719,7 +1719,7 @@ fi
+@@ -1727,7 +1727,7 @@ fi
  
  if test x"$starfield_excuse" = x; then
     for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do
diff -pruN 2.06-2/debian/patches/disable-floppies.patch 2.06-2ubuntu16/debian/patches/disable-floppies.patch
--- 2.06-2/debian/patches/disable-floppies.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/disable-floppies.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 6a1ff6845e571d2a9885763a3e52a16a9eec54bb Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@debian.org>
 Date: Mon, 13 Jan 2014 12:12:54 +0000
 Subject: Disable use of floppy devices
@@ -13,7 +12,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 d975265b2..f90b6c9ce 100644
+index d975265..f90b6c9 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 -pruN 2.06-2/debian/patches/dpkg-version-comparison.patch 2.06-2ubuntu16/debian/patches/dpkg-version-comparison.patch
--- 2.06-2/debian/patches/dpkg-version-comparison.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/dpkg-version-comparison.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 562d50025e18052cabc40c8eb63ed4d0bb5de236 Mon Sep 17 00:00:00 2001
 From: Robert Millan <rmh@aybabtu.com>
 Date: Mon, 13 Jan 2014 12:12:52 +0000
 Subject: Improve handling of Debian kernel version numbers
@@ -12,7 +11,7 @@ Patch-Name: dpkg-version-comparison.patc
  1 file changed, 4 insertions(+), 3 deletions(-)
 
 diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
-index 301d1ac22..17f9b3e58 100644
+index 301d1ac..17f9b3e 100644
 --- a/util/grub-mkconfig_lib.in
 +++ b/util/grub-mkconfig_lib.in
 @@ -243,8 +243,9 @@ version_test_numeric ()
diff -pruN 2.06-2/debian/patches/efi-add-definition-of-LoadFile2-protocol.patch 2.06-2ubuntu16/debian/patches/efi-add-definition-of-LoadFile2-protocol.patch
--- 2.06-2/debian/patches/efi-add-definition-of-LoadFile2-protocol.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/efi-add-definition-of-LoadFile2-protocol.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,61 @@
+From: Ard Biesheuvel <ard.biesheuvel@arm.com>
+Date: Thu, 28 Oct 2021 23:31:15 +0300
+Subject: efi: add definition of LoadFile2 protocol
+
+Incorporate the EFI_LOAD_FILE2_PROTOCOL GUID and C types from the
+UEFI spec.
+
+Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
+Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
+Signed-off-by: Nikita Ermakov <arei@altlinux.org>
+Origin: https://lists.gnu.org/archive/html/grub-devel/2021-10/msg00210.html
+---
+ grub-core/commands/efi/lsefi.c |  1 +
+ include/grub/efi/api.h         | 15 +++++++++++++++
+ 2 files changed, 16 insertions(+)
+
+diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c
+index d1ce99a..4085f5d 100644
+--- a/grub-core/commands/efi/lsefi.c
++++ b/grub-core/commands/efi/lsefi.c
+@@ -55,6 +55,7 @@ struct known_protocol
+     { GRUB_EFI_ABSOLUTE_POINTER_PROTOCOL_GUID, "absolute pointer" },
+     { GRUB_EFI_DRIVER_BINDING_PROTOCOL_GUID, "EFI driver binding" },
+     { GRUB_EFI_LOAD_FILE_PROTOCOL_GUID, "load file" },
++    { GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID, "load file2" },
+     { GRUB_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, "simple FS" },
+     { GRUB_EFI_TAPE_IO_PROTOCOL_GUID, "tape I/O" },
+     { GRUB_EFI_UNICODE_COLLATION_PROTOCOL_GUID, "unicode collation" },
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index f1a5221..3de0a7d 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -149,6 +149,11 @@
+     { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \
+   }
+ 
++#define GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID \
++  { 0x4006c0c1, 0xfcb3, 0x403e, \
++    { 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d } \
++  }
++
+ #define GRUB_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \
+   { 0x0964e5b22, 0x6459, 0x11d2, \
+     { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+@@ -1729,6 +1734,16 @@ struct grub_efi_rng_protocol
+ };
+ typedef struct grub_efi_rng_protocol grub_efi_rng_protocol_t;
+ 
++struct grub_efi_load_file2
++{
++  grub_efi_status_t (*load_file)(struct grub_efi_load_file2 *this,
++				 grub_efi_device_path_t *file_path,
++				 grub_efi_boolean_t boot_policy,
++				 grub_efi_uintn_t *buffer_size,
++				 void *buffer);
++};
++typedef struct grub_efi_load_file2 grub_efi_load_file2_t;
++
+ #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
+   || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \
+   || defined(__riscv)
diff -pruN 2.06-2/debian/patches/efi-correct-struct-grub_efi_boot_services.patch 2.06-2ubuntu16/debian/patches/efi-correct-struct-grub_efi_boot_services.patch
--- 2.06-2/debian/patches/efi-correct-struct-grub_efi_boot_services.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/efi-correct-struct-grub_efi_boot_services.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,28 @@
+From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+Date: Sat, 22 Jan 2022 11:11:32 +0100
+Subject: efi: correct struct grub_efi_boot_services
+
+The UEFI specification defines that the EFI_BOOT_SERVICES.Exit(() service
+may return EFI_SUCCESS or EFI_INVALID_PARAMETER. So it cannot be
+__attribute__((noreturn)).
+
+Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Origin: https://lists.gnu.org/archive/html/grub-devel/2022-01/msg00121.html
+---
+ include/grub/efi/api.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 3211f04..c5dd4af 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -1267,7 +1267,7 @@ struct grub_efi_boot_services
+   (*exit) (grub_efi_handle_t image_handle,
+ 	   grub_efi_status_t exit_status,
+ 	   grub_efi_uintn_t exit_data_size,
+-	   grub_efi_char16_t *exit_data) __attribute__((noreturn));
++	   grub_efi_char16_t *exit_data);
+ 
+   grub_efi_status_t
+   (*unload_image) (grub_efi_handle_t image_handle);
diff -pruN 2.06-2/debian/patches/efi-EFI-Device-Tree-Fixup-Protocol.patch 2.06-2ubuntu16/debian/patches/efi-EFI-Device-Tree-Fixup-Protocol.patch
--- 2.06-2/debian/patches/efi-EFI-Device-Tree-Fixup-Protocol.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/efi-EFI-Device-Tree-Fixup-Protocol.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,140 @@
+From: Heinrich Schuchardt <xypron.glpk@gmx.de>
+Date: Fri, 29 Jan 2021 07:36:42 +0100
+Subject: [PATCH] efi: EFI Device Tree Fixup Protocol
+
+Device-trees are used to convey information about hardware to the operating
+system. Some of the properties are only known at boot time. (One example of
+such a property is the number of the boot hart on RISC-V systems.) Therefore
+the firmware applies fix-ups to the original device-tree. Some nodes and
+properties are added or altered.
+
+When using GRUB's device-tree command the same fix-ups have to be applied.
+The EFI Device Tree Fixup Protocol allows to pass the loaded device tree
+to the firmware for this purpose.
+
+The protocol can
+
+* add nodes and update properties
+* reserve memory according to the /reserved-memory node and the memory
+  reservation block
+* install the device-tree as configuration table
+
+With the patch GRUB checks if the protocol is installed and invokes it if
+available. (LP: #1965796)
+
+Link: https://lists.gnu.org/archive/html/grub-devel/2021-02/msg00013.html
+Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
+---
+ grub-core/loader/efi/fdt.c | 37 +++++++++++++++++++++++++++++++++++++
+ include/grub/efi/api.h     | 22 ++++++++++++++++++++++
+ 2 files changed, 59 insertions(+)
+
+diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c
+index 12164cd..3bd5360 100644
+--- a/grub-core/loader/efi/fdt.c
++++ b/grub-core/loader/efi/fdt.c
+@@ -30,6 +30,7 @@
+ 
+ static void *loaded_fdt;
+ static void *fdt;
++static grub_efi_guid_t dt_fixup_guid = GRUB_EFI_DT_FIXUP_PROTOCOL_GUID;
+ 
+ #define FDT_ADDR_CELLS_STRING "#address-cells"
+ #define FDT_SIZE_CELLS_STRING "#size-cells"
+@@ -37,6 +38,39 @@ static void *fdt;
+                              sizeof (FDT_ADDR_CELLS_STRING) + \
+                              sizeof (FDT_SIZE_CELLS_STRING))
+ 
++static void *
++grub_fdt_fixup (void)
++{
++  grub_efi_dt_fixup_t *dt_fixup_prot;
++  grub_efi_uintn_t size = 0;
++  grub_efi_status_t status;
++  void *fixup_fdt;
++
++  dt_fixup_prot = grub_efi_locate_protocol (&dt_fixup_guid, 0);
++  if (!dt_fixup_prot)
++    return loaded_fdt;
++
++  grub_dprintf ("linux", "EFI_DT_FIXUP_PROTOCOL available\n");
++
++  status = efi_call_4 (dt_fixup_prot->fixup, dt_fixup_prot, loaded_fdt, &size,
++                       GRUB_EFI_DT_APPLY_FIXUPS | GRUB_EFI_DT_RESERVE_MEMORY);
++  if (status != GRUB_EFI_BUFFER_TOO_SMALL)
++    return loaded_fdt;
++
++  fixup_fdt = grub_realloc (loaded_fdt, size);
++  if (!fixup_fdt)
++    return loaded_fdt;
++  loaded_fdt = fixup_fdt;
++
++  status = efi_call_4 (dt_fixup_prot->fixup, dt_fixup_prot, loaded_fdt, &size,
++                       GRUB_EFI_DT_APPLY_FIXUPS | GRUB_EFI_DT_RESERVE_MEMORY);
++
++  if (status == GRUB_EFI_SUCCESS)
++    grub_dprintf ("linux", "Device tree fixed up via EFI_DT_FIXUP_PROTOCOL\n");
++
++  return loaded_fdt;
++}
++
+ void *
+ grub_fdt_load (grub_size_t additional_size)
+ {
+@@ -93,6 +127,9 @@ grub_fdt_install (void)
+   if (!fdt && !loaded_fdt)
+     return GRUB_ERR_NONE;
+ 
++  if (loaded_fdt)
++    loaded_fdt = grub_fdt_fixup();
++
+   b = grub_efi_system_table->boot_services;
+   status = b->install_configuration_table (&fdt_guid, fdt ?: loaded_fdt);
+   if (status != GRUB_EFI_SUCCESS)
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index c5dd4af..c222a2e 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -344,6 +344,11 @@
+     { 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 } \
+   }
+ 
++#define GRUB_EFI_DT_FIXUP_PROTOCOL_GUID \
++  { 0xe617d64c, 0xfe08, 0x46da, \
++    { 0xf4, 0xdc, 0xbb, 0xd5, 0x87, 0x0c, 0x73, 0x00 } \
++  }
++
+ #define GRUB_EFI_VENDOR_APPLE_GUID \
+   { 0x2B0585EB, 0xD8B8, 0x49A9,	\
+     { 0x8B, 0x8C, 0xE2, 0x1B, 0x01, 0xAE, 0xF2, 0xB7 } \
+@@ -1789,6 +1794,13 @@ enum
+     GRUB_EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST = 0x10,
+   };
+ 
++enum
++  {
++    GRUB_EFI_DT_APPLY_FIXUPS		= 0x01,
++    GRUB_EFI_DT_RESERVE_MEMORY		= 0x02,
++    GRUB_EFI_EFI_DT_INSTALL_TABLE	= 0x04,
++  };
++
+ struct grub_efi_simple_network
+ {
+   grub_uint64_t revision;
+@@ -1852,6 +1864,16 @@ struct grub_efi_block_io
+ };
+ typedef struct grub_efi_block_io grub_efi_block_io_t;
+ 
++struct grub_efi_dt_fixup
++{
++  grub_efi_uint64_t revision;
++  grub_efi_status_t (*fixup) (struct grub_efi_dt_fixup *this,
++			      void *fdt,
++			      grub_efi_uintn_t *buffer_size,
++			      grub_uint32_t flags);
++};
++typedef struct grub_efi_dt_fixup grub_efi_dt_fixup_t;
++
+ struct grub_efi_shim_lock_protocol
+ {
+   grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
diff -pruN 2.06-2/debian/patches/efi-implemented-LoadFile2-initrd-loading-protocol-fo.patch 2.06-2ubuntu16/debian/patches/efi-implemented-LoadFile2-initrd-loading-protocol-fo.patch
--- 2.06-2/debian/patches/efi-implemented-LoadFile2-initrd-loading-protocol-fo.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/efi-implemented-LoadFile2-initrd-loading-protocol-fo.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,183 @@
+From: Ard Biesheuvel <ard.biesheuvel@arm.com>
+Date: Thu, 28 Oct 2021 23:31:16 +0300
+Subject: efi: implemented LoadFile2 initrd loading protocol for Linux
+
+Recent Linux kernels will invoke the LoadFile2 protocol installed on
+a well-known vendor media path to load the initrd if it is exposed by
+the firmware. Using this method is preferred for two reasons:
+- the Linux kernel is in charge of allocating the memory, and so it can
+  implement any placement policy it wants (given that these tend to
+  change between kernel versions),
+- it is no longer necessary to modify the device tree provided by the
+  firmware.
+
+So let's install this protocol when handling the 'initrd' command if
+such a recent kernel was detected (based on the PE/COFF image version),
+and defer loading the initrd contents until the point where the kernel
+invokes the LoadFile2 protocol.
+
+Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
+Signed-off-by: Nikita Ermakov <arei@altlinux.org>
+Origin: https://lists.gnu.org/archive/html/grub-devel/2021-10/msg00214.html
+---
+ grub-core/loader/arm64/linux.c | 117 ++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 116 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
+index aed7a20..6b03455 100644
+--- a/grub-core/loader/arm64/linux.c
++++ b/grub-core/loader/arm64/linux.c
+@@ -48,9 +48,18 @@ static grub_uint32_t cmdline_size;
+ static grub_addr_t initrd_start;
+ static grub_addr_t initrd_end;
+ 
++static struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
++static grub_efi_handle_t initrd_lf2_handle;
++static int initrd_use_loadfile2;
++static grub_efi_guid_t load_file2_guid = GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID;
++static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID;
++
+ grub_err_t
+ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
+ {
++  struct grub_pe32_coff_header *coff_header;
++  struct grub_pe32_optional_header *optional_header;
++
+   if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE)
+     return grub_error(GRUB_ERR_BAD_OS, "invalid magic number");
+ 
+@@ -61,6 +70,21 @@ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
+   grub_dprintf ("linux", "UEFI stub kernel:\n");
+   grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset);
+ 
++  coff_header = (struct grub_pe32_coff_header *)((unsigned long)lh + lh->hdr_offset);
++  optional_header = (struct grub_pe32_optional_header *)(coff_header + 1);
++
++  /*
++   * Linux kernels built for any architecture are guaranteed to support the
++   * LoadFile2 based initrd loading protocol if the image version is >= 1.
++   */
++  if (optional_header->major_image_version >= 1)
++    initrd_use_loadfile2 = 1;
++   else
++    initrd_use_loadfile2 = 0;
++
++  grub_dprintf ("linux", "LoadFile2 initrd loading %sabled\n",
++		initrd_use_loadfile2 ? "en" : "dis");
++
+   return GRUB_ERR_NONE;
+ }
+ 
+@@ -230,13 +254,86 @@ allocate_initrd_mem (int initrd_pages)
+ 				       GRUB_EFI_LOADER_DATA);
+ }
+ 
++struct initrd_media_device_path {
++  grub_efi_vendor_media_device_path_t	vendor;
++  grub_efi_device_path_t		end;
++} GRUB_PACKED;
++
++#define LINUX_EFI_INITRD_MEDIA_GUID  \
++  { 0x5568e427, 0x68fc, 0x4f3d, \
++    { 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68 } \
++  }
++
++static struct initrd_media_device_path initrd_lf2_device_path = {
++  {
++    {
++      GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
++      GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE,
++      sizeof(grub_efi_vendor_media_device_path_t),
++    },
++    LINUX_EFI_INITRD_MEDIA_GUID
++  }, {
++    GRUB_EFI_END_DEVICE_PATH_TYPE,
++    GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
++    sizeof(grub_efi_device_path_t)
++  }
++};
++
++static grub_efi_status_t
++grub_efi_initrd_load_file2(grub_efi_load_file2_t *this,
++                           grub_efi_device_path_t *device_path,
++                           grub_efi_boolean_t boot_policy,
++                           grub_efi_uintn_t *buffer_size,
++                           void *buffer);
++
++static grub_efi_load_file2_t initrd_lf2 = {
++  grub_efi_initrd_load_file2
++};
++
++static grub_efi_status_t
++grub_efi_initrd_load_file2(grub_efi_load_file2_t *this,
++			   grub_efi_device_path_t *device_path,
++			   grub_efi_boolean_t boot_policy,
++			   grub_efi_uintn_t *buffer_size,
++			   void *buffer)
++{
++  grub_efi_status_t status = GRUB_EFI_SUCCESS;
++  grub_efi_uintn_t initrd_size;
++
++  if (!this || this != &initrd_lf2 || !buffer_size)
++    return GRUB_EFI_INVALID_PARAMETER;
++
++  if (device_path->type != GRUB_EFI_END_DEVICE_PATH_TYPE ||
++      device_path->subtype != GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE)
++    return GRUB_EFI_NOT_FOUND;
++
++  if (boot_policy)
++    return GRUB_EFI_UNSUPPORTED;
++
++  initrd_size = grub_get_initrd_size (&initrd_ctx);
++  if (!buffer || *buffer_size < initrd_size)
++    {
++      *buffer_size = initrd_size;
++      return GRUB_EFI_BUFFER_TOO_SMALL;
++    }
++
++  grub_dprintf ("linux", "Providing initrd via LOAD_FILE2_PROTOCOL\n");
++
++  if (grub_initrd_load (&initrd_ctx, buffer))
++    status = GRUB_EFI_LOAD_ERROR;
++
++  grub_initrd_close (&initrd_ctx);
++  return status;
++}
++
+ static grub_err_t
+ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ 		 int argc, char *argv[])
+ {
+-  struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
+   int initrd_size, initrd_pages;
+   void *initrd_mem = NULL;
++  grub_efi_boot_services_t *b;
++  grub_efi_status_t status;
+ 
+   if (argc == 0)
+     {
+@@ -254,6 +351,24 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   if (grub_initrd_init (argc, argv, &initrd_ctx))
+     goto fail;
+ 
++  if (initrd_use_loadfile2 && !initrd_lf2_handle)
++    {
++      b = grub_efi_system_table->boot_services;
++      status = b->install_multiple_protocol_interfaces (&initrd_lf2_handle,
++							&load_file2_guid,
++							&initrd_lf2,
++							&device_path_guid,
++							&initrd_lf2_device_path,
++							NULL);
++      if (status == GRUB_EFI_OUT_OF_RESOURCES)
++        {
++	  grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++	  return grub_errno;
++	}
++      grub_dprintf ("linux", "LoadFile2 initrd loading protocol installed\n");
++      return GRUB_ERR_NONE;
++    }
++
+   initrd_size = grub_get_initrd_size (&initrd_ctx);
+   grub_dprintf ("linux", "Loading initrd\n");
+ 
diff -pruN 2.06-2/debian/patches/efi-implement-grub_efi_run_image.patch 2.06-2ubuntu16/debian/patches/efi-implement-grub_efi_run_image.patch
--- 2.06-2/debian/patches/efi-implement-grub_efi_run_image.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/efi-implement-grub_efi_run_image.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,900 @@
+From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+Date: Tue, 18 Jan 2022 11:55:56 +0100
+Subject: efi: implement grub_efi_run_image
+
+Provide function grub_efi_run_image() which consumes a PE-COFF image
+loaded into memory. The function
+
+* checks validity of header
+* copies the sections
+* relocates the code
+* invalidates the instruction cache
+* executes the image
+* returns to caller
+
+Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+---
+ grub-core/Makefile.core.def    |   4 +
+ grub-core/loader/efi/linux.c   |  24 +-
+ grub-core/loader/efi/peimage.c | 765 +++++++++++++++++++++++++++++++++++++++++
+ include/grub/efi/linux.h       |   3 +
+ include/grub/efi/peimage.h     |  28 ++
+ 5 files changed, 823 insertions(+), 1 deletion(-)
+ create mode 100644 grub-core/loader/efi/peimage.c
+ create mode 100644 include/grub/efi/peimage.h
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 3b06462..2cfea95 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -1822,13 +1822,17 @@ module = {
+   arm_coreboot = loader/arm/linux.c;
+   arm_efi = loader/efi/linux.c;
+   arm_efi = loader/efi/linux_sb.c;
++  arm_efi = loader/efi/peimage.c;
+   arm_uboot = loader/arm/linux.c;
+   arm64 = loader/efi/linux.c;
+   arm64 = loader/efi/linux_sb.c;
++  arm64 = loader/efi/peimage.c;
+   riscv32 = loader/efi/linux.c;
+   riscv32 = loader/efi/linux_sb.c;
++  riscv32 = loader/efi/peimage.c;
+   riscv64 = loader/efi/linux.c;
+   riscv64 = loader/efi/linux_sb.c;
++  riscv64 = loader/efi/peimage.c;
+   cflags = '-Wno-error=cast-align';
+   common = loader/linux.c;
+   common = lib/cmdline.c;
+diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
+index 56d6745..576d8cb 100644
+--- a/grub-core/loader/efi/linux.c
++++ b/grub-core/loader/efi/linux.c
+@@ -190,7 +190,29 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr __attribute__((unused)),
+ 
+   grub_dprintf ("linux", "linux command line: '%s'\n", args);
+ 
+-  retval = grub_efi_linux_boot (kernel_addr, handover_offset, kernel_addr);
++/*
++ * FIXME:
++ *
++ * We know that grub_efi_linux_boot() is broken:
++ *
++ * - The entry point address is not correctly determined.
++ * - Section addresses are ignored.
++ * - Sections having a raw size that is smaller than the virtual size are not
++ *   filled up with zeros.
++ * - Relocations are ignored.
++ * - Binaries calling Exit() quit GRUB.
++ *
++ * Thus we expect kernels to fail badly.
++ *
++ * Yet reviewers suggested to only change the code path for RISC-V until a
++ * security audit of the code in grub_efi_run_image() is completed.
++ */
++#ifndef __riscv
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++      retval = grub_efi_linux_boot (kernel_addr, handover_offset, kernel_addr);
++  else
++#endif
++  retval = grub_efi_run_image (kernel_addr, kernel_size, linux_args);
+ 
+   /* When successful, not reached */
+   free_params();
+diff --git a/grub-core/loader/efi/peimage.c b/grub-core/loader/efi/peimage.c
+new file mode 100644
+index 0000000..fffdf65
+--- /dev/null
++++ b/grub-core/loader/efi/peimage.c
+@@ -0,0 +1,765 @@
++// SPDX-License-Identifier: GPL-3.0+
++
++#include <grub/cache.h>
++#include <grub/cpu/efi/memory.h>
++#include <grub/efi/efi.h>
++#include <grub/efi/linux.h>
++#include <grub/efi/pe32.h>
++#include <grub/efi/peimage.h>
++#include <grub/env.h>
++#include <grub/misc.h>
++#include <grub/mm.h>
++#include <grub/setjmp.h>
++
++struct image_info {
++	void *data;
++	grub_efi_uint32_t data_size;
++	grub_efi_uint16_t machine;
++	grub_efi_uint16_t num_sections;
++	struct grub_pe32_section_table *section;
++	struct grub_pe32_data_directory *reloc;
++	grub_uint64_t image_base;
++	grub_uint32_t section_alignment;
++	grub_uint32_t image_size;
++	void *alloc_addr;
++	grub_uint32_t alloc_pages;
++	void *image_addr;
++	grub_efi_entry_point entry_point;
++};
++
++static struct {
++	grub_jmp_buf jmp;
++	grub_efi_handle_t image_handle;
++	grub_efi_status_t exit_status;
++	grub_efi_status_t EFIAPI (*exit)(grub_efi_handle_t image_handle,
++					 grub_efi_status_t exit_status,
++					 grub_efi_uintn_t exit_data_size,
++					 grub_efi_char16_t *exit_data);
++} started_image;
++
++static int
++debug_enabled(const char *condition)
++{
++	const char *debug;
++
++	debug = grub_env_get ("debug");
++	if (!debug || !grub_strword(debug, condition))
++		return 0;
++
++	return 1;
++}
++
++static void
++debug(const char *constraint)
++{
++	volatile grub_uint64_t x;
++
++	if (!debug_enabled(constraint))
++		return;
++
++	grub_printf("Attach debugger\n");
++	for (x = 1; x; ++x)
++		;
++}
++
++__attribute__((unused)) static void
++dump(const char *text, void *addr, unsigned int size)
++{
++	char *pos = addr;
++
++	grub_printf("%s @ 0x%lx\n", text, (unsigned long)addr);
++	for (unsigned int i = 0; i < size; i += 16)
++		grub_printf("%04x: %02x%02x %02x%02x %02x%02x %02x%02x "
++			    "%02x%02x %02x%02x %02x%02x %02x%02x\n", i,
++			    pos[i + 0], pos[i + 1], pos[i + 2], pos[i + 3],
++			    pos[i + 4], pos[i + 5], pos[i + 6], pos[i + 7],
++			    pos[i + 8], pos[i + 9], pos[i + 10], pos[i + 11],
++			    pos[i + 12], pos[i + 13], pos[i + 14], pos[i + 15]);
++}
++
++static grub_uint16_t machines[] = {
++#if defined(__x86_64__)
++	GRUB_PE32_MACHINE_AMD64,
++#elif defined(__i386__) || defined(__i486__) || defined(__i686__)
++	GRUB_PE32_MACHINE_AMD64,
++	GRUB_PE32_MACHINE_I386,
++#elif defined(__aarch64__)
++	GRUB_PE32_MACHINE_ARM64,
++#elif defined(__arm__)
++	GRUB_PE32_MACHINE_ARMTHUMB_MIXED,
++#elif defined(__riscv) && __riscv_xlen == 32
++	GRUB_PE32_MACHINE_RISCV32,
++#elif defined(__riscv) && __riscv_xlen == 64
++	GRUB_PE32_MACHINE_RISCV64,
++#endif
++};
++
++/**
++ * check_machine_type() - check if the machine type matches the architecture
++ *
++ * @machine:	the value of the Machine field of the COFF file header.
++ * Return:	status code
++ */
++static grub_efi_status_t check_machine_type(grub_uint16_t machine)
++{
++	for (grub_size_t i = 0; i < sizeof(machines) / sizeof(*machines); ++i) {
++		if (machine == machines[i])
++			return GRUB_EFI_SUCCESS;
++	}
++
++	return GRUB_EFI_LOAD_ERROR;
++}
++
++/**
++ * check_pe_header() - check the headers of a PE-COFF image
++ *
++ * @info:	information about the image
++ */
++static grub_efi_status_t check_pe_header(struct image_info *info)
++{
++	struct grub_dos_stub *dos_stub = info->data;
++	void *pe_magic;
++	struct grub_pe32_coff_header *coff_header;
++	struct grub_pe32_optional_header *pe32_header;
++	struct grub_pe64_optional_header *pe64_header;
++	grub_uint32_t header_size;
++
++	if (info->data_size < sizeof(struct grub_dos_stub)) {
++		grub_error(GRUB_ERR_BAD_OS, "truncated image");
++		return GRUB_EFI_LOAD_ERROR;
++	}
++	if (dos_stub->magic != GRUB_PE32_MAGIC) {
++		grub_error(GRUB_ERR_BAD_OS, "not a PE-COFF file");
++		return GRUB_EFI_UNSUPPORTED;
++	}
++	if (info->data_size < dos_stub->pe_addr + sizeof(GRUB_PE_MAGIC) +
++			      sizeof(struct grub_pe32_coff_header) +
++			      sizeof(struct grub_pe64_optional_header)) {
++		grub_error(GRUB_ERR_BAD_OS, "truncated image");
++		return GRUB_EFI_LOAD_ERROR;
++	}
++	pe_magic = (void *)((unsigned long)info->data + dos_stub->pe_addr);
++	if (grub_memcmp(pe_magic, GRUB_PE_MAGIC, sizeof(GRUB_PE_MAGIC))) {
++		grub_error(GRUB_ERR_BAD_OS, "not a PE-COFF file");
++		return GRUB_EFI_LOAD_ERROR;
++	}
++
++	coff_header = (void *)((unsigned long)pe_magic + sizeof(GRUB_PE_MAGIC));
++	info->machine = coff_header->machine;
++	info->num_sections = coff_header->num_sections;
++
++	if (check_machine_type(info->machine) != GRUB_EFI_SUCCESS) {
++		grub_error(GRUB_ERR_BAD_OS, "wrong machine type %u",
++			   coff_header->machine);
++		return GRUB_EFI_LOAD_ERROR;
++	}
++
++	pe32_header = (void *)((unsigned long)coff_header +
++			       sizeof(*coff_header));
++	pe64_header = (void *)((unsigned long)coff_header +
++			       sizeof(*coff_header));
++
++	switch (pe32_header->magic) {
++	case GRUB_PE32_PE32_MAGIC:
++		info->section_alignment = pe32_header->section_alignment;
++		info->image_base = pe32_header->image_base;
++		info->image_size = pe32_header->image_size;
++		info->entry_point =
++			(void *)(unsigned long)pe32_header->entry_addr;
++		header_size = pe32_header->header_size;
++		if (info->data_size < header_size) {
++			grub_error(GRUB_ERR_BAD_OS, "truncated image");
++			return GRUB_EFI_LOAD_ERROR;
++		}
++
++		if (pe32_header->num_data_directories >= 6 &&
++		    pe32_header->base_relocation_table.size)
++			info->reloc = &pe32_header->base_relocation_table;
++
++		info->section = (void *)((unsigned long)&pe32_header->export_table +
++					 pe32_header->num_data_directories *
++					 sizeof(struct grub_pe32_data_directory));
++		break;
++	case GRUB_PE32_PE64_MAGIC:
++		info->section_alignment = pe64_header->section_alignment;
++		info->image_base = pe64_header->image_base;
++		info->image_size = pe64_header->image_size;
++		info->entry_point =
++			(void *)(unsigned long)pe64_header->entry_addr;
++		header_size = pe64_header->header_size;
++		if (info->data_size < header_size) {
++			grub_error(GRUB_ERR_BAD_OS, "truncated image");
++			return GRUB_EFI_LOAD_ERROR;
++		}
++
++		if (pe64_header->num_data_directories >= 6 &&
++		    pe64_header->base_relocation_table.size)
++			info->reloc = &pe64_header->base_relocation_table;
++
++		info->section = (void *)((unsigned long)&pe64_header->export_table +
++					 pe64_header->num_data_directories *
++					 sizeof(struct grub_pe32_data_directory));
++		break;
++	default:
++		grub_error(GRUB_ERR_BAD_OS, "not a PE-COFF file");
++		return GRUB_EFI_LOAD_ERROR;
++	}
++
++	if ((unsigned long)info->section +
++	    info->num_sections * sizeof(*info->section) >
++	    (unsigned long)info->data + info->data_size) {
++		grub_error(GRUB_ERR_BAD_OS, "truncated image");
++		return GRUB_EFI_LOAD_ERROR;
++	}
++
++	grub_dprintf("linux", "PE-COFF header checked\n");
++
++	return GRUB_EFI_SUCCESS;
++}
++
++/**
++ * load_sections() - load image sections into memory
++ *
++ * Allocate fresh memory and copy the image sections there.
++ *
++ * @info:	image information
++ */
++static grub_efi_status_t load_sections(struct image_info *info)
++{
++	struct grub_pe32_section_table *section;
++	unsigned long align_mask = 0xfff;
++
++	/* Section alignment must be a power of two */
++	if (info->section_alignment & (info->section_alignment - 1)) {
++		grub_error(GRUB_ERR_BAD_OS, "invalid section alignment");
++		return GRUB_EFI_LOAD_ERROR;
++	}
++
++	if (info->section_alignment > align_mask)
++		align_mask = info->section_alignment - 1;
++
++	info->alloc_pages = GRUB_EFI_BYTES_TO_PAGES(info->image_size +
++						    (align_mask & ~0xfffUL));
++
++	info->alloc_addr = grub_efi_allocate_pages_real(
++			GRUB_EFI_MAX_USABLE_ADDRESS, info->alloc_pages,
++			GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA);
++	if (!info->alloc_addr)
++		return GRUB_EFI_OUT_OF_RESOURCES;
++
++	info->image_addr =
++		(void *)(((unsigned long)info->alloc_addr + align_mask) &
++			 ~align_mask);
++
++	for (section = &info->section[0];
++	     section < &info->section[info->num_sections]; ++section) {
++		if (section->raw_data_offset + section->raw_data_size >
++		    info->data_size) {
++			grub_error(GRUB_ERR_BAD_OS, "truncated image");
++			return GRUB_EFI_LOAD_ERROR;
++		}
++		if (section->virtual_address + section->virtual_size >
++		    info->image_size) {
++			grub_error(GRUB_ERR_BAD_OS, "section outside image");
++			return GRUB_EFI_LOAD_ERROR;
++		}
++
++		grub_memset(
++			(void *)((unsigned long)info->image_addr +
++				 section->virtual_address), 0,
++			section->virtual_size);
++		grub_memcpy(
++			(void *)((unsigned long)info->image_addr +
++				 section->virtual_address),
++			(void *)((unsigned long)info->data +
++				 section->raw_data_offset),
++			section->raw_data_size);
++	}
++
++	info->entry_point = (void *)((unsigned long)info->entry_point +
++				     (unsigned long)info->image_addr);
++
++	grub_dprintf("linux", "sections loaded\n");
++
++	return GRUB_EFI_SUCCESS;
++}
++
++/**
++ * lo12i_get() - get the immediate value of a format I instruction
++ *
++ * Instruction format I::
++ *
++ *     +---------------------------------------------------------------+
++ *     |f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0|
++ *     +-----------------------+---------+-----+---------+-------------+
++ *     |       imm[11:0]       |   rs1   |fun3 |   rd    |   opcode    |
++ *     +-----------------------+---------+-----+---------+-------------+
++ *
++ * @instr:	pointer to instruction
++ * Return:	immediate value
++ */
++static grub_uint16_t
++lo12i_get(grub_uint32_t *instr)
++{
++	return ((*instr & 0xfff00000) >> 20);
++}
++
++/**
++ * lo12i_set() - set the immediate value of a format I instruction
++ *
++ * Instruction format I::
++ *
++ *     +---------------------------------------------------------------+
++ *     |f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0|
++ *     +-----------------------+---------+-----+---------+-------------+
++ *     |       imm[11:0]       |   rs1   |fun3 |   rd    |   opcode    |
++ *     +-----------------------+---------+-----+---------+-------------+
++ *
++ * @instr:	pointer to instruction
++ * @imm:	immediate value
++ */
++static void
++lo12i_set(grub_uint32_t *instr, grub_uint32_t imm)
++{
++	*instr = (*instr & 0x000fffff) |
++		 (imm & 0x00000fff << 20);
++}
++
++/**
++ * hi20_get() - get the immediate value of a format I instruction
++ *
++ * Instruction format U::
++ *
++ *     +---------------------------------------------------------------+
++ *     |f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0|
++ *     +---------------------------------------+---------+-------------+
++ *     |                imm[31:12]             |   rd    |   opcode    |
++ *     +---------------------------------------+---------+-------------+
++ *
++ * @instr:	pointer to instruction
++ * Return:	immediate value
++ */
++static grub_uint16_t
++hi20_get(grub_uint32_t *instr)
++{
++	return *instr & 0xfffff000;
++}
++
++/**
++ * hi20_set() - set the immediate value of a format I instruction
++ *
++ * Instruction format U::
++ *
++ *     +---------------------------------------------------------------+
++ *     |f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0|
++ *     +---------------------------------------+---------+-------------+
++ *     |                imm[31:12]             |   rd    |   opcode    |
++ *     +---------------------------------------+---------+-------------+
++ *
++ * @instr:	pointer to instruction
++ * @imm:	immediate value
++ */
++static void
++hi20_set(grub_uint32_t *instr, grub_uint32_t imm)
++{
++	*instr = (*instr & 0x00000fff) |
++		 (imm & 0xfffff000);
++}
++
++/**
++ * lo12s_get() - get the immediate value of a format I instruction
++ *
++ * Instruction format S::
++ *
++ *     +---------------------------------------------------------------+
++ *     |f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0|
++ *     +-------------+---------+---------+-----+----+----+-------------+
++ *     |  imm[11:5]  |   rs2   |   rs1   |fun3 |imm[4:0] |   opcode    |
++ *     +-------------+---------+---------+-----+----+----+-------------+
++ *
++ * @instr:	pointer to instruction
++ * Return:	immediate value
++ */
++static grub_uint16_t
++lo12s_get(grub_uint32_t *instr)
++{
++	return ((*instr & 0x00000f80) >> 7) |
++	       ((*instr & 0xfe000000) >> 20);
++}
++
++/**
++ * lo12s_set() - set the immediate value of a format I instruction
++ *
++ * Instruction format S::
++ *
++ *     +---------------------------------------------------------------+
++ *     |f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0|
++ *     +-------------+---------+---------+-----+----+----+-------------+
++ *     |  imm[11:5]  |   rs2   |   rs1   |fun3 |imm[4:0] |   opcode    |
++ *     +-------------+---------+---------+-----+----+----+-------------+
++ *
++ * @instr:	pointer to instruction
++ * @imm:	immediate value
++ */
++static void
++lo12s_set(grub_uint32_t *instr, grub_uint32_t imm)
++{
++	*instr = (*instr & 0x01fff07f) |
++		 (imm & 0x00000fe0 << 20) |
++		 (imm & 0x0000001f << 7);
++}
++
++/**
++ * movw_get_imm() - get the immediate value of MOVT and MOVW instructions
++ *
++ * MOVT::
++ *
++ *     +-------------------------------+-------------------------------+
++ *     |f e d c b a 9 8 7 6 5 4 3 2 1 0|f e d c b a 9 8 7 6 5 4 3 2 1 0|
++ *     +---------+-+-----------+-------+-+-----+-------+---------------+
++ *     |1 1 1 1 0|i|1 0 1 1 0 0| imm4  |0| imm3|   Rd  |     imm8      |
++ *     +---------+-+-----------+-------+-+-----+-------+---------------+
++ *
++ * MOVW::
++ *
++ *     +-------------------------------+-------------------------------+
++ *     |f e d c b a 9 8 7 6 5 4 3 2 1 0|f e d c b a 9 8 7 6 5 4 3 2 1 0|
++ *     +---------+-+-----------+-------+-+-----+-------+---------------+
++ *     |1 1 1 1 0|i|1 0 0 1 0 0| imm4  |0| imm3|   Rd  |     imm8      |
++ *     +---------+-+-----------+-------+-+-----+-------+---------------+
++ *
++ * @instr:	pointer to instruction
++ * Return:	immediate value
++ */
++static grub_uint16_t
++movw_get_imm(grub_uint16_t *instr)
++{
++	/* imm16 = imm4:i:imm3:imm8; */
++	return (instr[1] & 0x00ff) |
++	       ((instr[1] & 0x7000) >> 3) |
++	       ((instr[0] & 0x0400) >> 8) |
++	       ((instr[0] & 0x000f) << 12);
++}
++
++/**
++ * movw_set_imm() - set the immediate value of MOVT and MOVW instructions
++ *
++ * MOVT::
++ *
++ *     +-------------------------------+-------------------------------+
++ *     |f e d c b a 9 8 7 6 5 4 3 2 1 0|f e d c b a 9 8 7 6 5 4 3 2 1 0|
++ *     +---------+-+-----------+-------+-+-----+-------+---------------+
++ *     |1 1 1 1 0|i|1 0 1 1 0 0| imm4  |0| imm3|   Rd  |     imm8      |
++ *     +---------+-+-----------+-------+-+-----+-------+---------------+
++ *
++ * MOVW::
++ *
++ *     +-------------------------------+-------------------------------+
++ *     |f e d c b a 9 8 7 6 5 4 3 2 1 0|f e d c b a 9 8 7 6 5 4 3 2 1 0|
++ *     +---------+-+-----------+-------+-+-----+-------+---------------+
++ *     |1 1 1 1 0|i|1 0 0 1 0 0| imm4  |0| imm3|   Rd  |     imm8      |
++ *     +---------+-+-----------+-------+-+-----+-------+---------------+
++ *
++ * @instr:	pointer to instruction
++ * @imm		immediate value
++ */
++static void
++movw_set_imm(grub_uint16_t *instr, grub_uint16_t imm)
++{
++	/* imm16 = imm4:i:imm3:imm8; */
++	instr[0] = (instr[0] & 0xfbf0) |
++		   (imm & 0xf000) >> 12 |
++		   (imm & 0x0800) << 3;
++	instr[1] = (instr[0] & 0x8f00) |
++		   (imm & 0xff) |
++		   (imm & 0x0700) >> 4;
++}
++
++/**
++ * relocate() - apply relocations to the image
++ *
++ * @info:	information about the loaded image
++ */
++static grub_efi_status_t
++relocate(struct image_info *info)
++{
++	struct grub_pe32_fixup_block *block, *reloc_end;
++	unsigned long offset;
++	grub_uint16_t reloc_type;
++	grub_uint16_t *reloc_entry;
++	grub_uint32_t *rvhi20_addr = NULL;
++
++	if (!info->reloc || !(info->reloc->size)) {
++		grub_dprintf("linux", "no relocations\n");
++		return GRUB_EFI_SUCCESS;
++	}
++
++	if (info->reloc->rva + info->reloc->size > info->image_size) {
++		grub_error(GRUB_ERR_BAD_OS, "relocation block outside image");
++		return GRUB_EFI_LOAD_ERROR;
++	}
++
++	/*
++	 * The relocations are based on the difference between
++	 * actual load address and the preferred base address.
++	 */
++	offset = (unsigned long)info->image_addr - info->image_base;
++
++	block = (void *)((unsigned long)info->image_addr + info->reloc->rva);
++	reloc_end = (void *)((unsigned long)block + info->reloc->size);
++
++	for (; block < reloc_end;
++	     block = (void *)((unsigned long)block + block->block_size)) {
++		reloc_entry = block->entries;
++		grub_uint16_t *block_end =
++			(void *)((unsigned long)block + block->block_size);
++
++		for (; reloc_entry < block_end; ++reloc_entry) {
++			void *addr = (void *)((unsigned long)info->image_addr +
++					      block->page_rva +
++					      (*reloc_entry & 0xfff));
++
++			reloc_type = *reloc_entry >> 12;
++
++			switch (reloc_type) {
++			case GRUB_PE32_REL_BASED_ABSOLUTE:
++				/* skip */
++				break;
++			case GRUB_PE32_REL_BASED_HIGH:
++				*(grub_uint16_t *)addr += offset >> 16;
++				break;
++			case GRUB_PE32_REL_BASED_LOW:
++				*(grub_uint16_t *)addr += offset;
++				break;
++			case GRUB_PE32_REL_BASED_HIGHLOW:
++				*(grub_uint32_t *)addr += offset;
++				break;
++			case GRUB_PE32_REL_BASED_RISCV_HI20:
++				switch (info->machine) {
++				case GRUB_PE32_MACHINE_RISCV32:
++				case GRUB_PE32_MACHINE_RISCV64:
++					rvhi20_addr = addr;
++					break;
++				default:
++					goto bad_reloc;
++				}
++				break;
++			case GRUB_PE32_REL_BASED_ARM_MOV32T:
++			/* = GRUB_PE32_REL_BASED_RISCV_LOW12I */
++				switch (info->machine) {
++				case GRUB_PE32_MACHINE_ARMTHUMB_MIXED: {
++					grub_uint16_t *instr = addr;
++					grub_uint32_t val;
++
++					val = movw_get_imm(&instr[0]) +
++					      (movw_get_imm(&instr[2]) << 16) +
++					      offset;
++					movw_set_imm(&instr[0], val);
++					movw_set_imm(&instr[2], val >> 16);
++					break;
++				}
++				case GRUB_PE32_MACHINE_RISCV32:
++				case GRUB_PE32_MACHINE_RISCV64:
++					if (rvhi20_addr) {
++						grub_uint32_t val =
++							hi20_get(rvhi20_addr) +
++							lo12i_get(addr) +
++							offset;
++						hi20_set(rvhi20_addr, val);
++						lo12i_set(addr, val);
++						rvhi20_addr = NULL;
++					} else {
++						goto bad_reloc;
++					}
++					break;
++				default:
++					goto bad_reloc;
++				}
++				break;
++			case GRUB_PE32_REL_BASED_RISCV_LOW12S:
++				switch (info->machine) {
++				case GRUB_PE32_MACHINE_RISCV32:
++				case GRUB_PE32_MACHINE_RISCV64:
++					if (rvhi20_addr) {
++						grub_uint32_t val =
++							hi20_get(rvhi20_addr) +
++							lo12s_get(addr) +
++							offset;
++						hi20_set(rvhi20_addr, val);
++						lo12s_set(addr, val);
++						rvhi20_addr = NULL;
++					} else {
++						goto bad_reloc;
++					}
++					break;
++				default:
++					goto bad_reloc;
++				}
++				break;
++			case GRUB_PE32_REL_BASED_DIR64:
++				*(grub_uint64_t *)addr += offset;
++				break;
++			default:
++				goto bad_reloc;
++			}
++		}
++	}
++
++	grub_dprintf("linux", "image relocated\n");
++
++	return GRUB_EFI_SUCCESS;
++
++bad_reloc:
++	grub_error(GRUB_ERR_BAD_OS,
++		   "unsupported relocation type %d, rva 0x%08lx\n",
++		   *reloc_entry >> 12,
++		   (unsigned long)reloc_entry -
++		   (unsigned long)info->image_addr);
++	return GRUB_EFI_LOAD_ERROR;
++}
++
++/**
++ * efi_exit() - replacement for EFI_BOOT_SERVICES.Exit()
++ *
++ * This function is inserted into system table to trap invocations of
++ * EFI_BOOT_SERVICES.Exit(). If Exit() is called with our handle
++ * return to our start routine using a long jump.
++ *
++ * @image_handle:	handle of the application as passed on entry
++ * @exit_status:	the images exit code
++ * @exit_data_size:	size of @exit_data
++ * @exit_data:		null terminated string followed by optional data
++ */
++static grub_efi_status_t EFIAPI
++efi_exit(grub_efi_handle_t image_handle,
++	 grub_efi_status_t exit_status,
++	 grub_efi_uintn_t exit_data_size,
++	 grub_efi_char16_t *exit_data)
++{
++	grub_efi_system_table->boot_services->exit = started_image.exit;
++
++	if (!image_handle)
++		return GRUB_EFI_INVALID_PARAMETER;
++
++	if (image_handle != started_image.image_handle) {
++		grub_dprintf("linux", "delegating Exit()\n");
++		return efi_call_4(started_image.exit, image_handle,
++				  exit_status, exit_data_size,
++				  (grub_efi_char16_t *)exit_data);
++	}
++
++	started_image.exit_status = exit_status;
++
++	if (exit_status != GRUB_EFI_SUCCESS) {
++		grub_printf("Application failed, r = %d\n",
++			    (int)exit_status & 0x7fffffff);
++		if (exit_data_size && exit_data) {
++			grub_printf("exit message: ");
++			for (grub_efi_uintn_t pos = 0;
++			     exit_data[pos] && pos < exit_data_size / 2; ++pos)
++				grub_printf("%C", exit_data[pos]);
++			grub_printf("\n");
++		}
++	}
++	if (exit_data_size && exit_data) {
++		/* exit data must be freed by the caller */
++		efi_call_1(grub_efi_system_table->boot_services->free_pool,
++			   exit_data);
++	}
++	grub_longjmp(started_image.jmp, 1);
++}
++
++/**
++ * start_image() - our implementation of StartImage()
++ *
++ * As we do not load the image via LoadImage() we need our own implementation
++ * of StartImage() to launch the PE-COFF image.
++ */
++static grub_efi_status_t
++start_image(struct image_info *info)
++{
++	int ret;
++	grub_efi_status_t status;
++	grub_efi_loaded_image_t *loaded_image;
++
++	/*
++	 * TODO: It would better comply to the UEFI specification to
++	 *	 use a separate handle for the image we are running.
++	 */
++	started_image.image_handle = grub_efi_image_handle;
++
++	loaded_image = grub_efi_get_loaded_image(grub_efi_image_handle);
++	if (loaded_image) {
++		loaded_image->image_base = info->image_addr;
++		loaded_image->image_size = info->image_size;
++	} else {
++		grub_dprintf ("linux", "Loaded image protocol missing\n");
++	}
++
++	ret = grub_setjmp(started_image.jmp);
++	if (ret) {
++		started_image.image_handle = NULL;
++
++		return started_image.exit_status;
++	}
++
++	started_image.exit = grub_efi_system_table->boot_services->exit;
++	grub_efi_system_table->boot_services->exit = efi_exit;
++
++	grub_dprintf("linux",
++		     "Executing image loaded at 0x%lx\nEntry point 0x%lx\nSize 0x%08x\n",
++		     (unsigned long)info->image_addr,
++		     (unsigned long)info->entry_point,
++		     info->image_size);
++
++	/* Invalidate the instruction cache */
++	grub_arch_sync_caches(info->image_addr, info->image_size);
++
++	debug("pestart");
++	status = efi_call_2(info->entry_point, started_image.image_handle,
++			    grub_efi_system_table);
++
++	grub_dprintf("linux", "Application returned\n");
++
++	return efi_exit(started_image.image_handle, status, 0, NULL);
++}
++
++/**
++ * grub_efi_run_image() - run a PE-COFF image from memory
++ *
++ * TODO: move the creation of the load options here
++ *
++ * @data:	buffer with PE-COFF image
++ * @data_size:	size of the buffer
++ * @args:	command line to be passed as load options
++ */
++grub_efi_boolean_t
++grub_efi_run_image(void *data, grub_efi_uint32_t data_size,
++		   const char *args __attribute__((unused)))
++{
++	struct image_info info = {
++		.data = data,
++		.data_size = data_size,
++	};
++
++	/* read and check header */
++	if (check_pe_header(&info) != GRUB_EFI_SUCCESS)
++		goto err;
++	/* load sections */
++	if (load_sections(&info) != GRUB_EFI_SUCCESS)
++		goto err;
++
++	if (relocate(&info) != GRUB_EFI_SUCCESS)
++		goto err;
++
++	if (start_image(&info) != GRUB_EFI_SUCCESS)
++		goto err;
++
++err:
++	/* free allocated memory */
++	if (info.alloc_addr)
++		grub_efi_free_pages((unsigned long)info.alloc_addr,
++				    info.alloc_pages);
++
++	return 0;
++}
+diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h
+index 0033d93..39f5a9a 100644
+--- a/include/grub/efi/linux.h
++++ b/include/grub/efi/linux.h
+@@ -27,5 +27,8 @@ EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size);
+ grub_err_t
+ EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
+ 				  void *kernel_param);
++grub_efi_boolean_t
++EXPORT_FUNC(grub_efi_run_image) (void *data, grub_efi_uint32_t data_size,
++				 const char *args);
+ 
+ #endif /* ! GRUB_EFI_LINUX_HEADER */
+diff --git a/include/grub/efi/peimage.h b/include/grub/efi/peimage.h
+new file mode 100644
+index 0000000..70bfdc7
+--- /dev/null
++++ b/include/grub/efi/peimage.h
+@@ -0,0 +1,28 @@
++/* SPDX-License-Identifier: GPL-3.0+ */
++
++#define GRUB_PE_MAGIC "PE\0"
++
++#ifdef __x86_64__
++#define EFIAPI __attribute__((ms_abi))
++#else
++#define EFIAPI
++#endif
++
++#define EFI_LOADED_IMAGE_PROTOCOL_REVISION (0x1000)
++
++typedef grub_efi_status_t (*grub_efi_entry_point)
++	(grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table);
++
++struct grub_dos_stub {
++	grub_uint16_t magic;		/* MZ magic */
++	grub_uint16_t lbsize;		/* size of last block */
++	grub_uint32_t res0;		/* reserved */
++	grub_uint64_t res1;		/* reserved */
++	grub_uint64_t res2;		/* reserved */
++	grub_uint64_t res3;		/* reserved */
++	grub_uint64_t res4;		/* reserved */
++	grub_uint64_t res5;		/* reserved */
++	grub_uint64_t res6;		/* reserved */
++	grub_uint32_t linux_arch;	/* linux architecture */
++	grub_uint32_t pe_addr;		/* offset of PE/COFF header */
++};
diff -pruN 2.06-2/debian/patches/efinet-set-dns-from-uefi-proto.patch 2.06-2ubuntu16/debian/patches/efinet-set-dns-from-uefi-proto.patch
--- 2.06-2/debian/patches/efinet-set-dns-from-uefi-proto.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/efinet-set-dns-from-uefi-proto.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 5a2c53dd059351cf385575fa99d5763bc07e0de2 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
@@ -32,12 +31,12 @@ Last-Update: 2021-09-24
 
 Patch-Name: efinet-set-dns-from-uefi-proto.patch
 ---
- grub-core/net/drivers/efi/efinet.c | 163 +++++++++++++++++++++++++++++
- include/grub/efi/api.h             |  76 ++++++++++++++
+ grub-core/net/drivers/efi/efinet.c | 163 +++++++++++++++++++++++++++++++++++++
+ include/grub/efi/api.h             |  76 +++++++++++++++++
  2 files changed, 239 insertions(+)
 
 diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
-index 2d3b00f0e..82a28fb6e 100644
+index 2d3b00f..82a28fb 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+");
@@ -246,10 +245,10 @@ index 2d3b00f0e..82a28fb6e 100644
      }
  
 diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
-index 4b4652ca5..9cab1a51d 100644
+index d67c3f1..479c2a8 100644
 --- a/include/grub/efi/api.h
 +++ b/include/grub/efi/api.h
-@@ -354,6 +354,16 @@
+@@ -359,6 +359,16 @@
      { 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44 } \
    }
  
@@ -266,9 +265,9 @@ index 4b4652ca5..9cab1a51d 100644
  struct grub_efi_sal_system_table
  {
    grub_uint32_t signature;
-@@ -1793,6 +1803,72 @@ struct grub_efi_rng_protocol
+@@ -1808,6 +1818,72 @@ struct grub_efi_load_file2
  };
- typedef struct grub_efi_rng_protocol grub_efi_rng_protocol_t;
+ typedef struct grub_efi_load_file2 grub_efi_load_file2_t;
  
 +enum grub_efi_ip4_config2_data_type {
 +  GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO,
diff -pruN 2.06-2/debian/patches/efinet-set-network-from-uefi-devpath.patch 2.06-2ubuntu16/debian/patches/efinet-set-network-from-uefi-devpath.patch
--- 2.06-2/debian/patches/efinet-set-network-from-uefi-devpath.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/efinet-set-network-from-uefi-devpath.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 3f85b646c8f6188f6e2122fc90351fb900e1b337 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
@@ -29,12 +28,12 @@ Signed-off-by: Ken Lin <ken.lin@hpe.com>
 
 Patch-Name: efinet-set-network-from-uefi-devpath.patch
 ---
- grub-core/net/drivers/efi/efinet.c | 268 ++++++++++++++++++++++++++++-
+ grub-core/net/drivers/efi/efinet.c | 268 +++++++++++++++++++++++++++++++++++--
  include/grub/efi/api.h             |  11 ++
  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 fc90415..2d3b00f 100644
 --- a/grub-core/net/drivers/efi/efinet.c
 +++ b/grub-core/net/drivers/efi/efinet.c
 @@ -23,6 +23,7 @@
@@ -358,10 +357,10 @@ index fc90415f2..2d3b00f0e 100644
    }
  }
 diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
-index 50ab8e844..4b4652ca5 100644
+index 2c649cf..d67c3f1 100644
 --- a/include/grub/efi/api.h
 +++ b/include/grub/efi/api.h
-@@ -849,6 +849,8 @@ struct grub_efi_ipv4_device_path
+@@ -854,6 +854,8 @@ struct grub_efi_ipv4_device_path
    grub_efi_uint16_t remote_port;
    grub_efi_uint16_t protocol;
    grub_efi_uint8_t static_ip_address;
@@ -370,7 +369,7 @@ index 50ab8e844..4b4652ca5 100644
  } GRUB_PACKED;
  typedef struct grub_efi_ipv4_device_path grub_efi_ipv4_device_path_t;
  
-@@ -903,6 +905,15 @@ struct grub_efi_sata_device_path
+@@ -908,6 +910,15 @@ struct grub_efi_sata_device_path
  } GRUB_PACKED;
  typedef struct grub_efi_sata_device_path grub_efi_sata_device_path_t;
  
diff -pruN 2.06-2/debian/patches/efinet-uefi-ipv6-pxe-support.patch 2.06-2ubuntu16/debian/patches/efinet-uefi-ipv6-pxe-support.patch
--- 2.06-2/debian/patches/efinet-uefi-ipv6-pxe-support.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/efinet-uefi-ipv6-pxe-support.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From a124f295433d6d3f371730b93d6468e6d5ad58e1 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
@@ -12,12 +11,12 @@ Signed-off-by: Ken Lin <ken.lin@hpe.com>
 
 Patch-Name: efinet-uefi-ipv6-pxe-support.patch
 ---
- grub-core/net/drivers/efi/efinet.c | 24 ++++++++++---
- include/grub/efi/api.h             | 55 +++++++++++++++++++++++++++++-
+ grub-core/net/drivers/efi/efinet.c | 24 +++++++++++++----
+ include/grub/efi/api.h             | 55 +++++++++++++++++++++++++++++++++++++-
  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 5388f95..fc90415 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,10 +51,10 @@ index 5388f952b..fc90415f2 100644
    }
  }
 diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
-index f1a52210c..50ab8e844 100644
+index 3de0a7d..2c649cf 100644
 --- a/include/grub/efi/api.h
 +++ b/include/grub/efi/api.h
-@@ -1476,14 +1476,67 @@ typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output
+@@ -1481,14 +1481,67 @@ typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output
  
  typedef grub_uint8_t grub_efi_pxe_packet_t[1472];
  
diff -pruN 2.06-2/debian/patches/efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch 2.06-2ubuntu16/debian/patches/efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch
--- 2.06-2/debian/patches/efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,256 @@
+From: Lu Ken <ken.lu@intel.com>
+Date: Wed, 13 Jul 2022 10:06:12 +0800
+Subject: efi/tpm: Add EFI_CC_MEASUREMENT_PROTOCOL support
+
+The EFI_CC_MEASUREMENT_PROTOCOL abstracts the measurement for virtual firmware
+in confidential computing environment. It is similar to the EFI_TCG2_PROTOCOL.
+It was proposed by Intel and ARM and approved by UEFI organization.
+
+It is defined in Intel GHCI specification: https://cdrdv2.intel.com/v1/dl/getContent/726790 .
+The EDKII header file is available at https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/CcMeasurement.h .
+
+Signed-off-by: Lu Ken <ken.lu@intel.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/commands/efi/tpm.c |  48 ++++++++++++++
+ include/grub/efi/cc.h        | 151 +++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 199 insertions(+)
+ create mode 100644 include/grub/efi/cc.h
+
+diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c
+index 2286368..11cda48 100644
+--- a/grub-core/commands/efi/tpm.c
++++ b/grub-core/commands/efi/tpm.c
+@@ -22,6 +22,7 @@
+ #include <grub/i18n.h>
+ #include <grub/efi/api.h>
+ #include <grub/efi/efi.h>
++#include <grub/efi/cc.h>
+ #include <grub/efi/tpm.h>
+ #include <grub/mm.h>
+ #include <grub/tpm.h>
+@@ -31,6 +32,7 @@ typedef TCG_PCR_EVENT grub_tpm_event_t;
+ 
+ static grub_efi_guid_t tpm_guid = EFI_TPM_GUID;
+ static grub_efi_guid_t tpm2_guid = EFI_TPM2_GUID;
++static grub_efi_guid_t cc_measurement_guid = GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID;
+ 
+ static grub_efi_handle_t *grub_tpm_handle;
+ static grub_uint8_t grub_tpm_version;
+@@ -222,6 +224,50 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf,
+   return grub_efi_log_event_status (status);
+ }
+ 
++static void
++grub_cc_log_event (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
++		   const char *description)
++{
++  grub_efi_cc_event_t *event;
++  grub_efi_status_t status;
++  grub_efi_cc_protocol_t *cc;
++  grub_efi_cc_mr_index_t mr;
++
++  cc = grub_efi_locate_protocol (&cc_measurement_guid, NULL);
++  if (cc == NULL)
++    return;
++
++  status = efi_call_3 (cc->map_pcr_to_mr_index, cc, pcr, &mr);
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_efi_log_event_status (status);
++      return;
++    }
++
++  event = grub_zalloc (sizeof (grub_efi_cc_event_t) +
++		       grub_strlen (description) + 1);
++  if (event == NULL)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate CC event buffer"));
++      return;
++    }
++
++  event->Header.HeaderSize = sizeof (grub_efi_cc_event_header_t);
++  event->Header.HeaderVersion = GRUB_EFI_CC_EVENT_HEADER_VERSION;
++  event->Header.MrIndex = mr;
++  event->Header.EventType = EV_IPL;
++  event->Size = sizeof (*event) + grub_strlen (description) + 1;
++  grub_strcpy ((char *) event->Event, description);
++
++  status = efi_call_5 (cc->hash_log_extend_event, cc, 0,
++		       (grub_efi_physical_address_t)(grub_addr_t) buf,
++		       (grub_efi_uint64_t) size, event);
++  grub_free (event);
++
++  if (status != GRUB_EFI_SUCCESS)
++    grub_efi_log_event_status (status);
++}
++
+ grub_err_t
+ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
+ 		    const char *description)
+@@ -229,6 +275,8 @@ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
+   grub_efi_handle_t tpm_handle;
+   grub_efi_uint8_t protocol_version;
+ 
++  grub_cc_log_event(buf, size, pcr, description);
++
+   if (!grub_tpm_handle_find (&tpm_handle, &protocol_version))
+     return 0;
+ 
+diff --git a/include/grub/efi/cc.h b/include/grub/efi/cc.h
+new file mode 100644
+index 0000000..8960306
+--- /dev/null
++++ b/include/grub/efi/cc.h
+@@ -0,0 +1,151 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2022  Free Software Foundation, Inc.
++ *
++ *  GRUB is free software: you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation, either version 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef GRUB_EFI_CC_H
++#define GRUB_EFI_CC_H 1
++
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/err.h>
++
++#define GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID \
++  { 0x96751a3d, 0x72f4, 0x41a6, \
++    { 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b } \
++  };
++
++struct grub_efi_cc_version
++{
++  grub_efi_uint8_t Major;
++  grub_efi_uint8_t Minor;
++};
++typedef struct grub_efi_cc_version grub_efi_cc_version_t;
++
++/* EFI_CC Type/SubType definition. */
++#define GRUB_EFI_CC_TYPE_NONE	0
++#define GRUB_EFI_CC_TYPE_SEV	1
++#define GRUB_EFI_CC_TYPE_TDX	2
++
++struct grub_efi_cc_type
++{
++  grub_efi_uint8_t Type;
++  grub_efi_uint8_t SubType;
++};
++typedef struct grub_efi_cc_type grub_efi_cc_type_t;
++
++typedef grub_efi_uint32_t grub_efi_cc_event_log_bitmap_t;
++typedef grub_efi_uint32_t grub_efi_cc_event_log_format_t;
++typedef grub_efi_uint32_t grub_efi_cc_event_algorithm_bitmap_t;
++typedef grub_efi_uint32_t grub_efi_cc_mr_index_t;
++
++/* Intel TDX measure register index. */
++#define GRUB_TDX_MR_INDEX_MRTD	0
++#define GRUB_TDX_MR_INDEX_RTMR0	1
++#define GRUB_TDX_MR_INDEX_RTMR1	2
++#define GRUB_TDX_MR_INDEX_RTMR2	3
++#define GRUB_TDX_MR_INDEX_RTMR3	4
++
++#define GRUB_EFI_CC_EVENT_LOG_FORMAT_TCG_2	0x00000002
++#define GRUB_EFI_CC_BOOT_HASH_ALG_SHA384	0x00000004
++#define GRUB_EFI_CC_EVENT_HEADER_VERSION	1
++
++struct grub_efi_cc_event_header
++{
++  /* Size of the event header itself (sizeof(EFI_TD_EVENT_HEADER)). */
++  grub_efi_uint32_t      HeaderSize;
++
++  /*
++   * Header version. For this version of this specification,
++   * the value shall be 1.
++   */
++  grub_efi_uint16_t      HeaderVersion;
++
++  /* Index of the MR that shall be extended. */
++  grub_efi_cc_mr_index_t MrIndex;
++
++  /* Type of the event that shall be extended (and optionally logged). */
++  grub_efi_uint32_t      EventType;
++} GRUB_PACKED;
++typedef struct grub_efi_cc_event_header grub_efi_cc_event_header_t;
++
++struct grub_efi_cc_event
++{
++  /* Total size of the event including the Size component, the header and the Event data. */
++  grub_efi_uint32_t          Size;
++  grub_efi_cc_event_header_t Header;
++  grub_efi_uint8_t           Event[0];
++} GRUB_PACKED;
++typedef struct grub_efi_cc_event grub_efi_cc_event_t;
++
++struct grub_efi_cc_boot_service_capability
++{
++  /* Allocated size of the structure. */
++  grub_efi_uint8_t                     Size;
++
++  /*
++   * Version of the grub_efi_cc_boot_service_capability_t structure itself.
++   * For this version of the protocol, the Major version shall be set to 1
++   * and the Minor version shall be set to 1.
++   */
++  grub_efi_cc_version_t                StructureVersion;
++
++  /*
++   * Version of the EFI TD protocol.
++   * For this version of the protocol, the Major version shall be set to 1
++   * and the Minor version shall be set to 1.
++   */
++  grub_efi_cc_version_t                ProtocolVersion;
++
++  /* Supported hash algorithms. */
++  grub_efi_cc_event_algorithm_bitmap_t HashAlgorithmBitmap;
++
++  /* Bitmap of supported event log formats. */
++  grub_efi_cc_event_log_bitmap_t       SupportedEventLogs;
++
++  /* Indicates the CC type. */
++  grub_efi_cc_type_t CcType;
++};
++typedef struct grub_efi_cc_boot_service_capability grub_efi_cc_boot_service_capability_t;
++
++struct grub_efi_cc_protocol
++{
++  grub_efi_status_t
++  (*get_capability) (struct grub_efi_cc_protocol *this,
++		     grub_efi_cc_boot_service_capability_t *ProtocolCapability);
++
++  grub_efi_status_t
++  (*get_event_log) (struct grub_efi_cc_protocol *this,
++		    grub_efi_cc_event_log_format_t EventLogFormat,
++		    grub_efi_physical_address_t *EventLogLocation,
++		    grub_efi_physical_address_t *EventLogLastEntry,
++		    grub_efi_boolean_t *EventLogTruncated);
++
++  grub_efi_status_t
++  (*hash_log_extend_event) (struct grub_efi_cc_protocol *this,
++			    grub_efi_uint64_t Flags,
++			    grub_efi_physical_address_t DataToHash,
++			    grub_efi_uint64_t DataToHashLen,
++			    grub_efi_cc_event_t *EfiCcEvent);
++
++  grub_efi_status_t
++  (*map_pcr_to_mr_index) (struct grub_efi_cc_protocol *this,
++			  grub_efi_uint32_t PcrIndex,
++			  grub_efi_cc_mr_index_t *MrIndex);
++};
++typedef struct grub_efi_cc_protocol grub_efi_cc_protocol_t;
++
++#endif
diff -pruN 2.06-2/debian/patches/efivar-check-that-efivarfs-is-writeable.patch 2.06-2ubuntu16/debian/patches/efivar-check-that-efivarfs-is-writeable.patch
--- 2.06-2/debian/patches/efivar-check-that-efivarfs-is-writeable.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/efivar-check-that-efivarfs-is-writeable.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,74 @@
+From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+Date: Fri, 18 Mar 2022 15:21:33 +0100
+Subject: [PATCH 1/1] efivar: check that efivarfs is writeable
+
+Some UEFI implementations (notably U-Boot) don't implement the
+SetVariable() runtime service. On these systems the GRUB installation
+must be completed manually. Write a warning in this case but avoid
+throwing an error.  (LP: #1965288)
+
+Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+---
+ grub-core/osdep/unix/efivar.c | 34 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+diff --git a/grub-core/osdep/unix/efivar.c b/grub-core/osdep/unix/efivar.c
+index d34df0f..732f939 100644
+--- a/grub-core/osdep/unix/efivar.c
++++ b/grub-core/osdep/unix/efivar.c
+@@ -38,7 +38,10 @@
+ #include <grub/misc.h>
+ #include <grub/emu/exec.h>
+ #include <grub/emu/getroot.h>
++#include <linux/magic.h>
+ #include <sys/types.h>
++#include <sys/vfs.h>
++#include <sys/statvfs.h>
+ #include <ctype.h>
+ #include <errno.h>
+ #include <stdbool.h>
+@@ -511,6 +514,29 @@ devices_equal (const_efidp a, const_efidp b)
+   return false;
+ }
+ 
++/**
++ * efivar_is_rw - detect if the efivar file system exists and is writeable
++ *
++ * Return:	true if efivarfs is writeable
++ */
++static bool
++efivar_is_rw (void)
++{
++  int ret;
++  const char *mount = "/sys/firmware/efi/efivars";
++  struct statfs stat;
++
++  ret = statfs(mount, &stat);
++  if (ret == -1)
++    return false;
++  if (stat.f_type != EFIVARFS_MAGIC)
++      return false;
++  if (stat.f_flags & ST_RDONLY)
++    return false;
++
++  return true;
++}
++
+ int
+ grub_install_efivar_register_efi (grub_device_t efidir_grub_dev,
+ 				  const char *efidir, const char *efifile_path,
+@@ -528,6 +554,14 @@ grub_install_efivar_register_efi (grub_device_t efidir_grub_dev,
+   int rc;
+   bool is_boot_efi;
+ 
++  /* Check if EFI variable can be written */
++  if (!efivar_is_rw ())
++    {
++      grub_util_warn ("EFI variables cannot be set on this system");
++      grub_util_warn ("You will have to complete the GRUB setup manually");
++      return 0;
++    }
++
+   is_boot_efi = strstr (efidir, "/boot/efi") != NULL;
+   efidir_disk = grub_util_biosdisk_get_osdev (efidir_grub_dev->disk);
+   efidir_part = efidir_grub_dev->disk->partition ? efidir_grub_dev->disk->partition->number + 1 : 1;
diff -pruN 2.06-2/debian/patches/efi-variable-storage-minimise-writes.patch 2.06-2ubuntu16/debian/patches/efi-variable-storage-minimise-writes.patch
--- 2.06-2/debian/patches/efi-variable-storage-minimise-writes.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/efi-variable-storage-minimise-writes.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 6e3841fc4abf50d16d819c39ac5de74ccc4de225 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
@@ -51,8 +50,8 @@ Patch-Name: efi-variable-storage-minimis
  Makefile.util.def               |  20 ++
  configure.ac                    |  12 +
  grub-core/osdep/efivar.c        |   3 +
- grub-core/osdep/unix/efivar.c   | 508 ++++++++++++++++++++++++++++++++
- grub-core/osdep/unix/platform.c | 100 +------
+ grub-core/osdep/unix/efivar.c   | 508 ++++++++++++++++++++++++++++++++++++++++
+ grub-core/osdep/unix/platform.c | 100 +-------
  include/grub/util/install.h     |   5 +
  util/grub-install.c             |   4 +-
  8 files changed, 562 insertions(+), 95 deletions(-)
@@ -60,7 +59,7 @@ Patch-Name: efi-variable-storage-minimis
  create mode 100644 grub-core/osdep/unix/efivar.c
 
 diff --git a/INSTALL b/INSTALL
-index 79a0af7d9..590b52482 100644
+index 79a0af7..590b524 100644
 --- a/INSTALL
 +++ b/INSTALL
 @@ -23,6 +23,11 @@ configuring the GRUB.
@@ -76,7 +75,7 @@ index 79a0af7d9..590b52482 100644
  
  * libdevmapper 1.02.34 or later (recommended)
 diff --git a/Makefile.util.def b/Makefile.util.def
-index 27f948291..a3d134b03 100644
+index 27f9482..a3d134b 100644
 --- a/Makefile.util.def
 +++ b/Makefile.util.def
 @@ -570,6 +570,8 @@ program = {
@@ -180,7 +179,7 @@ index 27f948291..a3d134b03 100644
  
  script = {
 diff --git a/configure.ac b/configure.ac
-index e11df6bc5..b3fb7437e 100644
+index b4e33a6..d422626 100644
 --- a/configure.ac
 +++ b/configure.ac
 @@ -452,6 +452,18 @@ AC_CHECK_HEADER([util.h], [
@@ -204,7 +203,7 @@ index e11df6bc5..b3fb7437e 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 0000000..d2750e2
 --- /dev/null
 +++ b/grub-core/osdep/efivar.c
 @@ -0,0 +1,3 @@
@@ -213,7 +212,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 0000000..4a58328
 --- /dev/null
 +++ b/grub-core/osdep/unix/efivar.c
 @@ -0,0 +1,508 @@
@@ -726,7 +725,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 9c43932..b561174 100644
 --- a/grub-core/osdep/unix/platform.c
 +++ b/grub-core/osdep/unix/platform.c
 @@ -19,15 +19,12 @@
@@ -856,7 +855,7 @@ index 9c439326a..b561174ea 100644
  
  void
 diff --git a/include/grub/util/install.h b/include/grub/util/install.h
-index 135ba48d2..134b862ec 100644
+index 135ba48..134b862 100644
 --- a/include/grub/util/install.h
 +++ b/include/grub/util/install.h
 @@ -226,6 +226,11 @@ grub_install_get_default_x86_platform (void);
@@ -872,10 +871,10 @@ index 135ba48d2..134b862ec 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 58f1453ba..05b695226 100644
+index 3f40163..d482fdc 100644
 --- a/util/grub-install.c
 +++ b/util/grub-install.c
-@@ -2086,7 +2086,7 @@ main (int argc, char *argv[])
+@@ -2111,7 +2111,7 @@ main (int argc, char *argv[])
  					       "\\System\\Library\\CoreServices",
  					       efi_distributor);
  	      if (ret)
@@ -884,7 +883,7 @@ index 58f1453ba..05b695226 100644
  				 strerror (ret));
  	    }
  
-@@ -2203,7 +2203,7 @@ main (int argc, char *argv[])
+@@ -2231,7 +2231,7 @@ main (int argc, char *argv[])
  	  ret = grub_install_register_efi (efidir_grub_dev,
  					   efifile_path, efi_distributor);
  	  if (ret)
diff -pruN 2.06-2/debian/patches/fat-fix-listing-the-root-directory.patch 2.06-2ubuntu16/debian/patches/fat-fix-listing-the-root-directory.patch
--- 2.06-2/debian/patches/fat-fix-listing-the-root-directory.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/fat-fix-listing-the-root-directory.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,46 @@
+From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+Date: Fri, 21 Jan 2022 20:15:41 +0100
+Subject: fat: fix listing the root directory
+
+ls / for a FAT partition leads to
+
+   error: invalid modification timestamp for /.
+
+Not all entries of the directory are displayed.
+
+Linux never updates the modification timestamp of the /. directory entry.
+The FAT specification allows the access and creation date fields to be
+zero.
+
+We should follow Linux and render initial FAT timestamps as start of
+the epoch.
+
+Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+Origin: https://lists.gnu.org/archive/html/grub-devel/2022-01/msg00116.html
+---
+ grub-core/fs/fat.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c
+index dd82e4e..35ff0b2 100644
+--- a/grub-core/fs/fat.c
++++ b/grub-core/fs/fat.c
+@@ -901,6 +901,18 @@ grub_fat_timestamp (grub_uint16_t time, grub_uint16_t date, grub_int64_t *nix) {
+     .second = (time & 0x001F) * 2,
+   };
+ 
++  /*
++   * The modification time of the root directory is never set by Linux.
++   * Creation and access time are optional and can be zero.
++   * Follow Linux and render FAT initial timestamps as the start of the epoch.
++   */
++  if (date == 0 && time == 0)
++    {
++      datetime.year = 1970;
++      datetime.month = 1;
++      datetime.day = 1;
++    }
++
+   /* The conversion below allows seconds=60, so don't trust its validation. */
+   if ((time & 0x1F) > 29)
+     return 0;
diff -pruN 2.06-2/debian/patches/fbutil-Fix-integer-overflow.patch 2.06-2ubuntu16/debian/patches/fbutil-Fix-integer-overflow.patch
--- 2.06-2/debian/patches/fbutil-Fix-integer-overflow.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/fbutil-Fix-integer-overflow.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,81 @@
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Tue, 6 Sep 2022 03:03:21 +0800
+Subject: fbutil: Fix integer overflow
+
+Expressions like u64 = u32 * u32 are unsafe because their products are
+truncated to u32 even if left hand side is u64. This patch fixes all
+problems like that one in fbutil.
+
+To get right result not only left hand side have to be u64 but it's also
+necessary to cast at least one of the operands of all leaf operators of
+right hand side to u64, e.g. u64 = u32 * u32 + u32 * u32 should be
+u64 = (u64)u32 * u32 + (u64)u32 * u32.
+
+For 1-bit bitmaps grub_uint64_t have to be used. It's safe because any
+combination of values in (grub_uint64_t)u32 * u32 + u32 expression will
+not overflow grub_uint64_t.
+
+Other expressions like ptr + u32 * u32 + u32 * u32 are also vulnerable.
+They should be ptr + (grub_addr_t)u32 * u32 + (grub_addr_t)u32 * u32.
+
+This patch also adds a comment to grub_video_fb_get_video_ptr() which
+says it's arguments must be valid and no sanity check is performed
+(like its siblings in grub-core/video/fb/fbutil.c).
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/video/fb/fbutil.c |  4 ++--
+ include/grub/fbutil.h       | 13 +++++++++----
+ 2 files changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/grub-core/video/fb/fbutil.c b/grub-core/video/fb/fbutil.c
+index b98bb51..25ef39f 100644
+--- a/grub-core/video/fb/fbutil.c
++++ b/grub-core/video/fb/fbutil.c
+@@ -67,7 +67,7 @@ get_pixel (struct grub_video_fbblit_info *source,
+     case 1:
+       if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED)
+         {
+-          int bit_index = y * source->mode_info->width + x;
++          grub_uint64_t bit_index = (grub_uint64_t) y * source->mode_info->width + x;
+           grub_uint8_t *ptr = source->data + bit_index / 8;
+           int bit_pos = 7 - bit_index % 8;
+           color = (*ptr >> bit_pos) & 0x01;
+@@ -138,7 +138,7 @@ set_pixel (struct grub_video_fbblit_info *source,
+     case 1:
+       if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED)
+         {
+-          int bit_index = y * source->mode_info->width + x;
++          grub_uint64_t bit_index = (grub_uint64_t) y * source->mode_info->width + x;
+           grub_uint8_t *ptr = source->data + bit_index / 8;
+           int bit_pos = 7 - bit_index % 8;
+           *ptr = (*ptr & ~(1 << bit_pos)) | ((color & 0x01) << bit_pos);
+diff --git a/include/grub/fbutil.h b/include/grub/fbutil.h
+index 4205eb9..78a1ab3 100644
+--- a/include/grub/fbutil.h
++++ b/include/grub/fbutil.h
+@@ -31,14 +31,19 @@ struct grub_video_fbblit_info
+   grub_uint8_t *data;
+ };
+ 
+-/* Don't use for 1-bit bitmaps, addressing needs to be done at the bit level
+-   and it doesn't make sense, in general, to ask for a pointer
+-   to a particular pixel's data.  */
++/*
++ * Don't use for 1-bit bitmaps, addressing needs to be done at the bit level
++ * and it doesn't make sense, in general, to ask for a pointer
++ * to a particular pixel's data.
++ *
++ * This function assumes that bounds checking has been done in previous phase
++ * and they are opted out in here.
++ */
+ static inline void *
+ grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source,
+               unsigned int x, unsigned int y)
+ {
+-  return source->data + y * source->mode_info->pitch + x * source->mode_info->bytes_per_pixel;
++  return source->data + (grub_addr_t) y * source->mode_info->pitch + (grub_addr_t) x * source->mode_info->bytes_per_pixel;
+ }
+ 
+ /* Advance pointer by VAL bytes. If there is no unaligned access available,
diff -pruN 2.06-2/debian/patches/fdt-add-debug-output-to-devicetree-command.patch 2.06-2ubuntu16/debian/patches/fdt-add-debug-output-to-devicetree-command.patch
--- 2.06-2/debian/patches/fdt-add-debug-output-to-devicetree-command.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/fdt-add-debug-output-to-devicetree-command.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,31 @@
+From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+Date: Thu, 24 Mar 2022 13:21:26 +0100
+Subject: [PATCH] fdt: add debug output to devicetree command
+
+For debugging we need feedback that the devicetree command has be executed.
+
+Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+---
+ grub-core/loader/efi/fdt.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c
+index b846bf3..12164cd 100644
+--- a/grub-core/loader/efi/fdt.c
++++ b/grub-core/loader/efi/fdt.c
+@@ -128,6 +128,7 @@ grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
+   /* No arguments means "use firmware FDT".  */
+   if (argc == 0)
+     {
++      grub_dprintf ("fdt", "Using firmware FDT\n");
+       return GRUB_ERR_NONE;
+     }
+ 
+@@ -167,6 +168,7 @@ out:
+ 
+   if (blob)
+     {
++      grub_dprintf ("fdt", "Device-tree %s loaded\n", argv[0]);
+       if (grub_errno == GRUB_ERR_NONE)
+ 	loaded_fdt = blob;
+       else
diff -pruN 2.06-2/debian/patches/fix-lockdown.patch 2.06-2ubuntu16/debian/patches/fix-lockdown.patch
--- 2.06-2/debian/patches/fix-lockdown.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/fix-lockdown.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,45 +0,0 @@
-From b2c4515a832f82a4fe4ee8d32faa16b48de63d12 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 45b68c05a..532e4e512 100644
---- a/grub-core/loader/i386/efi/linux.c
-+++ b/grub-core/loader/i386/efi/linux.c
-@@ -29,6 +29,7 @@
- #include <grub/linux.h>
- #include <grub/efi/efi.h>
- #include <grub/efi/sb.h>
-+#include <stddef.h>
- 
- GRUB_MOD_LICENSE ("GPLv3+");
- 
-@@ -336,7 +337,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 -pruN 2.06-2/debian/patches/font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch 2.06-2ubuntu16/debian/patches/font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch
--- 2.06-2/debian/patches/font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,32 @@
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Fri, 28 Oct 2022 17:29:16 +0800
+Subject: font: Assign null_font to glyphs in ascii_font_glyph[]
+
+The calculations in blit_comb() need information from glyph's font, e.g.
+grub_font_get_xheight(main_glyph->font). However, main_glyph->font is
+NULL if main_glyph comes from ascii_font_glyph[]. Therefore
+grub_font_get_*() crashes because of NULL pointer.
+
+There is already a solution, the null_font. So, assign it to those glyphs
+in ascii_font_glyph[].
+
+Reported-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index 29fbb94..e6616e6 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -137,7 +137,7 @@ ascii_glyph_lookup (grub_uint32_t code)
+ 	  ascii_font_glyph[current]->offset_x = 0;
+ 	  ascii_font_glyph[current]->offset_y = -2;
+ 	  ascii_font_glyph[current]->device_width = 8;
+-	  ascii_font_glyph[current]->font = NULL;
++	  ascii_font_glyph[current]->font = &null_font;
+ 
+ 	  grub_memcpy (ascii_font_glyph[current]->bitmap,
+ 		       &ascii_bitmaps[current * ASCII_BITMAP_SIZE],
diff -pruN 2.06-2/debian/patches/font-Fix-an-integer-underflow-in-blit_comb.patch 2.06-2ubuntu16/debian/patches/font-Fix-an-integer-underflow-in-blit_comb.patch
--- 2.06-2/debian/patches/font-Fix-an-integer-underflow-in-blit_comb.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/font-Fix-an-integer-underflow-in-blit_comb.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,87 @@
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Mon, 24 Oct 2022 08:05:35 +0800
+Subject: font: Fix an integer underflow in blit_comb()
+
+The expression (ctx.bounds.height - combining_glyphs[i]->height) / 2 may
+evaluate to a very big invalid value even if both ctx.bounds.height and
+combining_glyphs[i]->height are small integers. For example, if
+ctx.bounds.height is 10 and combining_glyphs[i]->height is 12, this
+expression evaluates to 2147483647 (expected -1). This is because
+coordinates are allowed to be negative but ctx.bounds.height is an
+unsigned int. So, the subtraction operates on unsigned ints and
+underflows to a very big value. The division makes things even worse.
+The quotient is still an invalid value even if converted back to int.
+
+This patch fixes the problem by casting ctx.bounds.height to int. As
+a result the subtraction will operate on int and grub_uint16_t which
+will be promoted to an int. So, the underflow will no longer happen. Other
+uses of ctx.bounds.height (and ctx.bounds.width) are also casted to int,
+to ensure coordinates are always calculated on signed integers.
+
+Fixes: CVE-2022-3775
+
+Reported-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index 193dfec..12a5f0d 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -1203,12 +1203,12 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
+   ctx.bounds.height = main_glyph->height;
+ 
+   above_rightx = main_glyph->offset_x + main_glyph->width;
+-  above_righty = ctx.bounds.y + ctx.bounds.height;
++  above_righty = ctx.bounds.y + (int) ctx.bounds.height;
+ 
+   above_leftx = main_glyph->offset_x;
+-  above_lefty = ctx.bounds.y + ctx.bounds.height;
++  above_lefty = ctx.bounds.y + (int) ctx.bounds.height;
+ 
+-  below_rightx = ctx.bounds.x + ctx.bounds.width;
++  below_rightx = ctx.bounds.x + (int) ctx.bounds.width;
+   below_righty = ctx.bounds.y;
+ 
+   comb = grub_unicode_get_comb (glyph_id);
+@@ -1221,7 +1221,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
+ 
+       if (!combining_glyphs[i])
+ 	continue;
+-      targetx = (ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x;
++      targetx = ((int) ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x;
+       /* CGJ is to avoid diacritics reordering. */
+       if (comb[i].code
+ 	  == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER)
+@@ -1231,8 +1231,8 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
+ 	case GRUB_UNICODE_COMB_OVERLAY:
+ 	  do_blit (combining_glyphs[i],
+ 		   targetx,
+-		   (ctx.bounds.height - combining_glyphs[i]->height) / 2
+-		   - (ctx.bounds.height + ctx.bounds.y), &ctx);
++		   ((int) ctx.bounds.height - combining_glyphs[i]->height) / 2
++		   - ((int) ctx.bounds.height + ctx.bounds.y), &ctx);
+ 	  if (min_devwidth < combining_glyphs[i]->width)
+ 	    min_devwidth = combining_glyphs[i]->width;
+ 	  break;
+@@ -1305,7 +1305,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
+ 	  /* Fallthrough.  */
+ 	case GRUB_UNICODE_STACK_ATTACHED_ABOVE:
+ 	  do_blit (combining_glyphs[i], targetx,
+-		   -(ctx.bounds.height + ctx.bounds.y + space
++		   -((int) ctx.bounds.height + ctx.bounds.y + space
+ 		     + combining_glyphs[i]->height), &ctx);
+ 	  if (min_devwidth < combining_glyphs[i]->width)
+ 	    min_devwidth = combining_glyphs[i]->width;
+@@ -1313,7 +1313,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
+ 
+ 	case GRUB_UNICODE_COMB_HEBREW_DAGESH:
+ 	  do_blit (combining_glyphs[i], targetx,
+-		   -(ctx.bounds.height / 2 + ctx.bounds.y
++		   -((int) ctx.bounds.height / 2 + ctx.bounds.y
+ 		     + combining_glyphs[i]->height / 2), &ctx);
+ 	  if (min_devwidth < combining_glyphs[i]->width)
+ 	    min_devwidth = combining_glyphs[i]->width;
diff -pruN 2.06-2/debian/patches/font-Fix-integer-overflow-in-BMP-index.patch 2.06-2ubuntu16/debian/patches/font-Fix-integer-overflow-in-BMP-index.patch
--- 2.06-2/debian/patches/font-Fix-integer-overflow-in-BMP-index.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/font-Fix-integer-overflow-in-BMP-index.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,61 @@
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Mon, 15 Aug 2022 02:04:58 +0800
+Subject: font: Fix integer overflow in BMP index
+
+The BMP index (font->bmp_idx) is designed as a reverse lookup table of
+char entries (font->char_index), in order to speed up lookups for BMP
+chars (i.e. code < 0x10000). The values in BMP index are the subscripts
+of the corresponding char entries, stored in grub_uint16_t, while 0xffff
+means not found.
+
+This patch fixes the problem of large subscript truncated to grub_uint16_t,
+leading BMP index to return wrong char entry or report false miss. The
+code now checks for bounds and uses BMP index as a hint, and fallbacks
+to binary-search if necessary.
+
+On the occasion add a comment about BMP index is initialized to 0xffff.
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index d0e6340..b208a28 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -300,6 +300,8 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
+   font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t));
+   if (!font->bmp_idx)
+     return 1;
++
++  /* Init the BMP index array to 0xffff. */
+   grub_memset (font->bmp_idx, 0xff, 0x10000 * sizeof (grub_uint16_t));
+ 
+ 
+@@ -328,7 +330,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
+ 	  return 1;
+ 	}
+ 
+-      if (entry->code < 0x10000)
++      if (entry->code < 0x10000 && i < 0xffff)
+ 	font->bmp_idx[entry->code] = i;
+ 
+       last_code = entry->code;
+@@ -696,9 +698,12 @@ find_glyph (const grub_font_t font, grub_uint32_t code)
+   /* Use BMP index if possible.  */
+   if (code < 0x10000 && font->bmp_idx)
+     {
+-      if (font->bmp_idx[code] == 0xffff)
+-	return 0;
+-      return &table[font->bmp_idx[code]];
++      if (font->bmp_idx[code] < 0xffff)
++	return &table[font->bmp_idx[code]];
++      /*
++       * When we are here then lookup in BMP index result in miss,
++       * fallthough to binary-search.
++       */
+     }
+ 
+   /* Do a binary search in `char_index', which is ordered by code point.  */
diff -pruN 2.06-2/debian/patches/font-Fix-integer-overflow-in-ensure_comb_space.patch 2.06-2ubuntu16/debian/patches/font-Fix-integer-overflow-in-ensure_comb_space.patch
--- 2.06-2/debian/patches/font-Fix-integer-overflow-in-ensure_comb_space.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/font-Fix-integer-overflow-in-ensure_comb_space.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,44 @@
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Fri, 5 Aug 2022 02:27:05 +0800
+Subject: font: Fix integer overflow in ensure_comb_space()
+
+In fact it can't overflow at all because glyph_id->ncomb is only 8-bit
+wide. But let's keep safe if somebody changes the width of glyph_id->ncomb
+in the future. This patch also fixes the inconsistency between
+render_max_comb_glyphs and render_combining_glyphs when grub_malloc()
+returns NULL.
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index a115a63..d0e6340 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -1468,14 +1468,18 @@ ensure_comb_space (const struct grub_unicode_glyph *glyph_id)
+   if (glyph_id->ncomb <= render_max_comb_glyphs)
+     return;
+ 
+-  render_max_comb_glyphs = 2 * glyph_id->ncomb;
+-  if (render_max_comb_glyphs < 8)
++  if (grub_mul (glyph_id->ncomb, 2, &render_max_comb_glyphs))
++    render_max_comb_glyphs = 0;
++  if (render_max_comb_glyphs > 0 && render_max_comb_glyphs < 8)
+     render_max_comb_glyphs = 8;
+   grub_free (render_combining_glyphs);
+-  render_combining_glyphs = grub_malloc (render_max_comb_glyphs
+-					 * sizeof (render_combining_glyphs[0]));
++  render_combining_glyphs = (render_max_comb_glyphs > 0) ?
++    grub_calloc (render_max_comb_glyphs, sizeof (render_combining_glyphs[0])) : NULL;
+   if (!render_combining_glyphs)
+-    grub_errno = 0;
++    {
++      render_max_comb_glyphs = 0;
++      grub_errno = GRUB_ERR_NONE;
++    }
+ }
+ 
+ int
diff -pruN 2.06-2/debian/patches/font-Fix-integer-underflow-in-binary-search-of-char-index.patch 2.06-2ubuntu16/debian/patches/font-Fix-integer-underflow-in-binary-search-of-char-index.patch
--- 2.06-2/debian/patches/font-Fix-integer-underflow-in-binary-search-of-char-index.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/font-Fix-integer-underflow-in-binary-search-of-char-index.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,81 @@
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Sun, 14 Aug 2022 18:09:38 +0800
+Subject: font: Fix integer underflow in binary search of char index
+
+If search target is less than all entries in font->index then "hi"
+variable is set to -1, which translates to SIZE_MAX and leads to errors.
+
+This patch fixes the problem by replacing the entire binary search code
+with the libstdc++'s std::lower_bound() implementation.
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 40 ++++++++++++++++++++++------------------
+ 1 file changed, 22 insertions(+), 18 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index b208a28..193dfec 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -688,12 +688,12 @@ read_be_int16 (grub_file_t file, grub_int16_t * value)
+ static inline struct char_index_entry *
+ find_glyph (const grub_font_t font, grub_uint32_t code)
+ {
+-  struct char_index_entry *table;
+-  grub_size_t lo;
+-  grub_size_t hi;
+-  grub_size_t mid;
++  struct char_index_entry *table, *first, *end;
++  grub_size_t len;
+ 
+   table = font->char_index;
++  if (table == NULL)
++    return NULL;
+ 
+   /* Use BMP index if possible.  */
+   if (code < 0x10000 && font->bmp_idx)
+@@ -706,25 +706,29 @@ find_glyph (const grub_font_t font, grub_uint32_t code)
+        */
+     }
+ 
+-  /* Do a binary search in `char_index', which is ordered by code point.  */
+-  lo = 0;
+-  hi = font->num_chars - 1;
+-
+-  if (!table)
+-    return 0;
++  /*
++   * Do a binary search in char_index which is ordered by code point.
++   * The code below is the same as libstdc++'s std::lower_bound().
++   */
++  first = table;
++  len = font->num_chars;
++  end = first + len;
+ 
+-  while (lo <= hi)
++  while (len > 0)
+     {
+-      mid = lo + (hi - lo) / 2;
+-      if (code < table[mid].code)
+-	hi = mid - 1;
+-      else if (code > table[mid].code)
+-	lo = mid + 1;
++      grub_size_t half = len >> 1;
++      struct char_index_entry *middle = first + half;
++
++      if (middle->code < code)
++	{
++	  first = middle + 1;
++	  len = len - half - 1;
++	}
+       else
+-	return &table[mid];
++	len = half;
+     }
+ 
+-  return 0;
++  return (first < end && first->code == code) ? first : NULL;
+ }
+ 
+ /* Get a glyph for the Unicode character CODE in FONT.  The glyph is loaded
diff -pruN 2.06-2/debian/patches/font-Fix-several-integer-overflows-in-grub_font_construct.patch 2.06-2ubuntu16/debian/patches/font-Fix-several-integer-overflows-in-grub_font_construct.patch
--- 2.06-2/debian/patches/font-Fix-several-integer-overflows-in-grub_font_construct.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/font-Fix-several-integer-overflows-in-grub_font_construct.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,76 @@
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Fri, 5 Aug 2022 01:58:27 +0800
+Subject: font: Fix several integer overflows in grub_font_construct_glyph()
+
+This patch fixes several integer overflows in grub_font_construct_glyph().
+Glyphs of invalid size, zero or leading to an overflow, are rejected.
+The inconsistency between "glyph" and "max_glyph_size" when grub_malloc()
+returns NULL is fixed too.
+
+Fixes: CVE-2022-2601
+
+Reported-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 29 +++++++++++++++++------------
+ 1 file changed, 17 insertions(+), 12 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index 6a3fbeb..1fa181d 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -1517,6 +1517,7 @@ grub_font_construct_glyph (grub_font_t hinted_font,
+   struct grub_video_signed_rect bounds;
+   static struct grub_font_glyph *glyph = 0;
+   static grub_size_t max_glyph_size = 0;
++  grub_size_t cur_glyph_size;
+ 
+   ensure_comb_space (glyph_id);
+ 
+@@ -1533,29 +1534,33 @@ grub_font_construct_glyph (grub_font_t hinted_font,
+   if (!glyph_id->ncomb && !glyph_id->attributes)
+     return main_glyph;
+ 
+-  if (max_glyph_size < sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT)
++  if (grub_video_bitmap_calc_1bpp_bufsz (bounds.width, bounds.height, &cur_glyph_size) ||
++      grub_add (sizeof (*glyph), cur_glyph_size, &cur_glyph_size))
++    return main_glyph;
++
++  if (max_glyph_size < cur_glyph_size)
+     {
+       grub_free (glyph);
+-      max_glyph_size = (sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) * 2;
+-      if (max_glyph_size < 8)
+-	max_glyph_size = 8;
+-      glyph = grub_malloc (max_glyph_size);
++      if (grub_mul (cur_glyph_size, 2, &max_glyph_size))
++	max_glyph_size = 0;
++      glyph = max_glyph_size > 0 ? grub_malloc (max_glyph_size) : NULL;
+     }
+   if (!glyph)
+     {
++      max_glyph_size = 0;
+       grub_errno = GRUB_ERR_NONE;
+       return main_glyph;
+     }
+ 
+-  grub_memset (glyph, 0, sizeof (*glyph)
+-	       + (bounds.width * bounds.height
+-		  + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT);
++  grub_memset (glyph, 0, cur_glyph_size);
+ 
+   glyph->font = main_glyph->font;
+-  glyph->width = bounds.width;
+-  glyph->height = bounds.height;
+-  glyph->offset_x = bounds.x;
+-  glyph->offset_y = bounds.y;
++  if (bounds.width == 0 || bounds.height == 0 ||
++      grub_cast (bounds.width, &glyph->width) ||
++      grub_cast (bounds.height, &glyph->height) ||
++      grub_cast (bounds.x, &glyph->offset_x) ||
++      grub_cast (bounds.y, &glyph->offset_y))
++    return main_glyph;
+ 
+   if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR)
+     grub_font_blit_glyph_mirror (glyph, main_glyph,
diff -pruN 2.06-2/debian/patches/font-Fix-size-overflow-in-grub_font_get_glyph_internal.patch 2.06-2ubuntu16/debian/patches/font-Fix-size-overflow-in-grub_font_get_glyph_internal.patch
--- 2.06-2/debian/patches/font-Fix-size-overflow-in-grub_font_get_glyph_internal.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/font-Fix-size-overflow-in-grub_font_get_glyph_internal.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,108 @@
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Fri, 5 Aug 2022 00:51:20 +0800
+Subject: font: Fix size overflow in grub_font_get_glyph_internal()
+
+The length of memory allocation and file read may overflow. This patch
+fixes the problem by using safemath macros.
+
+There is a lot of code repetition like "(x * y + 7) / 8". It is unsafe
+if overflow happens. This patch introduces grub_video_bitmap_calc_1bpp_bufsz().
+It is safe replacement for such code. It has safemath-like prototype.
+
+This patch also introduces grub_cast(value, pointer), it casts value to
+typeof(*pointer) then store the value to *pointer. It returns true when
+overflow occurs or false if there is no overflow. The semantics of arguments
+and return value are designed to be consistent with other safemath macros.
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c   | 17 +++++++++++++----
+ include/grub/bitmap.h   | 18 ++++++++++++++++++
+ include/grub/safemath.h |  2 ++
+ 3 files changed, 33 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index 2f09a4a..6a3fbeb 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -739,7 +739,8 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
+       grub_int16_t xoff;
+       grub_int16_t yoff;
+       grub_int16_t dwidth;
+-      int len;
++      grub_ssize_t len;
++      grub_size_t sz;
+ 
+       if (index_entry->glyph)
+ 	/* Return cached glyph.  */
+@@ -768,9 +769,17 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
+ 	  return 0;
+ 	}
+ 
+-      len = (width * height + 7) / 8;
+-      glyph = grub_malloc (sizeof (struct grub_font_glyph) + len);
+-      if (!glyph)
++      /* Calculate real struct size of current glyph. */
++      if (grub_video_bitmap_calc_1bpp_bufsz (width, height, &len) ||
++	  grub_add (sizeof (struct grub_font_glyph), len, &sz))
++	{
++	  remove_font (font);
++	  return 0;
++	}
++
++      /* Allocate and initialize the glyph struct. */
++      glyph = grub_malloc (sz);
++      if (glyph == NULL)
+ 	{
+ 	  remove_font (font);
+ 	  return 0;
+diff --git a/include/grub/bitmap.h b/include/grub/bitmap.h
+index 5728f8c..0d9603f 100644
+--- a/include/grub/bitmap.h
++++ b/include/grub/bitmap.h
+@@ -23,6 +23,7 @@
+ #include <grub/symbol.h>
+ #include <grub/types.h>
+ #include <grub/video.h>
++#include <grub/safemath.h>
+ 
+ struct grub_video_bitmap
+ {
+@@ -79,6 +80,23 @@ grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap)
+   return bitmap->mode_info.height;
+ }
+ 
++/*
++ * Calculate and store the size of data buffer of 1bit bitmap in result.
++ * Equivalent to "*result = (width * height + 7) / 8" if no overflow occurs.
++ * Return true when overflow occurs or false if there is no overflow.
++ * This function is intentionally implemented as a macro instead of
++ * an inline function. Although a bit awkward, it preserves data types for
++ * safemath macros and reduces macro side effects as much as possible.
++ *
++ * XXX: Will report false overflow if width * height > UINT64_MAX.
++ */
++#define grub_video_bitmap_calc_1bpp_bufsz(width, height, result) \
++({ \
++  grub_uint64_t _bitmap_pixels; \
++  grub_mul ((width), (height), &_bitmap_pixels) ? 1 : \
++    grub_cast (_bitmap_pixels / GRUB_CHAR_BIT + !!(_bitmap_pixels % GRUB_CHAR_BIT), (result)); \
++})
++
+ void EXPORT_FUNC (grub_video_bitmap_get_mode_info) (struct grub_video_bitmap *bitmap,
+ 						    struct grub_video_mode_info *mode_info);
+ 
+diff --git a/include/grub/safemath.h b/include/grub/safemath.h
+index c17b89b..bb0f826 100644
+--- a/include/grub/safemath.h
++++ b/include/grub/safemath.h
+@@ -30,6 +30,8 @@
+ #define grub_sub(a, b, res)	__builtin_sub_overflow(a, b, res)
+ #define grub_mul(a, b, res)	__builtin_mul_overflow(a, b, res)
+ 
++#define grub_cast(a, res)	grub_add ((a), 0, (res))
++
+ #else
+ #error gcc 5.1 or newer or clang 3.8 or newer is required
+ #endif
diff -pruN 2.06-2/debian/patches/font-Harden-grub_font_blit_glyph-and-grub_font_blit_glyph.patch 2.06-2ubuntu16/debian/patches/font-Harden-grub_font_blit_glyph-and-grub_font_blit_glyph.patch
--- 2.06-2/debian/patches/font-Harden-grub_font_blit_glyph-and-grub_font_blit_glyph.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/font-Harden-grub_font_blit_glyph-and-grub_font_blit_glyph.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,71 @@
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Mon, 24 Oct 2022 07:15:41 +0800
+Subject: font: Harden grub_font_blit_glyph() and
+ grub_font_blit_glyph_mirror()
+
+As a mitigation and hardening measure add sanity checks to
+grub_font_blit_glyph() and grub_font_blit_glyph_mirror(). This patch
+makes these two functions do nothing if target blitting area isn't fully
+contained in target bitmap. Therefore, if complex calculations in caller
+overflows and malicious coordinates are given, we are still safe because
+any coordinates which result in out-of-bound-write are rejected. However,
+this patch only checks for invalid coordinates, and doesn't provide any
+protection against invalid source glyph or destination glyph, e.g.
+mismatch between glyph size and buffer size.
+
+This hardening measure is designed to mitigate possible overflows in
+blit_comb(). If overflow occurs, it may return invalid bounding box
+during dry run and call grub_font_blit_glyph() with malicious
+coordinates during actual blitting. However, we are still safe because
+the scratch glyph itself is valid, although its size makes no sense, and
+any invalid coordinates are rejected.
+
+It would be better to call grub_fatal() if illegal parameter is detected.
+However, doing this may end up in a dangerous recursion because grub_fatal()
+would print messages to the screen and we are in the progress of drawing
+characters on the screen.
+
+Reported-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index 12a5f0d..29fbb94 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -1069,8 +1069,15 @@ static void
+ grub_font_blit_glyph (struct grub_font_glyph *target,
+ 		      struct grub_font_glyph *src, unsigned dx, unsigned dy)
+ {
++  grub_uint16_t max_x, max_y;
+   unsigned src_bit, tgt_bit, src_byte, tgt_byte;
+   unsigned i, j;
++
++  /* Harden against out-of-bound writes. */
++  if ((grub_add (dx, src->width, &max_x) || max_x > target->width) ||
++      (grub_add (dy, src->height, &max_y) || max_y > target->height))
++    return;
++
+   for (i = 0; i < src->height; i++)
+     {
+       src_bit = (src->width * i) % 8;
+@@ -1102,9 +1109,16 @@ grub_font_blit_glyph_mirror (struct grub_font_glyph *target,
+ 			     struct grub_font_glyph *src,
+ 			     unsigned dx, unsigned dy)
+ {
++  grub_uint16_t max_x, max_y;
+   unsigned tgt_bit, src_byte, tgt_byte;
+   signed src_bit;
+   unsigned i, j;
++
++  /* Harden against out-of-bound writes. */
++  if ((grub_add (dx, src->width, &max_x) || max_x > target->width) ||
++      (grub_add (dy, src->height, &max_y) || max_y > target->height))
++    return;
++
+   for (i = 0; i < src->height; i++)
+     {
+       src_bit = (src->width * i + src->width - 1) % 8;
diff -pruN 2.06-2/debian/patches/font-Reject-glyphs-exceeds-font-max_glyph_width-or-font-m.patch 2.06-2ubuntu16/debian/patches/font-Reject-glyphs-exceeds-font-max_glyph_width-or-font-m.patch
--- 2.06-2/debian/patches/font-Reject-glyphs-exceeds-font-max_glyph_width-or-font-m.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/font-Reject-glyphs-exceeds-font-max_glyph_width-or-font-m.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,29 @@
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Wed, 3 Aug 2022 19:45:33 +0800
+Subject: font: Reject glyphs exceeds font->max_glyph_width or
+ font->max_glyph_height
+
+Check glyph's width and height against limits specified in font's
+metadata. Reject the glyph (and font) if such limits are exceeded.
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index d09bb38..2f09a4a 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -760,7 +760,9 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
+ 	  || read_be_uint16 (font->file, &height) != 0
+ 	  || read_be_int16 (font->file, &xoff) != 0
+ 	  || read_be_int16 (font->file, &yoff) != 0
+-	  || read_be_int16 (font->file, &dwidth) != 0)
++	  || read_be_int16 (font->file, &dwidth) != 0
++	  || width > font->max_char_width
++	  || height > font->max_char_height)
+ 	{
+ 	  remove_font (font);
+ 	  return 0;
diff -pruN 2.06-2/debian/patches/font-Remove-grub_font_dup_glyph.patch 2.06-2ubuntu16/debian/patches/font-Remove-grub_font_dup_glyph.patch
--- 2.06-2/debian/patches/font-Remove-grub_font_dup_glyph.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/font-Remove-grub_font_dup_glyph.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,38 @@
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Fri, 5 Aug 2022 02:13:29 +0800
+Subject: font: Remove grub_font_dup_glyph()
+
+Remove grub_font_dup_glyph() since nobody is using it since 2013, and
+I'm too lazy to fix the integer overflow problem in it.
+
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/font/font.c | 14 --------------
+ 1 file changed, 14 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index 1fa181d..a115a63 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -1055,20 +1055,6 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code)
+   return best_glyph;
+ }
+ 
+-#if 0
+-static struct grub_font_glyph *
+-grub_font_dup_glyph (struct grub_font_glyph *glyph)
+-{
+-  static struct grub_font_glyph *ret;
+-  ret = grub_malloc (sizeof (*ret) + (glyph->width * glyph->height + 7) / 8);
+-  if (!ret)
+-    return NULL;
+-  grub_memcpy (ret, glyph, sizeof (*ret)
+-	       + (glyph->width * glyph->height + 7) / 8);
+-  return ret;
+-}
+-#endif
+-
+ /* FIXME: suboptimal.  */
+ static void
+ grub_font_blit_glyph (struct grub_font_glyph *target,
diff -pruN 2.06-2/debian/patches/font-Try-opening-fonts-from-the-bundled-memdisk.patch 2.06-2ubuntu16/debian/patches/font-Try-opening-fonts-from-the-bundled-memdisk.patch
--- 2.06-2/debian/patches/font-Try-opening-fonts-from-the-bundled-memdisk.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/font-Try-opening-fonts-from-the-bundled-memdisk.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,76 @@
+From: Chris Coulson <chris.coulson@canonical.com>
+Date: Wed, 16 Nov 2022 14:40:04 +0000
+Subject: font: Try opening fonts from the bundled memdisk
+
+---
+ grub-core/font/font.c | 48 +++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 31 insertions(+), 17 deletions(-)
+
+diff --git a/grub-core/font/font.c b/grub-core/font/font.c
+index e6616e6..e421d1a 100644
+--- a/grub-core/font/font.c
++++ b/grub-core/font/font.c
+@@ -409,6 +409,27 @@ read_section_as_short (struct font_file_section *section,
+   return 0;
+ }
+ 
++static grub_file_t
++try_open_from_prefix (const char *prefix, const char *filename)
++{
++  grub_file_t file;
++  char *fullname, *ptr;
++
++  fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1
++			  + sizeof ("/fonts/") + sizeof (".pf2"));
++  if (!fullname)
++    return 0;
++  ptr = grub_stpcpy (fullname, prefix);
++  ptr = grub_stpcpy (ptr, "/fonts/");
++  ptr = grub_stpcpy (ptr, filename);
++  ptr = grub_stpcpy (ptr, ".pf2");
++  *ptr = 0;
++
++  file = grub_buffile_open (fullname, GRUB_FILE_TYPE_FONT, 1024);
++  grub_free (fullname);
++  return file;
++}
++
+ /* Load a font and add it to the beginning of the global font list.
+    Returns 0 upon success, nonzero upon failure.  */
+ grub_font_t
+@@ -427,25 +448,18 @@ grub_font_load (const char *filename)
+     file = grub_buffile_open (filename, GRUB_FILE_TYPE_FONT, 1024);
+   else
+     {
+-      const char *prefix = grub_env_get ("prefix");
+-      char *fullname, *ptr;
+-      if (!prefix)
++      file = try_open_from_prefix ("(memdisk)", filename);
++      if (!file)
+ 	{
+-	  grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"),
+-		      "prefix");
+-	  goto fail;
++	  const char *prefix = grub_env_get ("prefix");
++	  if (!prefix)
++	    {
++	      grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"),
++			  "prefix");
++	      goto fail;
++	    }
++	  file = try_open_from_prefix (prefix, filename);
+ 	}
+-      fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1
+-			      + sizeof ("/fonts/") + sizeof (".pf2"));
+-      if (!fullname)
+-	goto fail;
+-      ptr = grub_stpcpy (fullname, prefix);
+-      ptr = grub_stpcpy (ptr, "/fonts/");
+-      ptr = grub_stpcpy (ptr, filename);
+-      ptr = grub_stpcpy (ptr, ".pf2");
+-      *ptr = 0;
+-      file = grub_buffile_open (fullname, GRUB_FILE_TYPE_FONT, 1024);
+-      grub_free (fullname);
+     }
+   if (!file)
+     goto fail;
diff -pruN 2.06-2/debian/patches/gettext-quiet.patch 2.06-2ubuntu16/debian/patches/gettext-quiet.patch
--- 2.06-2/debian/patches/gettext-quiet.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/gettext-quiet.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From ddc3423d5c2bf1fb83a6f378726ff87b12794d19 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 +12,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 4d02e62..2a19389 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 -pruN 2.06-2/debian/patches/gfxpayload-dynamic.patch 2.06-2ubuntu16/debian/patches/gfxpayload-dynamic.patch
--- 2.06-2/debian/patches/gfxpayload-dynamic.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/gfxpayload-dynamic.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From bc7f762a1d253537eb524946884b0f3e50a419f0 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
@@ -13,19 +12,19 @@ Last-Update: 2019-05-25
 
 Patch-Name: gfxpayload-dynamic.patch
 ---
- configure.ac                         |  11 ++
+ configure.ac                         |  11 +++
  grub-core/Makefile.core.def          |   8 ++
- grub-core/commands/i386/pc/hwmatch.c | 146 +++++++++++++++++++++++++++
+ grub-core/commands/i386/pc/hwmatch.c | 146 +++++++++++++++++++++++++++++++++++
  include/grub/file.h                  |   1 +
- util/grub.d/10_linux.in              |  37 ++++++-
+ util/grub.d/10_linux.in              |  37 ++++++++-
  5 files changed, 200 insertions(+), 3 deletions(-)
  create mode 100644 grub-core/commands/i386/pc/hwmatch.c
 
 diff --git a/configure.ac b/configure.ac
-index c42e4c784..947fd529f 100644
+index 4882eba..3203749 100644
 --- a/configure.ac
 +++ b/configure.ac
-@@ -1937,6 +1937,17 @@ else
+@@ -1945,6 +1945,17 @@ else
  fi
  AC_SUBST([QUICK_BOOT])
  
@@ -44,7 +43,7 @@ index c42e4c784..947fd529f 100644
  
  AC_SUBST([FONT_SOURCE])
 diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
-index e5b3d27f5..2ff266806 100644
+index 1a3ead6..0d7bce1 100644
 --- a/grub-core/Makefile.core.def
 +++ b/grub-core/Makefile.core.def
 @@ -964,6 +964,14 @@ module = {
@@ -64,7 +63,7 @@ index e5b3d27f5..2ff266806 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 0000000..6de07ce
 --- /dev/null
 +++ b/grub-core/commands/i386/pc/hwmatch.c
 @@ -0,0 +1,146 @@
@@ -215,7 +214,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 3156748..e3c4cae 100644
 --- a/include/grub/file.h
 +++ b/include/grub/file.h
 @@ -122,6 +122,7 @@ enum grub_file_type
@@ -227,7 +226,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 80315a31b..d46d7852b 100644
+index 80315a3..d46d785 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -23,6 +23,7 @@ datarootdir="@datarootdir@"
diff -pruN 2.06-2/debian/patches/gfxpayload-keep-default.patch 2.06-2ubuntu16/debian/patches/gfxpayload-keep-default.patch
--- 2.06-2/debian/patches/gfxpayload-keep-default.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/gfxpayload-keep-default.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 70a2b23aadd93955a3869aa1c29a7f09c0696b95 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@debian.org>
 Date: Mon, 13 Jan 2014 12:12:57 +0000
 Subject: Disable gfxpayload=keep by default
@@ -23,7 +22,7 @@ Patch-Name: gfxpayload-keep-default.patc
  1 file changed, 4 deletions(-)
 
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index e8b01c0d0..9446d6833 100644
+index e8b01c0..9446d68 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -114,10 +114,6 @@ linux_entry ()
diff -pruN 2.06-2/debian/patches/grub.cfg-400.patch 2.06-2ubuntu16/debian/patches/grub.cfg-400.patch
--- 2.06-2/debian/patches/grub.cfg-400.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/grub.cfg-400.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 2f1be2e80ba5dd1278401f21cfe07526312838e9 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@debian.org>
 Date: Mon, 13 Jan 2014 12:12:55 +0000
 Subject: Make grub.cfg world-readable if it contains no passwords
@@ -9,7 +8,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 f8cbb8d7a..0fd618e35 100644
+index f8cbb8d..0fd618e 100644
 --- a/util/grub-mkconfig.in
 +++ b/util/grub-mkconfig.in
 @@ -289,6 +289,10 @@ for i in "${grub_mkconfig_dir}"/* ; do
diff -pruN 2.06-2/debian/patches/grub-install-extra-removable.patch 2.06-2ubuntu16/debian/patches/grub-install-extra-removable.patch
--- 2.06-2/debian/patches/grub-install-extra-removable.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/grub-install-extra-removable.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,202 +0,0 @@
-From a0bfbdf9139bc127d28c4102b941ee504f7f0041 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
-
-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.
-
-Signed-off-by: Steve McIntyre <93sam@debian.org>
-
-Bug-Debian: https://bugs.debian.org/767037 https://bugs.debian.org/773092
-Forwarded: Not yet
-Last-Update: 2021-09-24
-
-Patch-Name: grub-install-extra-removable.patch
----
- util/grub-install.c | 110 +++++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 108 insertions(+), 2 deletions(-)
-
-diff --git a/util/grub-install.c b/util/grub-install.c
-index 2304cc5c4..b51fe4710 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 recheck = 0;
- static int update_nvram = 1;
- static char *install_device = NULL;
-@@ -113,7 +114,8 @@ enum
-     OPTION_LABEL_BGCOLOR,
-     OPTION_PRODUCT_VERSION,
-     OPTION_UEFI_SECURE_BOOT,
--    OPTION_NO_UEFI_SECURE_BOOT
-+    OPTION_NO_UEFI_SECURE_BOOT,
-+    OPTION_FORCE_EXTRA_REMOVABLE
-   };
- 
- static int fs_probe = 1;
-@@ -216,6 +218,10 @@ argp_parser (int key, char *arg, struct argp_state *state)
-       removable = 1;
-       return 0;
- 
-+    case OPTION_FORCE_EXTRA_REMOVABLE:
-+      force_extra_removable = 1;
-+      return 0;
-+
-     case OPTION_ALLOW_FLOPPY:
-       allow_floppy = 1;
-       return 0;
-@@ -322,6 +328,9 @@ static struct argp_option options[] = {
-    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. "
-+      "This option is only available on EFI."), 2},
-   {0, 0, 0, 0, 0, 0}
- };
- 
-@@ -847,6 +856,91 @@ fill_core_services (const char *core_services)
-   free (sysv_plist);
- }
- 
-+/* Helper routine for also_install_removable() below. Walk through the
-+   specified dir, looking to see if there is a file/dir that matches
-+   the search string exactly, but in a case-insensitive manner. If so,
-+   return a copy of the exact file/dir that *does* exist. If not,
-+   return NULL */
-+static char *
-+check_component_exists(const char *dir,
-+		       const char *search)
-+{
-+  grub_util_fd_dir_t d;
-+  grub_util_fd_dirent_t de;
-+  char *found = NULL;
-+
-+  d = grub_util_fd_opendir (dir);
-+  if (!d)
-+    grub_util_error (_("cannot open directory `%s': %s"),
-+		     dir, grub_util_fd_strerror ());
-+
-+  while ((de = grub_util_fd_readdir (d)))
-+    {
-+      if (strcasecmp (de->d_name, search) == 0)
-+	{
-+	  found = xstrdup (de->d_name);
-+	  break;
-+	}
-+    }
-+  grub_util_fd_closedir (d);
-+  return found;
-+}
-+
-+/* Some complex directory-handling stuff in here, to cope with
-+ * case-insensitive FAT/VFAT filesystem semantics. Ugh. */
-+static void
-+also_install_removable(const char *src,
-+		       const char *base_efidir,
-+		       const char *efi_suffix_upper)
-+{
-+  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. */
-+
-+  /* Look for "EFI" in base_efidir. Make it if it does not exist in
-+   * some form. */
-+  found = check_component_exists(base_efidir, "EFI");
-+  if (found == NULL)
-+    found = xstrdup("EFI");
-+  dst = grub_util_path_concat (2, base_efidir, found);
-+  cur = xstrdup (dst);
-+  free (dst);
-+  free (found);
-+  grub_install_mkdir_p (cur);
-+
-+  /* Now BOOT */
-+  found = check_component_exists(cur, "BOOT");
-+  if (found == NULL)
-+    found = xstrdup("BOOT");
-+  dst = grub_util_path_concat (2, cur, found);
-+  cur = xstrdup (dst);
-+  free (dst);
-+  free (found);
-+  grub_install_mkdir_p (cur);
-+
-+  /* Now $efi_file */
-+  found = check_component_exists(cur, efi_file);
-+  if (found == NULL)
-+    found = xstrdup(efi_file);
-+  dst = grub_util_path_concat (2, cur, found);
-+  cur = xstrdup (dst);
-+  free (dst);
-+  free (found);
-+  grub_install_copy_file (src, cur, 1);
-+
-+  free (cur);
-+  free (efi_file);
-+}
-+
- int
- main (int argc, char *argv[])
- {
-@@ -864,6 +958,7 @@ main (int argc, char *argv[])
-   char *relative_grubdir;
-   char **efidir_device_names = NULL;
-   grub_device_t efidir_grub_dev = NULL;
-+  char *base_efidir = NULL;
-   char *efidir_grub_devname;
-   int efidir_is_mac = 0;
-   int is_prep = 0;
-@@ -896,6 +991,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 (!grub_install_source_directory)
-     {
-       if (!target)
-@@ -1115,6 +1213,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);
- 
-+      base_efidir = xstrdup(efidir);
-+
-       /* 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
-@@ -2048,9 +2148,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);
- 	  }
- 	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);
-+	  }
- 
- 	grub_set_install_backup_ponr ();
- 
diff -pruN 2.06-2/debian/patches/grub-install-pvxen-paths.patch 2.06-2ubuntu16/debian/patches/grub-install-pvxen-paths.patch
--- 2.06-2/debian/patches/grub-install-pvxen-paths.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/grub-install-pvxen-paths.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 4e93755cd1c371ba856b375f453664fd07a67205 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
@@ -20,18 +19,15 @@ Forwarded: http://lists.gnu.org/archive/
 Last-Update: 2014-10-24
 
 Patch-Name: grub-install-pvxen-paths.patch
-
----
-v2: Respect bootdir, create /boot/xen as needed.
 ---
  util/grub-install.c | 24 ++++++++++++++++++++++--
  1 file changed, 22 insertions(+), 2 deletions(-)
 
 diff --git a/util/grub-install.c b/util/grub-install.c
-index d02bd488a..2304cc5c4 100644
+index 4af831f..65277ea 100644
 --- a/util/grub-install.c
 +++ b/util/grub-install.c
-@@ -2085,6 +2085,28 @@ main (int argc, char *argv[])
+@@ -2088,6 +2088,28 @@ main (int argc, char *argv[])
  	}
        break;
  
@@ -60,7 +56,7 @@ index d02bd488a..2304cc5c4 100644
      case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
      case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
      case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
-@@ -2094,8 +2116,6 @@ main (int argc, char *argv[])
+@@ -2097,8 +2119,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 -pruN 2.06-2/debian/patches/grub-install-removable-shim.patch 2.06-2ubuntu16/debian/patches/grub-install-removable-shim.patch
--- 2.06-2/debian/patches/grub-install-removable-shim.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/grub-install-removable-shim.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,195 +0,0 @@
-From c8351a8a7a7664dfac4de63fb6df185b2a52a346 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: 2021-09-24
-
-Patch-Name: grub-install-removable-shim.patch
----
- util/grub-install.c | 83 +++++++++++++++++++++++++++++++++++----------
- 1 file changed, 66 insertions(+), 17 deletions(-)
-
-diff --git a/util/grub-install.c b/util/grub-install.c
-index 05b695226..43fc27c55 100644
---- a/util/grub-install.c
-+++ b/util/grub-install.c
-@@ -891,17 +891,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. */
-@@ -935,10 +931,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
-@@ -2103,11 +2098,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;
- 
-@@ -2116,11 +2114,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);
-@@ -2132,8 +2134,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
-@@ -2144,8 +2144,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);
-@@ -2153,30 +2151,81 @@ 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);
- 	  }
- 
- 	grub_set_install_backup_ponr ();
- 
-+	free (removable_file);
- 	free (dst);
-       }
-       if (!removable && update_nvram)
diff -pruN 2.06-2/debian/patches/grub-legacy-0-based-partitions.patch 2.06-2ubuntu16/debian/patches/grub-legacy-0-based-partitions.patch
--- 2.06-2/debian/patches/grub-legacy-0-based-partitions.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/grub-legacy-0-based-partitions.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From ae648ba6160a334707f8a8fc0768ec1bc60c4442 Mon Sep 17 00:00:00 2001
 From: Robert Millan <rmh@aybabtu.com>
 Date: Mon, 13 Jan 2014 12:12:53 +0000
 Subject: Support running grub-probe in grub-legacy's update-grub
@@ -13,7 +12,7 @@ Patch-Name: grub-legacy-0-based-partitio
  1 file changed, 14 insertions(+)
 
 diff --git a/util/getroot.c b/util/getroot.c
-index a5eaa64fd..6ae35ecaa 100644
+index a5eaa64..6ae35ec 100644
 --- a/util/getroot.c
 +++ b/util/getroot.c
 @@ -245,6 +245,20 @@ find_partition (grub_disk_t dsk __attribute__ ((unused)),
diff -pruN 2.06-2/debian/patches/ieee1275-clear-reset.patch 2.06-2ubuntu16/debian/patches/ieee1275-clear-reset.patch
--- 2.06-2/debian/patches/ieee1275-clear-reset.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ieee1275-clear-reset.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 791c1034910b5e87ec7ff4166300f0f26b647625 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 +17,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 85ecf06b4..e5ec77107 100644
+index 85ecf06..e5ec771 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 -pruN 2.06-2/debian/patches/ignore-grub_func_test-failures.patch 2.06-2ubuntu16/debian/patches/ignore-grub_func_test-failures.patch
--- 2.06-2/debian/patches/ignore-grub_func_test-failures.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ignore-grub_func_test-failures.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From f8d8c2e9dfd49bd0e59e27c09fc535a547d13c01 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 +13,7 @@ Patch-Name: ignore-grub_func_test-failur
  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 c67f9e4..728cd6e 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 -pruN 2.06-2/debian/patches/insmod-xzio-and-lzopio-on-xen.patch 2.06-2ubuntu16/debian/patches/insmod-xzio-and-lzopio-on-xen.patch
--- 2.06-2/debian/patches/insmod-xzio-and-lzopio-on-xen.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/insmod-xzio-and-lzopio-on-xen.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From bc8ec86089a4f6eb2ea19499a2b335dccdebd577 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
@@ -20,7 +19,7 @@ Patch-Name: insmod-xzio-and-lzopio-on-xe
  1 file changed, 1 insertion(+)
 
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index f88a2de10..635c609d6 100644
+index f88a2de..635c609 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -162,6 +162,7 @@ linux_entry ()
diff -pruN 2.06-2/debian/patches/install-efi-adjust-distributor.patch 2.06-2ubuntu16/debian/patches/install-efi-adjust-distributor.patch
--- 2.06-2/debian/patches/install-efi-adjust-distributor.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/install-efi-adjust-distributor.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 11ea79546da850296fabeb94bfc8c110a98fe7f6 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:27 +0000
 Subject: Adjust efi_distributor for some distributions
@@ -18,7 +17,7 @@ Patch-Name: install-efi-adjust-distribut
  1 file changed, 4 insertions(+)
 
 diff --git a/util/grub-install.c b/util/grub-install.c
-index f49c78d0b..48c8c0364 100644
+index 5ddd028..3a06718 100644
 --- a/util/grub-install.c
 +++ b/util/grub-install.c
 @@ -1123,6 +1123,10 @@ main (int argc, char *argv[])
diff -pruN 2.06-2/debian/patches/install-efi-fallback.patch 2.06-2ubuntu16/debian/patches/install-efi-fallback.patch
--- 2.06-2/debian/patches/install-efi-fallback.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/install-efi-fallback.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 7cf3ac7be59ef377a98ead5c7d3d5cb537c159c4 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
@@ -15,11 +14,11 @@ Last-Update: 2019-05-24
 
 Patch-Name: install-efi-fallback.patch
 ---
- grub-core/osdep/linux/platform.c | 40 ++++++++++++++++++++++++++++----
+ grub-core/osdep/linux/platform.c | 40 +++++++++++++++++++++++++++++++++++-----
  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 e28a79d..2e7f720 100644
 --- a/grub-core/osdep/linux/platform.c
 +++ b/grub-core/osdep/linux/platform.c
 @@ -19,10 +19,12 @@
diff -pruN 2.06-2/debian/patches/install-locale-langpack.patch 2.06-2ubuntu16/debian/patches/install-locale-langpack.patch
--- 2.06-2/debian/patches/install-locale-langpack.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/install-locale-langpack.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 31e9c5eaec14e18251db1fb7e6e44add22e56526 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 +12,7 @@ Patch-Name: install-locale-langpack.patc
  1 file changed, 30 insertions(+), 7 deletions(-)
 
 diff --git a/util/grub-install-common.c b/util/grub-install-common.c
-index 4e212e690..e53730485 100644
+index 4e212e6..e537304 100644
 --- a/util/grub-install-common.c
 +++ b/util/grub-install-common.c
 @@ -774,17 +774,25 @@ get_localedir (void)
diff -pruN 2.06-2/debian/patches/install-powerpc-machtypes.patch 2.06-2ubuntu16/debian/patches/install-powerpc-machtypes.patch
--- 2.06-2/debian/patches/install-powerpc-machtypes.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/install-powerpc-machtypes.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 4b6f846398109576c218394c3d10bcb075c065a7 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
@@ -17,15 +16,15 @@ Last-Update: 2014-10-15
 Patch-Name: install-powerpc-machtypes.patch
 ---
  grub-core/osdep/basic/platform.c   |  5 +++
- grub-core/osdep/linux/platform.c   | 72 ++++++++++++++++++++++++++++++
- grub-core/osdep/unix/platform.c    | 28 +++++++++---
- grub-core/osdep/windows/platform.c |  6 +++
+ grub-core/osdep/linux/platform.c   | 72 ++++++++++++++++++++++++++++++++++++++
+ grub-core/osdep/unix/platform.c    | 28 +++++++++++----
+ grub-core/osdep/windows/platform.c |  6 ++++
  include/grub/util/install.h        |  3 ++
- util/grub-install.c                | 11 +++++
+ util/grub-install.c                | 11 ++++++
  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 a7dafd8..6c293ed 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 +37,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 2e7f720..5b37366 100644
 --- a/grub-core/osdep/linux/platform.c
 +++ b/grub-core/osdep/linux/platform.c
 @@ -24,6 +24,7 @@
@@ -125,7 +124,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 55b8f40..9c43932 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 +164,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 253f8d101..d18488f20 100644
+index 253f8d1..d18488f 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 +181,7 @@ index 253f8d101..d18488f20 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 7df3191f4..135ba48d2 100644
+index 7df3191..135ba48 100644
 --- a/include/grub/util/install.h
 +++ b/include/grub/util/install.h
 @@ -223,6 +223,9 @@ grub_install_get_default_arm_platform (void);
@@ -196,7 +195,7 @@ index 7df3191f4..135ba48d2 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 48c8c0364..d02bd488a 100644
+index 3a06718..4af831f 100644
 --- a/util/grub-install.c
 +++ b/util/grub-install.c
 @@ -1187,7 +1187,18 @@ main (int argc, char *argv[])
diff -pruN 2.06-2/debian/patches/install-signed.patch 2.06-2ubuntu16/debian/patches/install-signed.patch
--- 2.06-2/debian/patches/install-signed.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/install-signed.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,311 +0,0 @@
-From 0bd31f4c7468f0b42ff6673f47112b9167c6381c 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
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Author: Stéphane Graber <stgraber@ubuntu.com>
-Author: Steve Langasek <steve.langasek@ubuntu.com>
-Author: Linn Crosetto <linn@hpe.com>
-Author: Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>
-Forwarded: no
-Last-Update: 2021-09-24
-
-Patch-Name: install-signed.patch
----
- util/grub-install.c | 212 ++++++++++++++++++++++++++++++++------------
- 1 file changed, 153 insertions(+), 59 deletions(-)
-
-diff --git a/util/grub-install.c b/util/grub-install.c
-index 48e2d3779..f49c78d0b 100644
---- a/util/grub-install.c
-+++ b/util/grub-install.c
-@@ -80,6 +80,7 @@ static char *label_color;
- static char *label_bgcolor;
- static char *product_version;
- static int add_rs_codes = 1;
-+static int uefi_secure_boot = 1;
- 
- enum
-   {
-@@ -110,7 +111,9 @@ enum
-     OPTION_LABEL_FONT,
-     OPTION_LABEL_COLOR,
-     OPTION_LABEL_BGCOLOR,
--    OPTION_PRODUCT_VERSION
-+    OPTION_PRODUCT_VERSION,
-+    OPTION_UEFI_SECURE_BOOT,
-+    OPTION_NO_UEFI_SECURE_BOOT
-   };
- 
- static int fs_probe = 1;
-@@ -234,6 +237,14 @@ argp_parser (int key, char *arg, struct argp_state *state)
-       bootloader_id = xstrdup (arg);
-       return 0;
- 
-+    case OPTION_UEFI_SECURE_BOOT:
-+      uefi_secure_boot = 1;
-+      return 0;
-+
-+    case OPTION_NO_UEFI_SECURE_BOOT:
-+      uefi_secure_boot = 0;
-+      return 0;
-+
-     case ARGP_KEY_ARG:
-       if (install_device)
- 	grub_util_error ("%s", _("More than one install device?"));
-@@ -303,6 +314,14 @@ static struct argp_option options[] = {
-   {"label-color", OPTION_LABEL_COLOR, N_("COLOR"), 0, N_("use COLOR for label"), 2},
-   {"label-bgcolor", OPTION_LABEL_BGCOLOR, N_("COLOR"), 0, N_("use COLOR for label background"), 2},
-   {"product-version", OPTION_PRODUCT_VERSION, N_("STRING"), 0, N_("use STRING as product version"), 2},
-+  {"uefi-secure-boot", OPTION_UEFI_SECURE_BOOT, 0, 0,
-+   N_("install an image usable with UEFI Secure Boot. "
-+      "This option is only available on EFI and if the grub-efi-amd64-signed "
-+      "package is installed."), 2},
-+  {"no-uefi-secure-boot", OPTION_NO_UEFI_SECURE_BOOT, 0, 0,
-+   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},
-   {0, 0, 0, 0, 0, 0}
- };
- 
-@@ -833,7 +852,8 @@ main (int argc, char *argv[])
- {
-   int is_efi = 0;
-   const char *efi_distributor = NULL;
--  const char *efi_file = NULL;
-+  const char *efi_suffix = NULL, *efi_suffix_upper = NULL;
-+  char *efi_file = NULL;
-   char **grub_devices;
-   grub_fs_t grub_fs;
-   grub_device_t grub_dev = NULL;
-@@ -1103,6 +1123,39 @@ main (int argc, char *argv[])
-       */
-       char *t;
-       efi_distributor = bootloader_id;
-+      switch (platform)
-+	{
-+	case GRUB_INSTALL_PLATFORM_I386_EFI:
-+	  efi_suffix = "ia32";
-+	  efi_suffix_upper = "IA32";
-+	  break;
-+	case GRUB_INSTALL_PLATFORM_X86_64_EFI:
-+	  efi_suffix = "x64";
-+	  efi_suffix_upper = "X64";
-+	  break;
-+	case GRUB_INSTALL_PLATFORM_IA64_EFI:
-+	  efi_suffix = "ia64";
-+	  efi_suffix_upper = "IA64";
-+	  break;
-+	case GRUB_INSTALL_PLATFORM_ARM_EFI:
-+	  efi_suffix = "arm";
-+	  efi_suffix_upper = "ARM";
-+	  break;
-+	case GRUB_INSTALL_PLATFORM_ARM64_EFI:
-+	  efi_suffix = "aa64";
-+	  efi_suffix_upper = "AA64";
-+	  break;
-+	case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
-+	  efi_suffix = "riscv32";
-+	  efi_suffix_upper = "RISCV32";
-+	  break;
-+	case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
-+	  efi_suffix = "riscv64";
-+	  efi_suffix_upper = "RISCV64";
-+	  break;
-+	default:
-+	  break;
-+	}
-       if (removable)
- 	{
- 	  /* The specification makes stricter requirements of removable
-@@ -1111,66 +1164,16 @@ main (int argc, char *argv[])
- 	     must have a specific file name depending on the architecture.
- 	  */
- 	  efi_distributor = "BOOT";
--	  switch (platform)
--	    {
--	    case GRUB_INSTALL_PLATFORM_I386_EFI:
--	      efi_file = "BOOTIA32.EFI";
--	      break;
--	    case GRUB_INSTALL_PLATFORM_X86_64_EFI:
--	      efi_file = "BOOTX64.EFI";
--	      break;
--	    case GRUB_INSTALL_PLATFORM_IA64_EFI:
--	      efi_file = "BOOTIA64.EFI";
--	      break;
--	    case GRUB_INSTALL_PLATFORM_ARM_EFI:
--	      efi_file = "BOOTARM.EFI";
--	      break;
--	    case GRUB_INSTALL_PLATFORM_ARM64_EFI:
--	      efi_file = "BOOTAA64.EFI";
--	      break;
--	    case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
--	      efi_file = "BOOTRISCV32.EFI";
--	      break;
--	    case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
--	      efi_file = "BOOTRISCV64.EFI";
--	      break;
--	    default:
--	      grub_util_error ("%s", _("You've found a bug"));
--	      break;
--	    }
-+	  if (!efi_suffix)
-+	    grub_util_error ("%s", _("You've found a bug"));
-+	  efi_file = xasprintf ("BOOT%s.EFI", efi_suffix_upper);
- 	}
-       else
- 	{
- 	  /* It is convenient for each architecture to have a different
- 	     efi_file, so that different versions can be installed in parallel.
- 	  */
--	  switch (platform)
--	    {
--	    case GRUB_INSTALL_PLATFORM_I386_EFI:
--	      efi_file = "grubia32.efi";
--	      break;
--	    case GRUB_INSTALL_PLATFORM_X86_64_EFI:
--	      efi_file = "grubx64.efi";
--	      break;
--	    case GRUB_INSTALL_PLATFORM_IA64_EFI:
--	      efi_file = "grubia64.efi";
--	      break;
--	    case GRUB_INSTALL_PLATFORM_ARM_EFI:
--	      efi_file = "grubarm.efi";
--	      break;
--	    case GRUB_INSTALL_PLATFORM_ARM64_EFI:
--	      efi_file = "grubaa64.efi";
--	      break;
--	    case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
--	      efi_file = "grubriscv32.efi";
--	      break;
--	    case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
--	      efi_file = "grubriscv64.efi";
--	      break;
--	    default:
--	      efi_file = "grub.efi";
--	      break;
--	    }
-+	  efi_file = xasprintf ("grub%s.efi", efi_suffix);
- 	}
-       t = grub_util_path_concat (3, efidir, "EFI", efi_distributor);
-       free (efidir);
-@@ -1376,14 +1379,41 @@ main (int argc, char *argv[])
- 	}
-     }
- 
--  if (!have_abstractions)
-+  char *efi_signed = NULL;
-+  switch (platform)
-+    {
-+    case GRUB_INSTALL_PLATFORM_I386_EFI:
-+    case GRUB_INSTALL_PLATFORM_X86_64_EFI:
-+    case GRUB_INSTALL_PLATFORM_ARM_EFI:
-+    case GRUB_INSTALL_PLATFORM_ARM64_EFI:
-+    case GRUB_INSTALL_PLATFORM_IA64_EFI:
-+      {
-+	char *dir = xasprintf ("%s-signed", grub_install_source_directory);
-+	char *signed_image;
-+	if (removable)
-+	  signed_image = xasprintf ("gcd%s.efi.signed", efi_suffix);
-+	else
-+	  signed_image = xasprintf ("grub%s.efi.signed", efi_suffix);
-+	efi_signed = grub_util_path_concat (2, dir, signed_image);
-+	break;
-+      }
-+
-+    default:
-+      break;
-+    }
-+
-+  if (!efi_signed || !grub_util_is_regular (efi_signed))
-+    uefi_secure_boot = 0;
-+
-+  if (!have_abstractions || uefi_secure_boot)
-     {
-       if ((disk_module && grub_strcmp (disk_module, "biosdisk") != 0)
- 	  || grub_drives[1]
- 	  || (!install_drive
- 	      && platform != GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275)
- 	  || (install_drive && !is_same_disk (grub_drives[0], install_drive))
--	  || !have_bootdev (platform))
-+	  || !have_bootdev (platform)
-+	  || uefi_secure_boot)
- 	{
- 	  char *uuid = NULL;
- 	  /*  generic method (used on coreboot and ata mod).  */
-@@ -1941,7 +1971,71 @@ main (int argc, char *argv[])
-     case GRUB_INSTALL_PLATFORM_IA64_EFI:
-       {
- 	char *dst = grub_util_path_concat (2, efidir, efi_file);
--	grub_install_copy_file (imgfile, dst, 1);
-+	if (uefi_secure_boot)
-+	  {
-+	    char *shim_signed = NULL;
-+	    char *mok_signed = NULL, *mok_file = NULL;
-+	    char *fb_signed = NULL, *fb_file = 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);
-+
-+	    if (grub_util_is_regular (shim_signed))
-+	      {
-+		char *chained_base, *chained_dst;
-+		char *mok_src, *mok_dst, *fb_src, *fb_dst;
-+		if (!removable)
-+		  {
-+		    free (efi_file);
-+		    efi_file = xasprintf ("shim%s.efi", efi_suffix);
-+		    free (dst);
-+		    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);
-+
-+		/* 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.  */
-+		mok_src = grub_util_path_concat (2, "/usr/lib/shim/",
-+						    mok_signed);
-+		mok_dst = grub_util_path_concat (2, efidir,
-+						    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);
-+		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);
-+	      }
-+	    else
-+	      grub_install_copy_file (efi_signed, dst, 1);
-+
-+	    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);
-+	  }
-+	else
-+	  grub_install_copy_file (imgfile, dst, 1);
- 
- 	grub_set_install_backup_ponr ();
- 
diff -pruN 2.06-2/debian/patches/install-stage2-confusion.patch 2.06-2ubuntu16/debian/patches/install-stage2-confusion.patch
--- 2.06-2/debian/patches/install-stage2-confusion.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/install-stage2-confusion.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 07ebcd8f769c2522b9a3a79c3d92082747f83781 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 +12,7 @@ Patch-Name: install-stage2-confusion.pat
  1 file changed, 14 insertions(+)
 
 diff --git a/util/grub-install.c b/util/grub-install.c
-index 0fbe7f78c..48e2d3779 100644
+index 0fbe7f7..48e2d37 100644
 --- a/util/grub-install.c
 +++ b/util/grub-install.c
 @@ -42,6 +42,7 @@
diff -pruN 2.06-2/debian/patches/kern-efi-sb-Enforce-verification-of-font-files.patch 2.06-2ubuntu16/debian/patches/kern-efi-sb-Enforce-verification-of-font-files.patch
--- 2.06-2/debian/patches/kern-efi-sb-Enforce-verification-of-font-files.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/kern-efi-sb-Enforce-verification-of-font-files.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,50 @@
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Sun, 14 Aug 2022 15:51:54 +0800
+Subject: kern/efi/sb: Enforce verification of font files
+
+As a mitigation and hardening measure enforce verification of font
+files. Then only trusted font files can be load. This will reduce the
+attack surface at cost of losing the ability of end-users to customize
+fonts if e.g. UEFI Secure Boot is enabled. Vendors can always customize
+fonts because they have ability to pack fonts into their GRUB bundles.
+
+This goal is achieved by:
+
+  * Removing GRUB_FILE_TYPE_FONT from shim lock verifier's
+    skip-verification list.
+
+  * Adding GRUB_FILE_TYPE_FONT to lockdown verifier's defer-auth list,
+    so font files must be verified by a verifier before they can be loaded.
+
+Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/kern/efi/sb.c   | 1 -
+ grub-core/kern/lockdown.c | 1 +
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
+index 89c4bb3..db42c25 100644
+--- a/grub-core/kern/efi/sb.c
++++ b/grub-core/kern/efi/sb.c
+@@ -145,7 +145,6 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
+     case GRUB_FILE_TYPE_PRINT_BLOCKLIST:
+     case GRUB_FILE_TYPE_TESTLOAD:
+     case GRUB_FILE_TYPE_GET_SIZE:
+-    case GRUB_FILE_TYPE_FONT:
+     case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY:
+     case GRUB_FILE_TYPE_CAT:
+     case GRUB_FILE_TYPE_HEXCAT:
+diff --git a/grub-core/kern/lockdown.c b/grub-core/kern/lockdown.c
+index 0bc70fd..af6d493 100644
+--- a/grub-core/kern/lockdown.c
++++ b/grub-core/kern/lockdown.c
+@@ -51,6 +51,7 @@ lockdown_verifier_init (grub_file_t io __attribute__ ((unused)),
+     case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE:
+     case GRUB_FILE_TYPE_ACPI_TABLE:
+     case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE:
++    case GRUB_FILE_TYPE_FONT:
+       *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH;
+ 
+       /* Fall through. */
diff -pruN 2.06-2/debian/patches/linuxefi-do-not-validate-kernels-twice.patch 2.06-2ubuntu16/debian/patches/linuxefi-do-not-validate-kernels-twice.patch
--- 2.06-2/debian/patches/linuxefi-do-not-validate-kernels-twice.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/linuxefi-do-not-validate-kernels-twice.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,227 @@
+From: Dimitri John Ledkov <dimitri.ledkov@canonical.com>
+Date: Thu, 3 Mar 2022 13:10:56 +0100
+Subject: linuxefi: do not validate kernels twice
+
+On codebases that have shim-lock-verifier built into the grub core
+(like 2.06 upstream), shim-lock-verifier is in enforcing mode when
+booted with secureboot. It means that grub_cmd_linux() command
+attempts to perform shim validate upon opening linux kernel image,
+including kernel measurement. And the verifier correctly returns file
+open error when shim validate protocol is not present or shim fails to
+validate the kernel.
+
+This makes the call to grub_linuxefi_secure_validate() redundant, but
+also harmful. As validating the kernel image twice, extends the PCRs
+with the same measurement twice. Which breaks existing sealing
+policies when upgrading from grub2.04+rhboot+sb+linuxefi to
+grub2.06+rhboot+sb+linuxefi builds. It is also incorrect to measure
+the kernel twice.
+
+This patch must not be ported to older editions of grub code bases
+that do not have verifiers framework, or it is not builtin, or
+shim-lock-verifier is an optional module.
+
+This patch is tested to ensure that unsigned kernels are not possible
+to boot in secureboot mode when shim rejects kernel, or shim protocol
+is missing, and that the measurements become stable once again. The
+above also ensures that CVE-2020-15705 is not reintroduced.
+
+This is a backport of https://github.com/rhboot/grub2/pull/97 onto
+Ubuntu packaging.
+
+Signed-off-by: Dimitri John Ledkov <dimitri.ledkov@canonical.com>
+---
+ grub-core/kern/arm/coreboot/coreboot.S |  2 --
+ grub-core/loader/efi/chainloader.c     |  8 ++-----
+ grub-core/loader/efi/linux.c           | 12 ----------
+ grub-core/loader/efi/linux_sb.c        | 41 ----------------------------------
+ grub-core/loader/i386/efi/linux.c      | 13 -----------
+ include/grub/efi/linux.h               |  2 --
+ 6 files changed, 2 insertions(+), 76 deletions(-)
+
+diff --git a/grub-core/kern/arm/coreboot/coreboot.S b/grub-core/kern/arm/coreboot/coreboot.S
+index 70998c0..13e73ac 100644
+--- a/grub-core/kern/arm/coreboot/coreboot.S
++++ b/grub-core/kern/arm/coreboot/coreboot.S
+@@ -42,8 +42,6 @@ FUNCTION(grub_armv7_get_timer_frequency)
+ 	mrc p15, 0, r0, c14, c0, 0
+ 	bx	lr
+ 
+-int
+-EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size);
+ grub_err_t
+ EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
+ 				  void *kernel_param);
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 4a85f41..c6ae2fc 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -910,7 +910,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   grub_efi_device_path_t *dp = 0;
+   char *filename;
+   void *boot_image = 0;
+-  int rc;
+ 
+   if (argc == 0)
+     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+@@ -1080,9 +1079,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+     }
+ #endif
+ 
+-  rc = grub_linuxefi_secure_validate((void *)((grub_addr_t) address), fsize);
+-  grub_dprintf ("chain", "linuxefi_secure_validate: %d\n", rc);
+-  if (rc > 0)
++  if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+     {
+       grub_file_close (file);
+       if (orig_dev)
+@@ -1092,7 +1089,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ 		       grub_secureboot_chainloader_unload, 0);
+       return 0;
+     }
+-  else if (rc == 0)
++  else
+     {
+       grub_load_and_start_image(boot_image);
+       grub_file_close (file);
+@@ -1103,7 +1100,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ 
+       return 0;
+     }
+-  // -1 fall-through to fail
+ 
+ fail:
+   if (orig_dev)
+diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
+index 576d8cb..24abc0c 100644
+--- a/grub-core/loader/efi/linux.c
++++ b/grub-core/loader/efi/linux.c
+@@ -433,7 +433,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   struct linux_arch_kernel_header lh;
+   struct grub_arm64_linux_pe_header *pe;
+   grub_err_t err;
+-  int rc;
+ 
+   grub_dl_ref (my_mod);
+ 
+@@ -478,17 +477,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+   grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
+ 
+-  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+-    {
+-      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;
+-        }
+-    }
+-
+   pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
+   handover_offset = pe->opt.entry_addr;
+ 
+diff --git a/grub-core/loader/efi/linux_sb.c b/grub-core/loader/efi/linux_sb.c
+index a09479c..13bcb02 100644
+--- a/grub-core/loader/efi/linux_sb.c
++++ b/grub-core/loader/efi/linux_sb.c
+@@ -25,47 +25,6 @@
+ #include <grub/efi/linux.h>
+ #include <grub/efi/sb.h>
+ 
+-#define SHIM_LOCK_GUID \
+- { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
+-
+-struct grub_efi_shim_lock
+-{
+-  grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
+-};
+-typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
+-
+-// Returns 1 on success, -1 on error, 0 when not available
+-int
+-grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
+-{
+-  grub_efi_guid_t guid = SHIM_LOCK_GUID;
+-  grub_efi_shim_lock_t *shim_lock;
+-  int status;
+-
+-  grub_dprintf ("linuxefi", "Locating shim protocol\n");
+-  shim_lock = grub_efi_locate_protocol(&guid, NULL);
+-  grub_dprintf ("secureboot", "shim_lock: %p\n", shim_lock);
+-  if (!shim_lock)
+-    {
+-      grub_dprintf ("secureboot", "shim not available\n");
+-      return 0;
+-    }
+-
+-  grub_dprintf ("secureboot", "Asking shim to verify kernel signature\n");
+-  status = shim_lock->verify (data, size);
+-  grub_dprintf ("secureboot", "shim_lock->verify(): %d\n", status);
+-  if (status == GRUB_EFI_SUCCESS)
+-    {
+-      grub_dprintf ("secureboot", "Kernel signature verification passed\n");
+-      return 1;
+-    }
+-
+-  grub_dprintf ("secureboot", "Kernel signature verification failed (0x%lx)\n",
+-		(unsigned long) status);
+-
+-  return -1;
+-}
+-
+ typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
+ 
+ grub_err_t
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 6a90743..cbd313a 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -27,7 +27,6 @@
+ #include <grub/lib/cmdline.h>
+ #include <grub/efi/efi.h>
+ #include <grub/efi/linux.h>
+-#include <grub/efi/sb.h>
+ #include <grub/safemath.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+@@ -170,7 +169,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_ssize_t start, filelen;
+   void *kernel = NULL;
+   int setup_header_end_offset;
+-  int rc;
+ 
+   grub_dl_ref (my_mod);
+ 
+@@ -201,17 +199,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+-    {
+-      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,
+ 					BYTES_TO_PAGES(sizeof(*params)));
+   if (! params)
+diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h
+index 39f5a9a..cedf20c 100644
+--- a/include/grub/efi/linux.h
++++ b/include/grub/efi/linux.h
+@@ -22,8 +22,6 @@
+ #include <grub/err.h>
+ #include <grub/symbol.h>
+ 
+-int
+-EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size);
+ grub_err_t
+ EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
+ 				  void *kernel_param);
diff -pruN 2.06-2/debian/patches/linuxefi-Invalidate-i-cache-before-starting-the-kern.patch 2.06-2ubuntu16/debian/patches/linuxefi-Invalidate-i-cache-before-starting-the-kern.patch
--- 2.06-2/debian/patches/linuxefi-Invalidate-i-cache-before-starting-the-kern.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/linuxefi-Invalidate-i-cache-before-starting-the-kern.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,111 @@
+From: dann frazier <dann.frazier@canonical.com>
+Date: Thu, 25 Aug 2022 17:08:09 -0600
+Subject: [PATCH] linuxefi: Invalidate i-cache before starting the kernel
+
+We need to flush the memory range of the code we are about to execute
+from the instruction cache before we can safely execute it. Not doing
+so appears to be the source of rare synchronous exceptions a user
+is seeing on a Cortex-A72-based platform while executing the Linux EFI
+stub. Notably they seem to correlate with an instruction on a cache
+line boundary.
+
+Signed-off-by: dann frazier <dann.frazier@canonical.com>
+
+Bug-Ubuntu: https://launchpad.net/bugs/1987924
+Forwarded: https://github.com/rhboot/grub2/pull/107
+Last-Updated: 2022-08-27
+---
+ grub-core/kern/arm/coreboot/coreboot.S | 4 ++--
+ grub-core/loader/efi/linux.c           | 3 ++-
+ grub-core/loader/efi/linux_sb.c        | 8 ++++++--
+ grub-core/loader/i386/efi/linux.c      | 1 +
+ include/grub/efi/linux.h               | 4 ++--
+ 5 files changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/grub-core/kern/arm/coreboot/coreboot.S b/grub-core/kern/arm/coreboot/coreboot.S
+index 13e73ac..4cb64b1 100644
+--- a/grub-core/kern/arm/coreboot/coreboot.S
++++ b/grub-core/kern/arm/coreboot/coreboot.S
+@@ -43,6 +43,6 @@ FUNCTION(grub_armv7_get_timer_frequency)
+ 	bx	lr
+ 
+ grub_err_t
+-EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
+-				  void *kernel_param);
++EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_size_t kernel_size,
++				  grub_off_t offset, void *kernel_param);
+ 
+diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
+index 6dd3196..99795c1 100644
+--- a/grub-core/loader/efi/linux.c
++++ b/grub-core/loader/efi/linux.c
+@@ -221,7 +221,8 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr __attribute__((unused)),
+  */
+ #ifndef __riscv
+   if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+-      retval = grub_efi_linux_boot (kernel_addr, handover_offset, kernel_addr);
++      retval = grub_efi_linux_boot (kernel_addr, kernel_size,
++                                    handover_offset, kernel_addr);
+   else
+ #endif
+   retval = grub_efi_run_image (kernel_addr, kernel_size, linux_args);
+diff --git a/grub-core/loader/efi/linux_sb.c b/grub-core/loader/efi/linux_sb.c
+index 13bcb02..7115e34 100644
+--- a/grub-core/loader/efi/linux_sb.c
++++ b/grub-core/loader/efi/linux_sb.c
+@@ -16,6 +16,7 @@
+  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+  */
+ 
++#include <grub/cache.h>
+ #include <grub/err.h>
+ #include <grub/mm.h>
+ #include <grub/types.h>
+@@ -28,8 +29,8 @@
+ typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
+ 
+ grub_err_t
+-grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
+-		     void *kernel_params)
++grub_efi_linux_boot (void *kernel_addr, grub_size_t kernel_size,
++		     grub_off_t handover_offset, void *kernel_params)
+ {
+   grub_efi_loaded_image_t *loaded_image = NULL;
+   handover_func hf;
+@@ -54,6 +55,9 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
+   grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n",
+ 		kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params);
+ 
++  /* Invalidate the instruction cache */
++  grub_arch_sync_caches((void *)kernel_addr, kernel_size);
++
+   hf = (handover_func)((char *)kernel_addr + handover_offset + offset);
+   hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
+ 
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 639e84a..7928a1f 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -55,6 +55,7 @@ grub_linuxefi_boot (void *data)
+   asm volatile ("cli");
+ 
+   return grub_efi_linux_boot ((char *)context->kernel_mem,
++			      context->kernel_size,
+ 			      context->handover_offset,
+ 			      context->params);
+ }
+diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h
+index cedf20c..9b2d81e 100644
+--- a/include/grub/efi/linux.h
++++ b/include/grub/efi/linux.h
+@@ -23,8 +23,8 @@
+ #include <grub/symbol.h>
+ 
+ grub_err_t
+-EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
+-				  void *kernel_param);
++EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_size_t kernel_size,
++				  grub_off_t offset, void *kernel_param);
+ grub_efi_boolean_t
+ EXPORT_FUNC(grub_efi_run_image) (void *data, grub_efi_uint32_t data_size,
+ 				 const char *args);
diff -pruN 2.06-2/debian/patches/linuxefi.patch 2.06-2ubuntu16/debian/patches/linuxefi.patch
--- 2.06-2/debian/patches/linuxefi.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/linuxefi.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,552 +0,0 @@
-From fc550c31c25dcf9eb58ca1e987f3ce2be8ebac28 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: 2021-09-24
-
-Patch-Name: linuxefi.patch
----
- grub-core/Makefile.core.def       |   7 +
- grub-core/kern/efi/mm.c           |  32 +++
- grub-core/loader/i386/efi/linux.c | 383 ++++++++++++++++++++++++++++++
- grub-core/loader/i386/linux.c     |  41 ++++
- include/grub/efi/efi.h            |   3 +
- 5 files changed, 466 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 8022e1c0a..e5b3d27f5 100644
---- a/grub-core/Makefile.core.def
-+++ b/grub-core/Makefile.core.def
-@@ -1874,6 +1874,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 9838fb2f5..f6aef0ef6 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..45b68c05a
---- /dev/null
-+++ b/grub-core/loader/i386/efi/linux.c
-@@ -0,0 +1,383 @@
-+/*
-+ *  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>
-+#include <grub/efi/sb.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_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
-+    {
-+      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_errno = GRUB_ERR_NONE;
-+
-+  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 9f74a96b1..be37a1640 100644
---- a/grub-core/loader/i386/linux.c
-+++ b/grub-core/loader/i386/linux.c
-@@ -78,6 +78,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;
-@@ -659,6 +661,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_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
-+    {
-+      /* 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"));
-@@ -1042,6 +1077,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 83d958f99..08f6ee00a 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 -pruN 2.06-2/debian/patches/linux-ignore-FDT-unless-we-need-to-modify-it.patch 2.06-2ubuntu16/debian/patches/linux-ignore-FDT-unless-we-need-to-modify-it.patch
--- 2.06-2/debian/patches/linux-ignore-FDT-unless-we-need-to-modify-it.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/linux-ignore-FDT-unless-we-need-to-modify-it.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,80 @@
+From: Ard Biesheuvel <ard.biesheuvel@arm.com>
+Date: Thu, 28 Oct 2021 23:31:17 +0300
+Subject: linux: ignore FDT unless we need to modify it
+
+Now that we implemented supported for the LoadFile2 protocol for initrd
+loading, there is no longer a need to pass the initrd parameters via
+the device tree. This means there is no longer a reason to update the
+device tree in the first place, and so we can ignore it entirely.
+
+The only remaining reason to deal with the devicetree is if we are
+using the 'devicetree' command to load one from disk, so tweak the
+logic in grub_fdt_install() to take that into account.
+
+Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
+Origin: https://lists.gnu.org/archive/html/grub-devel/2021-10/msg00216.html
+---
+ grub-core/loader/arm64/linux.c | 22 +++++++++++-----------
+ grub-core/loader/efi/fdt.c     |  7 +++++--
+ 2 files changed, 16 insertions(+), 13 deletions(-)
+
+diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
+index 6b03455..65f1275 100644
+--- a/grub-core/loader/arm64/linux.c
++++ b/grub-core/loader/arm64/linux.c
+@@ -95,21 +95,21 @@ finalize_params_linux (void)
+ 
+   void *fdt;
+ 
+-  fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE);
++  /* Set initrd info */
++  if (initrd_start && initrd_end > initrd_start)
++    {
++      fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE);
+ 
+-  if (!fdt)
+-    goto failure;
++      if (!fdt)
++	goto failure;
+ 
+-  node = grub_fdt_find_subnode (fdt, 0, "chosen");
+-  if (node < 0)
+-    node = grub_fdt_add_subnode (fdt, 0, "chosen");
++      node = grub_fdt_find_subnode (fdt, 0, "chosen");
++      if (node < 0)
++	node = grub_fdt_add_subnode (fdt, 0, "chosen");
+ 
+-  if (node < 1)
+-    goto failure;
++      if (node < 1)
++	goto failure;
+ 
+-  /* Set initrd info */
+-  if (initrd_start && initrd_end > initrd_start)
+-    {
+       grub_dprintf ("linux", "Initrd @ %p-%p\n",
+ 		    (void *) initrd_start, (void *) initrd_end);
+ 
+diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c
+index c86f283..771d455 100644
+--- a/grub-core/loader/efi/fdt.c
++++ b/grub-core/loader/efi/fdt.c
+@@ -89,13 +89,16 @@ grub_fdt_install (void)
+   grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
+   grub_efi_status_t status;
+ 
++  if (!fdt && !loaded_fdt)
++    return GRUB_ERR_NONE;
++
+   b = grub_efi_system_table->boot_services;
+-  status = b->install_configuration_table (&fdt_guid, fdt);
++  status = b->install_configuration_table (&fdt_guid, fdt ?: loaded_fdt);
+   if (status != GRUB_EFI_SUCCESS)
+     return grub_error (GRUB_ERR_IO, "failed to install FDT");
+ 
+   grub_dprintf ("fdt", "Installed/updated FDT configuration table @ %p\n",
+-		fdt);
++		fdt ?: loaded_fdt);
+   return GRUB_ERR_NONE;
+ }
+ 
diff -pruN 2.06-2/debian/patches/linux_xen-Properly-load-multiple-initrd-files.patch 2.06-2ubuntu16/debian/patches/linux_xen-Properly-load-multiple-initrd-files.patch
--- 2.06-2/debian/patches/linux_xen-Properly-load-multiple-initrd-files.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/linux_xen-Properly-load-multiple-initrd-files.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,123 @@
+From: Mauricio Faria de Oliveira <mfo@canonical.com>
+Date: Sat, 6 Aug 2022 20:46:48 -0300
+Subject: templates/linux_xen: Properly load multiple initrd files
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+The linux_xen template can put multiple initrd files in the
+same multiboot[2] module[2] command, which is against specs.
+
+This causes ONLY the _first_ initrd file to be loaded; other
+files just have filenames in a "cmdline" string of the first
+initrd file and are NOT loaded.
+
+Fix this by inserting a module[2] command per initrd file.
+
+Before:
+
+    # touch /boot/xen /boot/microcode.cpio
+    # grub-mkconfig 2>/dev/null | grep -P '^\t(multiboot|module)'
+            multiboot       /boot/xen ...
+            module  /boot/vmlinuz-5.4.0-122-generic ...
+            module  --nounzip   /boot/microcode.cpio /boot/initrd.img-5.4.0-122-generic
+
+After:
+
+    # touch /boot/xen /boot/microcode.cpio
+    # grub-mkconfig 2>/dev/null | grep -P '^\t(multiboot|module)'
+            multiboot      /boot/xen ...
+            module  /boot/vmlinuz-5.4.0-122-generic ...
+            module  --nounzip   /boot/microcode.cpio
+            module  --nounzip   /boot/initrd.img-5.4.0-122-generic
+
+Cause:
+
+The code was copied from the linux template, which is *apparently*
+equivalent.. but its backing command grub_cmd_initrd() *supports*
+multiple files (see grub_initrd_init()), while grub_cmd_module()
+*does not* (see grub_multiboot[2]_add_module()).
+
+See commit e86f6aafb8de ("grub-mkconfig/20_linux_xen: Support multiple early initrd images"):
+    'This is basically a copy of a698240d "grub-mkconfig/10_linux:
+     Support multiple early initrd images" ...'
+
+Specs:
+
+Both multiboot and multiboot2 specifications mention support for
+'multiple boot modules' (struct/tag used for kernel/initrd files):
+
+    "Boot loaders don’t have to support multiple boot modules,
+     but they are strongly encouraged to" [1,2]
+
+However, there is a 1:1 relationship between boot modules and files,
+more or less clearly; note the usage of singular/plural "module(s)".
+(Multiboot2, clearly: "One tag appears per module".)
+
+  Multiboot [1]:
+
+    "the ‘mods’ fields indicate ... what boot modules
+     were loaded ..., and where they can be found.
+     ‘mods_count’ contains the number of modules loaded"
+
+    "The first two fields contain the start and end addresses
+     of the boot module itself."
+
+  Multiboot2 [2]:
+
+    "This tag indicates ... what boot module was loaded ...,
+     and where it can be found."
+
+    "The ‘mod_start’ and ‘mod_end’ contain the start and end
+     physical addresses of the boot module itself."
+
+    "One tag appears per module.
+     This tag type may appear multiple times."
+
+And both clearly mention the 'string' field of a boot module,
+which is to be used by the operating system, not boot loader:
+
+     "The ‘string’ field provides an arbitrary string to be
+      associated with that particular boot module ...
+      its exact use is specific to the operating system."
+
+Links:
+
+[1] https://www.gnu.org/software/grub/manual/multiboot/multiboot.html
+    3.3 Boot information format
+
+[2] https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html
+    3.6.6 Modules
+
+Fixes: e86f6aafb8de ("grub-mkconfig/20_linux_xen: Support multiple early initrd images")
+
+Signed-off-by: Mauricio Faria de Oliveira <mfo@canonical.com>
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1987567
+Origin: backport, https://git.savannah.gnu.org/cgit/grub.git/commit/?id=b4b4acaf4ec7af1a78d122c10baed4e85187e2a5
+[mfo: backport: refresh lower context lines.]
+LP: #1987567
+---
+ util/grub.d/20_linux_xen.in | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
+index a12780e..6f38c5d 100644
+--- a/util/grub.d/20_linux_xen.in
++++ b/util/grub.d/20_linux_xen.in
+@@ -166,12 +166,12 @@ EOF
+     message="$(gettext_printf "Loading initial ramdisk ...")"
+     initrd_path=
+     for i in ${initrd}; do
+-       initrd_path="${initrd_path} ${rel_dirname}/${i}"
+-    done
+-    sed "s/^/$submenu_indentation/" << EOF
++       initrd_path="${rel_dirname}/${i}"
++       sed "s/^/$submenu_indentation/" << EOF
+ 	echo	'$(echo "$message" | grub_quote)'
+ 	${module_loader}	--nounzip   $(echo $initrd_path)
+ EOF
++    done
+   fi
+   if ${xsm} && test -n "${xenpolicy}" ; then
+     message="$(gettext_printf "Loading XSM policy ...")"
diff -pruN 2.06-2/debian/patches/linux_xen-Properly-order-multiple-initrd-files.patch 2.06-2ubuntu16/debian/patches/linux_xen-Properly-order-multiple-initrd-files.patch
--- 2.06-2/debian/patches/linux_xen-Properly-order-multiple-initrd-files.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/linux_xen-Properly-order-multiple-initrd-files.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,79 @@
+From: Mauricio Faria de Oliveira <mfo@canonical.com>
+Date: Sat, 6 Aug 2022 22:07:58 -0300
+Subject: templates/linux_xen: Properly order the multiple initrd files
+
+The linux_xen template orders the "early" initrd file(s) _first_
+(i.e., before the "real" initrd files) and that seems reasonable,
+as microcode updates usually come first.
+
+However, this usually breaks Linux boot with initrd under Xen
+because Xen assumes the real initrd is the first multiboot[2]
+module after the kernel, passing its address over to Linux.
+
+So, if a microcode-only initrd (i.e., without init/userspace)
+is found by grub-mkconfig, it ends up considered as a normal
+initrd by the Linux kernel, which cannot do anything with it
+(as it has no other files) and panic()s unable to mount root
+if it depends on a initrd to do that (e.g., root=UUID=...).
+
+...
+
+Well, since Xen doesn't actually use the provided microcode
+by default / unless the 'ucode=<module number|scan>' option
+is enabled, this isn't used in the general case (and breaks).
+
+Additionally, if an user enables the 'ucode=' option, that
+either specifies which module is to be used for microcode,
+or scans all modules (regardless of being first) for that.
+
+Thus, for Xen:
+- it is *not required* to have microcode first,
+- but it is *required* to have real initrd first
+
+So, fix it by ordering the real initrd before early initrd(s).
+
+...
+
+Corner case specific to Xen implementation details:
+
+It is actually _possible_ to have a microcode initrd first,
+but that requires a non-default option (so can't rely on it),
+and it turns out to be inconsistent with its counterpart
+(really shouldn't rely on it, as it may get confusing; below).
+
+'ucode=1' does manually specify the first module is microcode
+_AND_ clears its bit in the module bitmap. The next module is
+now the 'new first', and gets passed to Linux as initrd. Good.
+
+'ucode=scan' checks all modules for microcode, but does _NOT_
+clear a bit if it finds one (reasonable, as it can find that
+prepended in a "real" initrd anyway, which needs to be used).
+The first module still gets passed to Linux as initrd. Bad.
+
+Fixes: e86f6aafb8de ("grub-mkconfig/20_linux_xen: Support multiple early initrd images")
+
+Signed-off-by: Mauricio Faria de Oliveira <mfo@canonical.com>
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1987567
+Origin: upstream, https://git.savannah.gnu.org/cgit/grub.git/commit/?id=18d8eafdea2322dc80c37e826a75e4d62094fecc
+LP: #1987567
+---
+ util/grub.d/20_linux_xen.in | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
+index 6f38c5d..0629890 100644
+--- a/util/grub.d/20_linux_xen.in
++++ b/util/grub.d/20_linux_xen.in
+@@ -304,7 +304,10 @@ while [ "x${xen_list}" != "x" ] ; do
+ 
+ 	initrd=
+ 	if test -n "${initrd_early}" || test -n "${initrd_real}"; then
+-	    initrd="${initrd_early} ${initrd_real}"
++	    # Xen assumes the real initrd is the first module after the kernel.
++	    # Additional (later) initrds can also be used for microcode update,
++	    # with Xen option 'ucode=<scan|module number> (non-default anyway).
++	    initrd="${initrd_real} ${initrd_early}"
+ 
+ 	    initrd_display=
+ 	    for i in ${initrd}; do
diff -pruN 2.06-2/debian/patches/loader-drop-argv-argument-in-grub_initrd_load.patch 2.06-2ubuntu16/debian/patches/loader-drop-argv-argument-in-grub_initrd_load.patch
--- 2.06-2/debian/patches/loader-drop-argv-argument-in-grub_initrd_load.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/loader-drop-argv-argument-in-grub_initrd_load.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,178 @@
+From: Nikita Ermakov <arei@altlinux.org>
+Date: Thu, 28 Oct 2021 23:31:13 +0300
+Subject: loader: drop argv[] argument in grub_initrd_load()
+
+In the case of an error grub_initrd_load() uses argv[] to print the
+filename that caused the error. It is also possible to obtain the
+filename from the file handles and there is no need to duplicate that
+information in argv[], so let's drop it.
+
+Signed-off-by: Nikita Ermakov <arei@altlinux.org>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+
+Last-Update: 2022-01-03
+Origin: https://lists.gnu.org/archive/html/grub-devel/2021-10/msg00212.html
+---
+ grub-core/loader/arm/linux.c              | 2 +-
+ grub-core/loader/arm64/linux.c            | 2 +-
+ grub-core/loader/i386/linux.c             | 2 +-
+ grub-core/loader/i386/pc/linux.c          | 2 +-
+ grub-core/loader/i386/xen.c               | 3 +--
+ grub-core/loader/ia64/efi/linux.c         | 2 +-
+ grub-core/loader/linux.c                  | 4 ++--
+ grub-core/loader/mips/linux.c             | 2 +-
+ grub-core/loader/powerpc/ieee1275/linux.c | 2 +-
+ grub-core/loader/sparc64/ieee1275/linux.c | 2 +-
+ include/grub/linux.h                      | 2 +-
+ 11 files changed, 12 insertions(+), 13 deletions(-)
+
+diff --git a/grub-core/loader/arm/linux.c b/grub-core/loader/arm/linux.c
+index ed23dc7..1f7ab75 100644
+--- a/grub-core/loader/arm/linux.c
++++ b/grub-core/loader/arm/linux.c
+@@ -422,7 +422,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   grub_dprintf ("loader", "Loading initrd to 0x%08x\n",
+ 		(grub_addr_t) initrd_start);
+ 
+-  if (grub_initrd_load (&initrd_ctx, argv, (void *) initrd_start))
++  if (grub_initrd_load (&initrd_ctx, (void *) initrd_start))
+     goto fail;
+ 
+   initrd_end = initrd_start + size;
+diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
+index ef3e9f9..aed7a20 100644
+--- a/grub-core/loader/arm64/linux.c
++++ b/grub-core/loader/arm64/linux.c
+@@ -266,7 +266,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-  if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
++  if (grub_initrd_load (&initrd_ctx, initrd_mem))
+     goto fail;
+ 
+   initrd_start = (grub_addr_t) initrd_mem;
+diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
+index 9f74a96..f30a158 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -1107,7 +1107,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+     initrd_mem_target = get_physical_target_address (ch);
+   }
+ 
+-  if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
++  if (grub_initrd_load (&initrd_ctx, initrd_mem))
+     goto fail;
+ 
+   grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n",
+diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
+index 2a29952..efeeeb2 100644
+--- a/grub-core/loader/i386/pc/linux.c
++++ b/grub-core/loader/i386/pc/linux.c
+@@ -462,7 +462,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+     initrd_addr = get_physical_target_address (ch);
+   }
+ 
+-  if (grub_initrd_load (&initrd_ctx, argv, initrd_chunk))
++  if (grub_initrd_load (&initrd_ctx, initrd_chunk))
+     goto fail;
+ 
+   lh->ramdisk_image = initrd_addr;
+diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
+index cd24874..3b856e8 100644
+--- a/grub-core/loader/i386/xen.c
++++ b/grub-core/loader/i386/xen.c
+@@ -809,8 +809,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+       if (err)
+ 	goto fail;
+ 
+-      if (grub_initrd_load (&initrd_ctx, argv,
+-			    get_virtual_current_address (ch)))
++      if (grub_initrd_load (&initrd_ctx, get_virtual_current_address (ch)))
+ 	goto fail;
+     }
+ 
+diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c
+index 7987fd1..8873b7a 100644
+--- a/grub-core/loader/ia64/efi/linux.c
++++ b/grub-core/loader/ia64/efi/linux.c
+@@ -563,7 +563,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   grub_dprintf ("linux", "[addr=0x%lx, size=0x%lx]\n",
+ 		(grub_uint64_t) initrd_mem, initrd_size);
+ 
+-  if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
++  if (grub_initrd_load (&initrd_ctx, initrd_mem))
+     goto fail;
+  fail:
+   grub_initrd_close (&initrd_ctx);
+diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
+index 3fe390f..d19df67 100644
+--- a/grub-core/loader/linux.c
++++ b/grub-core/loader/linux.c
+@@ -271,7 +271,7 @@ grub_initrd_close (struct grub_linux_initrd_context *initrd_ctx)
+ 
+ grub_err_t
+ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
+-		  char *argv[], void *target)
++		  void *target)
+ {
+   grub_uint8_t *ptr = target;
+   int i;
+@@ -317,7 +317,7 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
+ 	{
+ 	  if (!grub_errno)
+ 	    grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
+-			argv[i]);
++			initrd_ctx->components[i].file->name);
+ 	  grub_initrd_close (initrd_ctx);
+ 	  return grub_errno;
+ 	}
+diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c
+index e4ed959..9459472 100644
+--- a/grub-core/loader/mips/linux.c
++++ b/grub-core/loader/mips/linux.c
+@@ -452,7 +452,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+     initrd_dest = get_physical_target_address (ch) | 0x80000000;
+   }
+ 
+-  if (grub_initrd_load (&initrd_ctx, argv, initrd_src))
++  if (grub_initrd_load (&initrd_ctx, initrd_src))
+     goto fail;
+ 
+ #ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
+diff --git a/grub-core/loader/powerpc/ieee1275/linux.c b/grub-core/loader/powerpc/ieee1275/linux.c
+index 818b2a8..a51e7a7 100644
+--- a/grub-core/loader/powerpc/ieee1275/linux.c
++++ b/grub-core/loader/powerpc/ieee1275/linux.c
+@@ -363,7 +363,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ 
+   grub_dprintf ("loader", "Loading initrd at 0x%x, size 0x%x\n", addr, size);
+ 
+-  if (grub_initrd_load (&initrd_ctx, argv, (void *) addr))
++  if (grub_initrd_load (&initrd_ctx, (void *) addr))
+     goto fail;
+ 
+   initrd_addr = addr;
+diff --git a/grub-core/loader/sparc64/ieee1275/linux.c b/grub-core/loader/sparc64/ieee1275/linux.c
+index bb47ee0..ac2206f 100644
+--- a/grub-core/loader/sparc64/ieee1275/linux.c
++++ b/grub-core/loader/sparc64/ieee1275/linux.c
+@@ -413,7 +413,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+   grub_dprintf ("loader", "Loading initrd at vaddr 0x%lx, paddr 0x%lx, size 0x%lx\n",
+ 		addr, paddr, size);
+ 
+-  if (grub_initrd_load (&initrd_ctx, argv, (void *) addr))
++  if (grub_initrd_load (&initrd_ctx, (void *) addr))
+     goto fail;
+ 
+   initrd_addr = addr;
+diff --git a/include/grub/linux.h b/include/grub/linux.h
+index 594a3f3..a96ac20 100644
+--- a/include/grub/linux.h
++++ b/include/grub/linux.h
+@@ -21,4 +21,4 @@ grub_initrd_close (struct grub_linux_initrd_context *initrd_ctx);
+ 
+ grub_err_t
+ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
+-		  char *argv[], void *target);
++		  void *target);
diff -pruN 2.06-2/debian/patches/loader-Move-arm64-linux-loader-to-common-code.patch 2.06-2ubuntu16/debian/patches/loader-Move-arm64-linux-loader-to-common-code.patch
--- 2.06-2/debian/patches/loader-Move-arm64-linux-loader-to-common-code.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/loader-Move-arm64-linux-loader-to-common-code.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,1091 @@
+From: Atish Patra <atish.patra@wdc.com>
+Date: Thu, 28 Oct 2021 23:31:18 +0300
+Subject: loader: Move arm64 linux loader to common code
+
+ARM64 linux loader code is written in such a way that it can be reused
+across different architectures without much change. Move it to common
+code so that RISC-V doesn't have to define a separate loader.
+
+Signed-off-by: Atish Patra <atish.patra@wdc.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+Origin: https://lists.gnu.org/archive/html/grub-devel/2021-10/msg00215.html
+---
+ grub-core/Makefile.core.def    |   4 +-
+ grub-core/loader/arm64/linux.c | 508 -----------------------------------------
+ grub-core/loader/efi/linux.c   | 508 +++++++++++++++++++++++++++++++++++++++++
+ include/grub/arm/linux.h       |   2 +-
+ include/grub/arm64/linux.h     |   2 +-
+ 5 files changed, 512 insertions(+), 512 deletions(-)
+ delete mode 100644 grub-core/loader/arm64/linux.c
+ create mode 100644 grub-core/loader/efi/linux.c
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 8022e1c..b36cf66 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -1806,9 +1806,9 @@ module = {
+   sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c;
+   ia64_efi = loader/ia64/efi/linux.c;
+   arm_coreboot = loader/arm/linux.c;
+-  arm_efi = loader/arm64/linux.c;
++  arm_efi = loader/efi/linux.c;
+   arm_uboot = loader/arm/linux.c;
+-  arm64 = loader/arm64/linux.c;
++  arm64 = loader/efi/linux.c;
+   riscv32 = loader/riscv/linux.c;
+   riscv64 = loader/riscv/linux.c;
+   common = loader/linux.c;
+diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
+deleted file mode 100644
+index 65f1275..0000000
+--- a/grub-core/loader/arm64/linux.c
++++ /dev/null
+@@ -1,508 +0,0 @@
+-/*
+- *  GRUB  --  GRand Unified Bootloader
+- *  Copyright (C) 2013  Free Software Foundation, Inc.
+- *
+- *  GRUB is free software: you can redistribute it and/or modify
+- *  it under the terms of the GNU General Public License as published by
+- *  the Free Software Foundation, either version 3 of the License, or
+- *  (at your option) any later version.
+- *
+- *  GRUB is distributed in the hope that it will be useful,
+- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- *  GNU General Public License for more details.
+- *
+- *  You should have received a copy of the GNU General Public License
+- *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+- */
+-
+-#include <grub/charset.h>
+-#include <grub/command.h>
+-#include <grub/err.h>
+-#include <grub/file.h>
+-#include <grub/fdt.h>
+-#include <grub/linux.h>
+-#include <grub/loader.h>
+-#include <grub/mm.h>
+-#include <grub/types.h>
+-#include <grub/cpu/linux.h>
+-#include <grub/efi/efi.h>
+-#include <grub/efi/fdtload.h>
+-#include <grub/efi/memory.h>
+-#include <grub/efi/pe32.h>
+-#include <grub/i18n.h>
+-#include <grub/lib/cmdline.h>
+-#include <grub/verify.h>
+-
+-GRUB_MOD_LICENSE ("GPLv3+");
+-
+-static grub_dl_t my_mod;
+-static int loaded;
+-
+-static void *kernel_addr;
+-static grub_uint64_t kernel_size;
+-
+-static char *linux_args;
+-static grub_uint32_t cmdline_size;
+-
+-static grub_addr_t initrd_start;
+-static grub_addr_t initrd_end;
+-
+-static struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
+-static grub_efi_handle_t initrd_lf2_handle;
+-static int initrd_use_loadfile2;
+-static grub_efi_guid_t load_file2_guid = GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID;
+-static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID;
+-
+-grub_err_t
+-grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
+-{
+-  struct grub_pe32_coff_header *coff_header;
+-  struct grub_pe32_optional_header *optional_header;
+-
+-  if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE)
+-    return grub_error(GRUB_ERR_BAD_OS, "invalid magic number");
+-
+-  if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC)
+-    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+-		       N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
+-
+-  grub_dprintf ("linux", "UEFI stub kernel:\n");
+-  grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset);
+-
+-  coff_header = (struct grub_pe32_coff_header *)((unsigned long)lh + lh->hdr_offset);
+-  optional_header = (struct grub_pe32_optional_header *)(coff_header + 1);
+-
+-  /*
+-   * Linux kernels built for any architecture are guaranteed to support the
+-   * LoadFile2 based initrd loading protocol if the image version is >= 1.
+-   */
+-  if (optional_header->major_image_version >= 1)
+-    initrd_use_loadfile2 = 1;
+-   else
+-    initrd_use_loadfile2 = 0;
+-
+-  grub_dprintf ("linux", "LoadFile2 initrd loading %sabled\n",
+-		initrd_use_loadfile2 ? "en" : "dis");
+-
+-  return GRUB_ERR_NONE;
+-}
+-
+-static grub_err_t
+-finalize_params_linux (void)
+-{
+-  int node, retval;
+-
+-  void *fdt;
+-
+-  /* Set initrd info */
+-  if (initrd_start && initrd_end > initrd_start)
+-    {
+-      fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE);
+-
+-      if (!fdt)
+-	goto failure;
+-
+-      node = grub_fdt_find_subnode (fdt, 0, "chosen");
+-      if (node < 0)
+-	node = grub_fdt_add_subnode (fdt, 0, "chosen");
+-
+-      if (node < 1)
+-	goto failure;
+-
+-      grub_dprintf ("linux", "Initrd @ %p-%p\n",
+-		    (void *) initrd_start, (void *) initrd_end);
+-
+-      retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start",
+-				    initrd_start);
+-      if (retval)
+-	goto failure;
+-      retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end",
+-				    initrd_end);
+-      if (retval)
+-	goto failure;
+-    }
+-
+-  if (grub_fdt_install() != GRUB_ERR_NONE)
+-    goto failure;
+-
+-  return GRUB_ERR_NONE;
+-
+-failure:
+-  grub_fdt_unload();
+-  return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
+-}
+-
+-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;
+-
+-  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");
+-
+-  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);
+-
+-  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));
+-
+-  return grub_errno;
+-}
+-
+-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));
+-}
+-
+-static grub_err_t
+-grub_linux_unload (void)
+-{
+-  grub_dl_unref (my_mod);
+-  loaded = 0;
+-  if (initrd_start)
+-    grub_efi_free_pages ((grub_efi_physical_address_t) initrd_start,
+-			 GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start));
+-  initrd_start = initrd_end = 0;
+-  grub_free (linux_args);
+-  if (kernel_addr)
+-    grub_efi_free_pages ((grub_addr_t) kernel_addr,
+-			 GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+-  grub_fdt_unload ();
+-  return GRUB_ERR_NONE;
+-}
+-
+-/*
+- * As per linux/Documentation/arm/Booting
+- * ARM initrd needs to be covered by kernel linear mapping,
+- * so place it in the first 512MB of DRAM.
+- *
+- * As per linux/Documentation/arm64/booting.txt
+- * ARM64 initrd needs to be contained entirely within a 1GB aligned window
+- * of up to 32GB of size that covers the kernel image as well.
+- * Since the EFI stub loader will attempt to load the kernel near start of
+- * RAM, place the buffer in the first 32GB of RAM.
+- */
+-#ifdef __arm__
+-#define INITRD_MAX_ADDRESS_OFFSET (512U * 1024 * 1024)
+-#else /* __aarch64__ */
+-#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024)
+-#endif
+-
+-/*
+- * This function returns a pointer to a legally allocated initrd buffer,
+- * or NULL if unsuccessful
+- */
+-static void *
+-allocate_initrd_mem (int initrd_pages)
+-{
+-  grub_addr_t max_addr;
+-
+-  if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE)
+-    return NULL;
+-
+-  max_addr += INITRD_MAX_ADDRESS_OFFSET - 1;
+-
+-  return grub_efi_allocate_pages_real (max_addr, initrd_pages,
+-				       GRUB_EFI_ALLOCATE_MAX_ADDRESS,
+-				       GRUB_EFI_LOADER_DATA);
+-}
+-
+-struct initrd_media_device_path {
+-  grub_efi_vendor_media_device_path_t	vendor;
+-  grub_efi_device_path_t		end;
+-} GRUB_PACKED;
+-
+-#define LINUX_EFI_INITRD_MEDIA_GUID  \
+-  { 0x5568e427, 0x68fc, 0x4f3d, \
+-    { 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68 } \
+-  }
+-
+-static struct initrd_media_device_path initrd_lf2_device_path = {
+-  {
+-    {
+-      GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
+-      GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE,
+-      sizeof(grub_efi_vendor_media_device_path_t),
+-    },
+-    LINUX_EFI_INITRD_MEDIA_GUID
+-  }, {
+-    GRUB_EFI_END_DEVICE_PATH_TYPE,
+-    GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
+-    sizeof(grub_efi_device_path_t)
+-  }
+-};
+-
+-static grub_efi_status_t
+-grub_efi_initrd_load_file2(grub_efi_load_file2_t *this,
+-                           grub_efi_device_path_t *device_path,
+-                           grub_efi_boolean_t boot_policy,
+-                           grub_efi_uintn_t *buffer_size,
+-                           void *buffer);
+-
+-static grub_efi_load_file2_t initrd_lf2 = {
+-  grub_efi_initrd_load_file2
+-};
+-
+-static grub_efi_status_t
+-grub_efi_initrd_load_file2(grub_efi_load_file2_t *this,
+-			   grub_efi_device_path_t *device_path,
+-			   grub_efi_boolean_t boot_policy,
+-			   grub_efi_uintn_t *buffer_size,
+-			   void *buffer)
+-{
+-  grub_efi_status_t status = GRUB_EFI_SUCCESS;
+-  grub_efi_uintn_t initrd_size;
+-
+-  if (!this || this != &initrd_lf2 || !buffer_size)
+-    return GRUB_EFI_INVALID_PARAMETER;
+-
+-  if (device_path->type != GRUB_EFI_END_DEVICE_PATH_TYPE ||
+-      device_path->subtype != GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE)
+-    return GRUB_EFI_NOT_FOUND;
+-
+-  if (boot_policy)
+-    return GRUB_EFI_UNSUPPORTED;
+-
+-  initrd_size = grub_get_initrd_size (&initrd_ctx);
+-  if (!buffer || *buffer_size < initrd_size)
+-    {
+-      *buffer_size = initrd_size;
+-      return GRUB_EFI_BUFFER_TOO_SMALL;
+-    }
+-
+-  grub_dprintf ("linux", "Providing initrd via LOAD_FILE2_PROTOCOL\n");
+-
+-  if (grub_initrd_load (&initrd_ctx, buffer))
+-    status = GRUB_EFI_LOAD_ERROR;
+-
+-  grub_initrd_close (&initrd_ctx);
+-  return status;
+-}
+-
+-static grub_err_t
+-grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+-		 int argc, char *argv[])
+-{
+-  int initrd_size, initrd_pages;
+-  void *initrd_mem = NULL;
+-  grub_efi_boot_services_t *b;
+-  grub_efi_status_t status;
+-
+-  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;
+-
+-  if (initrd_use_loadfile2 && !initrd_lf2_handle)
+-    {
+-      b = grub_efi_system_table->boot_services;
+-      status = b->install_multiple_protocol_interfaces (&initrd_lf2_handle,
+-							&load_file2_guid,
+-							&initrd_lf2,
+-							&device_path_guid,
+-							&initrd_lf2_device_path,
+-							NULL);
+-      if (status == GRUB_EFI_OUT_OF_RESOURCES)
+-        {
+-	  grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+-	  return grub_errno;
+-	}
+-      grub_dprintf ("linux", "LoadFile2 initrd loading protocol installed\n");
+-      return GRUB_ERR_NONE;
+-    }
+-
+-  initrd_size = grub_get_initrd_size (&initrd_ctx);
+-  grub_dprintf ("linux", "Loading initrd\n");
+-
+-  initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size));
+-  initrd_mem = allocate_initrd_mem (initrd_pages);
+-
+-  if (!initrd_mem)
+-    {
+-      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+-      goto fail;
+-    }
+-
+-  if (grub_initrd_load (&initrd_ctx, initrd_mem))
+-    goto fail;
+-
+-  initrd_start = (grub_addr_t) initrd_mem;
+-  initrd_end = initrd_start + initrd_size;
+-  grub_dprintf ("linux", "[addr=%p, size=0x%x]\n",
+-		(void *) initrd_start, initrd_size);
+-
+- fail:
+-  grub_initrd_close (&initrd_ctx);
+-  if (initrd_mem && !initrd_start)
+-    grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages);
+-
+-  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_arch_kernel_header lh;
+-  grub_err_t err;
+-
+-  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;
+-
+-  kernel_size = grub_file_size (file);
+-
+-  if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh))
+-    return grub_errno;
+-
+-  if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE)
+-    goto fail;
+-
+-  grub_loader_unset();
+-
+-  grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size);
+-  kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+-  grub_dprintf ("linux", "kernel numpages: %lld\n",
+-		(long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+-  if (!kernel_addr)
+-    {
+-      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+-      goto fail;
+-    }
+-
+-  grub_file_seek (file, 0);
+-  if (grub_file_read (file, kernel_addr, kernel_size)
+-      < (grub_int64_t) kernel_size)
+-    {
+-      if (!grub_errno)
+-	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
+-      goto fail;
+-    }
+-
+-  grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
+-
+-  cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
+-  linux_args = grub_malloc (cmdline_size);
+-  if (!linux_args)
+-    {
+-      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+-      goto fail;
+-    }
+-  grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
+-  err = grub_create_loader_cmdline (argc, argv,
+-				    linux_args + sizeof (LINUX_IMAGE) - 1,
+-				    cmdline_size,
+-				    GRUB_VERIFY_KERNEL_CMDLINE);
+-  if (err)
+-    goto fail;
+-
+-  if (grub_errno == GRUB_ERR_NONE)
+-    {
+-      grub_loader_set (grub_linux_boot, grub_linux_unload, 0);
+-      loaded = 1;
+-    }
+-
+-fail:
+-  if (file)
+-    grub_file_close (file);
+-
+-  if (grub_errno != GRUB_ERR_NONE)
+-    {
+-      grub_dl_unref (my_mod);
+-      loaded = 0;
+-    }
+-
+-  if (linux_args && !loaded)
+-    grub_free (linux_args);
+-
+-  if (kernel_addr && !loaded)
+-    grub_efi_free_pages ((grub_addr_t) kernel_addr,
+-			 GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+-
+-  return grub_errno;
+-}
+-
+-
+-static grub_command_t cmd_linux, cmd_initrd;
+-
+-GRUB_MOD_INIT (linux)
+-{
+-  cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0,
+-				     N_("Load Linux."));
+-  cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0,
+-				      N_("Load initrd."));
+-  my_mod = mod;
+-}
+-
+-GRUB_MOD_FINI (linux)
+-{
+-  grub_unregister_command (cmd_linux);
+-  grub_unregister_command (cmd_initrd);
+-}
+diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
+new file mode 100644
+index 0000000..3292cab
+--- /dev/null
++++ b/grub-core/loader/efi/linux.c
+@@ -0,0 +1,508 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2013  Free Software Foundation, Inc.
++ *
++ *  GRUB is free software: you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation, either version 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <grub/charset.h>
++#include <grub/command.h>
++#include <grub/err.h>
++#include <grub/file.h>
++#include <grub/fdt.h>
++#include <grub/linux.h>
++#include <grub/loader.h>
++#include <grub/mm.h>
++#include <grub/types.h>
++#include <grub/cpu/linux.h>
++#include <grub/efi/efi.h>
++#include <grub/efi/fdtload.h>
++#include <grub/efi/memory.h>
++#include <grub/efi/pe32.h>
++#include <grub/i18n.h>
++#include <grub/lib/cmdline.h>
++#include <grub/verify.h>
++
++GRUB_MOD_LICENSE ("GPLv3+");
++
++static grub_dl_t my_mod;
++static int loaded;
++
++static void *kernel_addr;
++static grub_uint64_t kernel_size;
++
++static char *linux_args;
++static grub_uint32_t cmdline_size;
++
++static grub_addr_t initrd_start;
++static grub_addr_t initrd_end;
++
++static struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
++static grub_efi_handle_t initrd_lf2_handle;
++static int initrd_use_loadfile2;
++static grub_efi_guid_t load_file2_guid = GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID;
++static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID;
++
++grub_err_t
++grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
++{
++  struct grub_pe32_coff_header *coff_header;
++  struct grub_pe32_optional_header *optional_header;
++
++  if (lh->magic != GRUB_LINUX_ARCH_MAGIC_SIGNATURE)
++    return grub_error(GRUB_ERR_BAD_OS, "invalid magic number");
++
++  if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC)
++    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
++		       N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
++
++  grub_dprintf ("linux", "UEFI stub kernel:\n");
++  grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset);
++
++  coff_header = (struct grub_pe32_coff_header *)((unsigned long)lh + lh->hdr_offset);
++  optional_header = (struct grub_pe32_optional_header *)(coff_header + 1);
++
++  /*
++   * Linux kernels built for any architecture are guaranteed to support the
++   * LoadFile2 based initrd loading protocol if the image version is >= 1.
++   */
++  if (optional_header->major_image_version >= 1)
++    initrd_use_loadfile2 = 1;
++   else
++    initrd_use_loadfile2 = 0;
++
++  grub_dprintf ("linux", "LoadFile2 initrd loading %sabled\n",
++		initrd_use_loadfile2 ? "en" : "dis");
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++finalize_params_linux (void)
++{
++  int node, retval;
++
++  void *fdt = NULL;
++
++  /* Set initrd info */
++  if (initrd_start && initrd_end > initrd_start)
++    {
++      fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE);
++
++      if (!fdt)
++	goto failure;
++
++      node = grub_fdt_find_subnode (fdt, 0, "chosen");
++      if (node < 0)
++	node = grub_fdt_add_subnode (fdt, 0, "chosen");
++
++      if (node < 1)
++	goto failure;
++
++      grub_dprintf ("linux", "Initrd @ %p-%p\n",
++		    (void *) initrd_start, (void *) initrd_end);
++
++      retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start",
++				    initrd_start);
++      if (retval)
++	goto failure;
++      retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end",
++				    initrd_end);
++      if (retval)
++	goto failure;
++    }
++
++  if (grub_fdt_install() != GRUB_ERR_NONE)
++    goto failure;
++
++  return GRUB_ERR_NONE;
++
++failure:
++  grub_fdt_unload();
++  return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
++}
++
++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;
++
++  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");
++
++  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);
++
++  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));
++
++  return grub_errno;
++}
++
++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));
++}
++
++static grub_err_t
++grub_linux_unload (void)
++{
++  grub_dl_unref (my_mod);
++  loaded = 0;
++  if (initrd_start)
++    grub_efi_free_pages ((grub_efi_physical_address_t) initrd_start,
++			 GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start));
++  initrd_start = initrd_end = 0;
++  grub_free (linux_args);
++  if (kernel_addr)
++    grub_efi_free_pages ((grub_addr_t) kernel_addr,
++			 GRUB_EFI_BYTES_TO_PAGES (kernel_size));
++  grub_fdt_unload ();
++  return GRUB_ERR_NONE;
++}
++
++/*
++ * As per linux/Documentation/arm/Booting
++ * ARM initrd needs to be covered by kernel linear mapping,
++ * so place it in the first 512MB of DRAM.
++ *
++ * As per linux/Documentation/arm64/booting.txt
++ * ARM64 initrd needs to be contained entirely within a 1GB aligned window
++ * of up to 32GB of size that covers the kernel image as well.
++ * Since the EFI stub loader will attempt to load the kernel near start of
++ * RAM, place the buffer in the first 32GB of RAM.
++ */
++#ifdef __arm__
++#define INITRD_MAX_ADDRESS_OFFSET (512U * 1024 * 1024)
++#else /* __aarch64__ */
++#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024)
++#endif
++
++/*
++ * This function returns a pointer to a legally allocated initrd buffer,
++ * or NULL if unsuccessful
++ */
++static void *
++allocate_initrd_mem (int initrd_pages)
++{
++  grub_addr_t max_addr;
++
++  if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE)
++    return NULL;
++
++  max_addr += INITRD_MAX_ADDRESS_OFFSET - 1;
++
++  return grub_efi_allocate_pages_real (max_addr, initrd_pages,
++				       GRUB_EFI_ALLOCATE_MAX_ADDRESS,
++				       GRUB_EFI_LOADER_DATA);
++}
++
++struct initrd_media_device_path {
++  grub_efi_vendor_media_device_path_t	vendor;
++  grub_efi_device_path_t		end;
++} GRUB_PACKED;
++
++#define LINUX_EFI_INITRD_MEDIA_GUID  \
++  { 0x5568e427, 0x68fc, 0x4f3d, \
++    { 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68 } \
++  }
++
++static struct initrd_media_device_path initrd_lf2_device_path = {
++  {
++    {
++      GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
++      GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE,
++      sizeof(grub_efi_vendor_media_device_path_t),
++    },
++    LINUX_EFI_INITRD_MEDIA_GUID
++  }, {
++    GRUB_EFI_END_DEVICE_PATH_TYPE,
++    GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
++    sizeof(grub_efi_device_path_t)
++  }
++};
++
++static grub_efi_status_t
++grub_efi_initrd_load_file2(grub_efi_load_file2_t *this,
++                           grub_efi_device_path_t *device_path,
++                           grub_efi_boolean_t boot_policy,
++                           grub_efi_uintn_t *buffer_size,
++                           void *buffer);
++
++static grub_efi_load_file2_t initrd_lf2 = {
++  grub_efi_initrd_load_file2
++};
++
++static grub_efi_status_t
++grub_efi_initrd_load_file2(grub_efi_load_file2_t *this,
++			   grub_efi_device_path_t *device_path,
++			   grub_efi_boolean_t boot_policy,
++			   grub_efi_uintn_t *buffer_size,
++			   void *buffer)
++{
++  grub_efi_status_t status = GRUB_EFI_SUCCESS;
++  grub_efi_uintn_t initrd_size;
++
++  if (!this || this != &initrd_lf2 || !buffer_size)
++    return GRUB_EFI_INVALID_PARAMETER;
++
++  if (device_path->type != GRUB_EFI_END_DEVICE_PATH_TYPE ||
++      device_path->subtype != GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE)
++    return GRUB_EFI_NOT_FOUND;
++
++  if (boot_policy)
++    return GRUB_EFI_UNSUPPORTED;
++
++  initrd_size = grub_get_initrd_size (&initrd_ctx);
++  if (!buffer || *buffer_size < initrd_size)
++    {
++      *buffer_size = initrd_size;
++      return GRUB_EFI_BUFFER_TOO_SMALL;
++    }
++
++  grub_dprintf ("linux", "Providing initrd via LOAD_FILE2_PROTOCOL\n");
++
++  if (grub_initrd_load (&initrd_ctx, buffer))
++    status = GRUB_EFI_LOAD_ERROR;
++
++  grub_initrd_close (&initrd_ctx);
++  return status;
++}
++
++static grub_err_t
++grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
++		 int argc, char *argv[])
++{
++  int initrd_size, initrd_pages;
++  void *initrd_mem = NULL;
++  grub_efi_boot_services_t *b;
++  grub_efi_status_t status;
++
++  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;
++
++  if (initrd_use_loadfile2 && !initrd_lf2_handle)
++    {
++      b = grub_efi_system_table->boot_services;
++      status = b->install_multiple_protocol_interfaces (&initrd_lf2_handle,
++							&load_file2_guid,
++							&initrd_lf2,
++							&device_path_guid,
++							&initrd_lf2_device_path,
++							NULL);
++      if (status == GRUB_EFI_OUT_OF_RESOURCES)
++        {
++	  grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++	  return grub_errno;
++	}
++      grub_dprintf ("linux", "LoadFile2 initrd loading protocol installed\n");
++      return GRUB_ERR_NONE;
++    }
++
++  initrd_size = grub_get_initrd_size (&initrd_ctx);
++  grub_dprintf ("linux", "Loading initrd\n");
++
++  initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size));
++  initrd_mem = allocate_initrd_mem (initrd_pages);
++
++  if (!initrd_mem)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++      goto fail;
++    }
++
++  if (grub_initrd_load (&initrd_ctx, initrd_mem))
++    goto fail;
++
++  initrd_start = (grub_addr_t) initrd_mem;
++  initrd_end = initrd_start + initrd_size;
++  grub_dprintf ("linux", "[addr=%p, size=0x%x]\n",
++		(void *) initrd_start, initrd_size);
++
++ fail:
++  grub_initrd_close (&initrd_ctx);
++  if (initrd_mem && !initrd_start)
++    grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages);
++
++  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_arch_kernel_header lh;
++  grub_err_t err;
++
++  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;
++
++  kernel_size = grub_file_size (file);
++
++  if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh))
++    return grub_errno;
++
++  if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE)
++    goto fail;
++
++  grub_loader_unset();
++
++  grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size);
++  kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (kernel_size));
++  grub_dprintf ("linux", "kernel numpages: %lld\n",
++		(long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size));
++  if (!kernel_addr)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++      goto fail;
++    }
++
++  grub_file_seek (file, 0);
++  if (grub_file_read (file, kernel_addr, kernel_size)
++      < (grub_int64_t) kernel_size)
++    {
++      if (!grub_errno)
++	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
++      goto fail;
++    }
++
++  grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
++
++  cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
++  linux_args = grub_malloc (cmdline_size);
++  if (!linux_args)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++      goto fail;
++    }
++  grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
++  err = grub_create_loader_cmdline (argc, argv,
++				    linux_args + sizeof (LINUX_IMAGE) - 1,
++				    cmdline_size,
++				    GRUB_VERIFY_KERNEL_CMDLINE);
++  if (err)
++    goto fail;
++
++  if (grub_errno == GRUB_ERR_NONE)
++    {
++      grub_loader_set (grub_linux_boot, grub_linux_unload, 0);
++      loaded = 1;
++    }
++
++fail:
++  if (file)
++    grub_file_close (file);
++
++  if (grub_errno != GRUB_ERR_NONE)
++    {
++      grub_dl_unref (my_mod);
++      loaded = 0;
++    }
++
++  if (linux_args && !loaded)
++    grub_free (linux_args);
++
++  if (kernel_addr && !loaded)
++    grub_efi_free_pages ((grub_addr_t) kernel_addr,
++			 GRUB_EFI_BYTES_TO_PAGES (kernel_size));
++
++  return grub_errno;
++}
++
++
++static grub_command_t cmd_linux, cmd_initrd;
++
++GRUB_MOD_INIT (linux)
++{
++  cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0,
++				     N_("Load Linux."));
++  cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0,
++				      N_("Load initrd."));
++  my_mod = mod;
++}
++
++GRUB_MOD_FINI (linux)
++{
++  grub_unregister_command (cmd_linux);
++  grub_unregister_command (cmd_initrd);
++}
+diff --git a/include/grub/arm/linux.h b/include/grub/arm/linux.h
+index bcd5a7e..8c13978 100644
+--- a/include/grub/arm/linux.h
++++ b/include/grub/arm/linux.h
+@@ -35,7 +35,7 @@ struct linux_arm_kernel_header {
+ };
+ 
+ #if defined(__arm__)
+-# define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM_MAGIC_SIGNATURE
++# define GRUB_LINUX_ARCH_MAGIC_SIGNATURE GRUB_LINUX_ARM_MAGIC_SIGNATURE
+ # define linux_arch_kernel_header linux_arm_kernel_header
+ #endif
+ 
+diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h
+index 7e22b4a..effd870 100644
+--- a/include/grub/arm64/linux.h
++++ b/include/grub/arm64/linux.h
+@@ -39,7 +39,7 @@ struct linux_arm64_kernel_header
+ };
+ 
+ #if defined(__aarch64__)
+-# define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM64_MAGIC_SIGNATURE
++# define GRUB_LINUX_ARCH_MAGIC_SIGNATURE GRUB_LINUX_ARM64_MAGIC_SIGNATURE
+ # define linux_arch_kernel_header linux_arm64_kernel_header
+ #endif
+ 
diff -pruN 2.06-2/debian/patches/maybe-quiet.patch 2.06-2ubuntu16/debian/patches/maybe-quiet.patch
--- 2.06-2/debian/patches/maybe-quiet.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/maybe-quiet.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 0b33def5d9ace3488fa612e09a5bb813c5e3cd90 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:26 +0000
 Subject: Add configure option to reduce visual clutter at boot time
@@ -46,7 +45,7 @@ Patch-Name: maybe-quiet.patch
  9 files changed, 111 insertions(+), 6 deletions(-)
 
 diff --git a/config.h.in b/config.h.in
-index 9e8f9911b..d2c4ce8e5 100644
+index 9e8f991..d2c4ce8 100644
 --- a/config.h.in
 +++ b/config.h.in
 @@ -12,6 +12,8 @@
@@ -59,10 +58,10 @@ 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 74778a6f8..256fc44ef 100644
+index fb980fd..2869155 100644
 --- a/configure.ac
 +++ b/configure.ac
-@@ -1915,6 +1915,17 @@ else
+@@ -1923,6 +1923,17 @@ else
  fi
  AC_SUBST([UBUNTU_RECOVERY])
  
@@ -80,7 +79,7 @@ index 74778a6f8..256fc44ef 100644
  LIBS=""
  
  AC_SUBST([FONT_SOURCE])
-@@ -2177,5 +2188,10 @@ echo "With stack smashing protector: Yes"
+@@ -2185,5 +2196,10 @@ echo "With stack smashing protector: Yes"
  else
  echo "With stack smashing protector: No"
  fi
@@ -92,7 +91,7 @@ index 74778a6f8..256fc44ef 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 2bd0b2d..b0c0f22 100644
 --- a/grub-core/boot/i386/pc/boot.S
 +++ b/grub-core/boot/i386/pc/boot.S
 @@ -19,6 +19,9 @@
@@ -124,7 +123,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 c1addc0..9b6d7a7 100644
 --- a/grub-core/boot/i386/pc/diskboot.S
 +++ b/grub-core/boot/i386/pc/diskboot.S
 @@ -18,6 +18,9 @@
@@ -204,7 +203,7 @@ index c1addc0df..9b6d7a7ed 100644
  
  notification_step:	.asciz "."
 diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
-index 73967e2f5..2879d644a 100644
+index 73967e2..2879d64 100644
 --- a/grub-core/kern/main.c
 +++ b/grub-core/kern/main.c
 @@ -265,15 +265,25 @@ reclaim_module_space (void)
@@ -247,7 +246,7 @@ index 73967e2f5..2879d644a 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 dcd7d44..a93524e 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 +260,7 @@ index dcd7d4439..a93524eab 100644
    while (1)
      {
 diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
-index c4ebe9e22..a1750e09c 100644
+index c4ebe9e..a1750e0 100644
 --- a/grub-core/normal/main.c
 +++ b/grub-core/normal/main.c
 @@ -407,6 +407,15 @@ static grub_err_t
@@ -291,7 +290,7 @@ index c4ebe9e22..a1750e09c 100644
    while (1)
      {
 diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
-index 8397886fa..e9d8444b5 100644
+index 8397886..e9d8444 100644
 --- a/grub-core/normal/menu.c
 +++ b/grub-core/normal/menu.c
 @@ -807,12 +807,18 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
@@ -338,7 +337,7 @@ index 8397886fa..e9d8444b5 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 1b8c6e146..869a7eec5 100644
+index 1b8c6e1..869a7ee 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -21,6 +21,7 @@ prefix="@prefix@"
diff -pruN 2.06-2/debian/patches/minilzo-2.10.patch 2.06-2ubuntu16/debian/patches/minilzo-2.10.patch
--- 2.06-2/debian/patches/minilzo-2.10.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/minilzo-2.10.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From dbcbb3e5b9fac665b92d630eb24de7bd8c43652e Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@debian.org>
 Date: Sun, 28 Nov 2021 23:42:30 +0000
 Subject: minilzo: Update to minilzo-2.10
@@ -30,14 +29,14 @@ Last-Update: 2021-11-29
 Patch-Name: minilzo-2.10.patch
 ---
  docs/grub-dev.texi              |  10 +-
- grub-core/lib/minilzo/lzoconf.h |  41 ++-
- grub-core/lib/minilzo/lzodefs.h | 416 +++++++++++++++++++-----
- grub-core/lib/minilzo/minilzo.c | 542 +++++++++++++++++++++++++-------
+ grub-core/lib/minilzo/lzoconf.h |  41 +--
+ grub-core/lib/minilzo/lzodefs.h | 416 ++++++++++++++++++++++++------
+ grub-core/lib/minilzo/minilzo.c | 542 +++++++++++++++++++++++++++++++---------
  grub-core/lib/minilzo/minilzo.h |  22 +-
  5 files changed, 817 insertions(+), 214 deletions(-)
 
 diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi
-index 6c629a23e..eb755d998 100644
+index 6c629a2..eb755d9 100644
 --- a/docs/grub-dev.texi
 +++ b/docs/grub-dev.texi
 @@ -575,12 +575,12 @@ To upgrade to a new version of the miniLZO library, download the release
@@ -59,7 +58,7 @@ index 6c629a23e..eb755d998 100644
  
  @node Porting
 diff --git a/grub-core/lib/minilzo/lzoconf.h b/grub-core/lib/minilzo/lzoconf.h
-index 61be29c5d..f9a8bdbee 100644
+index 61be29c..f9a8bdb 100644
 --- a/grub-core/lib/minilzo/lzoconf.h
 +++ b/grub-core/lib/minilzo/lzoconf.h
 @@ -2,7 +2,7 @@
@@ -192,7 +191,7 @@ index 61be29c5d..f9a8bdbee 100644
  #if defined(LZO_CFG_COMPAT)
  
 diff --git a/grub-core/lib/minilzo/lzodefs.h b/grub-core/lib/minilzo/lzodefs.h
-index f4ae9487e..c3e2bcf5d 100644
+index f4ae948..c3e2bcf 100644
 --- a/grub-core/lib/minilzo/lzodefs.h
 +++ b/grub-core/lib/minilzo/lzodefs.h
 @@ -2,7 +2,7 @@
@@ -1177,7 +1176,7 @@ index f4ae9487e..c3e2bcf5d 100644
  LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t))
  #endif
 diff --git a/grub-core/lib/minilzo/minilzo.c b/grub-core/lib/minilzo/minilzo.c
-index ab2be5f4f..8fd866450 100644
+index ab2be5f..8fd8664 100644
 --- a/grub-core/lib/minilzo/minilzo.c
 +++ b/grub-core/lib/minilzo/minilzo.c
 @@ -2,7 +2,7 @@
@@ -2489,7 +2488,7 @@ index ab2be5f4f..8fd866450 100644
  #else
  static void
 diff --git a/grub-core/lib/minilzo/minilzo.h b/grub-core/lib/minilzo/minilzo.h
-index 793745467..c1c229757 100644
+index 7937454..c1c2297 100644
 --- a/grub-core/lib/minilzo/minilzo.h
 +++ b/grub-core/lib/minilzo/minilzo.h
 @@ -2,7 +2,7 @@
diff -pruN 2.06-2/debian/patches/mkconfig-loopback.patch 2.06-2ubuntu16/debian/patches/mkconfig-loopback.patch
--- 2.06-2/debian/patches/mkconfig-loopback.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/mkconfig-loopback.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 3f0c88e2ffa15cfb34641397cc9bdbe39085f1ba 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 +20,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 17f9b3e58..e62cfc22b 100644
+index 17f9b3e..e62cfc2 100644
 --- a/util/grub-mkconfig_lib.in
 +++ b/util/grub-mkconfig_lib.in
 @@ -133,6 +133,22 @@ prepare_grub_to_access_device ()
@@ -63,7 +62,7 @@ index 17f9b3e58..e62cfc22b 100644
  
  grub_get_device_id ()
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index 9446d6833..46696dd66 100644
+index 9446d68..46696dd 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -40,6 +40,11 @@ fi
@@ -79,7 +78,7 @@ index 9446d6833..46696dd66 100644
  esac
  
 diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
-index 3b1f47049..7620a14fa 100644
+index 3b1f470..7620a14 100644
 --- a/util/grub.d/20_linux_xen.in
 +++ b/util/grub.d/20_linux_xen.in
 @@ -40,6 +40,11 @@ fi
diff -pruN 2.06-2/debian/patches/mkconfig-nonexistent-loopback.patch 2.06-2ubuntu16/debian/patches/mkconfig-nonexistent-loopback.patch
--- 2.06-2/debian/patches/mkconfig-nonexistent-loopback.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/mkconfig-nonexistent-loopback.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 989f83d664999deeb28d03a847e8f00a28639d7d 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 +13,7 @@ Patch-Name: mkconfig-nonexistent-loopbac
  2 files changed, 6 insertions(+), 5 deletions(-)
 
 diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
-index e62cfc22b..b6a1d7dec 100644
+index e62cfc2..b6a1d7d 100644
 --- a/util/grub-mkconfig_lib.in
 +++ b/util/grub-mkconfig_lib.in
 @@ -143,7 +143,7 @@ prepare_grub_to_access_device ()
@@ -27,7 +26,7 @@ index e62cfc22b..b6a1d7dec 100644
        esac
      ;;
 diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
-index 37d5f05b5..e2ec80eb9 100644
+index 37d5f05..e2ec80e 100644
 --- a/util/grub.d/30_os-prober.in
 +++ b/util/grub.d/30_os-prober.in
 @@ -222,6 +222,11 @@ EOF
diff -pruN 2.06-2/debian/patches/mkconfig-other-inits.patch 2.06-2ubuntu16/debian/patches/mkconfig-other-inits.patch
--- 2.06-2/debian/patches/mkconfig-other-inits.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/mkconfig-other-inits.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From f8382052a32839fbc3715d1c5076f1b6bbcbcb63 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 +17,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 635c609d6..4e09797f8 100644
+index 635c609..4e09797 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -32,6 +32,7 @@ export TEXTDOMAIN=@PACKAGE@
@@ -53,7 +52,7 @@ index 635c609d6..4e09797f8 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 64e26e4b4..d99751a94 100644
+index 64e26e4..d99751a 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 -pruN 2.06-2/debian/patches/mkconfig-recovery-title.patch 2.06-2ubuntu16/debian/patches/mkconfig-recovery-title.patch
--- 2.06-2/debian/patches/mkconfig-recovery-title.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/mkconfig-recovery-title.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From fd81fffa2d498d66dce65b50da2532690c806ea4 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
@@ -21,7 +20,7 @@ Patch-Name: mkconfig-recovery-title.patc
  7 files changed, 17 insertions(+), 7 deletions(-)
 
 diff --git a/docs/grub.texi b/docs/grub.texi
-index 0b58dafb2..86e46f33b 100644
+index 0b58daf..86e46f3 100644
 --- a/docs/grub.texi
 +++ b/docs/grub.texi
 @@ -1577,6 +1577,11 @@ a console is restricted or limited.
@@ -37,7 +36,7 @@ index 0b58dafb2..86e46f33b 100644
  
  The following options are still accepted for compatibility with existing
 diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
-index fa9c53a92..0d39c8f05 100644
+index fa9c53a..0d39c8f 100644
 --- a/util/grub-mkconfig.in
 +++ b/util/grub-mkconfig.in
 @@ -201,6 +201,10 @@ GRUB_ACTUAL_DEFAULT="$GRUB_DEFAULT"
@@ -62,7 +61,7 @@ index fa9c53a92..0d39c8f05 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 3663d360e..8f6041894 100644
+index 3663d36..8f60418 100644
 --- a/util/grub.d/10_hurd.in
 +++ b/util/grub.d/10_hurd.in
 @@ -88,8 +88,8 @@ hurd_entry () {
@@ -77,7 +76,7 @@ index 3663d360e..8f6041894 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 199b20e16..bbd63cf74 100644
+index 199b20e..bbd63cf 100644
 --- a/util/grub.d/10_kfreebsd.in
 +++ b/util/grub.d/10_kfreebsd.in
 @@ -76,7 +76,7 @@ kfreebsd_entry ()
@@ -90,7 +89,7 @@ index 199b20e16..bbd63cf74 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 64204c216..f88a2de10 100644
+index 64204c2..f88a2de 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -126,7 +126,7 @@ linux_entry ()
@@ -103,7 +102,7 @@ index 64204c216..f88a2de10 100644
  	      title="$(gettext_printf "%s, with Linux %s" "${os}" "${version}")" ;;
        esac
 diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in
-index dc0cd1b17..336895012 100644
+index dc0cd1b..3368950 100644
 --- a/util/grub.d/10_netbsd.in
 +++ b/util/grub.d/10_netbsd.in
 @@ -102,7 +102,7 @@ netbsd_entry ()
@@ -116,7 +115,7 @@ index dc0cd1b17..336895012 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 7620a14fa..64e26e4b4 100644
+index 7620a14..64e26e4 100644
 --- a/util/grub.d/20_linux_xen.in
 +++ b/util/grub.d/20_linux_xen.in
 @@ -122,7 +122,7 @@ linux_entry_xsm ()
diff -pruN 2.06-2/debian/patches/mkconfig-signed-kernel.patch 2.06-2ubuntu16/debian/patches/mkconfig-signed-kernel.patch
--- 2.06-2/debian/patches/mkconfig-signed-kernel.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/mkconfig-signed-kernel.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 9eefe03f4b52e65cb4f372e0ff12a2b68cada425 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:21 +0000
 Subject: Generate configuration for signed UEFI kernels if available
@@ -12,7 +11,7 @@ Patch-Name: mkconfig-signed-kernel.patch
  1 file changed, 15 insertions(+)
 
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index 1603a75a7..1b8c6e146 100644
+index 1603a75..1b8c6e1 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -161,8 +161,16 @@ linux_entry ()
diff -pruN 2.06-2/debian/patches/mkconfig-ubuntu-distributor.patch 2.06-2ubuntu16/debian/patches/mkconfig-ubuntu-distributor.patch
--- 2.06-2/debian/patches/mkconfig-ubuntu-distributor.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/mkconfig-ubuntu-distributor.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 84938bc37ee1cfabf84915ad4b6c8904b4770ef6 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
@@ -16,7 +15,7 @@ Patch-Name: mkconfig-ubuntu-distributor.
  1 file changed, 8 insertions(+), 1 deletion(-)
 
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index f215e3213..1603a75a7 100644
+index f215e32..1603a75 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"
diff -pruN 2.06-2/debian/patches/mkconfig-ubuntu-recovery.patch 2.06-2ubuntu16/debian/patches/mkconfig-ubuntu-recovery.patch
--- 2.06-2/debian/patches/mkconfig-ubuntu-recovery.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/mkconfig-ubuntu-recovery.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,9 +1,8 @@
-From 13c9a7101d2611bbc02b464ef4e32b02cfc7860b Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@ubuntu.com>
 Date: Mon, 13 Jan 2014 12:13:06 +0000
 Subject: "single" -> "recovery" when friendly-recovery is installed
 MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
+Content-Type: text/plain; charset="utf-8"
 Content-Transfer-Encoding: 8bit
 
 If configured with --enable-ubuntu-recovery, also set nomodeset for
@@ -23,10 +22,10 @@ Patch-Name: mkconfig-ubuntu-recovery.pat
  3 files changed, 26 insertions(+), 3 deletions(-)
 
 diff --git a/configure.ac b/configure.ac
-index 7517fc49d..74778a6f8 100644
+index e3d4d72..fb980fd 100644
 --- a/configure.ac
 +++ b/configure.ac
-@@ -1904,6 +1904,17 @@ fi
+@@ -1912,6 +1912,17 @@ fi
  AC_SUBST([LIBZFS])
  AC_SUBST([LIBNVPAIR])
  
@@ -45,7 +44,7 @@ index 7517fc49d..74778a6f8 100644
  
  AC_SUBST([FONT_SOURCE])
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index 46696dd66..f215e3213 100644
+index 46696dd..f215e32 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -20,6 +20,7 @@ set -e
@@ -93,7 +92,7 @@ index 46696dd66..f215e3213 100644
  
    list=`echo $list | tr ' ' '\n' | fgrep -vx "$linux" | tr '\n' ' '`
 diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
-index 5984e92d2..37d5f05b5 100644
+index 5984e92..37d5f05 100644
 --- a/util/grub.d/30_os-prober.in
 +++ b/util/grub.d/30_os-prober.in
 @@ -223,7 +223,7 @@ EOF
diff -pruN 2.06-2/debian/patches/mkimage-fix-section-sizes.patch 2.06-2ubuntu16/debian/patches/mkimage-fix-section-sizes.patch
--- 2.06-2/debian/patches/mkimage-fix-section-sizes.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/mkimage-fix-section-sizes.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From e5be30174c7ed596ca2fd28d636a4fbc26a0199a Mon Sep 17 00:00:00 2001
 From: Javier Martinez Canillas <javierm@redhat.com>
 Date: Fri, 16 Apr 2021 21:37:23 +0200
 Subject: util/mkimage: Some fixes to PE binaries section size calculation
@@ -30,7 +29,7 @@ Patch-Name: mkimage-fix-section-sizes.pa
  1 file changed, 12 insertions(+), 9 deletions(-)
 
 diff --git a/util/mkimage.c b/util/mkimage.c
-index a26cf76f7..b84311f1f 100644
+index a26cf76..b84311f 100644
 --- a/util/mkimage.c
 +++ b/util/mkimage.c
 @@ -841,7 +841,7 @@ init_pe_section(const struct grub_install_image_target_desc *image_target,
diff -pruN 2.06-2/debian/patches/mkrescue-efi-modules.patch 2.06-2ubuntu16/debian/patches/mkrescue-efi-modules.patch
--- 2.06-2/debian/patches/mkrescue-efi-modules.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/mkrescue-efi-modules.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 41f0edb8bebe40b7d9302418100034dead84dfe9 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 +13,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 fb4dcc6d5..fcb35726c 100644
+index fb4dcc6..fcb3572 100644
 --- a/util/grub-mkrescue.c
 +++ b/util/grub-mkrescue.c
 @@ -753,6 +753,7 @@ main (int argc, char *argv[])
diff -pruN 2.06-2/debian/patches/net-read-bracketed-ipv6-addr.patch 2.06-2ubuntu16/debian/patches/net-read-bracketed-ipv6-addr.patch
--- 2.06-2/debian/patches/net-read-bracketed-ipv6-addr.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/net-read-bracketed-ipv6-addr.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From c7e2338904e5e1e2546f1097cad1a020615463cf 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
@@ -11,14 +10,14 @@ Last-Update: 2021-09-24
 
 Patch-Name: net-read-bracketed-ipv6-addr.patch
 ---
- grub-core/net/http.c | 21 ++++++++--
- grub-core/net/net.c  | 93 +++++++++++++++++++++++++++++++++++++++++---
- grub-core/net/tftp.c |  6 ++-
+ grub-core/net/http.c | 21 +++++++++---
+ grub-core/net/net.c  | 93 ++++++++++++++++++++++++++++++++++++++++++++++++----
+ grub-core/net/tftp.c |  6 +++-
  include/grub/net.h   |  1 +
  4 files changed, 110 insertions(+), 11 deletions(-)
 
 diff --git a/grub-core/net/http.c b/grub-core/net/http.c
-index b616cf40b..3fe155f1b 100644
+index b616cf4..3fe155f 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)
@@ -76,7 +75,7 @@ index b616cf40b..3fe155f1b 100644
  				  file);
    if (!data->sock)
 diff --git a/grub-core/net/net.c b/grub-core/net/net.c
-index 4d3eb5c1a..15a2f29a9 100644
+index 4d3eb5c..15a2f29 100644
 --- a/grub-core/net/net.c
 +++ b/grub-core/net/net.c
 @@ -442,6 +442,12 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
@@ -213,7 +212,7 @@ index 4d3eb5c1a..15a2f29a9 100644
  	  }
        }
 diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
-index 7f44b30f5..f3e787938 100644
+index 7f44b30..f3e7879 100644
 --- a/grub-core/net/tftp.c
 +++ b/grub-core/net/tftp.c
 @@ -295,6 +295,7 @@ tftp_open (struct grub_file *file, const char *filename)
@@ -242,7 +241,7 @@ index 7f44b30f5..f3e787938 100644
    if (!data->sock)
      {
 diff --git a/include/grub/net.h b/include/grub/net.h
-index 7ae4b6bd8..69bfe0947 100644
+index 7ae4b6b..69bfe09 100644
 --- a/include/grub/net.h
 +++ b/include/grub/net.h
 @@ -270,6 +270,7 @@ typedef struct grub_net
diff -pruN 2.06-2/debian/patches/no-devicetree-if-secure-boot.patch 2.06-2ubuntu16/debian/patches/no-devicetree-if-secure-boot.patch
--- 2.06-2/debian/patches/no-devicetree-if-secure-boot.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/no-devicetree-if-secure-boot.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,66 @@
+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.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Signed-off-by: Steve McIntyre <93sam@debian.org>
+
+Origin: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=927888#15
+Bug-Debian: https://bugs.debian.org/927888
+Last-Update: 2019-05-04
+
+Patch-Name: no-devicetree-if-secure-boot.patch
+---
+ grub-core/loader/arm/linux.c | 12 ++++++++++++
+ grub-core/loader/efi/fdt.c   |  8 ++++++++
+ 2 files changed, 20 insertions(+)
+
+diff --git a/grub-core/loader/arm/linux.c b/grub-core/loader/arm/linux.c
+index 1f7ab75..feb707b 100644
+--- a/grub-core/loader/arm/linux.c
++++ b/grub-core/loader/arm/linux.c
+@@ -30,6 +30,10 @@
+ #include <grub/linux.h>
+ #include <grub/verify.h>
+ 
++#ifdef GRUB_MACHINE_EFI
++#include <grub/efi/efi.h>
++#endif
++
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+ static grub_dl_t my_mod;
+@@ -471,6 +475,14 @@ grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
+   if (argc != 1)
+     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+ 
++#ifdef GRUB_MACHINE_EFI
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    {
++      return grub_error (GRUB_ERR_ACCESS_DENIED,
++		  "Secure Boot forbids loading devicetree from %s", argv[0]);
++    }
++#endif
++
+   dtb = grub_file_open (argv[0], GRUB_FILE_TYPE_DEVICE_TREE_IMAGE);
+   if (!dtb)
+     return grub_errno;
+diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c
+index 971e84d..b846bf3 100644
+--- a/grub-core/loader/efi/fdt.c
++++ b/grub-core/loader/efi/fdt.c
+@@ -131,6 +131,14 @@ grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
+       return GRUB_ERR_NONE;
+     }
+ 
++#ifdef GRUB_MACHINE_EFI
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    {
++      return grub_error (GRUB_ERR_ACCESS_DENIED,
++		  "Secure Boot forbids loading devicetree from %s", argv[0]);
++    }
++#endif
++
+   dtb = grub_file_open (argv[0], GRUB_FILE_TYPE_DEVICE_TREE_IMAGE);
+   if (!dtb)
+     goto out;
diff -pruN 2.06-2/debian/patches/no-insmod-on-sb.patch 2.06-2ubuntu16/debian/patches/no-insmod-on-sb.patch
--- 2.06-2/debian/patches/no-insmod-on-sb.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/no-insmod-on-sb.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,45 @@
+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
+
+Author: Colin Watson <cjwatson@ubuntu.com>
+Origin: vendor, http://pkgs.fedoraproject.org/cgit/grub2.git/tree/grub-2.00-no-insmod-on-sb.patch
+Forwarded: no
+Last-Update: 2013-12-25
+
+Patch-Name: no-insmod-on-sb.patch
+---
+ grub-core/kern/dl.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
+index 48f8a79..51a800a 100644
+--- a/grub-core/kern/dl.c
++++ b/grub-core/kern/dl.c
+@@ -38,6 +38,10 @@
+ #define GRUB_MODULES_MACHINE_READONLY
+ #endif
+ 
++#ifdef GRUB_MACHINE_EFI
++#include <grub/efi/efi.h>
++#endif
++
+ 
+ 
+ #pragma GCC diagnostic ignored "-Wcast-align"
+@@ -695,6 +699,15 @@ grub_dl_load_file (const char *filename)
+   void *core = 0;
+   grub_dl_t mod = 0;
+ 
++#ifdef GRUB_MACHINE_EFI
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    {
++      grub_error (GRUB_ERR_ACCESS_DENIED,
++		  "Secure Boot forbids loading module from %s", filename);
++      return 0;
++    }
++#endif
++
+   grub_boot_time ("Loading module %s", filename);
+ 
+   file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE);
diff -pruN 2.06-2/debian/patches/normal-charset-Fix-an-integer-overflow-in-grub_unicode_ag.patch 2.06-2ubuntu16/debian/patches/normal-charset-Fix-an-integer-overflow-in-grub_unicode_ag.patch
--- 2.06-2/debian/patches/normal-charset-Fix-an-integer-overflow-in-grub_unicode_ag.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/normal-charset-Fix-an-integer-overflow-in-grub_unicode_ag.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,51 @@
+From: Zhang Boyang <zhangboyang.id@gmail.com>
+Date: Fri, 28 Oct 2022 21:31:39 +0800
+Subject: normal/charset: Fix an integer overflow in
+ grub_unicode_aglomerate_comb()
+
+The out->ncomb is a bit-field of 8 bits. So, the max possible value is 255.
+However, code in grub_unicode_aglomerate_comb() doesn't check for an
+overflow when incrementing out->ncomb. If out->ncomb is already 255,
+after incrementing it will get 0 instead of 256, and cause illegal
+memory access in subsequent processing.
+
+This patch introduces GRUB_UNICODE_NCOMB_MAX to represent the max
+acceptable value of ncomb. The code now checks for this limit and
+ignores additional combining characters when limit is reached.
+
+Reported-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/normal/charset.c | 3 +++
+ include/grub/unicode.h     | 2 ++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c
+index 7a5a7c1..c243ca6 100644
+--- a/grub-core/normal/charset.c
++++ b/grub-core/normal/charset.c
+@@ -472,6 +472,9 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen,
+ 	  if (!haveout)
+ 	    continue;
+ 
++	  if (out->ncomb == GRUB_UNICODE_NCOMB_MAX)
++	    continue;
++
+ 	  if (comb_type == GRUB_UNICODE_COMB_MC
+ 	      || comb_type == GRUB_UNICODE_COMB_ME
+ 	      || comb_type == GRUB_UNICODE_COMB_MN)
+diff --git a/include/grub/unicode.h b/include/grub/unicode.h
+index 4de986a..c4f6fca 100644
+--- a/include/grub/unicode.h
++++ b/include/grub/unicode.h
+@@ -147,7 +147,9 @@ struct grub_unicode_glyph
+   grub_uint8_t bidi_level:6; /* minimum: 6 */
+   enum grub_bidi_type bidi_type:5; /* minimum: :5 */
+ 
++#define GRUB_UNICODE_NCOMB_MAX ((1 << 8) - 1)
+   unsigned ncomb:8;
++
+   /* Hint by unicode subsystem how wide this character usually is.
+      Real width is determined by font. Set only in UTF-8 stream.  */
+   int estimated_width:8;
diff -pruN 2.06-2/debian/patches/olpc-prefix-hack.patch 2.06-2ubuntu16/debian/patches/olpc-prefix-hack.patch
--- 2.06-2/debian/patches/olpc-prefix-hack.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/olpc-prefix-hack.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 39e079ec50c46fa2fc2f43a1a2e01172ef7dd7c6 Mon Sep 17 00:00:00 2001
 From: Colin Watson <cjwatson@debian.org>
 Date: Mon, 13 Jan 2014 12:12:50 +0000
 Subject: Hack prefix for OLPC
@@ -11,7 +10,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 d483e35..8b089b4 100644
 --- a/grub-core/kern/ieee1275/init.c
 +++ b/grub-core/kern/ieee1275/init.c
 @@ -76,6 +76,7 @@ grub_exit (void)
diff -pruN 2.06-2/debian/patches/pc-verifiers-module.patch 2.06-2ubuntu16/debian/patches/pc-verifiers-module.patch
--- 2.06-2/debian/patches/pc-verifiers-module.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/pc-verifiers-module.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 4a6abe501f39c4c8afe4ed7405ff99aff8559a13 Mon Sep 17 00:00:00 2001
 From: Michael Chang <mchang@suse.com>
 Date: Thu, 18 Mar 2021 19:30:26 +0800
 Subject: i386-pc: build verifiers API as module
@@ -39,7 +38,7 @@ Patch-Name: pc-verifiers-module.patch
  5 files changed, 39 insertions(+), 1 deletion(-)
 
 diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
-index ee88e44e9..b6872d20f 100644
+index ee88e44..b6872d2 100644
 --- a/grub-core/Makefile.am
 +++ b/grub-core/Makefile.am
 @@ -93,7 +93,9 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
@@ -53,7 +52,7 @@ index ee88e44e9..b6872d20f 100644
  KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
  KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
 diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
-index 2ff266806..da3269899 100644
+index 0d7bce1..f252725 100644
 --- a/grub-core/Makefile.core.def
 +++ b/grub-core/Makefile.core.def
 @@ -141,7 +141,7 @@ kernel = {
@@ -79,7 +78,7 @@ index 2ff266806..da3269899 100644
    name = hdparm;
    common = commands/hdparm.c;
 diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
-index 2879d644a..c6fb66853 100644
+index 2879d64..c6fb668 100644
 --- a/grub-core/kern/main.c
 +++ b/grub-core/kern/main.c
 @@ -29,7 +29,9 @@
@@ -104,7 +103,7 @@ index 2879d644a..c6fb66853 100644
    grub_load_config ();
  
 diff --git a/grub-core/kern/verifiers.c b/grub-core/kern/verifiers.c
-index 75d7994cf..1245d0d9e 100644
+index 75d7994..1245d0d 100644
 --- a/grub-core/kern/verifiers.c
 +++ b/grub-core/kern/verifiers.c
 @@ -221,8 +221,25 @@ grub_verify_string (char *str, enum grub_verify_string_type type)
@@ -134,7 +133,7 @@ index 75d7994cf..1245d0d9e 100644
 +}
 +#endif
 diff --git a/include/grub/verify.h b/include/grub/verify.h
-index cd129c398..6fde244fc 100644
+index cd129c3..6fde244 100644
 --- a/include/grub/verify.h
 +++ b/include/grub/verify.h
 @@ -64,10 +64,14 @@ struct grub_file_verifier
diff -pruN 2.06-2/debian/patches/ppc64el-disable-vsx.patch 2.06-2ubuntu16/debian/patches/ppc64el-disable-vsx.patch
--- 2.06-2/debian/patches/ppc64el-disable-vsx.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ppc64el-disable-vsx.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From c1c72eb757d40208128fb1da02199b0210a206ab 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 +20,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 21c884b..de9a960 100644
 --- a/grub-core/kern/powerpc/ieee1275/startup.S
 +++ b/grub-core/kern/powerpc/ieee1275/startup.S
 @@ -20,6 +20,8 @@
diff -pruN 2.06-2/debian/patches/probe-fusionio.patch 2.06-2ubuntu16/debian/patches/probe-fusionio.patch
--- 2.06-2/debian/patches/probe-fusionio.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/probe-fusionio.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 611974f8c3231d87ca572feda72eb6d1a5a6b309 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 +13,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 001b818fe..c506f4cb5 100644
+index 001b818..c506f4c 100644
 --- a/grub-core/osdep/linux/getroot.c
 +++ b/grub-core/osdep/linux/getroot.c
 @@ -963,6 +963,19 @@ grub_util_part_to_disk (const char *os_dev, struct stat *st,
@@ -38,7 +37,7 @@ index 001b818fe..c506f4cb5 100644
  
    return path;
 diff --git a/util/deviceiter.c b/util/deviceiter.c
-index b5b9ac6ab..3a8f2770e 100644
+index b5b9ac6..3a8f277 100644
 --- a/util/deviceiter.c
 +++ b/util/deviceiter.c
 @@ -384,6 +384,12 @@ get_nvme_disk_name (char *name, int controller, int namespace)
diff -pruN 2.06-2/debian/patches/quick-boot-lvm.patch 2.06-2ubuntu16/debian/patches/quick-boot-lvm.patch
--- 2.06-2/debian/patches/quick-boot-lvm.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/quick-boot-lvm.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,8 +1,7 @@
-From 4f5e080c61055b04db3cdf8067cf180f193cf89f 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
- menu
+Subject: If we don't have writable grubenv and we're on EFI,
+ always show the menu
 
 If we don't have writable grubenv, recordfail doesn't work, which means our
 quickboot behavior - with a timeout of 0 - leaves the user without a
@@ -26,7 +25,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 674a761..b7135b6 100644
 --- a/util/grub.d/00_header.in
 +++ b/util/grub.d/00_header.in
 @@ -115,7 +115,7 @@ EOF
diff -pruN 2.06-2/debian/patches/quick-boot.patch 2.06-2ubuntu16/debian/patches/quick-boot.patch
--- 2.06-2/debian/patches/quick-boot.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/quick-boot.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From e760841d961fc46c5f7a82830d2e0eb6d4b53e8d 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
@@ -23,20 +22,20 @@ Last-Update: 2015-09-04
 
 Patch-Name: quick-boot.patch
 ---
- configure.ac                | 11 ++++++
- docs/grub.texi              | 14 +++++++
- grub-core/normal/menu.c     | 24 ++++++++++++
+ configure.ac                | 11 +++++++
+ docs/grub.texi              | 14 +++++++++
+ grub-core/normal/menu.c     | 24 ++++++++++++++
  util/grub-mkconfig.in       |  3 +-
- util/grub.d/00_header.in    | 77 +++++++++++++++++++++++++++++++------
- util/grub.d/10_linux.in     |  4 ++
- util/grub.d/30_os-prober.in | 21 ++++++++++
+ util/grub.d/00_header.in    | 77 ++++++++++++++++++++++++++++++++++++++-------
+ util/grub.d/10_linux.in     |  4 +++
+ util/grub.d/30_os-prober.in | 21 +++++++++++++
  7 files changed, 141 insertions(+), 13 deletions(-)
 
 diff --git a/configure.ac b/configure.ac
-index 256fc44ef..c42e4c784 100644
+index 2869155..4882eba 100644
 --- a/configure.ac
 +++ b/configure.ac
-@@ -1926,6 +1926,17 @@ else
+@@ -1934,6 +1934,17 @@ else
  fi
  AC_SUBST([QUIET_BOOT])
  
@@ -55,7 +54,7 @@ index 256fc44ef..c42e4c784 100644
  
  AC_SUBST([FONT_SOURCE])
 diff --git a/docs/grub.texi b/docs/grub.texi
-index f8b4b3b21..0b58dafb2 100644
+index f8b4b3b..0b58daf 100644
 --- a/docs/grub.texi
 +++ b/docs/grub.texi
 @@ -1563,6 +1563,20 @@ This option may be set to a list of GRUB module names separated by spaces.
@@ -80,7 +79,7 @@ index f8b4b3b21..0b58dafb2 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 e9d8444b5..0440340b8 100644
+index e9d8444..0440340 100644
 --- a/grub-core/normal/menu.c
 +++ b/grub-core/normal/menu.c
 @@ -603,6 +603,30 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
@@ -115,7 +114,7 @@ index e9d8444b5..0440340b8 100644
  	{
  	  pos = grub_term_save_pos ();
 diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
-index 0265a5a66..fa9c53a92 100644
+index 0265a5a..fa9c53a 100644
 --- a/util/grub-mkconfig.in
 +++ b/util/grub-mkconfig.in
 @@ -256,7 +256,8 @@ export GRUB_DEFAULT \
@@ -129,7 +128,7 @@ index 0265a5a66..fa9c53a92 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 93a9023..674a761 100644
 --- a/util/grub.d/00_header.in
 +++ b/util/grub.d/00_header.in
 @@ -21,6 +21,8 @@ prefix="@prefix@"
@@ -258,7 +257,7 @@ index 93a90233e..674a76140 100644
  EOF
  }
 diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
-index 869a7eec5..80315a31b 100644
+index 869a7ee..80315a3 100644
 --- a/util/grub.d/10_linux.in
 +++ b/util/grub.d/10_linux.in
 @@ -22,6 +22,7 @@ exec_prefix="@exec_prefix@"
@@ -280,7 +279,7 @@ index 869a7eec5..80315a31b 100644
        save_default_entry | grub_add_tab
    fi
 diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
-index 98aee403e..225a3baf7 100644
+index 98aee40..225a3ba 100644
 --- a/util/grub.d/30_os-prober.in
 +++ b/util/grub.d/30_os-prober.in
 @@ -20,12 +20,26 @@ set -e
diff -pruN 2.06-2/debian/patches/restore-mkdevicemap.patch 2.06-2ubuntu16/debian/patches/restore-mkdevicemap.patch
--- 2.06-2/debian/patches/restore-mkdevicemap.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/restore-mkdevicemap.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From a7b960126fbc0d4541babe5553546e5f9530ac48 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
@@ -17,9 +16,9 @@ Patch-Name: restore-mkdevicemap.patch
  Makefile.util.def              |   17 +
  docs/man/grub-mkdevicemap.h2m  |    4 +
  include/grub/util/deviceiter.h |   14 +
- util/deviceiter.c              | 1027 ++++++++++++++++++++++++++++++++
+ util/deviceiter.c              | 1027 ++++++++++++++++++++++++++++++++++++++++
  util/devicemap.c               |   13 +
- util/grub-mkdevicemap.c        |  181 ++++++
+ util/grub-mkdevicemap.c        |  181 +++++++
  6 files changed, 1256 insertions(+)
  create mode 100644 docs/man/grub-mkdevicemap.h2m
  create mode 100644 include/grub/util/deviceiter.h
@@ -28,7 +27,7 @@ Patch-Name: restore-mkdevicemap.patch
  create mode 100644 util/grub-mkdevicemap.c
 
 diff --git a/Makefile.util.def b/Makefile.util.def
-index f8b356cc1..27f948291 100644
+index f8b356c..27f9482 100644
 --- a/Makefile.util.def
 +++ b/Makefile.util.def
 @@ -336,6 +336,23 @@ program = {
@@ -57,7 +56,7 @@ index f8b356cc1..27f948291 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 0000000..96cd6ee
 --- /dev/null
 +++ b/docs/man/grub-mkdevicemap.h2m
 @@ -0,0 +1,4 @@
@@ -67,7 +66,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 0000000..8537497
 --- /dev/null
 +++ b/include/grub/util/deviceiter.h
 @@ -0,0 +1,14 @@
@@ -87,7 +86,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..b5b9ac6ab
+index 0000000..b5b9ac6
 --- /dev/null
 +++ b/util/deviceiter.c
 @@ -0,0 +1,1027 @@
@@ -1120,7 +1119,7 @@ index 000000000..b5b9ac6ab
 +}
 diff --git a/util/devicemap.c b/util/devicemap.c
 new file mode 100644
-index 000000000..c61864420
+index 0000000..c618644
 --- /dev/null
 +++ b/util/devicemap.c
 @@ -0,0 +1,13 @@
@@ -1139,7 +1138,7 @@ index 000000000..c61864420
 +}
 diff --git a/util/grub-mkdevicemap.c b/util/grub-mkdevicemap.c
 new file mode 100644
-index 000000000..c4bbdbf69
+index 0000000..c4bbdbf
 --- /dev/null
 +++ b/util/grub-mkdevicemap.c
 @@ -0,0 +1,181 @@
diff -pruN 2.06-2/debian/patches/rhboot-bounce-buffers.patch 2.06-2ubuntu16/debian/patches/rhboot-bounce-buffers.patch
--- 2.06-2/debian/patches/rhboot-bounce-buffers.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-bounce-buffers.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,117 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Fri, 12 Jul 2019 09:53:32 +0200
+Subject: x86-efi: Use bounce buffers for reading to addresses > 4GB
+
+Lots of machines apparently can't DMA correctly above 4GB during UEFI,
+so use bounce buffers for the initramfs read.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+Gpb-Pq: Name rhboot-x86-efi-use-bounce-buffers.patch
+
+x86-efi: Reduce maximum bounce buffer size to 16 MiB
+
+The EFI linux loader allocates a bounce buffer to copy the initrd since in
+some machines doing DMA on addresses above 4GB is not possible during EFI.
+
+But the verifiers framework also allocates a buffer to copy the initrd in
+its grub_file_open() handler. It does this since the data to verify has to
+be passed as a single chunk to modules that use the verifiers framework.
+
+If the initrd image size is big there may not be enough memory in the heap
+to allocate two buffers of that size. This causes an allocation failure in
+the verifiers framework and leads to the initrd not being read.
+
+To prevent these allocation failures, let's reduce the maximum size of the
+bounce buffer used in the EFI loader. Since the data read can be copied to
+the actual initrd address in multilple chunks.
+
+Resolves: rhbz#1838633
+
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+---
+ grub-core/loader/i386/efi/linux.c | 50 ++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 44 insertions(+), 6 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 8b1aa7d..5448dcd 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -46,6 +46,11 @@ struct grub_linuxefi_context {
+   void *initrd_mem;
+ };
+ 
++#define MIN(a, b) \
++  ({ typeof (a) _a = (a); \
++     typeof (b) _b = (b); \
++     _a < _b ? _a : _b; })
++
+ #define BYTES_TO_PAGES(bytes)   (((bytes) + 0xfff) >> 12)
+ 
+ static grub_err_t
+@@ -88,6 +93,44 @@ grub_linuxefi_unload (void *data)
+   return GRUB_ERR_NONE;
+ }
+ 
++#define BOUNCE_BUFFER_MAX 0x1000000ull
++
++static grub_ssize_t
++read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len)
++{
++  grub_ssize_t bufpos = 0;
++  static grub_size_t bbufsz = 0;
++  static char *bbuf = NULL;
++
++  if (bbufsz == 0)
++    bbufsz = MIN(BOUNCE_BUFFER_MAX, len);
++
++  while (!bbuf && bbufsz)
++    {
++      bbuf = grub_malloc(bbufsz);
++      if (!bbuf)
++	bbufsz >>= 1;
++    }
++  if (!bbuf)
++    grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate bounce buffer"));
++
++  while (bufpos < (long long)len)
++    {
++      grub_ssize_t sz;
++
++      sz = grub_file_read (file, bbuf, MIN(bbufsz, len - bufpos));
++      if (sz < 0)
++	return sz;
++      if (sz == 0)
++	break;
++
++      grub_memcpy(bufp + bufpos, bbuf, sz);
++      bufpos += sz;
++    }
++
++  return bufpos;
++}
++
+ static grub_err_t
+ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+ {
+@@ -149,7 +192,7 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+   for (i = 0; i < nfiles; i++)
+     {
+       grub_ssize_t cursize = grub_file_size (files[i]);
+-      if (grub_file_read (files[i], ptr, cursize) != cursize)
++      if (read (files[i], ptr, cursize) != cursize)
+         {
+           if (!grub_errno)
+             grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
+@@ -180,11 +223,6 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+   return grub_errno;
+ }
+ 
+-#define MIN(a, b) \
+-  ({ typeof (a) _a = (a); \
+-     typeof (b) _b = (b); \
+-     _a < _b ? _a : _b; })
+-
+ static grub_err_t
+ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 		int argc, char *argv[])
diff -pruN 2.06-2/debian/patches/rhboot-efi-allocate-in-kernel-bounds.patch 2.06-2ubuntu16/debian/patches/rhboot-efi-allocate-in-kernel-bounds.patch
--- 2.06-2/debian/patches/rhboot-efi-allocate-in-kernel-bounds.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-efi-allocate-in-kernel-bounds.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,55 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 Aug 2022 14:07:50 -0400
+Subject: efi: allocate the initrd within the bounds expressed by the kernel
+
+Currently on x86, only linux kernels built with CONFIG_RELOCATABLE for
+x86_64 can be loaded above 4G, but the maximum address for the initramfs
+is specified via a HdrS field.  This allows us to utilize that value,
+and unless loading the kernel above 4G, uses the value present there.
+If loading kernel above 4G is allowed, we assume loading the initramfs
+above 4G also works; in practice this has been true in the kernel code
+for quite some time.
+
+Resolves: rhbz#2112134
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/i386/efi/linux.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 65b6c30..78e8c07 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -185,6 +185,8 @@ grub_linuxefi_unload (void *data)
+   cmd_initrd->data = 0;
+   grub_free (context);
+ 
++  max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
++
+   return GRUB_ERR_NONE;
+ }
+ 
+@@ -415,11 +417,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+     }
+ #endif
+ 
++  max_addresses[INITRD_MAX_ADDRESS].addr = lh->initrd_addr_max;
+ #if defined(__x86_64__)
+   if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G)
+     {
+       grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n");
+       max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_USABLE_ADDRESS;
++      max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_USABLE_ADDRESS;
+     }
+   else
+     {
+@@ -547,6 +551,8 @@ fail:
+ 
+   grub_dl_unref (my_mod);
+ 
++  max_addresses[INITRD_MAX_ADDRESS].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
++
+   if (cmdline && lh)
+     kernel_free (cmdline, lh->cmdline_size + 1);
+ 
diff -pruN 2.06-2/debian/patches/rhboot-efi-allocate-kernel-as-code-for-real.patch 2.06-2ubuntu16/debian/patches/rhboot-efi-allocate-kernel-as-code-for-real.patch
--- 2.06-2/debian/patches/rhboot-efi-allocate-kernel-as-code-for-real.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-efi-allocate-kernel-as-code-for-real.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,59 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 Aug 2022 13:04:43 -0400
+Subject: efi: use EFI_LOADER_(CODE|DATA) for kernel and initrd allocations
+
+At some point due to an erroneous kernel warning, we switched kernel and
+initramfs to being loaded in EFI_RUNTIME_SERVICES_CODE and
+EFI_RUNTIME_SERVICES_DATA memory pools.  This doesn't appear to be
+correct according to the spec, and that kernel warning has gone away.
+
+This patch puts them back in EFI_LOADER_CODE and EFI_LOADER_DATA
+allocations, respectively.
+
+Resolves: rhbz#2108456
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/i386/efi/linux.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 78e8c07..e9962ea 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -274,7 +274,7 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+     }
+ 
+   grub_dprintf ("linux", "Trying to allocate initrd mem\n");
+-  initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_RUNTIME_SERVICES_DATA,
++  initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_LOADER_DATA,
+ 			    N_("can't allocate initrd"));
+   if (initrd_mem == NULL)
+     goto fail;
+@@ -432,7 +432,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ #endif
+ 
+   params = kernel_alloc (KERNEL_MEM, sizeof(*params),
+-			 GRUB_EFI_RUNTIME_SERVICES_DATA,
++			 GRUB_EFI_LOADER_DATA,
+ 			 "cannot allocate kernel parameters");
+   if (!params)
+     goto fail;
+@@ -455,7 +455,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+   grub_dprintf ("linux", "setting up cmdline\n");
+   cmdline = kernel_alloc (KERNEL_MEM, lh->cmdline_size + 1,
+-			  GRUB_EFI_RUNTIME_SERVICES_DATA,
++			  GRUB_EFI_LOADER_DATA,
+ 			  N_("can't allocate cmdline"));
+   if (!cmdline)
+     goto fail;
+@@ -504,7 +504,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   kernel_size = lh->init_size;
+   grub_dprintf ("linux", "Trying to allocate kernel mem\n");
+   kernel_mem = kernel_alloc (KERNEL_MEM, kernel_size,
+-			     GRUB_EFI_RUNTIME_SERVICES_CODE,
++			     GRUB_EFI_LOADER_CODE,
+ 			     N_("can't allocate kernel"));
+   restore_addresses();
+   if (!kernel_mem)
diff -pruN 2.06-2/debian/patches/rhboot-efi-allocate-kernel-as-code.patch 2.06-2ubuntu16/debian/patches/rhboot-efi-allocate-kernel-as-code.patch
--- 2.06-2/debian/patches/rhboot-efi-allocate-kernel-as-code.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-efi-allocate-kernel-as-code.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,87 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 9 Feb 2022 16:08:20 -0500
+Subject: EFI: allocate kernel in EFI_RUNTIME_SERVICES_CODE instead of
+ EFI_LOADER_DATA.
+
+On some of the firmwares with more security mitigations, EFI_LOADER_DATA
+doesn't get you executable memory, and we take a fault and reboot when
+we enter kernel.
+
+This patch correctly allocates the kernel code as EFI_RUNTIME_SERVICES_CODE
+rather than EFI_LOADER_DATA.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+[rharwood: use kernel_size]
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+---
+ grub-core/loader/i386/efi/linux.c | 22 +++++++++++++++-------
+ 1 file changed, 15 insertions(+), 7 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 819c6ec..9ba9b25 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -84,7 +84,9 @@ kernel_free(void *addr, grub_efi_uintn_t size)
+ }
+ 
+ static void *
+-kernel_alloc(grub_efi_uintn_t size, const char * const errmsg)
++kernel_alloc(grub_efi_uintn_t size,
++	     grub_efi_memory_type_t memtype,
++	     const char * const errmsg)
+ {
+   void *addr = 0;
+   unsigned int i;
+@@ -110,7 +112,7 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg)
+       prev_max = max;
+       addr = grub_efi_allocate_pages_real (max, pages,
+ 					   max_addresses[i].alloc_type,
+-					   GRUB_EFI_LOADER_DATA);
++					   memtype);
+       if (addr)
+ 	grub_dprintf ("linux", "Allocated at %p\n", addr);
+     }
+@@ -245,7 +247,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+ 	}
+     }
+ 
+-  initrd_mem = kernel_alloc(size, N_("can't allocate initrd"));
++  initrd_mem = kernel_alloc(size, GRUB_EFI_RUNTIME_SERVICES_DATA,
++			    N_("can't allocate initrd"));
+   if (initrd_mem == NULL)
+     goto fail;
+   grub_dprintf ("linuxefi", "initrd_mem = %p\n", initrd_mem);
+@@ -399,7 +402,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+     }
+ #endif
+ 
+-  params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters");
++  params = kernel_alloc (sizeof(*params), GRUB_EFI_RUNTIME_SERVICES_DATA,
++			 "cannot allocate kernel parameters");
+   if (!params)
+     goto fail;
+   grub_dprintf ("linuxefi", "params = %p\n", params);
+@@ -419,8 +423,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   lh = (struct linux_i386_kernel_header *)params;
+   grub_dprintf ("linuxefi", "new lh is at %p\n", lh);
+ 
+-  grub_dprintf ("linuxefi", "setting up cmdline\n");
+-  cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline"));
++  grub_dprintf ("linux", "setting up cmdline\n");
++  cmdline = kernel_alloc (lh->cmdline_size + 1,
++			  GRUB_EFI_RUNTIME_SERVICES_DATA,
++			  N_("can't allocate cmdline"));
+   if (!cmdline)
+     goto fail;
+   grub_dprintf ("linuxefi", "linux_cmdline = %p\n", cmdline);
+@@ -465,7 +471,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+     }
+   max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
+   max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
+-  kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel"));
++  kernel_size = lh->init_size;
++  kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE,
++			     N_("can't allocate kernel"));
+   restore_addresses();
+   if (!kernel_mem)
+     goto fail;
diff -pruN 2.06-2/debian/patches/rhboot-efi-enumerated-array-for-allocation-choice.patch 2.06-2ubuntu16/debian/patches/rhboot-efi-enumerated-array-for-allocation-choice.patch
--- 2.06-2/debian/patches/rhboot-efi-enumerated-array-for-allocation-choice.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-efi-enumerated-array-for-allocation-choice.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,79 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 Aug 2022 14:06:30 -0400
+Subject: efi: use enumerated array positions for our allocation choices
+
+In our kernel allocator on EFI systems, we currently have a growing
+amount of code that references the various allocation policies by
+position in the array, and of course maintenance of this code scales
+very poorly.
+
+This patch changes them to be enumerated, so they're easier to refer to
+farther along in the code without confusion.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/i386/efi/linux.c | 31 ++++++++++++++++++++-----------
+ 1 file changed, 20 insertions(+), 11 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 9ba9b25..42886e8 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -58,17 +58,26 @@ struct allocation_choice {
+     grub_efi_allocate_type_t alloc_type;
+ };
+ 
+-static struct allocation_choice max_addresses[4] =
++enum {
++    KERNEL_PREF_ADDRESS,
++    KERNEL_4G_LIMIT,
++    KERNEL_NO_LIMIT,
++};
++
++static struct allocation_choice max_addresses[] =
+   {
+     /* the kernel overrides this one with pref_address and
+      * GRUB_EFI_ALLOCATE_ADDRESS */
+-    { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
++    [KERNEL_PREF_ADDRESS] =
++      { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
++    /* If the flag in params is set, this one gets changed to be above 4GB. */
++    [KERNEL_4G_LIMIT] =
++      { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+     /* this one is always below 4GB, which we still *prefer* even if the flag
+      * is set. */
+-    { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+-    /* If the flag in params is set, this one gets changed to be above 4GB. */
+-    { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+-    { 0, 0 }
++    [KERNEL_NO_LIMIT] =
++      { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
++    { NO_MEM, 0, 0 }
+   };
+ static struct allocation_choice saved_addresses[4];
+ 
+@@ -394,7 +403,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G)
+     {
+       grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n");
+-      max_addresses[2].addr = GRUB_EFI_MAX_USABLE_ADDRESS;
++      max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_USABLE_ADDRESS;
+     }
+   else
+     {
+@@ -466,11 +475,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_dprintf ("linuxefi", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address);
+   if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS)
+     {
+-      max_addresses[0].addr = lh->pref_address;
+-      max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS;
++      max_addresses[KERNEL_PREF_ADDRESS].addr = lh->pref_address;
++      max_addresses[KERNEL_PREF_ADDRESS].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS;
+     }
+-  max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
+-  max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
++  max_addresses[KERNEL_4G_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
++  max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
+   kernel_size = lh->init_size;
+   kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE,
+ 			     N_("can't allocate kernel"));
diff -pruN 2.06-2/debian/patches/rhboot-efi-fix-incorrect-array-size.patch 2.06-2ubuntu16/debian/patches/rhboot-efi-fix-incorrect-array-size.patch
--- 2.06-2/debian/patches/rhboot-efi-fix-incorrect-array-size.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-efi-fix-incorrect-array-size.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,35 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 11 Oct 2022 17:00:50 -0400
+Subject: x86-efi: Fix an incorrect array size in kernel allocation
+
+In 81a6ebf62bbe166ddc968463df2e8bd481bf697c ("efi: split allocation
+policy for kernel vs initrd memories."), I introduced a split in the
+kernel allocator to allow for different dynamic policies for the kernel
+and the initrd allocations.
+
+Unfortunately, that change increased the size of the policy data used to
+make decisions, but did not change the size of the temporary storage we
+use to back it up and restore.  This results in some of .data getting
+clobbered at runtime, and hilarity ensues.
+
+This patch makes the size of the backup storage be based on the size of
+the initial policy data.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ 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 e9962ea..33565ed 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -90,7 +90,7 @@ static struct allocation_choice max_addresses[] =
+       { INITRD_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+     { NO_MEM, 0, 0 }
+   };
+-static struct allocation_choice saved_addresses[4];
++static struct allocation_choice saved_addresses[sizeof(max_addresses) / sizeof(max_addresses[0])];
+ 
+ #define save_addresses() grub_memcpy(saved_addresses, max_addresses, sizeof(max_addresses))
+ #define restore_addresses() grub_memcpy(max_addresses, saved_addresses, sizeof(max_addresses))
diff -pruN 2.06-2/debian/patches/rhboot-efi-initrd-above-4gb.patch 2.06-2ubuntu16/debian/patches/rhboot-efi-initrd-above-4gb.patch
--- 2.06-2/debian/patches/rhboot-efi-initrd-above-4gb.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-efi-initrd-above-4gb.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,169 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 12 Sep 2018 16:12:27 -0400
+Subject: x86-efi: Allow initrd+params+cmdline allocations above 4GB.
+
+This enables everything except the kernel itself to be above 4GB.
+Putting the kernel up there still doesn't work, because of the way
+params->code32_start is used.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/i386/efi/linux.c | 69 ++++++++++++++++++++++++++++++++++-----
+ include/grub/i386/linux.h         |  6 +++-
+ 2 files changed, 66 insertions(+), 9 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 81de6fa..819c6ec 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -58,13 +58,22 @@ struct allocation_choice {
+     grub_efi_allocate_type_t alloc_type;
+ };
+ 
+-static struct allocation_choice max_addresses[] =
++static struct allocation_choice max_addresses[4] =
+   {
++    /* the kernel overrides this one with pref_address and
++     * GRUB_EFI_ALLOCATE_ADDRESS */
+     { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
++    /* this one is always below 4GB, which we still *prefer* even if the flag
++     * is set. */
+     { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
++    /* If the flag in params is set, this one gets changed to be above 4GB. */
+     { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+     { 0, 0 }
+   };
++static struct allocation_choice saved_addresses[4];
++
++#define save_addresses() grub_memcpy(saved_addresses, max_addresses, sizeof(max_addresses))
++#define restore_addresses() grub_memcpy(max_addresses, saved_addresses, sizeof(max_addresses))
+ 
+ static inline void
+ kernel_free(void *addr, grub_efi_uintn_t size)
+@@ -86,6 +95,11 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg)
+       grub_uint64_t max = max_addresses[i].addr;
+       grub_efi_uintn_t pages;
+ 
++      /*
++       * When we're *not* loading the kernel, or >4GB allocations aren't
++       * supported, these entries are basically all the same, so don't re-try
++       * the same parameters.
++       */
+       if (max == prev_max)
+ 	continue;
+ 
+@@ -186,6 +200,9 @@ read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len)
+   return bufpos;
+ }
+ 
++#define LOW_U32(val) ((grub_uint32_t)(((grub_addr_t)(val)) & 0xffffffffull))
++#define HIGH_U32(val) ((grub_uint32_t)(((grub_addr_t)(val) >> 32) & 0xffffffffull))
++
+ static grub_err_t
+ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+ {
+@@ -233,8 +250,12 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+     goto fail;
+   grub_dprintf ("linuxefi", "initrd_mem = %p\n", initrd_mem);
+ 
+-  params->ramdisk_size = size;
+-  params->ramdisk_image = (grub_uint32_t) (grub_addr_t) initrd_mem; /* FIXME: casts are not in rhboot */
++  params->ramdisk_size = LOW_U32(size);
++  params->ramdisk_image = LOW_U32(initrd_mem);
++#if defined(__x86_64__)
++  params->ext_ramdisk_size = HIGH_U32(size);
++  params->ext_ramdisk_image = HIGH_U32(initrd_mem);
++#endif
+ 
+   ptr = initrd_mem;
+ 
+@@ -366,6 +387,18 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+     }
+ #endif
+ 
++#if defined(__x86_64__)
++  if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G)
++    {
++      grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n");
++      max_addresses[2].addr = GRUB_EFI_MAX_USABLE_ADDRESS;
++    }
++  else
++    {
++      grub_dprintf ("linux", "Loading kernel above 4GB is not supported\n");
++    }
++#endif
++
+   params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters");
+   if (!params)
+     goto fail;
+@@ -399,28 +432,48 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 			      GRUB_VERIFY_KERNEL_CMDLINE);
+ 
+   grub_dprintf ("linuxefi", "cmdline:%s\n", cmdline);
+-  grub_dprintf ("linuxefi", "setting lh->cmd_line_ptr to %p\n",
+-		cmdline);
+-  lh->cmd_line_ptr = (grub_uint32_t) (grub_addr_t) cmdline;
++  grub_dprintf ("linuxefi", "setting lh->cmd_line_ptr to 0x%08x\n",
++		LOW_U32(cmdline));
++  lh->cmd_line_ptr = LOW_U32(cmdline);
++#if defined(__x86_64__)
++  if ((grub_efi_uintn_t)cmdline > 0xffffffffull)
++    {
++      grub_dprintf ("linuxefi", "setting params->ext_cmd_line_ptr to 0x%08x\n",
++		    HIGH_U32(cmdline));
++      params->ext_cmd_line_ptr = HIGH_U32(cmdline);
++    }
++#endif
+ 
+   handover_offset = lh->handover_offset;
+   grub_dprintf("linuxefi", "handover_offset: 0x%08x\n", handover_offset);
+ 
+   start = (lh->setup_sects + 1) * 512;
+ 
++  /*
++   * AFAICS >4GB for kernel *cannot* work because of params->code32_start being
++   * 32-bit and getting called unconditionally in head_64.S from either entry
++  * point.
++   *
++   * so nerf that out here...
++   */
++  save_addresses();
+   grub_dprintf ("linuxefi", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address);
+   if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS)
+     {
+       max_addresses[0].addr = lh->pref_address;
+       max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS;
+     }
++  max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
++  max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
+   kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel"));
++  restore_addresses();
+   if (!kernel_mem)
+     goto fail;
+   grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem);
+ 
+-  grub_dprintf ("linuxefi", "setting lh->code32_start to %p\n", kernel_mem);
+-  lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
++  grub_dprintf ("linuxefi", "setting lh->code32_start to 0x%08x\n",
++		LOW_U32(kernel_mem));
++  lh->code32_start = LOW_U32(kernel_mem);
+ 
+   grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start);
+ 
+diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
+index 25ef52c..fac2247 100644
+--- a/include/grub/i386/linux.h
++++ b/include/grub/i386/linux.h
+@@ -236,7 +236,11 @@ struct linux_kernel_params
+   grub_uint32_t ofw_cif_handler;	/* b8 */
+   grub_uint32_t ofw_idt;		/* bc */
+ 
+-  grub_uint8_t padding7[0x1b8 - 0xc0];
++  grub_uint32_t ext_ramdisk_image;	/* 0xc0 */
++  grub_uint32_t ext_ramdisk_size;	/* 0xc4 */
++  grub_uint32_t ext_cmd_line_ptr;	/* 0xc8 */
++
++  grub_uint8_t padding7[0x1b8 - 0xcc];
+ 
+   union
+     {
diff -pruN 2.06-2/debian/patches/rhboot-efi-kernel-allocator.patch 2.06-2ubuntu16/debian/patches/rhboot-efi-kernel-allocator.patch
--- 2.06-2/debian/patches/rhboot-efi-kernel-allocator.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-efi-kernel-allocator.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,253 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 12 Sep 2018 16:03:55 -0400
+Subject: x86-efi: Make our own allocator for kernel stuff
+
+This helps enable allocations above 4GB.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/i386/efi/linux.c | 156 ++++++++++++++++++++++----------------
+ 1 file changed, 89 insertions(+), 67 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 9044700..81de6fa 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -53,6 +53,65 @@ struct grub_linuxefi_context {
+ 
+ #define BYTES_TO_PAGES(bytes)   (((bytes) + 0xfff) >> 12)
+ 
++struct allocation_choice {
++    grub_efi_physical_address_t addr;
++    grub_efi_allocate_type_t alloc_type;
++};
++
++static struct allocation_choice max_addresses[] =
++  {
++    { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
++    { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
++    { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
++    { 0, 0 }
++  };
++
++static inline void
++kernel_free(void *addr, grub_efi_uintn_t size)
++{
++  if (addr && size)
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)addr,
++			 BYTES_TO_PAGES(size));
++}
++
++static void *
++kernel_alloc(grub_efi_uintn_t size, const char * const errmsg)
++{
++  void *addr = 0;
++  unsigned int i;
++  grub_efi_physical_address_t prev_max = 0;
++
++  for (i = 0; max_addresses[i].addr != 0 && addr == 0; i++)
++    {
++      grub_uint64_t max = max_addresses[i].addr;
++      grub_efi_uintn_t pages;
++
++      if (max == prev_max)
++	continue;
++
++      pages = BYTES_TO_PAGES(size);
++      grub_dprintf ("linux", "Trying to allocate %lu pages from %p\n",
++		    pages, (void *)max);
++
++      prev_max = max;
++      addr = grub_efi_allocate_pages_real (max, pages,
++					   max_addresses[i].alloc_type,
++					   GRUB_EFI_LOADER_DATA);
++      if (addr)
++	grub_dprintf ("linux", "Allocated at %p\n", addr);
++    }
++
++  while (grub_error_pop ())
++    {
++      ;
++    }
++
++  if (addr == NULL)
++    grub_error (GRUB_ERR_OUT_OF_MEMORY, "%s", errmsg);
++
++  return addr;
++}
++
+ static grub_err_t
+ grub_linuxefi_boot (void *data)
+ {
+@@ -75,17 +134,13 @@ grub_linuxefi_unload (void *data)
+   grub_dl_unref (my_mod);
+ 
+   if (context->initrd_mem)
+-    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->initrd_mem,
+-			 BYTES_TO_PAGES(params->ramdisk_size));
++    kernel_free(context->initrd_mem, params->ramdisk_size);
+   if (context->cmdline)
+-    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->cmdline,
+-			 BYTES_TO_PAGES(params->cmdline_size + 1));
++    kernel_free(context->cmdline, params->cmdline_size + 1);
+   if (context->kernel_mem)
+-    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->kernel_mem,
+-			 BYTES_TO_PAGES(context->kernel_size));
++    kernel_free(context->kernel_mem, context->kernel_size);
+   if (params)
+-    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params,
+-			 BYTES_TO_PAGES(16384));
++    kernel_free(params, sizeof(*params));
+ 
+   cmd_initrd->data = 0;
+   grub_free (context);
+@@ -173,19 +228,13 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+ 	}
+     }
+ 
+-  initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, BYTES_TO_PAGES(size));
+-  if (!initrd_mem)
+-    initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, 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) context->initrd_mem);
++  initrd_mem = kernel_alloc(size, N_("can't allocate initrd"));
++  if (initrd_mem == NULL)
++    goto fail;
++  grub_dprintf ("linuxefi", "initrd_mem = %p\n", initrd_mem);
+ 
+   params->ramdisk_size = size;
+-  params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem;
++  params->ramdisk_image = (grub_uint32_t) (grub_addr_t) initrd_mem; /* FIXME: casts are not in rhboot */
+ 
+   ptr = initrd_mem;
+ 
+@@ -254,7 +303,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   filelen = grub_file_size (file);
+ 
+   kernel = grub_malloc(filelen);
+-
+   if (!kernel)
+     {
+       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
+@@ -299,7 +347,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-#if defined(__x86_64__) || defined(__aarch64__)
++#if defined(__x86_64__)
+   grub_dprintf ("linuxefi", "checking lh->xloadflags\n");
+   if (!(lh->xloadflags & LINUX_XLF_KERNEL_64))
+     {
+@@ -318,17 +366,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+     }
+ #endif
+ 
+-  params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+-					BYTES_TO_PAGES(sizeof(*params)));
++  params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters");
+   if (!params)
+-    params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
+-					  BYTES_TO_PAGES(sizeof(*params)));
+-  if (! params)
+-    {
+-      grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
+-      goto fail;
+-    }
+-
++    goto fail;
+   grub_dprintf ("linuxefi", "params = %p\n", params);
+ 
+   grub_memset (params, 0, sizeof(*params));
+@@ -347,18 +387,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_dprintf ("linuxefi", "new lh is at %p\n", lh);
+ 
+   grub_dprintf ("linuxefi", "setting up cmdline\n");
+-  cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+-					BYTES_TO_PAGES(lh->cmdline_size + 1));
++  cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline"));
+   if (!cmdline)
+-    cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
+-					  BYTES_TO_PAGES(lh->cmdline_size + 1));
+-  if (!cmdline)
+-    {
+-      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
+-      goto fail;
+-    }
+-
+-  grub_dprintf ("linuxefi", "cmdline = %lx\n", (unsigned long)cmdline);
++    goto fail;
++  grub_dprintf ("linuxefi", "linux_cmdline = %p\n", cmdline);
+ 
+   grub_memcpy (cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
+   grub_create_loader_cmdline (argc, argv,
+@@ -366,33 +398,26 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 			      lh->cmdline_size - (sizeof (LINUX_IMAGE) - 1),
+ 			      GRUB_VERIFY_KERNEL_CMDLINE);
+ 
+-  grub_dprintf ("linuxefi", "setting lh->cmd_line_ptr\n");
+-  lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)cmdline;
++  grub_dprintf ("linuxefi", "cmdline:%s\n", cmdline);
++  grub_dprintf ("linuxefi", "setting lh->cmd_line_ptr to %p\n",
++		cmdline);
++  lh->cmd_line_ptr = (grub_uint32_t) (grub_addr_t) cmdline;
+ 
+   handover_offset = lh->handover_offset;
+-  grub_dprintf ("linuxefi", "handover offset: %08x\n", handover_offset);
++  grub_dprintf("linuxefi", "handover_offset: 0x%08x\n", handover_offset);
+ 
+   start = (lh->setup_sects + 1) * 512;
+ 
+-  kernel_size = lh->init_size;
+-  kernel_mem = grub_efi_allocate_fixed(lh->pref_address,
+-				       BYTES_TO_PAGES(kernel_size));
+-
+-  if (!kernel_mem)
++  grub_dprintf ("linuxefi", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address);
++  if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS)
+     {
+-      grub_error_pop();
+-      kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+-					       BYTES_TO_PAGES(kernel_size));
++      max_addresses[0].addr = lh->pref_address;
++      max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS;
+     }
++  kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel"));
+   if (!kernel_mem)
+-    kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
+-					     BYTES_TO_PAGES(kernel_size));
+-  if (!kernel_mem)
+-    {
+-      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
+-      goto fail;
+-    }
+-  grub_dprintf ("linuxefi", "kernel_mem = %p\n", kernel_mem);
++    goto fail;
++  grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem);
+ 
+   grub_dprintf ("linuxefi", "setting lh->code32_start to %p\n", kernel_mem);
+   lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
+@@ -434,16 +459,13 @@ fail:
+   grub_dl_unref (my_mod);
+ 
+   if (cmdline && lh)
+-    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)cmdline,
+-			 BYTES_TO_PAGES(lh->cmdline_size + 1));
++    kernel_free (cmdline, lh->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));
++    kernel_free (kernel_mem, kernel_size);
+ 
+   if (params)
+-    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params,
+-			 sizeof(*params));
++    kernel_free (params, sizeof(*params));
+ 
+   grub_free (context);
+ 
diff -pruN 2.06-2/debian/patches/rhboot-efi-rearrange-grub-cmd-linux.patch 2.06-2ubuntu16/debian/patches/rhboot-efi-rearrange-grub-cmd-linux.patch
--- 2.06-2/debian/patches/rhboot-efi-rearrange-grub-cmd-linux.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-efi-rearrange-grub-cmd-linux.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,137 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 13 Sep 2018 14:42:34 -0400
+Subject: x86-efi: Re-arrange grub_cmd_linux() a little bit.
+
+This just helps the next patch be easier to read.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+(reconstructed manually by hand)
+
+Signed-off-by: Julian Andres Klode <julian.klode@canonical.com>
+---
+ grub-core/loader/i386/efi/linux.c | 71 ++++++++++++++++++++-------------------
+ 1 file changed, 37 insertions(+), 34 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 5448dcd..9044700 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -268,32 +268,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-  params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+-					BYTES_TO_PAGES(sizeof(*params)));
+-  if (!params)
+-    params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
+-					  BYTES_TO_PAGES(sizeof(*params)));
+-  if (! params)
+-    {
+-      grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
+-      goto fail;
+-    }
+-
+-  grub_dprintf ("linuxefi", "params = %p\n", params);
+-
+-  grub_memset (params, 0, sizeof(*params));
++  lh = (struct linux_i386_kernel_header *)kernel;
++  grub_dprintf ("linuxefi", "original lh is at %p\n", kernel);
+ 
+-  setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201);
+-  grub_dprintf ("linuxefi", "copying %" PRIuGRUB_SIZE " bytes from %p to %p\n",
+-		MIN((grub_size_t)0x202+setup_header_end_offset,
+-		    sizeof (*params)) - 0x1f1,
+-		(grub_uint8_t *)kernel + 0x1f1,
+-		(grub_uint8_t *)params + 0x1f1);
+-  grub_memcpy ((grub_uint8_t *)params + 0x1f1,
+-	       (grub_uint8_t *)kernel + 0x1f1,
+-		MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
+-  lh = (struct linux_i386_kernel_header *)params;
+-  grub_dprintf ("linuxefi", "lh is at %p\n", lh);
+   grub_dprintf ("linuxefi", "checking lh->boot_flag\n");
+   if (lh->boot_flag != grub_cpu_to_le16 (0xaa55))
+     {
+@@ -341,6 +318,34 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+     }
+ #endif
+ 
++  params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
++					BYTES_TO_PAGES(sizeof(*params)));
++  if (!params)
++    params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
++					  BYTES_TO_PAGES(sizeof(*params)));
++  if (! params)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
++      goto fail;
++    }
++
++  grub_dprintf ("linuxefi", "params = %p\n", params);
++
++  grub_memset (params, 0, sizeof(*params));
++
++  setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201);
++  grub_dprintf ("linuxefi", "copying %" PRIuGRUB_SIZE " bytes from %p to %p\n",
++		MIN((grub_size_t)0x202+setup_header_end_offset,
++		    sizeof (*params)) - 0x1f1,
++		(grub_uint8_t *)kernel + 0x1f1,
++		(grub_uint8_t *)params + 0x1f1);
++  grub_memcpy ((grub_uint8_t *)params + 0x1f1,
++	       (grub_uint8_t *)kernel + 0x1f1,
++		MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
++
++  lh = (struct linux_i386_kernel_header *)params;
++  grub_dprintf ("linuxefi", "new lh is at %p\n", lh);
++
+   grub_dprintf ("linuxefi", "setting up cmdline\n");
+   cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+ 					BYTES_TO_PAGES(lh->cmdline_size + 1));
+@@ -364,8 +369,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_dprintf ("linuxefi", "setting lh->cmd_line_ptr\n");
+   lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)cmdline;
+ 
+-  grub_dprintf ("linuxefi", "computing handover offset\n");
+   handover_offset = lh->handover_offset;
++  grub_dprintf ("linuxefi", "handover offset: %08x\n", handover_offset);
+ 
+   start = (lh->setup_sects + 1) * 512;
+ 
+@@ -387,23 +392,21 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       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);
++  grub_dprintf ("linuxefi", "kernel_mem = %p\n", kernel_mem);
+ 
+   grub_dprintf ("linuxefi", "setting lh->code32_start to %p\n", kernel_mem);
+   lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
+ 
+   grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start);
+ 
+-  grub_dprintf ("linuxefi", "setting lh->type_of_loader\n");
+   lh->type_of_loader = 0x6;
++  grub_dprintf ("linuxefi", "setting lh->type_of_loader = 0x%02x\n",											lh->type_of_loader);
+ 
+-  grub_dprintf ("linuxefi", "setting lh->ext_loader_{type,ver}\n");
+   params->ext_loader_type = 0;
+   params->ext_loader_ver = 2;
+-  grub_dprintf("linuxefi", "kernel_mem: %p handover_offset: %08x\n",
+-	       kernel_mem, handover_offset);
+-
++  grub_dprintf ("linuxefi",
++		"setting lh->ext_loader_{type,ver} = {0x%02x,0x%02x}\n",
++		params->ext_loader_type, params->ext_loader_ver);
+   context = grub_zalloc (sizeof (*context));
+   if (!context)
+     goto fail;
+@@ -421,7 +424,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_free (kernel);
+   return 0;
+ 
+- fail:
++fail:
+   if (file)
+     grub_file_close (file);
+ 
diff -pruN 2.06-2/debian/patches/rhboot-efi-split-allocation-policy.patch 2.06-2ubuntu16/debian/patches/rhboot-efi-split-allocation-policy.patch
--- 2.06-2/debian/patches/rhboot-efi-split-allocation-policy.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-efi-split-allocation-policy.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,126 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 1 Aug 2022 14:24:39 -0400
+Subject: efi: split allocation policy for kernel vs initrd memories.
+
+Currently in our kernel allocator, we use the same set of choices for
+all of our various kernel and initramfs allocations, though they do not
+have exactly the same constraints.
+
+This patch adds the concept of an allocation purpose, which currently
+can be KERNEL_MEM or INITRD_MEM, and updates kernel_alloc() calls
+appropriately, but does not change any current policy decision.  It
+also adds a few debug prints.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+---
+ grub-core/loader/i386/efi/linux.c | 35 +++++++++++++++++++++++++++--------
+ 1 file changed, 27 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 42886e8..65b6c30 100644
+--- a/grub-core/loader/i386/efi/linux.c
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -53,7 +53,14 @@ struct grub_linuxefi_context {
+ 
+ #define BYTES_TO_PAGES(bytes)   (((bytes) + 0xfff) >> 12)
+ 
++typedef enum {
++    NO_MEM,
++    KERNEL_MEM,
++    INITRD_MEM,
++} kernel_alloc_purpose_t;
++
+ struct allocation_choice {
++    kernel_alloc_purpose_t purpose;
+     grub_efi_physical_address_t addr;
+     grub_efi_allocate_type_t alloc_type;
+ };
+@@ -62,6 +69,7 @@ enum {
+     KERNEL_PREF_ADDRESS,
+     KERNEL_4G_LIMIT,
+     KERNEL_NO_LIMIT,
++    INITRD_MAX_ADDRESS,
+ };
+ 
+ static struct allocation_choice max_addresses[] =
+@@ -69,14 +77,17 @@ static struct allocation_choice max_addresses[] =
+     /* the kernel overrides this one with pref_address and
+      * GRUB_EFI_ALLOCATE_ADDRESS */
+     [KERNEL_PREF_ADDRESS] =
+-      { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
++      { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+     /* If the flag in params is set, this one gets changed to be above 4GB. */
+     [KERNEL_4G_LIMIT] =
+-      { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
++      { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+     /* this one is always below 4GB, which we still *prefer* even if the flag
+      * is set. */
+     [KERNEL_NO_LIMIT] =
+-      { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
++      { KERNEL_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
++    /* this is for the initrd */
++    [INITRD_MAX_ADDRESS] =
++      { INITRD_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+     { NO_MEM, 0, 0 }
+   };
+ static struct allocation_choice saved_addresses[4];
+@@ -93,7 +104,8 @@ kernel_free(void *addr, grub_efi_uintn_t size)
+ }
+ 
+ static void *
+-kernel_alloc(grub_efi_uintn_t size,
++kernel_alloc(kernel_alloc_purpose_t purpose,
++	     grub_efi_uintn_t size,
+ 	     grub_efi_memory_type_t memtype,
+ 	     const char * const errmsg)
+ {
+@@ -106,6 +118,9 @@ kernel_alloc(grub_efi_uintn_t size,
+       grub_uint64_t max = max_addresses[i].addr;
+       grub_efi_uintn_t pages;
+ 
++      if (purpose != max_addresses[i].purpose)
++	continue;
++
+       /*
+        * When we're *not* loading the kernel, or >4GB allocations aren't
+        * supported, these entries are basically all the same, so don't re-try
+@@ -256,7 +271,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+ 	}
+     }
+ 
+-  initrd_mem = kernel_alloc(size, GRUB_EFI_RUNTIME_SERVICES_DATA,
++  grub_dprintf ("linux", "Trying to allocate initrd mem\n");
++  initrd_mem = kernel_alloc(INITRD_MEM, size, GRUB_EFI_RUNTIME_SERVICES_DATA,
+ 			    N_("can't allocate initrd"));
+   if (initrd_mem == NULL)
+     goto fail;
+@@ -411,7 +427,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+     }
+ #endif
+ 
+-  params = kernel_alloc (sizeof(*params), GRUB_EFI_RUNTIME_SERVICES_DATA,
++  params = kernel_alloc (KERNEL_MEM, sizeof(*params),
++			 GRUB_EFI_RUNTIME_SERVICES_DATA,
+ 			 "cannot allocate kernel parameters");
+   if (!params)
+     goto fail;
+@@ -433,7 +450,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_dprintf ("linuxefi", "new lh is at %p\n", lh);
+ 
+   grub_dprintf ("linux", "setting up cmdline\n");
+-  cmdline = kernel_alloc (lh->cmdline_size + 1,
++  cmdline = kernel_alloc (KERNEL_MEM, lh->cmdline_size + 1,
+ 			  GRUB_EFI_RUNTIME_SERVICES_DATA,
+ 			  N_("can't allocate cmdline"));
+   if (!cmdline)
+@@ -481,7 +498,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   max_addresses[KERNEL_4G_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
+   max_addresses[KERNEL_NO_LIMIT].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
+   kernel_size = lh->init_size;
+-  kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE,
++  grub_dprintf ("linux", "Trying to allocate kernel mem\n");
++  kernel_mem = kernel_alloc (KERNEL_MEM, kernel_size,
++			     GRUB_EFI_RUNTIME_SERVICES_CODE,
+ 			     N_("can't allocate kernel"));
+   restore_addresses();
+   if (!kernel_mem)
diff -pruN 2.06-2/debian/patches/rhboot-f34-dont-use-int-for-efi-status.patch 2.06-2ubuntu16/debian/patches/rhboot-f34-dont-use-int-for-efi-status.patch
--- 2.06-2/debian/patches/rhboot-f34-dont-use-int-for-efi-status.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-f34-dont-use-int-for-efi-status.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,23 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 26 Jun 2017 12:44:59 -0400
+Subject: don't use int for efi status
+
+(cherry picked from commit eee6d2db7e3a392b8fe134fa75a7e28c9ae8cda5)
+Patch-Name: rhboot-f34-dont-use-int-for-efi-status.patch
+---
+ grub-core/kern/efi/efi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index 05d8237..ae9885e 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -167,7 +167,7 @@ grub_reboot (void)
+ void
+ grub_exit (int retval)
+ {
+-  int rc = GRUB_EFI_LOAD_ERROR;
++  grub_efi_status_t rc = GRUB_EFI_LOAD_ERROR;
+ 
+   if (retval == 0)
+     rc = GRUB_EFI_SUCCESS;
diff -pruN 2.06-2/debian/patches/rhboot-f34-efinet-also-use-the-firmware-acceleration-for-http.patch 2.06-2ubuntu16/debian/patches/rhboot-f34-efinet-also-use-the-firmware-acceleration-for-http.patch
--- 2.06-2/debian/patches/rhboot-f34-efinet-also-use-the-firmware-acceleration-for-http.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-f34-efinet-also-use-the-firmware-acceleration-for-http.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,26 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Mon, 30 Jul 2018 14:06:42 -0400
+Subject: efinet: also use the firmware acceleration for http
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+Patch-Name: rhboot-f34-efinet-also-use-the-firmware-acceleration-for-http.patch
+---
+ grub-core/net/efi/net.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c
+index 9b7a218..b2fe4db 100644
+--- a/grub-core/net/efi/net.c
++++ b/grub-core/net/efi/net.c
+@@ -1336,7 +1336,9 @@ grub_efi_net_boot_from_https (void)
+ 	  && (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE))
+ 	{
+ 	  grub_efi_uri_device_path_t *uri_dp = (grub_efi_uri_device_path_t *) dp;
+-	  return (grub_strncmp ((const char*)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0) ? 1 : 0;
++	  grub_dprintf ("efinet", "url:%s\n", (const char *)uri_dp->uri);
++	  return (grub_strncmp ((const char *)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0 ||
++	          grub_strncmp ((const char *)uri_dp->uri, "http://", sizeof ("http://") - 1) == 0);
+ 	}
+ 
+       if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
diff -pruN 2.06-2/debian/patches/rhboot-f34-make-exit-take-a-return-code.patch 2.06-2ubuntu16/debian/patches/rhboot-f34-make-exit-take-a-return-code.patch
--- 2.06-2/debian/patches/rhboot-f34-make-exit-take-a-return-code.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-f34-make-exit-take-a-return-code.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,268 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 26 Feb 2014 21:49:12 -0500
+Subject: Make "exit" take a return code.
+
+This adds "exit" with a return code.  With this patch, any "exit"
+command /may/ include a return code, and on platforms that support
+returning with an exit status, we will do so.  By default we return the
+same exit status we did before this patch.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+(cherry picked from commit ccce3d69ae3eacc7bdc70217304586bd7e74fe1e)
+Patch-Name: rhboot-f34-make-exit-take-a-return-code.patch
+---
+ grub-core/commands/minicmd.c         | 20 ++++++++++++++++----
+ grub-core/kern/efi/efi.c             |  9 +++++++--
+ grub-core/kern/emu/main.c            |  2 +-
+ grub-core/kern/emu/misc.c            |  5 +++--
+ grub-core/kern/i386/coreboot/init.c  |  2 +-
+ grub-core/kern/i386/qemu/init.c      |  2 +-
+ grub-core/kern/ieee1275/init.c       |  2 +-
+ grub-core/kern/mips/arc/init.c       |  2 +-
+ grub-core/kern/mips/loongson/init.c  |  2 +-
+ grub-core/kern/mips/qemu_mips/init.c |  2 +-
+ grub-core/kern/misc.c                | 11 ++++++++++-
+ grub-core/kern/uboot/init.c          |  6 +++---
+ grub-core/kern/xen/init.c            |  2 +-
+ include/grub/misc.h                  |  2 +-
+ 14 files changed, 48 insertions(+), 21 deletions(-)
+
+diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
+index fa49893..2bd3ac7 100644
+--- a/grub-core/commands/minicmd.c
++++ b/grub-core/commands/minicmd.c
+@@ -182,12 +182,24 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
+ }
+ 
+ /* exit */
+-static grub_err_t __attribute__ ((noreturn))
++static grub_err_t
+ grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
+-		    int argc __attribute__ ((unused)),
+-		    char *argv[] __attribute__ ((unused)))
++		    int argc, char *argv[])
+ {
+-  grub_exit ();
++  int retval = -1;
++  unsigned long n;
++
++  if (argc < 0 || argc > 1)
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
++
++  if (argc == 1)
++    {
++      n = grub_strtoul (argv[0], 0, 10);
++      if (n != ~0UL)
++	retval = n;
++    }
++
++  grub_exit (retval);
+   /* Not reached.  */
+ }
+ 
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index 8cff7be..05d8237 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -165,11 +165,16 @@ grub_reboot (void)
+ }
+ 
+ void
+-grub_exit (void)
++grub_exit (int retval)
+ {
++  int rc = GRUB_EFI_LOAD_ERROR;
++
++  if (retval == 0)
++    rc = GRUB_EFI_SUCCESS;
++
+   grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
+   efi_call_4 (grub_efi_system_table->boot_services->exit,
+-              grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0);
++              grub_efi_image_handle, rc, 0, 0);
+   for (;;) ;
+ }
+ 
+diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c
+index 425bb96..55ea5a1 100644
+--- a/grub-core/kern/emu/main.c
++++ b/grub-core/kern/emu/main.c
+@@ -67,7 +67,7 @@ grub_reboot (void)
+ }
+ 
+ void
+-grub_exit (void)
++grub_exit (int retval __attribute__((unused)))
+ {
+   grub_reboot ();
+ }
+diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c
+index dfd8a8e..0ff13bc 100644
+--- a/grub-core/kern/emu/misc.c
++++ b/grub-core/kern/emu/misc.c
+@@ -151,9 +151,10 @@ xasprintf (const char *fmt, ...)
+ 
+ #if !defined (GRUB_MACHINE_EMU) || defined (GRUB_UTIL)
+ void
+-grub_exit (void)
++__attribute__ ((noreturn))
++grub_exit (int rc)
+ {
+-  exit (1);
++  exit (rc < 0 ? 1 : rc);
+ }
+ #endif
+ 
+diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c
+index 3314f02..36f9134 100644
+--- a/grub-core/kern/i386/coreboot/init.c
++++ b/grub-core/kern/i386/coreboot/init.c
+@@ -41,7 +41,7 @@ extern grub_uint8_t _end[];
+ extern grub_uint8_t _edata[];
+ 
+ void  __attribute__ ((noreturn))
+-grub_exit (void)
++grub_exit (int rc __attribute__((unused)))
+ {
+   /* We can't use grub_fatal() in this function.  This would create an infinite
+      loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit().  */
+diff --git a/grub-core/kern/i386/qemu/init.c b/grub-core/kern/i386/qemu/init.c
+index 271b6fb..9fafe98 100644
+--- a/grub-core/kern/i386/qemu/init.c
++++ b/grub-core/kern/i386/qemu/init.c
+@@ -42,7 +42,7 @@ extern grub_uint8_t _end[];
+ extern grub_uint8_t _edata[];
+ 
+ void  __attribute__ ((noreturn))
+-grub_exit (void)
++grub_exit (int rc __attribute__((unused)))
+ {
+   /* We can't use grub_fatal() in this function.  This would create an infinite
+      loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit().  */
+diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
+index 8b089b4..085a6a3 100644
+--- a/grub-core/kern/ieee1275/init.c
++++ b/grub-core/kern/ieee1275/init.c
+@@ -71,7 +71,7 @@ grub_addr_t grub_ieee1275_original_stack;
+ #endif
+ 
+ void
+-grub_exit (void)
++grub_exit (int rc __attribute__((unused)))
+ {
+   grub_ieee1275_exit ();
+ }
+diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c
+index 2ed3ff3..5c40c34 100644
+--- a/grub-core/kern/mips/arc/init.c
++++ b/grub-core/kern/mips/arc/init.c
+@@ -276,7 +276,7 @@ grub_halt (void)
+ }
+ 
+ void
+-grub_exit (void)
++grub_exit (int rc __attribute__((unused)))
+ {
+   GRUB_ARC_FIRMWARE_VECTOR->exit ();
+ 
+diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c
+index 7b96531..dff598c 100644
+--- a/grub-core/kern/mips/loongson/init.c
++++ b/grub-core/kern/mips/loongson/init.c
+@@ -304,7 +304,7 @@ grub_halt (void)
+ }
+ 
+ void
+-grub_exit (void)
++grub_exit (int rc __attribute__((unused)))
+ {
+   grub_halt ();
+ }
+diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c
+index be88b77..8b6c55f 100644
+--- a/grub-core/kern/mips/qemu_mips/init.c
++++ b/grub-core/kern/mips/qemu_mips/init.c
+@@ -75,7 +75,7 @@ grub_machine_fini (int flags __attribute__ ((unused)))
+ }
+ 
+ void
+-grub_exit (void)
++grub_exit (int rc __attribute__((unused)))
+ {
+   grub_halt ();
+ }
+diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
+index 3af336e..63b586d 100644
+--- a/grub-core/kern/misc.c
++++ b/grub-core/kern/misc.c
+@@ -1209,9 +1209,18 @@ grub_abort (void)
+       grub_getkey ();
+     }
+ 
+-  grub_exit ();
++  grub_exit (1);
+ }
+ 
++#if defined (__clang__) && !defined (GRUB_UTIL)
++/* clang emits references to abort().  */
++void __attribute__ ((noreturn))
++abort (void)
++{
++  grub_abort ();
++}
++#endif
++
+ void
+ grub_fatal (const char *fmt, ...)
+ {
+diff --git a/grub-core/kern/uboot/init.c b/grub-core/kern/uboot/init.c
+index 3e33864..be2a5be 100644
+--- a/grub-core/kern/uboot/init.c
++++ b/grub-core/kern/uboot/init.c
+@@ -39,9 +39,9 @@ extern grub_size_t grub_total_module_size;
+ static unsigned long timer_start;
+ 
+ void
+-grub_exit (void)
++grub_exit (int rc)
+ {
+-  grub_uboot_return (0);
++  grub_uboot_return (rc < 0 ? 1 : rc);
+ }
+ 
+ static grub_uint64_t
+@@ -78,7 +78,7 @@ grub_machine_init (void)
+   if (!ver)
+     {
+       /* Don't even have a console to log errors to... */
+-      grub_exit ();
++      grub_exit (-1);
+     }
+   else if (ver > API_SIG_VERSION)
+     {
+diff --git a/grub-core/kern/xen/init.c b/grub-core/kern/xen/init.c
+index 782ca72..708b060 100644
+--- a/grub-core/kern/xen/init.c
++++ b/grub-core/kern/xen/init.c
+@@ -584,7 +584,7 @@ grub_machine_init (void)
+ }
+ 
+ void
+-grub_exit (void)
++grub_exit (int rc __attribute__((unused)))
+ {
+   struct sched_shutdown arg;
+ 
+diff --git a/include/grub/misc.h b/include/grub/misc.h
+index 7d2b551..fd18e63 100644
+--- a/include/grub/misc.h
++++ b/include/grub/misc.h
+@@ -353,7 +353,7 @@ int EXPORT_FUNC(grub_vsnprintf) (char *str, grub_size_t n, const char *fmt,
+ char *EXPORT_FUNC(grub_xasprintf) (const char *fmt, ...)
+      __attribute__ ((format (GNU_PRINTF, 1, 2))) WARN_UNUSED_RESULT;
+ char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args) WARN_UNUSED_RESULT;
+-void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn));
++void EXPORT_FUNC(grub_exit) (int rc) __attribute__ ((noreturn));
+ grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
+ 					  grub_uint64_t d,
+ 					  grub_uint64_t *r);
diff -pruN 2.06-2/debian/patches/rhboot-f34-make-pmtimer-tsc-calibration-fast.patch 2.06-2ubuntu16/debian/patches/rhboot-f34-make-pmtimer-tsc-calibration-fast.patch
--- 2.06-2/debian/patches/rhboot-f34-make-pmtimer-tsc-calibration-fast.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-f34-make-pmtimer-tsc-calibration-fast.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,213 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 7 Nov 2017 17:12:17 -0500
+Subject: Make pmtimer tsc calibration not take 51 seconds to fail.
+
+On my laptop running at 2.4GHz, if I run a VM where tsc calibration
+using pmtimer will fail presuming a broken pmtimer, it takes ~51 seconds
+to do so (as measured with the stopwatch on my phone), with a tsc delta
+of 0x1cd1c85300, or around 125 billion cycles.
+
+If instead of trying to wait for 5-200ms to show up on the pmtimer, we try
+to wait for 5-200us, it decides it's broken in ~0x2626aa0 TSCs, aka ~2.4
+million cycles, or more or less instantly.
+
+Additionally, this reading the pmtimer was returning 0xffffffff anyway,
+and that's obviously an invalid return.  I've added a check for that and
+0 so we don't bother waiting for the test if what we're seeing is dead
+pins with no response at all.
+
+If "debug" is includes "pmtimer", you will see one of the following
+three outcomes.  If pmtimer gives all 0 or all 1 bits, you will see:
+
+kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 1
+kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 2
+kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 3
+kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 4
+kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 5
+kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 6
+kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 7
+kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 8
+kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 9
+kern/i386/tsc_pmtimer.c:77: pmtimer: 0xffffff bad_reads: 10
+kern/i386/tsc_pmtimer.c:78: timer is broken; giving up.
+
+This outcome was tested using qemu+kvm with UEFI (OVMF) firmware and
+these options: -machine pc-q35-2.10 -cpu Broadwell-noTSX
+
+If pmtimer gives any other bit patterns but is not actually marching
+forward fast enough to use for clock calibration, you will see:
+
+kern/i386/tsc_pmtimer.c:121: pmtimer delta is 0x0 (1904 iterations)
+kern/i386/tsc_pmtimer.c:124: tsc delta is implausible: 0x2626aa0
+
+This outcome was tested using grub compiled with GRUB_PMTIMER_IGNORE_BAD_READS
+defined (so as not to trip the bad read test) using qemu+kvm with UEFI
+(OVMF) firmware, and these options: -machine pc-q35-2.10 -cpu Broadwell-noTSX
+
+If pmtimer actually works, you'll see something like:
+
+kern/i386/tsc_pmtimer.c:121: pmtimer delta is 0x0 (1904 iterations)
+kern/i386/tsc_pmtimer.c:124: tsc delta is implausible: 0x2626aa0
+
+This outcome was tested using qemu+kvm with UEFI (OVMF) firmware, and
+these options: -machine pc-i440fx-2.4 -cpu Broadwell-noTSX
+
+I've also tested this outcome on a real Intel Xeon E3-1275v3 on an Intel
+Server Board S1200V3RPS using the SDV.RP.B8 "Release" build here:
+https://firmware.intel.com/sites/default/files/UEFIDevKit_S1200RP_vB8.zip
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+(cherry picked from commit cf0448d61e00acb548f8f22d57ba6e4f3b37f394)
+
+Patch-Name: rhboot-f34-make-pmtimer-tsc-calibration-fast.patch
+---
+ grub-core/kern/i386/tsc_pmtimer.c | 109 +++++++++++++++++++++++++++++++-------
+ 1 file changed, 89 insertions(+), 20 deletions(-)
+
+diff --git a/grub-core/kern/i386/tsc_pmtimer.c b/grub-core/kern/i386/tsc_pmtimer.c
+index c9c3616..ca15c3a 100644
+--- a/grub-core/kern/i386/tsc_pmtimer.c
++++ b/grub-core/kern/i386/tsc_pmtimer.c
+@@ -28,40 +28,101 @@
+ #include <grub/acpi.h>
+ #include <grub/cpu/io.h>
+ 
++/*
++ * Define GRUB_PMTIMER_IGNORE_BAD_READS if you're trying to test a timer that's
++ * present but doesn't keep time well.
++ */
++// #define GRUB_PMTIMER_IGNORE_BAD_READS
++
+ grub_uint64_t
+ grub_pmtimer_wait_count_tsc (grub_port_t pmtimer,
+ 			     grub_uint16_t num_pm_ticks)
+ {
+   grub_uint32_t start;
+-  grub_uint32_t last;
+-  grub_uint32_t cur, end;
++  grub_uint64_t cur, end;
+   grub_uint64_t start_tsc;
+   grub_uint64_t end_tsc;
+-  int num_iter = 0;
++  unsigned int num_iter = 0;
++#ifndef GRUB_PMTIMER_IGNORE_BAD_READS
++  int bad_reads = 0;
++#endif
+ 
+-  start = grub_inl (pmtimer) & 0xffffff;
+-  last = start;
++  /*
++   * Some timers are 24-bit and some are 32-bit, but it doesn't make much
++   * difference to us.  Caring which one we have isn't really worth it since
++   * the low-order digits will give us enough data to calibrate TSC.  So just
++   * mask the top-order byte off.
++   */
++  cur = start = grub_inl (pmtimer) & 0xffffffUL;
+   end = start + num_pm_ticks;
+   start_tsc = grub_get_tsc ();
+   while (1)
+     {
+-      cur = grub_inl (pmtimer) & 0xffffff;
+-      if (cur < last)
+-	cur |= 0x1000000;
+-      num_iter++;
++      cur &= 0xffffffffff000000ULL;
++      cur |= grub_inl (pmtimer) & 0xffffffUL;
++
++      end_tsc = grub_get_tsc();
++
++#ifndef GRUB_PMTIMER_IGNORE_BAD_READS
++      /*
++       * If we get 10 reads in a row that are obviously dead pins, there's no
++       * reason to do this thousands of times.
++       */
++      if (cur == 0xffffffUL || cur == 0)
++	{
++	  bad_reads++;
++	  grub_dprintf ("pmtimer",
++			"pmtimer: 0x%"PRIxGRUB_UINT64_T" bad_reads: %d\n",
++			cur, bad_reads);
++	  grub_dprintf ("pmtimer", "timer is broken; giving up.\n");
++
++	  if (bad_reads == 10)
++	    return 0;
++	}
++#endif
++
++      if (cur < start)
++	cur += 0x1000000;
++
+       if (cur >= end)
+ 	{
+-	  end_tsc = grub_get_tsc ();
++	  grub_dprintf ("pmtimer", "pmtimer delta is 0x%"PRIxGRUB_UINT64_T"\n",
++			cur - start);
++	  grub_dprintf ("pmtimer", "tsc delta is 0x%"PRIxGRUB_UINT64_T"\n",
++			end_tsc - start_tsc);
+ 	  return end_tsc - start_tsc;
+ 	}
+-      /* Check for broken PM timer.
+-	 50000000 TSCs is between 5 ms (10GHz) and 200 ms (250 MHz)
+-	 if after this time we still don't have 1 ms on pmtimer, then
+-	 pmtimer is broken.
++
++      /*
++       * Check for broken PM timer.  1ms at 10GHz should be 1E+7 TSCs; at
++       * 250MHz it should be 2.5E6.  So if after 4E+7 TSCs on a 10GHz machine,
++       * we should have seen pmtimer show 4ms of change (i.e. cur =~
++       * start+14320); on a 250MHz machine that should be 16ms (start+57280).
++       * If after this a time we still don't have 1ms on pmtimer, then pmtimer
++       * is broken.
++       *
++       * Likewise, if our code is perfectly efficient and introduces no delays
++       * whatsoever, on a 10GHz system we should see a TSC delta of 3580 in
++       * ~3580 iterations.  On a 250MHz machine that should be ~900 iterations.
++       *
++       * With those factors in mind, there are two limits here.  There's a hard
++       * limit here at 8x our desired pm timer delta, picked as an arbitrarily
++       * large value that's still not a lot of time to humans, because if we
++       * get that far this is either an implausibly fast machine or the pmtimer
++       * is not running.  And there's another limit on 4x our 10GHz tsc delta
++       * without seeing cur converge on our target value.
+        */
+-      if ((num_iter & 0xffffff) == 0 && grub_get_tsc () - start_tsc > 5000000) {
+-	return 0;
+-      }
++      if ((++num_iter > (grub_uint32_t)num_pm_ticks << 3UL) ||
++	  end_tsc - start_tsc > 40000000)
++	{
++	  grub_dprintf ("pmtimer",
++			"pmtimer delta is 0x%"PRIxGRUB_UINT64_T" (%u iterations)\n",
++			cur - start, num_iter);
++	  grub_dprintf ("pmtimer",
++			"tsc delta is implausible: 0x%"PRIxGRUB_UINT64_T"\n",
++			end_tsc - start_tsc);
++	  return 0;
++	}
+     }
+ }
+ 
+@@ -74,12 +135,20 @@ grub_tsc_calibrate_from_pmtimer (void)
+ 
+   fadt = grub_acpi_find_fadt ();
+   if (!fadt)
+-    return 0;
++    {
++      grub_dprintf ("pmtimer", "No FADT found; not using pmtimer.\n");
++      return 0;
++    }
+   pmtimer = fadt->pmtimer;
+   if (!pmtimer)
+-    return 0;
++    {
++      grub_dprintf ("pmtimer", "FADT does not specify pmtimer; skipping.\n");
++      return 0;
++    }
+ 
+-  /* It's 3.579545 MHz clock. Wait 1 ms.  */
++  /*
++   * It's 3.579545 MHz clock. Wait 1 ms.
++   */
+   tsc_diff = grub_pmtimer_wait_count_tsc (pmtimer, 3580);
+   if (tsc_diff == 0)
+     return 0;
diff -pruN 2.06-2/debian/patches/rhboot-try-to-pick-better-locations-for-kernel-and-initrd.patch 2.06-2ubuntu16/debian/patches/rhboot-try-to-pick-better-locations-for-kernel-and-initrd.patch
--- 2.06-2/debian/patches/rhboot-try-to-pick-better-locations-for-kernel-and-initrd.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/rhboot-try-to-pick-better-locations-for-kernel-and-initrd.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,215 @@
+From: Peter Jones <pjones@redhat.com>
+Date: Thu, 11 Jul 2019 17:17:02 +0200
+Subject: Try to pick better locations for kernel and initrd
+
+- Don't limit allocations on 64-bit platforms to < 0x[37f]fffffff if
+  we're using the "large" code model ; use __UINTPTR_MAX__.
+- Get the comparison right to check the address we've allocated.
+- Fix the allocation for the command line as well.
+
+*But*, when we did this some systems started failing badly; coudln't
+parse partition tables, etc.  What's going on here is the disk controller
+is silently failing DMAs to addresses above 4GB, so we're trying to parse
+uninitialized (or HW zeroed) ram when looking for the partition table,
+etc.
+
+So to limit this, we make grub_malloc() pick addresses below 4GB on
+x86_64, but the direct EFI page allocation functions can get addresses
+above that.
+
+Additionally, we now try to locate kernel+initrd+cmdline+etc below
+0x7fffffff, and if they're too big to fit any memory window there, then
+we try a higher address.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+[david.abdurachmanov: fix macro for riscv64]
+Signed-off-by: David Abdurachmanov <david.abdurachmanov@sifive.com>
+Signed-off-by: Robbie Harwood <rharwood@redhat.com>
+Signed-off-by: Gerald Yang <gerald.yang@canonical.com>
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1989446
+---
+ grub-core/kern/efi/mm.c           |  8 ++++----
+ grub-core/loader/i386/efi/linux.c | 26 ++++++++++++++++++--------
+ include/grub/arm/efi/memory.h     |  1 +
+ include/grub/arm64/efi/memory.h   |  1 +
+ include/grub/i386/efi/memory.h    |  1 +
+ include/grub/ia64/efi/memory.h    |  1 +
+ include/grub/riscv64/efi/memory.h |  1 +
+ include/grub/x86_64/efi/memory.h  |  4 +++-
+ 8 files changed, 30 insertions(+), 13 deletions(-)
+
+diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
+index f6aef0e..7741d66 100644
+--- a/grub-core/kern/efi/mm.c
++++ b/grub-core/kern/efi/mm.c
+@@ -122,7 +122,7 @@ grub_efi_allocate_pages_max (grub_efi_physical_address_t max,
+   grub_efi_boot_services_t *b;
+   grub_efi_physical_address_t address = max;
+ 
+-  if (max > 0xffffffff)
++  if (max > GRUB_EFI_MAX_USABLE_ADDRESS)
+     return 0;
+ 
+   b = grub_efi_system_table->boot_services;
+@@ -476,7 +476,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
+     {
+       if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
+ #if 1
+-	  && desc->physical_start <= GRUB_EFI_MAX_USABLE_ADDRESS
++	  && desc->physical_start <= GRUB_EFI_MAX_ALLOCATION_ADDRESS
+ #endif
+ 	  && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000
+ 	  && desc->num_pages != 0)
+@@ -494,9 +494,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
+ #if 1
+ 	  if (BYTES_TO_PAGES (filtered_desc->physical_start)
+ 	      + filtered_desc->num_pages
+-	      > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS))
++	      > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS))
+ 	    filtered_desc->num_pages
+-	      = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS)
++	      = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS)
+ 		 - BYTES_TO_PAGES (filtered_desc->physical_start));
+ #endif
+ 
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+index 7928a1f..8b1aa7d 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/safemath.h>
++#include <grub/cpu/efi/memory.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -129,9 +130,10 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
+ 	}
+     }
+ 
+-  initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
+-
+-  if (initrd_mem == NULL)
++  initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, BYTES_TO_PAGES(size));
++  if (!initrd_mem)
++    initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, BYTES_TO_PAGES(size));
++  if (!initrd_mem)
+     {
+       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
+       goto fail;
+@@ -228,8 +230,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
+-  params = grub_efi_allocate_pages_max (0x3fffffff,
++  params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+ 					BYTES_TO_PAGES(sizeof(*params)));
++  if (!params)
++    params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
++					  BYTES_TO_PAGES(sizeof(*params)));
+   if (! params)
+     {
+       grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
+@@ -299,8 +304,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ #endif
+ 
+   grub_dprintf ("linuxefi", "setting up cmdline\n");
+-  cmdline = grub_efi_allocate_pages_max(0x3fffffff,
++  cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+ 					BYTES_TO_PAGES(lh->cmdline_size + 1));
++  if (!cmdline)
++    cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
++					  BYTES_TO_PAGES(lh->cmdline_size + 1));
+   if (!cmdline)
+     {
+       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
+@@ -330,10 +338,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   if (!kernel_mem)
+     {
+       grub_error_pop();
+-      kernel_mem = grub_efi_allocate_pages_max (
+-          0x3fffffff, BYTES_TO_PAGES (kernel_size));
++      kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
++					       BYTES_TO_PAGES(kernel_size));
+     }
+-
++  if (!kernel_mem)
++    kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
++					     BYTES_TO_PAGES(kernel_size));
+   if (!kernel_mem)
+     {
+       grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
+diff --git a/include/grub/arm/efi/memory.h b/include/grub/arm/efi/memory.h
+index 2c64918..a4c2ec8 100644
+--- a/include/grub/arm/efi/memory.h
++++ b/include/grub/arm/efi/memory.h
+@@ -2,5 +2,6 @@
+ #include <grub/efi/memory.h>
+ 
+ #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
+ 
+ #endif /* ! GRUB_MEMORY_CPU_HEADER */
+diff --git a/include/grub/arm64/efi/memory.h b/include/grub/arm64/efi/memory.h
+index c6cb324..acb61dc 100644
+--- a/include/grub/arm64/efi/memory.h
++++ b/include/grub/arm64/efi/memory.h
+@@ -2,5 +2,6 @@
+ #include <grub/efi/memory.h>
+ 
+ #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffffffffULL
++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
+ 
+ #endif /* ! GRUB_MEMORY_CPU_HEADER */
+diff --git a/include/grub/i386/efi/memory.h b/include/grub/i386/efi/memory.h
+index 2c64918..a4c2ec8 100644
+--- a/include/grub/i386/efi/memory.h
++++ b/include/grub/i386/efi/memory.h
+@@ -2,5 +2,6 @@
+ #include <grub/efi/memory.h>
+ 
+ #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
+ 
+ #endif /* ! GRUB_MEMORY_CPU_HEADER */
+diff --git a/include/grub/ia64/efi/memory.h b/include/grub/ia64/efi/memory.h
+index 2c64918..a4c2ec8 100644
+--- a/include/grub/ia64/efi/memory.h
++++ b/include/grub/ia64/efi/memory.h
+@@ -2,5 +2,6 @@
+ #include <grub/efi/memory.h>
+ 
+ #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
+ 
+ #endif /* ! GRUB_MEMORY_CPU_HEADER */
+diff --git a/include/grub/riscv64/efi/memory.h b/include/grub/riscv64/efi/memory.h
+index c6cb324..acb61dc 100644
+--- a/include/grub/riscv64/efi/memory.h
++++ b/include/grub/riscv64/efi/memory.h
+@@ -2,5 +2,6 @@
+ #include <grub/efi/memory.h>
+ 
+ #define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffffffffULL
++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
+ 
+ #endif /* ! GRUB_MEMORY_CPU_HEADER */
+diff --git a/include/grub/x86_64/efi/memory.h b/include/grub/x86_64/efi/memory.h
+index 46e9145..e81cfb3 100644
+--- a/include/grub/x86_64/efi/memory.h
++++ b/include/grub/x86_64/efi/memory.h
+@@ -2,9 +2,11 @@
+ #include <grub/efi/memory.h>
+ 
+ #if defined (__code_model_large__)
+-#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
++#define GRUB_EFI_MAX_USABLE_ADDRESS __UINTPTR_MAX__
++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS 0x7fffffff
+ #else
+ #define GRUB_EFI_MAX_USABLE_ADDRESS 0x7fffffff
++#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
+ #endif
+ 
+ #endif /* ! GRUB_MEMORY_CPU_HEADER */
diff -pruN 2.06-2/debian/patches/riscv-adjust-march-flags-for-binutils-2.38.patch 2.06-2ubuntu16/debian/patches/riscv-adjust-march-flags-for-binutils-2.38.patch
--- 2.06-2/debian/patches/riscv-adjust-march-flags-for-binutils-2.38.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/riscv-adjust-march-flags-for-binutils-2.38.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,43 @@
+From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+Date: Sat, 29 Jan 2022 11:26:58 +0100
+Subject: riscv: adjust -march flags for binutils 2.38
+
+As of version 2.38 binutils defaults to ISA specification version
+2019-12-13. This version of the specification has has separated the
+the csr read/write (csrr*/csrw*) instructions and the fence.i from
+the I extension and put them into separate Zicsr and Zifencei
+extensions.
+
+This implies that we have to adjust the -march flag passed to the
+compiler accordingly.
+
+Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+Origin: https://lists.gnu.org/archive/html/grub-devel/2022-01/msg00173.html
+---
+ configure.ac | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/configure.ac b/configure.ac
+index 7517fc4..e3d4d72 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -852,11 +852,19 @@ if test x"$platform" != xemu ; then
+        CFLAGS="$TARGET_CFLAGS -march=rv32imac -mabi=ilp32 -Werror"
+        AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
+ 		         [grub_cv_target_cc_soft_float="-march=rv32imac -mabi=ilp32"], [])
++       # ISA spec version 20191213 factored out extensions Zicsr and Zifencei
++       CFLAGS="$TARGET_CFLAGS -march=rv32imac_zicsr_zifencei -mabi=ilp32 -Werror"
++       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
++		         [grub_cv_target_cc_soft_float="-march=rv32imac_zicsr_zifencei -mabi=ilp32"], [])
+     fi
+     if test "x$target_cpu" = xriscv64; then
+        CFLAGS="$TARGET_CFLAGS -march=rv64imac -mabi=lp64 -Werror"
+        AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
+ 		         [grub_cv_target_cc_soft_float="-march=rv64imac -mabi=lp64"], [])
++       # ISA spec version 20191213 factored out extensions Zicsr and Zifencei
++       CFLAGS="$TARGET_CFLAGS -march=rv64imac_zicsr_zifencei -mabi=lp64 -Werror"
++       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
++		         [grub_cv_target_cc_soft_float="-march=rv64imac_zicsr_zifencei -mabi=lp64"], [])
+     fi
+     if test "x$target_cpu" = xia64; then
+        CFLAGS="$TARGET_CFLAGS -mno-inline-float-divide -mno-inline-sqrt -Werror"
diff -pruN 2.06-2/debian/patches/RISC-V-Update-image-header.patch 2.06-2ubuntu16/debian/patches/RISC-V-Update-image-header.patch
--- 2.06-2/debian/patches/RISC-V-Update-image-header.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/RISC-V-Update-image-header.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,84 @@
+From: Atish Patra <atish.patra@wdc.com>
+Date: Thu, 28 Oct 2021 23:31:19 +0300
+Subject: RISC-V: Update image header
+
+Update the RISC-V Linux kernel image headers as per the current header.
+
+Reference:
+<Linux kernel source>/Documentation/riscv/boot-image-header.rst
+
+Signed-off-by: Atish Patra <atish.patra@wdc.com>
+Origin: https://lists.gnu.org/archive/html/grub-devel/2021-10/msg00213.html
+---
+ include/grub/riscv32/linux.h | 15 ++++++++-------
+ include/grub/riscv64/linux.h | 15 ++++++++-------
+ 2 files changed, 16 insertions(+), 14 deletions(-)
+
+diff --git a/include/grub/riscv32/linux.h b/include/grub/riscv32/linux.h
+index 512b777..de0dbdc 100644
+--- a/include/grub/riscv32/linux.h
++++ b/include/grub/riscv32/linux.h
+@@ -19,20 +19,21 @@
+ #ifndef GRUB_RISCV32_LINUX_HEADER
+ #define GRUB_RISCV32_LINUX_HEADER 1
+ 
+-#define GRUB_LINUX_RISCV_MAGIC_SIGNATURE 0x52534356 /* 'RSCV' */
++#define GRUB_LINUX_RISCV_MAGIC_SIGNATURE 0x05435352 /* 'RSC\0x5' */
+ 
+-/* From linux/Documentation/riscv/booting.txt */
++/* From linux/Documentation/riscv/boot-image-header.rst */
+ struct linux_riscv_kernel_header
+ {
+   grub_uint32_t code0;		/* Executable code */
+   grub_uint32_t code1;		/* Executable code */
+-  grub_uint64_t text_offset;	/* Image load offset */
+-  grub_uint64_t res0;		/* reserved */
+-  grub_uint64_t res1;		/* reserved */
++  grub_uint64_t text_offset;	/* Image load offset, little endian */
++  grub_uint64_t image_size;	/* Effective Image size, little endian */
++  grub_uint64_t flags;		/* kernel flags, little endian */
++  grub_uint32_t version;	/* Version of this header */
++  grub_uint32_t res1;		/* reserved */
+   grub_uint64_t res2;		/* reserved */
+   grub_uint64_t res3;		/* reserved */
+-  grub_uint64_t res4;		/* reserved */
+-  grub_uint32_t magic;		/* Magic number, little endian, "RSCV" */
++  grub_uint32_t magic;		/* Magic number, little endian, "RSC\x05" */
+   grub_uint32_t hdr_offset;	/* Offset of PE/COFF header */
+ };
+ 
+diff --git a/include/grub/riscv64/linux.h b/include/grub/riscv64/linux.h
+index 3630c30..7c28bc9 100644
+--- a/include/grub/riscv64/linux.h
++++ b/include/grub/riscv64/linux.h
+@@ -19,22 +19,23 @@
+ #ifndef GRUB_RISCV64_LINUX_HEADER
+ #define GRUB_RISCV64_LINUX_HEADER 1
+ 
+-#define GRUB_LINUX_RISCV_MAGIC_SIGNATURE 0x52534356 /* 'RSCV' */
++#define GRUB_LINUX_RISCV_MAGIC_SIGNATURE 0x05435352 /* 'RSC\0x5' */
+ 
+ #define GRUB_EFI_PE_MAGIC	0x5A4D
+ 
+-/* From linux/Documentation/riscv/booting.txt */
++/* From linux/Documentation/riscv/boot-image-header.rst */
+ struct linux_riscv_kernel_header
+ {
+   grub_uint32_t code0;		/* Executable code */
+   grub_uint32_t code1;		/* Executable code */
+-  grub_uint64_t text_offset;	/* Image load offset */
+-  grub_uint64_t res0;		/* reserved */
+-  grub_uint64_t res1;		/* reserved */
++  grub_uint64_t text_offset;	/* Image load offset, little endian */
++  grub_uint64_t image_size;	/* Effective Image size, little endian */
++  grub_uint64_t flags;		/* kernel flags, little endian */
++  grub_uint32_t version;	/* Version of this header */
++  grub_uint32_t res1;		/* reserved */
+   grub_uint64_t res2;		/* reserved */
+   grub_uint64_t res3;		/* reserved */
+-  grub_uint64_t res4;		/* reserved */
+-  grub_uint32_t magic;		/* Magic number, little endian, "RSCV" */
++  grub_uint32_t magic;		/* Magic number, little endian, "RSC\x05" */
+   grub_uint32_t hdr_offset;	/* Offset of PE/COFF header */
+ };
+ 
diff -pruN 2.06-2/debian/patches/RISC-V-Use-common-linux-loader.patch 2.06-2ubuntu16/debian/patches/RISC-V-Use-common-linux-loader.patch
--- 2.06-2/debian/patches/RISC-V-Use-common-linux-loader.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/RISC-V-Use-common-linux-loader.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,120 @@
+From: Atish Patra <atish.patra@wdc.com>
+Date: Thu, 28 Oct 2021 23:31:20 +0300
+Subject: RISC-V: Use common linux loader
+
+RISC-V doesn't have to do anything very different from other architectures
+to loader EFI stub linux kernel. As a result, just use the common linux
+loader instead of defining a RISC-V specific linux loader.
+
+Signed-off-by: Atish Patra <atish.patra@wdc.com>
+Origin: https://lists.gnu.org/archive/html/grub-devel/2021-10/msg00211.html
+---
+ grub-core/Makefile.core.def    |  4 +--
+ grub-core/loader/riscv/linux.c | 59 ------------------------------------------
+ include/grub/riscv32/linux.h   |  1 +
+ include/grub/riscv64/linux.h   |  1 +
+ 4 files changed, 4 insertions(+), 61 deletions(-)
+ delete mode 100644 grub-core/loader/riscv/linux.c
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index b36cf66..0536575 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -1809,8 +1809,8 @@ module = {
+   arm_efi = loader/efi/linux.c;
+   arm_uboot = loader/arm/linux.c;
+   arm64 = loader/efi/linux.c;
+-  riscv32 = loader/riscv/linux.c;
+-  riscv64 = loader/riscv/linux.c;
++  riscv32 = loader/efi/linux.c;
++  riscv64 = loader/efi/linux.c;
+   common = loader/linux.c;
+   common = lib/cmdline.c;
+   enable = noemu;
+diff --git a/grub-core/loader/riscv/linux.c b/grub-core/loader/riscv/linux.c
+deleted file mode 100644
+index d17c488..0000000
+--- a/grub-core/loader/riscv/linux.c
++++ /dev/null
+@@ -1,59 +0,0 @@
+-/*
+- *  GRUB  --  GRand Unified Bootloader
+- *  Copyright (C) 2018  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/command.h>
+-#include <grub/dl.h>
+-#include <grub/lib/cmdline.h>
+-
+-GRUB_MOD_LICENSE ("GPLv3+");
+-
+-static grub_err_t
+-grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+-		 int argc __attribute__ ((unused)),
+-		 char *argv[] __attribute__ ((unused)))
+-{
+-  grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, N_("Linux not supported yet"));
+-
+-  return grub_errno;
+-}
+-
+-static grub_err_t
+-grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+-		int argc __attribute__ ((unused)),
+-		char *argv[] __attribute__ ((unused)))
+-{
+-  grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, N_("Linux not supported yet"));
+-
+-  return grub_errno;
+-}
+-
+-static grub_command_t cmd_linux, cmd_initrd;
+-
+-GRUB_MOD_INIT (linux)
+-{
+-  cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0,
+-				     N_("Load Linux."));
+-  cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0,
+-				      N_("Load initrd."));
+-}
+-
+-GRUB_MOD_FINI (linux)
+-{
+-  grub_unregister_command (cmd_linux);
+-  grub_unregister_command (cmd_initrd);
+-}
+diff --git a/include/grub/riscv32/linux.h b/include/grub/riscv32/linux.h
+index de0dbdc..706c690 100644
+--- a/include/grub/riscv32/linux.h
++++ b/include/grub/riscv32/linux.h
+@@ -38,5 +38,6 @@ struct linux_riscv_kernel_header
+ };
+ 
+ #define linux_arch_kernel_header linux_riscv_kernel_header
++# define GRUB_LINUX_ARCH_MAGIC_SIGNATURE GRUB_LINUX_RISCV_MAGIC_SIGNATURE
+ 
+ #endif /* ! GRUB_RISCV32_LINUX_HEADER */
+diff --git a/include/grub/riscv64/linux.h b/include/grub/riscv64/linux.h
+index 7c28bc9..88d5df7 100644
+--- a/include/grub/riscv64/linux.h
++++ b/include/grub/riscv64/linux.h
+@@ -40,5 +40,6 @@ struct linux_riscv_kernel_header
+ };
+ 
+ #define linux_arch_kernel_header linux_riscv_kernel_header
++# define GRUB_LINUX_ARCH_MAGIC_SIGNATURE GRUB_LINUX_RISCV_MAGIC_SIGNATURE
+ 
+ #endif /* ! GRUB_RISCV64_LINUX_HEADER */
diff -pruN 2.06-2/debian/patches/series 2.06-2ubuntu16/debian/patches/series
--- 2.06-2/debian/patches/series	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/series	2022-12-09 16:11:44.000000000 +0000
@@ -1,3 +1,11 @@
+riscv-adjust-march-flags-for-binutils-2.38.patch
+loader-drop-argv-argument-in-grub_initrd_load.patch
+efi-add-definition-of-LoadFile2-protocol.patch
+efi-implemented-LoadFile2-initrd-loading-protocol-fo.patch
+linux-ignore-FDT-unless-we-need-to-modify-it.patch
+loader-Move-arm64-linux-loader-to-common-code.patch
+RISC-V-Update-image-header.patch
+RISC-V-Use-common-linux-loader.patch
 olpc-prefix-hack.patch
 core-in-fs.patch
 dpkg-version-comparison.patch
@@ -14,12 +22,13 @@ install-efi-fallback.patch
 mkconfig-ubuntu-recovery.patch
 install-locale-langpack.patch
 mkconfig-nonexistent-loopback.patch
+no-insmod-on-sb.patch
 default-grub-d.patch
 blacklist-1440x900x32.patch
 mkconfig-ubuntu-distributor.patch
-linuxefi.patch
+ubuntu-linuxefi.patch
 mkconfig-signed-kernel.patch
-install-signed.patch
+ubuntu-install-signed.patch
 wubi-no-windows.patch
 maybe-quiet.patch
 install-efi-adjust-distributor.patch
@@ -35,7 +44,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
@@ -44,13 +53,11 @@ 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
 uefi-secure-boot-cryptomount.patch
 efi-variable-storage-minimise-writes.patch
-grub-install-removable-shim.patch
 dejavu-font-path.patch
 xen-no-xsm-policy-in-non-xsm-options.patch
 pc-verifiers-module.patch
@@ -60,3 +67,145 @@ tpm-unknown-error-non-fatal.patch
 xfs-fix-v4-superblock.patch
 tests-ahci-update-qemu-device-name.patch
 minilzo-2.10.patch
+zstd-require-8-byte-buffer.patch
+ubuntu-zfs-enhance-support.patch
+ubuntu-zfs-gfxpayload-keep-default.patch
+ubuntu-zfs-mkconfig-ubuntu-recovery.patch
+ubuntu-zfs-mkconfig-ubuntu-distributor.patch
+ubuntu-zfs-mkconfig-signed-kernel.patch
+ubuntu-zfs-maybe-quiet.patch
+ubuntu-zfs-quick-boot.patch
+ubuntu-zfs-gfxpayload-dynamic.patch
+ubuntu-zfs-vt-handoff.patch
+ubuntu-zfs-mkconfig-recovery-title.patch
+ubuntu-zfs-insmod-xzio-and-lzopio-on-xen.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-efi-allow-loopmount-chainload.patch
+0076-ubuntu-Make-the-linux-command-in-EFI-grub-always-try.patch
+ubuntu-resilient-boot-ignore-alternative-esps.patch
+ubuntu-resilient-boot-boot-order.patch
+ubuntu-speed-zsys-history.patch
+ubuntu-flavour-order.patch
+ubuntu-dont-verify-loopback-images.patch
+ubuntu-recovery-dis_ucode_ldr.patch
+ubuntu-linuxefi-arm64.patch
+ubuntu-linuxefi-arm64-set-base-addr.patch
+ubuntu-add-initrd-less-boot-messages.patch
+rhboot-f34-make-exit-take-a-return-code.patch
+rhboot-f34-dont-use-int-for-efi-status.patch
+rhboot-f34-make-pmtimer-tsc-calibration-fast.patch
+suse-grub.texi-add-net_bootp6-document.patch
+suse-add-support-for-UEFI-network-protocols.patch
+suse-AUDIT-0-http-boot-tracker-bug.patch
+rhboot-f34-efinet-also-use-the-firmware-acceleration-for-http.patch
+0241-Call-hwmatch-only-on-the-grub-pc-platform.patch
+cherrypick-efinet-correct-closing-snp-protocol.patch
+cherrypick-efi-grub_efi_close_protocol.patch
+no-devicetree-if-secure-boot.patch
+0077-ubuntu-Update-the-linux-boot-protocol-version-check.patch
+0096-linuxefi-fail-kernel-validation-without-shim-protoco.patch
+0099-chainloader-Avoid-a-double-free-when-validation-fail.patch
+0105-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch
+ubuntu-verifiers-last.patch
+ubuntu-fuse3.patch
+ubuntu-os-prober-auto.patch
+efi-correct-struct-grub_efi_boot_services.patch
+efi-implement-grub_efi_run_image.patch
+fat-fix-listing-the-root-directory.patch
+efivar-check-that-efivarfs-is-writeable.patch
+linuxefi-do-not-validate-kernels-twice.patch
+fdt-add-debug-output-to-devicetree-command.patch
+efi-EFI-Device-Tree-Fixup-Protocol.patch
+ubuntu-disable-LOAD-FILE2-protocol-for-initrd-on-ARM.patch
+0129-loader-efi-chainloader-grub_load_and_start_image-doe.patch
+0130-loader-efi-chainloader-simplify-the-loader-state.patch
+0131-commands-boot-Add-API-to-pass-context-to-loader.patch
+0132-loader-efi-chainloader-Use-grub_loader_set_ex.patch
+0133-loader-i386-efi-linux-Use-grub_loader_set_ex.patch
+0134-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch
+0135-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
+0136-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch
+0137-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
+0138-video-readers-png-Refuse-to-handle-multiple-image-he.patch
+0139-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
+0140-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch
+0141-video-readers-png-Sanity-check-some-huffman-codes.patch
+0142-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
+0143-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch
+0144-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch
+0145-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch
+0146-normal-charset-Fix-array-out-of-bounds-formatting-un.patch
+0147-net-netbuff-Block-overly-large-netbuff-allocs.patch
+0148-net-ip-Do-IP-fragment-maths-safely.patch
+0149-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch
+0150-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch
+0151-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
+0152-net-tftp-Avoid-a-trivial-UAF.patch
+0153-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch
+0154-net-http-Fix-OOB-write-for-split-http-headers.patch
+0155-net-http-Error-out-on-headers-with-LF-without-CR.patch
+0156-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch
+0157-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
+0158-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
+0159-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch
+0160-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
+0161-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
+linux_xen-Properly-load-multiple-initrd-files.patch
+linux_xen-Properly-order-multiple-initrd-files.patch
+linuxefi-Invalidate-i-cache-before-starting-the-kern.patch
+rhboot-try-to-pick-better-locations-for-kernel-and-initrd.patch
+rhboot-bounce-buffers.patch
+font-Reject-glyphs-exceeds-font-max_glyph_width-or-font-m.patch
+font-Fix-size-overflow-in-grub_font_get_glyph_internal.patch
+font-Fix-several-integer-overflows-in-grub_font_construct.patch
+font-Remove-grub_font_dup_glyph.patch
+font-Fix-integer-overflow-in-ensure_comb_space.patch
+font-Fix-integer-overflow-in-BMP-index.patch
+font-Fix-integer-underflow-in-binary-search-of-char-index.patch
+kern-efi-sb-Enforce-verification-of-font-files.patch
+fbutil-Fix-integer-overflow.patch
+font-Fix-an-integer-underflow-in-blit_comb.patch
+font-Harden-grub_font_blit_glyph-and-grub_font_blit_glyph.patch
+font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch
+normal-charset-Fix-an-integer-overflow-in-grub_unicode_ag.patch
+font-Try-opening-fonts-from-the-bundled-memdisk.patch
+commands-efi-tpm-Refine-the-status-of-log-event.patch
+commands-efi-tpm-Use-grub_strcpy-instead-of-grub_memcpy.patch
+efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch
+tests-Explicitly-unset-SOURCE_DATE_EPOCH-before-running-f.patch
+rhboot-efi-rearrange-grub-cmd-linux.patch
+rhboot-efi-kernel-allocator.patch
+rhboot-efi-initrd-above-4gb.patch
+rhboot-efi-allocate-kernel-as-code.patch
+rhboot-efi-enumerated-array-for-allocation-choice.patch
+rhboot-efi-split-allocation-policy.patch
+rhboot-efi-allocate-in-kernel-bounds.patch
+rhboot-efi-allocate-kernel-as-code-for-real.patch
+rhboot-efi-fix-incorrect-array-size.patch
+ubuntu-rhboot-cast-fixups.patch
+2.12-mm/0194-mm-Clarify-grub_real_malloc.patch
+2.12-mm/0195-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch
+2.12-mm/0196-mm-Document-grub_free.patch
+2.12-mm/0197-mm-Document-grub_mm_init_region.patch
+2.12-mm/0198-kern-Remove-trailing-whitespaces.patch
+2.12-mm/0199-mm-Document-GRUB-internal-memory-management-structur.patch
+2.12-mm/0200-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch
+2.12-mm/0201-mm-When-adding-a-region-merge-with-region-after-as-w.patch
+2.12-mm/0202-mm-Debug-support-for-region-operations.patch
+2.12-mm/0203-mm-Drop-unused-unloading-of-modules-on-OOM.patch
+2.12-mm/0204-mm-Allow-dynamically-requesting-additional-memory-re.patch
+2.12-mm/0205-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch
+2.12-mm/0206-kern-efi-mm-Extract-function-to-add-memory-regions.patch
+2.12-mm/0207-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch
+2.12-mm/0208-kern-efi-mm-Implement-runtime-addition-of-pages.patch
+2.12-mm/0209-efi-Increase-default-memory-allocation-to-32-MiB.patch
+2.12-mm/0210-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch
+ubuntu-efi-loader-code.patch
diff -pruN 2.06-2/debian/patches/skip-grub_cmd_set_date.patch 2.06-2ubuntu16/debian/patches/skip-grub_cmd_set_date.patch
--- 2.06-2/debian/patches/skip-grub_cmd_set_date.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/skip-grub_cmd_set_date.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From dc8f60ab6ca24cb871fe17955385138d43712727 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 +11,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 aac120a..1bb5be4 100644
 --- a/tests/grub_cmd_set_date.in
 +++ b/tests/grub_cmd_set_date.in
 @@ -1,6 +1,9 @@
diff -pruN 2.06-2/debian/patches/suse-add-support-for-UEFI-network-protocols.patch 2.06-2ubuntu16/debian/patches/suse-add-support-for-UEFI-network-protocols.patch
--- 2.06-2/debian/patches/suse-add-support-for-UEFI-network-protocols.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/suse-add-support-for-UEFI-network-protocols.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,4941 @@
+From: Michael Chang <mchang@suse.com>
+Date: Wed, 22 Feb 2017 14:27:50 +0800
+Subject: Support UEFI networking protocols
+
+References: fate#320130, bsc#1015589, bsc#1076132
+Patch-Mainline: no
+
+V1:
+  * Add preliminary support of UEFI networking protocols
+  * Support UEFI HTTPS Boot
+
+V2:
+  * Workaround http data access in firmware
+  * Fix DNS device path parsing for efinet device
+  * Relaxed UEFI Protocol requirement
+  * Support Intel OPA (Omni-Path Architecture) PXE Boot
+
+V3:
+  * Fix bufio in calculating address of next_buf
+  * Check HTTP respond code
+  * Use HEAD request method to test before GET
+  * Finish HTTP transaction in one go
+  * Fix bsc#1076132
+
+V4:
+  * Add fs_ prefix with upstream commit
+    ad4bfeec5 Change fs functions to add fs_ prefix
+
+V5:
+  * Use overflow checking primitives where the arithmetic expression for
+    buffer allocations may include unvalidated data
+  * Use grub_calloc for overflow check and return NULL when it would
+    occur.
+
+V6:
+  * Don't force grub_print_error if no best route found as boot process
+    could be interrupted by logged error. The default interface will be
+    used as fallback in this case
+---
+ grub-core/Makefile.core.def        |    6 +
+ grub-core/io/bufio.c               |    2 +-
+ grub-core/kern/efi/efi.c           |   96 ++-
+ grub-core/net/drivers/efi/efinet.c |   27 +
+ grub-core/net/efi/dhcp.c           |  399 ++++++++++
+ grub-core/net/efi/http.c           |  424 +++++++++++
+ grub-core/net/efi/ip4_config.c     |  409 ++++++++++
+ grub-core/net/efi/ip6_config.c     |  430 +++++++++++
+ grub-core/net/efi/net.c            | 1440 ++++++++++++++++++++++++++++++++++++
+ grub-core/net/efi/pxe.c            |  424 +++++++++++
+ grub-core/net/net.c                |   74 ++
+ include/grub/efi/api.h             |  181 ++++-
+ include/grub/efi/dhcp.h            |  343 +++++++++
+ include/grub/efi/http.h            |  215 ++++++
+ include/grub/net/efi.h             |  144 ++++
+ 15 files changed, 4577 insertions(+), 37 deletions(-)
+ create mode 100644 grub-core/net/efi/dhcp.c
+ create mode 100644 grub-core/net/efi/http.c
+ create mode 100644 grub-core/net/efi/ip4_config.c
+ create mode 100644 grub-core/net/efi/ip6_config.c
+ create mode 100644 grub-core/net/efi/net.c
+ create mode 100644 grub-core/net/efi/pxe.c
+ create mode 100644 include/grub/efi/dhcp.h
+ create mode 100644 include/grub/efi/http.h
+ create mode 100644 include/grub/net/efi.h
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 0b5b4e7..3b06462 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -2324,6 +2324,12 @@ module = {
+   common = net/ethernet.c;
+   common = net/arp.c;
+   common = net/netbuff.c;
++  efi = net/efi/net.c;
++  efi = net/efi/http.c;
++  efi = net/efi/pxe.c;
++  efi = net/efi/ip4_config.c;
++  efi = net/efi/ip6_config.c;
++  efi = net/efi/dhcp.c;
+ };
+ 
+ module = {
+diff --git a/grub-core/io/bufio.c b/grub-core/io/bufio.c
+index a458c3a..1637731 100644
+--- a/grub-core/io/bufio.c
++++ b/grub-core/io/bufio.c
+@@ -139,7 +139,7 @@ grub_bufio_read (grub_file_t file, char *buf, grub_size_t len)
+     return res;
+ 
+   /* Need to read some more.  */
+-  next_buf = (file->offset + res + len - 1) & ~((grub_off_t) bufio->block_size - 1);
++  next_buf = (grub_divmod64 (file->offset + res + len - 1, bufio->block_size, NULL)) * bufio->block_size;
+   /* Now read between file->offset + res and bufio->buffer_at.  */
+   if (file->offset + res < next_buf)
+     {
+diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
+index ae9885e..a3cae1e 100644
+--- a/grub-core/kern/efi/efi.c
++++ b/grub-core/kern/efi/efi.c
+@@ -755,7 +755,7 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
+ 	      {
+ 		grub_efi_ipv4_device_path_t *ipv4
+ 		  = (grub_efi_ipv4_device_path_t *) dp;
+-		grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x)",
++		grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x",
+ 			     (unsigned) ipv4->local_ip_address[0],
+ 			     (unsigned) ipv4->local_ip_address[1],
+ 			     (unsigned) ipv4->local_ip_address[2],
+@@ -768,33 +768,60 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
+ 			     (unsigned) ipv4->remote_port,
+ 			     (unsigned) ipv4->protocol,
+ 			     (unsigned) ipv4->static_ip_address);
++		if (len == sizeof (*ipv4))
++		  {
++		    grub_printf (",%u.%u.%u.%u,%u.%u.%u.%u",
++			(unsigned) ipv4->gateway_ip_address[0],
++			(unsigned) ipv4->gateway_ip_address[1],
++			(unsigned) ipv4->gateway_ip_address[2],
++			(unsigned) ipv4->gateway_ip_address[3],
++			(unsigned) ipv4->subnet_mask[0],
++			(unsigned) ipv4->subnet_mask[1],
++			(unsigned) ipv4->subnet_mask[2],
++			(unsigned) ipv4->subnet_mask[3]);
++		  }
++		grub_printf (")");
+ 	      }
+ 	      break;
+ 	    case GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE:
+ 	      {
+ 		grub_efi_ipv6_device_path_t *ipv6
+ 		  = (grub_efi_ipv6_device_path_t *) dp;
+-		grub_printf ("/IPv6(%x:%x:%x:%x:%x:%x:%x:%x,%x:%x:%x:%x:%x:%x:%x:%x,%u,%u,%x,%x)",
+-			     (unsigned) ipv6->local_ip_address[0],
+-			     (unsigned) ipv6->local_ip_address[1],
+-			     (unsigned) ipv6->local_ip_address[2],
+-			     (unsigned) ipv6->local_ip_address[3],
+-			     (unsigned) ipv6->local_ip_address[4],
+-			     (unsigned) ipv6->local_ip_address[5],
+-			     (unsigned) ipv6->local_ip_address[6],
+-			     (unsigned) ipv6->local_ip_address[7],
+-			     (unsigned) ipv6->remote_ip_address[0],
+-			     (unsigned) ipv6->remote_ip_address[1],
+-			     (unsigned) ipv6->remote_ip_address[2],
+-			     (unsigned) ipv6->remote_ip_address[3],
+-			     (unsigned) ipv6->remote_ip_address[4],
+-			     (unsigned) ipv6->remote_ip_address[5],
+-			     (unsigned) ipv6->remote_ip_address[6],
+-			     (unsigned) ipv6->remote_ip_address[7],
++		grub_printf ("/IPv6(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,%u,%u,%x,%x",
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[0]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[1]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[2]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[3]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[4]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[5]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[6]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->local_ip_address[7]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[0]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[1]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[2]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[3]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[4]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[5]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[6]),
++			     (unsigned) grub_be_to_cpu16 (ipv6->remote_ip_address[7]),
+ 			     (unsigned) ipv6->local_port,
+ 			     (unsigned) ipv6->remote_port,
+ 			     (unsigned) ipv6->protocol,
+ 			     (unsigned) ipv6->static_ip_address);
++		if (len == sizeof (*ipv6))
++		  {
++		    grub_printf (",%u,%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
++			(unsigned) ipv6->prefix_length,
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[0]),
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[1]),
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[2]),
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[3]),
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[4]),
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[5]),
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[6]),
++			(unsigned) grub_be_to_cpu16 (ipv6->gateway_ip_address[7]));
++		  }
++		grub_printf (")");
+ 	      }
+ 	      break;
+ 	    case GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE:
+@@ -834,6 +861,39 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
+ 	      dump_vendor_path ("Messaging",
+ 				(grub_efi_vendor_device_path_t *) dp);
+ 	      break;
++	    case GRUB_EFI_URI_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_uri_device_path_t *uri
++		  = (grub_efi_uri_device_path_t *) dp;
++		grub_printf ("/URI(%s)", uri->uri);
++	      }
++	      break;
++	    case GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE:
++	      {
++		grub_efi_dns_device_path_t *dns
++		  = (grub_efi_dns_device_path_t *) dp;
++		if (dns->is_ipv6)
++		  {
++		    grub_printf ("/DNS(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x)",
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[0]) >> 16),
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[0])),
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[1]) >> 16),
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[1])),
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[2]) >> 16),
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[2])),
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[3]) >> 16),
++			    (grub_uint16_t)(grub_be_to_cpu32(dns->dns_server_ip[0].addr[3])));
++		  }
++		else
++		  {
++		    grub_printf ("/DNS(%d.%d.%d.%d)",
++			  dns->dns_server_ip[0].v4.addr[0],
++			  dns->dns_server_ip[0].v4.addr[1],
++			  dns->dns_server_ip[0].v4.addr[2],
++			  dns->dns_server_ip[0].v4.addr[3]);
++		  }
++	      }
++	      break;
+ 	    default:
+ 	      grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype);
+ 	      break;
+diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
+index 82a28fb..f189209 100644
+--- a/grub-core/net/drivers/efi/efinet.c
++++ b/grub-core/net/drivers/efi/efinet.c
+@@ -24,6 +24,7 @@
+ #include <grub/efi/efi.h>
+ #include <grub/i18n.h>
+ #include <grub/net/netbuff.h>
++#include <grub/env.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -481,6 +482,17 @@ grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *u
+ 
+   ldp = grub_efi_find_last_device_path (ddp);
+ 
++  /* Skip the DNS Device */
++  if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
++      && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE)
++    {
++      ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++      ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++      ldp->length = sizeof (*ldp);
++
++      ldp = grub_efi_find_last_device_path (ddp);
++    }
++
+   if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
+       || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
+           && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
+@@ -744,6 +756,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 	if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
+ 	    || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
+ 		&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE
++		&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE
+ 		&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE))
+ 	  continue;
+ 	dup_dp = grub_efi_duplicate_device_path (dp);
+@@ -758,6 +771,15 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 	    dup_ldp->length = sizeof (*dup_ldp);
+ 	  }
+ 
++	dup_ldp = grub_efi_find_last_device_path (dup_dp);
++	if (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE)
++	  {
++	    dup_ldp = grub_efi_find_last_device_path (dup_dp);
++	    dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++	    dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++	    dup_ldp->length = sizeof (*dup_ldp);
++	  }
++
+ 	dup_ldp = grub_efi_find_last_device_path (dup_dp);
+ 	dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+ 	dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+@@ -816,6 +838,9 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
+ 
+ GRUB_MOD_INIT(efinet)
+ {
++  if (grub_efi_net_config)
++    return;
++
+   grub_efinet_findcards ();
+   grub_efi_net_config = grub_efi_net_config_real;
+ }
+@@ -827,5 +852,7 @@ GRUB_MOD_FINI(efinet)
+   FOR_NET_CARDS_SAFE (card, next) 
+     if (card->driver == &efidriver)
+       grub_net_card_unregister (card);
++
++  grub_efi_net_config = NULL;
+ }
+ 
+diff --git a/grub-core/net/efi/dhcp.c b/grub-core/net/efi/dhcp.c
+new file mode 100644
+index 0000000..4001c04
+--- /dev/null
++++ b/grub-core/net/efi/dhcp.c
+@@ -0,0 +1,399 @@
++#include <grub/mm.h>
++#include <grub/command.h>
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/misc.h>
++#include <grub/net/efi.h>
++#include <grub/charset.h>
++
++#ifdef GRUB_EFI_NET_DEBUG
++static void
++dhcp4_mode_print (grub_efi_dhcp4_mode_data_t *mode)
++{
++    switch (mode->state)
++      {
++	case GRUB_EFI_DHCP4_STOPPED:
++	  grub_printf ("STATE: STOPPED\n");
++	  break;
++	case GRUB_EFI_DHCP4_INIT:
++	  grub_printf ("STATE: INIT\n");
++	  break;
++	case GRUB_EFI_DHCP4_SELECTING:
++	  grub_printf ("STATE: SELECTING\n");
++	  break;
++	case GRUB_EFI_DHCP4_REQUESTING:
++	  grub_printf ("STATE: REQUESTING\n");
++	  break;
++	case GRUB_EFI_DHCP4_BOUND:
++	  grub_printf ("STATE: BOUND\n");
++	  break;
++	case GRUB_EFI_DHCP4_RENEWING:
++	  grub_printf ("STATE: RENEWING\n");
++	  break;
++	case GRUB_EFI_DHCP4_REBINDING:
++	  grub_printf ("STATE: REBINDING\n");
++	  break;
++	case GRUB_EFI_DHCP4_INIT_REBOOT:
++	  grub_printf ("STATE: INIT_REBOOT\n");
++	  break;
++	case GRUB_EFI_DHCP4_REBOOTING:
++	  grub_printf ("STATE: REBOOTING\n");
++	  break;
++	default:
++	  grub_printf ("STATE: UNKNOWN\n");
++	  break;
++      }
++
++    grub_printf ("CLIENT_ADDRESS: %u.%u.%u.%u\n",
++      mode->client_address[0],
++      mode->client_address[1],
++      mode->client_address[2],
++      mode->client_address[3]);
++    grub_printf ("SERVER_ADDRESS: %u.%u.%u.%u\n",
++      mode->server_address[0],
++      mode->server_address[1],
++      mode->server_address[2],
++      mode->server_address[3]);
++    grub_printf ("SUBNET_MASK: %u.%u.%u.%u\n",
++      mode->subnet_mask[0],
++      mode->subnet_mask[1],
++      mode->subnet_mask[2],
++      mode->subnet_mask[3]);
++    grub_printf ("ROUTER_ADDRESS: %u.%u.%u.%u\n",
++      mode->router_address[0],
++      mode->router_address[1],
++      mode->router_address[2],
++      mode->router_address[3]);
++}
++#endif
++
++static grub_efi_ipv4_address_t *
++grub_efi_dhcp4_parse_dns (grub_efi_dhcp4_protocol_t *dhcp4, grub_efi_dhcp4_packet_t *reply_packet)
++{
++  grub_efi_dhcp4_packet_option_t **option_list;
++  grub_efi_status_t status;
++  grub_efi_uint32_t option_count = 0;
++  grub_efi_uint32_t i;
++
++  status = efi_call_4 (dhcp4->parse, dhcp4, reply_packet, &option_count, NULL);
++
++  if (status != GRUB_EFI_BUFFER_TOO_SMALL)
++    return NULL;
++
++  option_list = grub_calloc (option_count, sizeof(*option_list));
++  if (!option_list)
++    return NULL;
++
++  status = efi_call_4 (dhcp4->parse, dhcp4, reply_packet, &option_count, option_list);
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (option_list);
++      return NULL;
++    }
++
++  for (i = 0; i < option_count; ++i)
++    {
++      if (option_list[i]->op_code == 6)
++	{
++	  grub_efi_ipv4_address_t *dns_address;
++
++	  if (((option_list[i]->length & 0x3) != 0) || (option_list[i]->length == 0))
++	    continue;
++
++	  /* We only contact primary dns */
++	  dns_address = grub_malloc (sizeof (*dns_address));
++	  if (!dns_address)
++	    {
++	      grub_free (option_list);
++	      return NULL;
++	    }
++	  grub_memcpy (dns_address, option_list[i]->data, sizeof (dns_address));
++	  grub_free (option_list);
++	  return dns_address;
++	}
++    }
++
++  grub_free (option_list);
++  return NULL;
++}
++
++#if 0
++/* Somehow this doesn't work ... */
++static grub_err_t
++grub_cmd_efi_bootp (struct grub_command *cmd __attribute__ ((unused)),
++		    int argc __attribute__ ((unused)),
++		    char **args __attribute__ ((unused)))
++{
++  struct grub_efi_net_device *dev;
++  for (dev = net_devices; dev; dev = dev->next)
++    {
++      grub_efi_pxe_t *pxe = dev->ip4_pxe;
++      grub_efi_pxe_mode_t *mode = pxe->mode;
++      grub_efi_status_t status;
++
++      if (!mode->started)
++	{
++	  status = efi_call_2 (pxe->start, pxe, 0);
++
++	  if (status != GRUB_EFI_SUCCESS)
++	      grub_printf ("Couldn't start PXE\n");
++	}
++
++      status = efi_call_2 (pxe->dhcp, pxe, 0);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("dhcp4 configure failed, %d\n", (int)status);
++	  continue;
++	}
++
++      dev->prefer_ip6 = 0;
++    }
++
++  return GRUB_ERR_NONE;
++}
++#endif
++
++static grub_err_t
++grub_cmd_efi_bootp (struct grub_command *cmd __attribute__ ((unused)),
++		    int argc,
++		    char **args)
++{
++  struct grub_efi_net_device *netdev;
++
++  for (netdev = net_devices; netdev; netdev = netdev->next)
++    {
++      grub_efi_status_t status;
++      grub_efi_dhcp4_mode_data_t mode;
++      grub_efi_dhcp4_config_data_t config;
++      grub_efi_dhcp4_packet_option_t *options;
++      grub_efi_ipv4_address_t *dns_address;
++      grub_efi_net_ip_manual_address_t net_ip;
++      grub_efi_net_ip_address_t ip_addr;
++      grub_efi_net_interface_t *inf = NULL;
++
++      if (argc > 0 && grub_strcmp (netdev->card_name, args[0]) != 0)
++	continue;
++
++      grub_memset (&config, 0, sizeof(config));
++
++      config.option_count = 1;
++      options = grub_malloc (sizeof(*options) + 2);
++      /* Parameter request list */
++      options->op_code = 55;
++      options->length = 3;
++      /* subnet mask */
++      options->data[0] = 1;
++      /* router */
++      options->data[1] = 3;
++      /* DNS */
++      options->data[2] = 6;
++      config.option_list = &options;
++
++      /* FIXME: What if the dhcp has bounded */
++      status = efi_call_2 (netdev->dhcp4->configure, netdev->dhcp4, &config);
++      grub_free (options);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("dhcp4 configure failed, %d\n", (int)status);
++	  continue;
++	}
++
++      status = efi_call_2 (netdev->dhcp4->start, netdev->dhcp4, NULL);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("dhcp4 start failed, %d\n", (int)status);
++	  continue;
++	}
++
++      status = efi_call_2 (netdev->dhcp4->get_mode_data, netdev->dhcp4, &mode);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("dhcp4 get mode failed, %d\n", (int)status);
++	  continue;
++	}
++
++#ifdef GRUB_EFI_NET_DEBUG
++      dhcp4_mode_print (&mode);
++#endif
++
++      for (inf = netdev->net_interfaces; inf; inf = inf->next)
++	if (inf->prefer_ip6 == 0)
++	  break;
++
++      grub_memcpy (net_ip.ip4.address, mode.client_address, sizeof (net_ip.ip4.address));
++      grub_memcpy (net_ip.ip4.subnet_mask, mode.subnet_mask, sizeof (net_ip.ip4.subnet_mask));
++
++      if (!inf)
++	{
++	  char *name = grub_xasprintf ("%s:dhcp", netdev->card_name);
++
++	  net_ip.is_ip6 = 0;
++	  inf = grub_efi_net_create_interface (netdev,
++		    name,
++		    &net_ip,
++		    1);
++	  grub_free (name);
++	}
++      else
++	{
++	  efi_net_interface_set_address (inf, &net_ip, 1);
++	}
++
++      grub_memcpy (ip_addr.ip4, mode.router_address, sizeof (ip_addr.ip4));
++      efi_net_interface_set_gateway (inf, &ip_addr);
++
++      dns_address = grub_efi_dhcp4_parse_dns (netdev->dhcp4, mode.reply_packet);
++      if (dns_address)
++	efi_net_interface_set_dns (inf, (grub_efi_net_ip_address_t *)&dns_address);
++
++    }
++
++  return GRUB_ERR_NONE;
++}
++
++
++static grub_err_t
++grub_cmd_efi_bootp6 (struct grub_command *cmd __attribute__ ((unused)),
++		    int argc,
++		    char **args)
++{
++  struct grub_efi_net_device *dev;
++  grub_efi_uint32_t ia_id;
++
++  for (dev = net_devices, ia_id = 0; dev; dev = dev->next, ia_id++)
++    {
++      grub_efi_dhcp6_config_data_t config;
++      grub_efi_dhcp6_packet_option_t *option_list[1];
++      grub_efi_dhcp6_packet_option_t *opt;
++      grub_efi_status_t status;
++      grub_efi_dhcp6_mode_data_t mode;
++      grub_efi_dhcp6_retransmission_t retrans;
++      grub_efi_net_ip_manual_address_t net_ip;
++      grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
++      grub_efi_net_interface_t *inf = NULL;
++
++      if (argc > 0 && grub_strcmp (dev->card_name, args[0]) != 0)
++	continue;
++
++      opt = grub_malloc (sizeof(*opt) + 2 * sizeof (grub_efi_uint16_t));
++
++#define GRUB_EFI_DHCP6_OPT_ORO 6
++
++      opt->op_code = grub_cpu_to_be16_compile_time (GRUB_EFI_DHCP6_OPT_ORO);
++      opt->op_len = grub_cpu_to_be16_compile_time (2 * sizeof (grub_efi_uint16_t));
++
++#define GRUB_EFI_DHCP6_OPT_BOOT_FILE_URL 59
++#define GRUB_EFI_DHCP6_OPT_DNS_SERVERS 23
++
++      grub_set_unaligned16 (opt->data, grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_BOOT_FILE_URL));
++      grub_set_unaligned16 (opt->data + 1 * sizeof (grub_efi_uint16_t),
++	      grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_DNS_SERVERS));
++
++      option_list[0] = opt;
++      retrans.irt = 4;
++      retrans.mrc = 4;
++      retrans.mrt = 32;
++      retrans.mrd = 60;
++
++      config.dhcp6_callback = NULL;
++      config.callback_context = NULL;
++      config.option_count = 1;
++      config.option_list = option_list;
++      config.ia_descriptor.ia_id = ia_id;
++      config.ia_descriptor.type = GRUB_EFI_DHCP6_IA_TYPE_NA;
++      config.ia_info_event = NULL;
++      config.reconfigure_accept = 0;
++      config.rapid_commit = 0;
++      config.solicit_retransmission = &retrans;
++
++      status = efi_call_2 (dev->dhcp6->configure, dev->dhcp6, &config);
++      grub_free (opt);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("dhcp6 configure failed, %d\n", (int)status);
++	  continue;
++	}
++      status = efi_call_1 (dev->dhcp6->start, dev->dhcp6);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("dhcp6 start failed, %d\n", (int)status);
++	  continue;
++	}
++
++      status = efi_call_3 (dev->dhcp6->get_mode_data, dev->dhcp6, &mode, NULL);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("dhcp4 get mode failed, %d\n", (int)status);
++	  continue;
++	}
++
++      for (inf = dev->net_interfaces; inf; inf = inf->next)
++	if (inf->prefer_ip6 == 1)
++	  break;
++
++      grub_memcpy (net_ip.ip6.address, mode.ia->ia_address[0].ip_address, sizeof (net_ip.ip6.address));
++      net_ip.ip6.prefix_length = 64;
++      net_ip.ip6.is_anycast = 0;
++      net_ip.is_ip6 = 1;
++
++      if (!inf)
++	{
++	  char *name = grub_xasprintf ("%s:dhcp", dev->card_name);
++
++	  inf = grub_efi_net_create_interface (dev,
++		    name,
++		    &net_ip,
++		    1);
++	  grub_free (name);
++	}
++      else
++	{
++	  efi_net_interface_set_address (inf, &net_ip, 1);
++	}
++
++      {
++	grub_efi_uint32_t count = 0;
++	grub_efi_dhcp6_packet_option_t **options = NULL;
++	grub_efi_uint32_t i;
++
++	status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, NULL);
++
++	if (status == GRUB_EFI_BUFFER_TOO_SMALL && count)
++	  {
++	    options = grub_calloc (count, sizeof(*options));
++	    if (!options)
++	      return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
++	    status = efi_call_4 (dev->dhcp6->parse, dev->dhcp6, mode.ia->reply_packet, &count, options);
++	  }
++
++	if (status != GRUB_EFI_SUCCESS)
++	  {
++	    if (options)
++	      grub_free (options);
++	    continue;
++	  }
++
++	for (i = 0; i < count; ++i)
++	  {
++	    if (options[i]->op_code == grub_cpu_to_be16_compile_time(GRUB_EFI_DHCP6_OPT_DNS_SERVERS))
++	      {
++		grub_efi_net_ip_address_t dns;
++		grub_memcpy (dns.ip6, options[i]->data, sizeof(net_ip.ip6));
++		efi_net_interface_set_dns (inf, &dns);
++		break;
++	      }
++	  }
++
++	if (options)
++	  grub_free (options);
++      }
++
++      efi_call_1 (b->free_pool, mode.client_id);
++      efi_call_1 (b->free_pool, mode.ia);
++    }
++
++  return GRUB_ERR_NONE;
++}
++
++grub_command_func_t grub_efi_net_bootp = grub_cmd_efi_bootp;
++grub_command_func_t grub_efi_net_bootp6 = grub_cmd_efi_bootp6;
+diff --git a/grub-core/net/efi/http.c b/grub-core/net/efi/http.c
+new file mode 100644
+index 0000000..ee78e17
+--- /dev/null
++++ b/grub-core/net/efi/http.c
+@@ -0,0 +1,424 @@
++
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/misc.h>
++#include <grub/net/efi.h>
++#include <grub/charset.h>
++#include <grub/safemath.h>
++
++static void
++http_configure (struct grub_efi_net_device *dev, int prefer_ip6)
++{
++  grub_efi_http_config_data_t http_config;
++  grub_efi_httpv4_access_point_t httpv4_node;
++  grub_efi_httpv6_access_point_t httpv6_node;
++  grub_efi_status_t status;
++
++  grub_efi_http_t *http = dev->http;
++
++  grub_memset (&http_config, 0, sizeof(http_config));
++  http_config.http_version = GRUB_EFI_HTTPVERSION11;
++  http_config.timeout_millisec = 5000;
++
++  if (prefer_ip6)
++    {
++      grub_efi_uintn_t sz;
++      grub_efi_ip6_config_manual_address_t manual_address;
++
++      http_config.local_address_is_ipv6 = 1;
++      sz = sizeof (manual_address);
++      status = efi_call_4 (dev->ip6_config->get_data, dev->ip6_config,
++			GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS,
++			&sz, &manual_address);
++
++      if (status == GRUB_EFI_NOT_FOUND)
++	{
++	  grub_printf ("The MANUAL ADDRESS is not found\n");
++	}
++
++      /* FIXME: The manual interface would return BUFFER TOO SMALL !!! */
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  grub_printf ("??? %d\n",(int) status);
++	  return;
++	}
++
++      grub_memcpy (httpv6_node.local_address, manual_address.address, sizeof (httpv6_node.local_address));
++      httpv6_node.local_port = 0;
++      http_config.access_point.ipv6_node = &httpv6_node;
++    }
++  else
++    {
++      http_config.local_address_is_ipv6 = 0;
++      grub_memset (&httpv4_node, 0, sizeof(httpv4_node));
++      httpv4_node.use_default_address = 1;
++
++      /* Use random port here */
++      /* See TcpBind() in edk2/NetworkPkg/TcpDxe/TcpDispatcher.c */
++      httpv4_node.local_port = 0;
++      http_config.access_point.ipv4_node = &httpv4_node;
++    }
++
++  status = efi_call_2 (http->configure, http, &http_config);
++
++  if (status == GRUB_EFI_ALREADY_STARTED)
++    {
++      /* XXX: This hangs HTTPS boot */
++#if 0
++      if (efi_call_2 (http->configure, http, NULL) != GRUB_EFI_SUCCESS)
++	{
++	  grub_error (GRUB_ERR_IO, N_("couldn't reset http instance"));
++	  grub_print_error ();
++	  return;
++	}
++      status = efi_call_2 (http->configure, http, &http_config);
++#endif
++      return;
++    }
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_error (GRUB_ERR_IO, N_("couldn't configure http protocol, reason: %d"), (int)status);
++      grub_print_error ();
++      return ;
++    }
++}
++
++static grub_efi_boolean_t request_callback_done;
++static grub_efi_boolean_t response_callback_done;
++
++static void
++grub_efi_http_request_callback (grub_efi_event_t event __attribute__ ((unused)),
++				void *context __attribute__ ((unused)))
++{
++  request_callback_done = 1;
++}
++
++static void
++grub_efi_http_response_callback (grub_efi_event_t event __attribute__ ((unused)),
++				void *context __attribute__ ((unused)))
++{
++  response_callback_done = 1;
++}
++
++static grub_err_t
++efihttp_request (grub_efi_http_t *http, char *server, char *name, int use_https, int headeronly, grub_off_t *file_size)
++{
++  grub_efi_http_request_data_t request_data;
++  grub_efi_http_message_t request_message;
++  grub_efi_http_token_t request_token;
++  grub_efi_http_response_data_t response_data;
++  grub_efi_http_message_t response_message;
++  grub_efi_http_token_t response_token;
++  grub_efi_http_header_t request_headers[3];
++
++  grub_efi_status_t status;
++  grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
++  char *url = NULL;
++
++  request_headers[0].field_name = (grub_efi_char8_t *)"Host";
++  request_headers[0].field_value = (grub_efi_char8_t *)server;
++  request_headers[1].field_name = (grub_efi_char8_t *)"Accept";
++  request_headers[1].field_value = (grub_efi_char8_t *)"*/*";
++  request_headers[2].field_name = (grub_efi_char8_t *)"User-Agent";
++  request_headers[2].field_value = (grub_efi_char8_t *)"UefiHttpBoot/1.0";
++
++  {
++    grub_efi_ipv6_address_t address;
++    const char *rest;
++    grub_efi_char16_t *ucs2_url;
++    grub_size_t url_len, ucs2_url_len;
++    const char *protocol = (use_https == 1) ? "https" : "http";
++    grub_size_t sz;
++
++    if (grub_efi_string_to_ip6_address (server, &address, &rest) && *rest == 0)
++      url = grub_xasprintf ("%s://[%s]%s", protocol, server, name);
++    else
++      url = grub_xasprintf ("%s://%s%s", protocol, server, name);
++
++    if (!url)
++      {
++	return grub_errno;
++      }
++
++    url_len = grub_strlen (url);
++    if (grub_mul (url_len, GRUB_MAX_UTF16_PER_UTF8, &ucs2_url_len) ||
++	grub_add (ucs2_url_len, 1, &sz))
++      return GRUB_ERR_OUT_OF_RANGE;
++
++    ucs2_url = grub_calloc (sz, sizeof (ucs2_url[0]));
++
++    if (!ucs2_url)
++      {
++	grub_free (url);
++	return grub_errno;
++      }
++
++    ucs2_url_len = grub_utf8_to_utf16 (ucs2_url, ucs2_url_len, (grub_uint8_t *)url, url_len, NULL); /* convert string format from ascii to usc2 */
++    ucs2_url[ucs2_url_len] = 0;
++    grub_free (url);
++    request_data.url = ucs2_url;
++  }
++
++  request_data.method = (headeronly > 0) ? GRUB_EFI_HTTPMETHODHEAD : GRUB_EFI_HTTPMETHODGET;
++
++  request_message.data.request = &request_data;
++  request_message.header_count = 3;
++  request_message.headers = request_headers;
++  request_message.body_length = 0;
++  request_message.body = NULL;
++
++  /* request token */
++  request_token.event = NULL;
++  request_token.status = GRUB_EFI_NOT_READY;
++  request_token.message = &request_message;
++
++  request_callback_done = 0;
++  status = efi_call_5 (b->create_event,
++                       GRUB_EFI_EVT_NOTIFY_SIGNAL,
++                       GRUB_EFI_TPL_CALLBACK,
++                       grub_efi_http_request_callback,
++                       NULL,
++                       &request_token.event);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (request_data.url);
++      return grub_error (GRUB_ERR_IO, "Fail to create an event! status=0x%" PRIxGRUB_SIZE, status);
++    }
++
++  status = efi_call_2 (http->request, http, &request_token);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      efi_call_1 (b->close_event, request_token.event);
++      grub_free (request_data.url);
++      return grub_error (GRUB_ERR_IO, "Fail to send a request! status=0x%" PRIxGRUB_SIZE, status);
++    }
++  /* TODO: Add Timeout */
++  while (!request_callback_done)
++    efi_call_1(http->poll, http);
++
++  response_data.status_code = GRUB_EFI_HTTP_STATUS_UNSUPPORTED_STATUS;
++  response_message.data.response = &response_data;
++  /* herader_count will be updated by the HTTP driver on response */
++  response_message.header_count = 0;
++  /* headers will be populated by the driver on response */
++  response_message.headers = NULL;
++  /* use zero BodyLength to only receive the response headers */
++  response_message.body_length = 0;
++  response_message.body = NULL;
++  response_token.event = NULL;
++
++  status = efi_call_5 (b->create_event,
++              GRUB_EFI_EVT_NOTIFY_SIGNAL,
++              GRUB_EFI_TPL_CALLBACK,
++              grub_efi_http_response_callback,
++              NULL,
++              &response_token.event);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      efi_call_1 (b->close_event, request_token.event);
++      grub_free (request_data.url);
++      return grub_error (GRUB_ERR_IO, "Fail to create an event! status=0x%" PRIxGRUB_SIZE, status);
++    }
++
++  response_token.status = GRUB_EFI_SUCCESS;
++  response_token.message = &response_message;
++
++  /* wait for HTTP response */
++  response_callback_done = 0;
++  status = efi_call_2 (http->response, http, &response_token);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      efi_call_1 (b->close_event, response_token.event);
++      efi_call_1 (b->close_event, request_token.event);
++      grub_free (request_data.url);
++      return grub_error (GRUB_ERR_IO, "Fail to receive a response! status=%d\n", (int)status);
++    }
++
++  /* TODO: Add Timeout */
++  while (!response_callback_done)
++    efi_call_1 (http->poll, http);
++
++  if (response_message.data.response->status_code != GRUB_EFI_HTTP_STATUS_200_OK)
++    {
++      grub_efi_http_status_code_t status_code = response_message.data.response->status_code;
++
++      if (response_message.headers)
++	efi_call_1 (b->free_pool, response_message.headers);
++      efi_call_1 (b->close_event, response_token.event);
++      efi_call_1 (b->close_event, request_token.event);
++      grub_free (request_data.url);
++      if (status_code == GRUB_EFI_HTTP_STATUS_404_NOT_FOUND)
++	{
++	  return grub_error (GRUB_ERR_FILE_NOT_FOUND, _("file `%s' not found"), name);
++	}
++      else
++	{
++	  return grub_error (GRUB_ERR_NET_UNKNOWN_ERROR,
++		  _("unsupported uefi http status code 0x%x"), status_code);
++	}
++    }
++
++  if (file_size)
++    {
++      int i;
++      /* parse the length of the file from the ContentLength header */
++      for (*file_size = 0, i = 0; i < (int)response_message.header_count; ++i)
++	{
++	  if (!grub_strcmp((const char*)response_message.headers[i].field_name, "Content-Length"))
++	    {
++	      *file_size = grub_strtoul((const char*)response_message.headers[i].field_value, 0, 10);
++	      break;
++	    }
++	}
++    }
++
++  if (response_message.headers)
++    efi_call_1 (b->free_pool, response_message.headers);
++  efi_call_1 (b->close_event, response_token.event);
++  efi_call_1 (b->close_event, request_token.event);
++  grub_free (request_data.url);
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_ssize_t
++efihttp_read (struct grub_efi_net_device *dev,
++		  char *buf,
++		  grub_size_t len)
++{
++  grub_efi_http_message_t response_message;
++  grub_efi_http_token_t response_token;
++
++  grub_efi_status_t status;
++  grub_size_t sum = 0;
++  grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
++  grub_efi_http_t *http = dev->http;
++
++  if (!len)
++    {
++      grub_error (GRUB_ERR_BUG, "Invalid arguments to EFI HTTP Read");
++      return -1;
++    }
++
++  efi_call_5 (b->create_event,
++              GRUB_EFI_EVT_NOTIFY_SIGNAL,
++              GRUB_EFI_TPL_CALLBACK,
++              grub_efi_http_response_callback,
++              NULL,
++              &response_token.event);
++
++  while (len)
++    {
++      response_message.data.response = NULL;
++      response_message.header_count = 0;
++      response_message.headers = NULL;
++      response_message.body_length = len;
++      response_message.body = buf;
++
++      response_token.message = &response_message;
++      response_token.status = GRUB_EFI_NOT_READY;
++
++      response_callback_done = 0;
++
++      status = efi_call_2 (http->response, http, &response_token);
++      if (status != GRUB_EFI_SUCCESS)
++	{
++	  efi_call_1 (b->close_event, response_token.event);
++	  grub_error (GRUB_ERR_IO, "Error! status=%d\n", (int)status);
++	  return -1;
++	}
++
++      while (!response_callback_done)
++	efi_call_1(http->poll, http);
++
++      sum += response_message.body_length;
++      buf += response_message.body_length;
++      len -= response_message.body_length;
++    }
++
++  efi_call_1 (b->close_event, response_token.event);
++
++  return sum;
++}
++
++static grub_err_t
++grub_efihttp_open (struct grub_efi_net_device *dev,
++		  int prefer_ip6 __attribute__ ((unused)),
++		  grub_file_t file,
++		  const char *filename __attribute__ ((unused)),
++		  int type)
++{
++  grub_err_t err;
++  grub_off_t size;
++  char *buf;
++
++  err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 1, 0);
++  if (err != GRUB_ERR_NONE)
++    return err;
++
++  err = efihttp_request (dev->http, file->device->net->server, file->device->net->name, type, 0, &size);
++  if (err != GRUB_ERR_NONE)
++    return err;
++
++  buf = grub_malloc (size);
++  efihttp_read (dev, buf, size);
++
++  file->size = size;
++  file->data = buf;
++  file->not_easily_seekable = 0;
++  file->device->net->offset = 0;
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_efihttp_close (struct grub_efi_net_device *dev __attribute__ ((unused)),
++		    int prefer_ip6 __attribute__ ((unused)),
++		    grub_file_t file)
++{
++  if (file->data)
++    grub_free (file->data);
++
++  file->data = 0;
++  file->offset = 0;
++  file->size = 0;
++  file->device->net->offset = 0;
++  return GRUB_ERR_NONE;
++}
++
++static grub_ssize_t
++grub_efihttp_read (struct grub_efi_net_device *dev __attribute__((unused)),
++		  int prefer_ip6 __attribute__((unused)),
++		  grub_file_t file,
++		  char *buf,
++		  grub_size_t len)
++{
++  grub_size_t r = len;
++
++  if (!file->data || !buf || !len)
++    return 0;
++
++  if ((file->device->net->offset + len) > file->size)
++    r = file->size - file->device->net->offset;
++
++  if (r)
++    {
++      grub_memcpy (buf, (char *)file->data + file->device->net->offset, r);
++      file->device->net->offset += r;
++    }
++
++  return r;
++}
++
++struct grub_efi_net_io io_http =
++  {
++    .configure = http_configure,
++    .open = grub_efihttp_open,
++    .read = grub_efihttp_read,
++    .close = grub_efihttp_close
++  };
+diff --git a/grub-core/net/efi/ip4_config.c b/grub-core/net/efi/ip4_config.c
+new file mode 100644
+index 0000000..40238d4
+--- /dev/null
++++ b/grub-core/net/efi/ip4_config.c
+@@ -0,0 +1,409 @@
++
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/misc.h>
++#include <grub/net/efi.h>
++#include <grub/charset.h>
++#include <grub/safemath.h>
++
++char *
++grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address)
++{
++  char *hw_addr, *p;
++  int s;
++  int i;
++  grub_size_t sz;
++
++  if (grub_mul (hw_address_size, sizeof ("XX:") - 1, &sz) ||
++      grub_add (sz, 1, &sz))
++    return NULL;
++
++  hw_addr = grub_malloc (sz);
++  if (!hw_addr)
++    return NULL;
++
++  p = hw_addr;
++  s = sz;
++  for (i = 0; i < (int)hw_address_size; i++)
++    {
++      grub_snprintf (p, sz, "%02x:", hw_address[i]);
++      p +=  sizeof ("XX:") - 1;
++      s -=  sizeof ("XX:") - 1;
++    }
++
++  hw_addr[sz - 2] = '\0';
++  return hw_addr;
++}
++
++char *
++grub_efi_ip4_address_to_string (grub_efi_ipv4_address_t *address)
++{
++  char *addr;
++
++  addr = grub_malloc (sizeof ("XXX.XXX.XXX.XXX"));
++  if (!addr)
++      return NULL;
++
++  /* FIXME: Use grub_xasprintf ? */
++  grub_snprintf (addr,
++	  sizeof ("XXX.XXX.XXX.XXX"),
++	  "%u.%u.%u.%u",
++	  (*address)[0],
++	  (*address)[1],
++	  (*address)[2],
++	  (*address)[3]);
++
++  return addr;
++}
++
++int
++grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest)
++{
++  grub_uint32_t newip = 0;
++  int i;
++  const char *ptr = val;
++
++  for (i = 0; i < 4; i++)
++    {
++      unsigned long t;
++      t = grub_strtoul (ptr, &ptr, 0);
++      if (grub_errno)
++	{
++	  grub_errno = GRUB_ERR_NONE;
++	  return 0;
++	}
++      if (*ptr != '.' && i == 0)
++	{
++	  /* XXX: t is in host byte order */
++	  newip = t;
++	  break;
++	}
++      if (t & ~0xff)
++	return 0;
++      newip <<= 8;
++      newip |= t;
++      if (i != 3 && *ptr != '.')
++	return 0;
++      ptr++;
++    }
++
++  newip =  grub_cpu_to_be32 (newip);
++
++  grub_memcpy (address, &newip, sizeof(*address));
++
++  if (rest)
++    *rest = (ptr - 1);
++  return 1;
++}
++
++static grub_efi_ip4_config2_interface_info_t *
++efi_ip4_config_interface_info (grub_efi_ip4_config2_protocol_t *ip4_config)
++{
++  grub_efi_uintn_t sz;
++  grub_efi_status_t status;
++  grub_efi_ip4_config2_interface_info_t *interface_info;
++
++  sz = sizeof (*interface_info) + sizeof (*interface_info->route_table);
++  interface_info = grub_malloc (sz);
++  if (!interface_info)
++    return NULL;
++
++  status = efi_call_4 (ip4_config->get_data, ip4_config,
++		GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO,
++		&sz, interface_info);
++
++  if (status == GRUB_EFI_BUFFER_TOO_SMALL)
++    {
++      grub_free (interface_info);
++      interface_info = grub_malloc (sz);
++      status = efi_call_4 (ip4_config->get_data, ip4_config,
++		    GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO,
++		    &sz, interface_info);
++    }
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (interface_info);
++      return NULL;
++    }
++
++  return interface_info;
++}
++
++static grub_efi_ip4_config2_manual_address_t *
++efi_ip4_config_manual_address (grub_efi_ip4_config2_protocol_t *ip4_config)
++{
++  grub_efi_uintn_t sz;
++  grub_efi_status_t status;
++  grub_efi_ip4_config2_manual_address_t *manual_address;
++
++  sz = sizeof (*manual_address);
++  manual_address = grub_malloc (sz);
++  if (!manual_address)
++    return NULL;
++
++  status = efi_call_4 (ip4_config->get_data, ip4_config,
++		    GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
++		    &sz, manual_address);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (manual_address);
++      return NULL;
++    }
++
++  return manual_address;
++}
++
++char *
++grub_efi_ip4_interface_name (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip4_config2_interface_info_t *interface_info;
++  char *name;
++
++  interface_info = efi_ip4_config_interface_info (dev->ip4_config);
++
++  if (!interface_info)
++    return NULL;
++
++  name = grub_malloc (GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE
++		      * GRUB_MAX_UTF8_PER_UTF16 + 1);
++  *grub_utf16_to_utf8 ((grub_uint8_t *)name, interface_info->name,
++		      GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE) = 0;
++  grub_free (interface_info);
++  return name;
++}
++
++static char *
++grub_efi_ip4_interface_hw_address (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip4_config2_interface_info_t *interface_info;
++  char *hw_addr;
++
++  interface_info = efi_ip4_config_interface_info (dev->ip4_config);
++
++  if (!interface_info)
++    return NULL;
++
++  hw_addr = grub_efi_hw_address_to_string (interface_info->hw_address_size, interface_info->hw_address);
++  grub_free (interface_info);
++
++  return hw_addr;
++}
++
++static char *
++grub_efi_ip4_interface_address (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip4_config2_manual_address_t *manual_address;
++  char *addr;
++
++  manual_address = efi_ip4_config_manual_address (dev->ip4_config);
++
++  if (!manual_address)
++    return NULL;
++
++  addr = grub_efi_ip4_address_to_string (&manual_address->address);
++  grub_free (manual_address);
++  return addr;
++}
++
++
++static int
++address_mask_size (grub_efi_ipv4_address_t *address)
++{
++  grub_uint8_t i;
++  grub_uint32_t u32_addr = grub_be_to_cpu32 (grub_get_unaligned32 (address));
++
++  if (u32_addr == 0)
++    return 0;
++
++  for (i = 0; i < 32 ; ++i)
++    {
++      if (u32_addr == ((0xffffffff >> i) << i))
++	return (32 - i);
++    }
++
++  return -1;
++}
++
++static char **
++grub_efi_ip4_interface_route_table (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip4_config2_interface_info_t *interface_info;
++  char **ret;
++  int i, id;
++  grub_size_t sz;
++
++  interface_info = efi_ip4_config_interface_info (dev->ip4_config);
++  if (!interface_info)
++    return NULL;
++
++  if (grub_add (interface_info->route_table_size, 1, &sz))
++    {
++      grub_free (interface_info);
++      return NULL;
++    }
++
++  ret = grub_calloc (sz, sizeof (*ret));
++
++  if (!ret)
++    {
++      grub_free (interface_info);
++      return NULL;
++    }
++
++  id = 0;
++  for (i = 0; i < (int)interface_info->route_table_size; i++)
++    {
++      char *subnet, *gateway, *mask;
++      grub_uint32_t u32_subnet, u32_gateway;
++      int mask_size;
++      grub_efi_ip4_route_table_t *route_table = interface_info->route_table + i;
++      grub_efi_net_interface_t *inf;
++      char *interface_name = NULL;
++
++      for (inf = dev->net_interfaces; inf; inf = inf->next)
++	if (!inf->prefer_ip6)
++	  interface_name = inf->name;
++
++      u32_gateway = grub_get_unaligned32 (&route_table->gateway_address);
++      gateway = grub_efi_ip4_address_to_string (&route_table->gateway_address);
++      u32_subnet = grub_get_unaligned32 (&route_table->subnet_address);
++      subnet = grub_efi_ip4_address_to_string (&route_table->subnet_address);
++      mask_size = address_mask_size (&route_table->subnet_mask);
++      mask = grub_efi_ip4_address_to_string (&route_table->subnet_mask);
++      if (u32_subnet && !u32_gateway && interface_name)
++	ret[id++] = grub_xasprintf ("%s:local %s/%d %s", dev->card_name, subnet, mask_size, interface_name);
++      else if (u32_subnet && u32_gateway)
++	ret[id++] = grub_xasprintf ("%s:gw %s/%d gw %s", dev->card_name, subnet, mask_size, gateway);
++      else if (!u32_subnet && u32_gateway)
++	ret[id++] = grub_xasprintf ("%s:default %s/%d gw %s", dev->card_name, subnet, mask_size, gateway);
++      grub_free (subnet);
++      grub_free (gateway);
++      grub_free (mask);
++    }
++
++  ret[id] = NULL;
++  grub_free (interface_info);
++  return ret;
++}
++
++static grub_efi_net_interface_t *
++grub_efi_ip4_interface_match (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *ip_address)
++{
++  grub_efi_ip4_config2_interface_info_t *interface_info;
++  grub_efi_net_interface_t *inf;
++  int i;
++  grub_efi_ipv4_address_t *address = &ip_address->ip4;
++
++  interface_info = efi_ip4_config_interface_info (dev->ip4_config);
++  if (!interface_info)
++    return NULL;
++
++  for (i = 0; i < (int)interface_info->route_table_size; i++)
++    {
++      grub_efi_ip4_route_table_t *route_table = interface_info->route_table + i;
++      grub_uint32_t u32_address, u32_mask, u32_subnet;
++
++      u32_address = grub_get_unaligned32 (address);
++      u32_subnet = grub_get_unaligned32 (route_table->subnet_address);
++      u32_mask = grub_get_unaligned32 (route_table->subnet_mask);
++
++      /* SKIP Default GATEWAY */
++      if (!u32_subnet && !u32_mask)
++	continue;
++
++      if ((u32_address & u32_mask) == u32_subnet)
++	{
++	  for (inf = dev->net_interfaces; inf; inf = inf->next)
++	    if (!inf->prefer_ip6)
++	      {
++		grub_free (interface_info);
++		return inf;
++	      }
++	}
++    }
++
++  grub_free (interface_info);
++  return NULL;
++}
++
++static int
++grub_efi_ip4_interface_set_manual_address (struct grub_efi_net_device *dev,
++	    grub_efi_net_ip_manual_address_t *net_ip,
++	    int with_subnet)
++{
++  grub_efi_status_t status;
++  grub_efi_ip4_config2_manual_address_t *address = &net_ip->ip4;
++
++  if (!with_subnet)
++    {
++      grub_efi_ip4_config2_manual_address_t *manual_address =
++      efi_ip4_config_manual_address (dev->ip4_config);
++
++      if (manual_address)
++	{
++	  grub_memcpy (address->subnet_mask, manual_address->subnet_mask, sizeof(address->subnet_mask));
++	  grub_free (manual_address);
++	}
++      else
++	{
++	  /* XXX: */
++	  address->subnet_mask[0] = 0xff;
++	  address->subnet_mask[1] = 0xff;
++	  address->subnet_mask[2] = 0xff;
++	  address->subnet_mask[3] = 0;
++	}
++    }
++
++  status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config,
++		    GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
++		    sizeof(*address), address);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++
++  return 1;
++}
++
++static int
++grub_efi_ip4_interface_set_gateway (struct grub_efi_net_device *dev,
++	      grub_efi_net_ip_address_t *address)
++{
++  grub_efi_status_t status;
++
++  status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config,
++		GRUB_EFI_IP4_CONFIG2_DATA_TYPE_GATEWAY,
++		sizeof (address->ip4), &address->ip4);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++  return 1;
++}
++
++/* FIXME: Multiple DNS */
++static int
++grub_efi_ip4_interface_set_dns (struct grub_efi_net_device *dev,
++	      grub_efi_net_ip_address_t *address)
++{
++  grub_efi_status_t status;
++
++  status = efi_call_4 (dev->ip4_config->set_data, dev->ip4_config,
++		GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
++		sizeof (address->ip4), &address->ip4);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++  return 1;
++}
++
++grub_efi_net_ip_config_t *efi_net_ip4_config = &(grub_efi_net_ip_config_t)
++  {
++    .get_hw_address = grub_efi_ip4_interface_hw_address,
++    .get_address = grub_efi_ip4_interface_address,
++    .get_route_table = grub_efi_ip4_interface_route_table,
++    .best_interface = grub_efi_ip4_interface_match,
++    .set_address = grub_efi_ip4_interface_set_manual_address,
++    .set_gateway = grub_efi_ip4_interface_set_gateway,
++    .set_dns = grub_efi_ip4_interface_set_dns
++  };
+diff --git a/grub-core/net/efi/ip6_config.c b/grub-core/net/efi/ip6_config.c
+new file mode 100644
+index 0000000..a9d995d
+--- /dev/null
++++ b/grub-core/net/efi/ip6_config.c
+@@ -0,0 +1,430 @@
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/misc.h>
++#include <grub/net/efi.h>
++#include <grub/charset.h>
++#include <grub/safemath.h>
++
++char *
++grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address)
++{
++  char *str = grub_malloc (sizeof ("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX"));
++  char *p;
++  int i;
++  int squash;
++
++  if (!str)
++    return NULL;
++
++  p = str;
++  squash = 0;
++  for (i = 0; i < 8; ++i)
++    {
++      grub_uint16_t addr;
++
++      if (i == 7)
++	squash = 2;
++
++      addr = grub_get_unaligned16 (address->addr + i * 2);
++
++      if (grub_be_to_cpu16 (addr))
++	{
++	  char buf[sizeof ("XXXX")];
++	  if (i > 0)
++	    *p++ = ':';
++	  grub_snprintf (buf, sizeof (buf), "%x", grub_be_to_cpu16 (addr));
++	  grub_strcpy (p, buf);
++	  p += grub_strlen (buf);
++
++	  if (squash == 1)
++	    squash = 2;
++	}
++      else
++	{
++	  if (squash == 0)
++	    {
++	      *p++ = ':';
++	      squash = 1;
++	    }
++	  else if (squash == 2)
++	    {
++	      *p++ = ':';
++	      *p++ = '0';
++	    }
++	}
++    }
++  *p = '\0';
++  return str;
++}
++
++int
++grub_efi_string_to_ip6_address (const char *val, grub_efi_ipv6_address_t *address, const char **rest)
++{
++  grub_uint16_t newip[8];
++  const char *ptr = val;
++  int word, quaddot = -1;
++  int bracketed = 0;
++
++  if (ptr[0] == '[') {
++    bracketed = 1;
++    ptr++;
++  }
++
++  if (ptr[0] == ':' && ptr[1] != ':')
++    return 0;
++  if (ptr[0] == ':')
++    ptr++;
++
++  for (word = 0; word < 8; word++)
++    {
++      unsigned long t;
++      if (*ptr == ':')
++	{
++	  quaddot = word;
++	  word--;
++	  ptr++;
++	  continue;
++	}
++      t = grub_strtoul (ptr, &ptr, 16);
++      if (grub_errno)
++	{
++	  grub_errno = GRUB_ERR_NONE;
++	  break;
++	}
++      if (t & ~0xffff)
++	return 0;
++      newip[word] = grub_cpu_to_be16 (t);
++      if (*ptr != ':')
++	break;
++      ptr++;
++    }
++  if (quaddot == -1 && word < 7)
++    return 0;
++  if (quaddot != -1)
++    {
++      grub_memmove (&newip[quaddot + 7 - word], &newip[quaddot],
++		    (word - quaddot + 1) * sizeof (newip[0]));
++      grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0]));
++    }
++  grub_memcpy (address, newip, 16);
++  if (bracketed && *ptr == ']') {
++    ptr++;
++  }
++  if (rest)
++    *rest = ptr;
++  return 1;
++}
++
++static grub_efi_ip6_config_interface_info_t *
++efi_ip6_config_interface_info (grub_efi_ip6_config_protocol_t *ip6_config)
++{
++  grub_efi_uintn_t sz;
++  grub_efi_status_t status;
++  grub_efi_ip6_config_interface_info_t *interface_info;
++
++  sz = sizeof (*interface_info) + sizeof (*interface_info->route_table);
++  interface_info = grub_malloc (sz);
++
++  status = efi_call_4 (ip6_config->get_data, ip6_config,
++		GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO,
++		&sz, interface_info);
++
++  if (status == GRUB_EFI_BUFFER_TOO_SMALL)
++    {
++      grub_free (interface_info);
++      interface_info = grub_malloc (sz);
++      status = efi_call_4 (ip6_config->get_data, ip6_config,
++		    GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO,
++		    &sz, interface_info);
++    }
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (interface_info);
++      return NULL;
++    }
++
++  return interface_info;
++}
++
++static grub_efi_ip6_config_manual_address_t *
++efi_ip6_config_manual_address (grub_efi_ip6_config_protocol_t *ip6_config)
++{
++  grub_efi_uintn_t sz;
++  grub_efi_status_t status;
++  grub_efi_ip6_config_manual_address_t *manual_address;
++
++  sz = sizeof (*manual_address);
++  manual_address = grub_malloc (sz);
++  if (!manual_address)
++    return NULL;
++
++  status = efi_call_4 (ip6_config->get_data, ip6_config,
++		    GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS,
++		    &sz, manual_address);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (manual_address);
++      return NULL;
++    }
++
++  return manual_address;
++}
++
++char *
++grub_efi_ip6_interface_name (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip6_config_interface_info_t *interface_info;
++  char *name;
++
++  interface_info = efi_ip6_config_interface_info (dev->ip6_config);
++
++  if (!interface_info)
++    return NULL;
++
++  name = grub_malloc (GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE
++		      * GRUB_MAX_UTF8_PER_UTF16 + 1);
++  *grub_utf16_to_utf8 ((grub_uint8_t *)name, interface_info->name,
++		      GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE) = 0;
++  grub_free (interface_info);
++  return name;
++}
++
++static char *
++grub_efi_ip6_interface_hw_address (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip6_config_interface_info_t *interface_info;
++  char *hw_addr;
++
++  interface_info = efi_ip6_config_interface_info (dev->ip6_config);
++
++  if (!interface_info)
++    return NULL;
++
++  hw_addr = grub_efi_hw_address_to_string (interface_info->hw_address_size, interface_info->hw_address);
++  grub_free (interface_info);
++
++  return hw_addr;
++}
++
++static char *
++grub_efi_ip6_interface_address (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip6_config_manual_address_t *manual_address;
++  char *addr;
++
++  manual_address = efi_ip6_config_manual_address (dev->ip6_config);
++
++  if (!manual_address)
++    return NULL;
++
++  addr = grub_efi_ip6_address_to_string ((grub_efi_pxe_ipv6_address_t *)&manual_address->address);
++  grub_free (manual_address);
++  return addr;
++}
++
++static char **
++grub_efi_ip6_interface_route_table (struct grub_efi_net_device *dev)
++{
++  grub_efi_ip6_config_interface_info_t *interface_info;
++  char **ret;
++  int i, id;
++  grub_size_t sz;
++
++  interface_info = efi_ip6_config_interface_info (dev->ip6_config);
++  if (!interface_info)
++    return NULL;
++
++  if (grub_add (interface_info->route_count, 1, &sz))
++    {
++      grub_free (interface_info);
++      return NULL;
++    }
++
++  ret = grub_calloc (sz, sizeof (*ret));
++
++  if (!ret)
++    {
++      grub_free (interface_info);
++      return NULL;
++    }
++
++  id = 0;
++  for (i = 0; i < (int)interface_info->route_count ; i++)
++    {
++      char *gateway, *destination;
++      grub_uint64_t u64_gateway[2];
++      grub_uint64_t u64_destination[2];
++      grub_efi_ip6_route_table_t *route_table = interface_info->route_table + i;
++      grub_efi_net_interface_t *inf;
++      char *interface_name = NULL;
++
++      gateway = grub_efi_ip6_address_to_string (&route_table->gateway);
++      destination = grub_efi_ip6_address_to_string (&route_table->destination);
++
++      u64_gateway[0] = grub_get_unaligned64 (route_table->gateway.addr);
++      u64_gateway[1] = grub_get_unaligned64 (route_table->gateway.addr + 8);
++      u64_destination[0] = grub_get_unaligned64 (route_table->destination.addr);
++      u64_destination[1] = grub_get_unaligned64 (route_table->destination.addr + 8);
++
++      for (inf = dev->net_interfaces; inf; inf = inf->next)
++	if (inf->prefer_ip6)
++	  interface_name = inf->name;
++
++      if ((!u64_gateway[0] && !u64_gateway[1])
++	  && (u64_destination[0] || u64_destination[1]))
++	{
++	  if (interface_name)
++	    {
++	      if ((grub_be_to_cpu64 (u64_destination[0]) == 0xfe80000000000000ULL)
++	      && (!u64_destination[1])
++	      && (route_table->prefix_length == 64))
++		ret[id++] = grub_xasprintf ("%s:link %s/%d %s", dev->card_name, destination, route_table->prefix_length, interface_name);
++	      else
++		ret[id++] = grub_xasprintf ("%s:local %s/%d %s", dev->card_name, destination, route_table->prefix_length, interface_name);
++	    }
++	}
++      else if ((u64_gateway[0] || u64_gateway[1])
++	  && (u64_destination[0] || u64_destination[1]))
++	ret[id++] = grub_xasprintf ("%s:gw %s/%d gw %s", dev->card_name, destination, route_table->prefix_length, gateway);
++      else if ((u64_gateway[0] || u64_gateway[1])
++	  && (!u64_destination[0] && !u64_destination[1]))
++	ret[id++] = grub_xasprintf ("%s:default %s/%d gw %s", dev->card_name, destination, route_table->prefix_length, gateway);
++
++      grub_free (gateway);
++      grub_free (destination);
++    }
++
++  ret[id] = NULL;
++  grub_free (interface_info);
++  return ret;
++}
++
++static grub_efi_net_interface_t *
++grub_efi_ip6_interface_match (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *ip_address)
++{
++  grub_efi_ip6_config_interface_info_t *interface_info;
++  grub_efi_net_interface_t *inf;
++  int i;
++  grub_efi_ipv6_address_t *address = &ip_address->ip6;
++
++  interface_info = efi_ip6_config_interface_info (dev->ip6_config);
++  if (!interface_info)
++    return NULL;
++
++  for (i = 0; i < (int)interface_info->route_count ; i++)
++    {
++      grub_uint64_t u64_addr[2];
++      grub_uint64_t u64_subnet[2];
++      grub_uint64_t u64_mask[2];
++
++      grub_efi_ip6_route_table_t *route_table = interface_info->route_table + i;
++
++      /* SKIP Default GATEWAY */
++      if (route_table->prefix_length == 0)
++	continue;
++
++      u64_addr[0] = grub_get_unaligned64 (address);
++      u64_addr[1] = grub_get_unaligned64 (address + 4);
++      u64_subnet[0] = grub_get_unaligned64 (route_table->destination.addr);
++      u64_subnet[1] = grub_get_unaligned64 (route_table->destination.addr + 8);
++      u64_mask[0] = (route_table->prefix_length <= 64) ?
++	    0xffffffffffffffffULL << (64 - route_table->prefix_length) :
++	    0xffffffffffffffffULL;
++      u64_mask[1] = (route_table->prefix_length <= 64) ?
++	    0 :
++	    0xffffffffffffffffULL << (128 - route_table->prefix_length);
++
++      if (((u64_addr[0] & u64_mask[0]) == u64_subnet[0])
++	  && ((u64_addr[1] & u64_mask[1]) == u64_subnet[1]))
++	{
++	  for (inf = dev->net_interfaces; inf; inf = inf->next)
++	    if (inf->prefer_ip6)
++	      {
++		grub_free (interface_info);
++		return inf;
++	      }
++	}
++    }
++
++  grub_free (interface_info);
++  return NULL;
++}
++
++static int
++grub_efi_ip6_interface_set_manual_address (struct grub_efi_net_device *dev,
++	    grub_efi_net_ip_manual_address_t *net_ip,
++	    int with_subnet)
++{
++  grub_efi_status_t status;
++  grub_efi_ip6_config_manual_address_t *address = &net_ip->ip6;
++
++  if (!with_subnet)
++    {
++      grub_efi_ip6_config_manual_address_t *manual_address =
++      efi_ip6_config_manual_address (dev->ip6_config);
++
++      if (manual_address)
++	{
++	  address->prefix_length = manual_address->prefix_length;
++	  grub_free (manual_address);
++	}
++      else
++	{
++	  /* XXX: */
++	  address->prefix_length = 64;
++	}
++    }
++
++  status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config,
++		    GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS,
++		    sizeof(*address), address);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++
++  return 1;
++}
++
++static int
++grub_efi_ip6_interface_set_gateway (struct grub_efi_net_device *dev,
++	      grub_efi_net_ip_address_t *address)
++{
++  grub_efi_status_t status;
++
++  status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config,
++		GRUB_EFI_IP6_CONFIG_DATA_TYPE_GATEWAY,
++		sizeof (address->ip6), &address->ip6);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++  return 1;
++}
++
++static int
++grub_efi_ip6_interface_set_dns (struct grub_efi_net_device *dev,
++	      grub_efi_net_ip_address_t *address)
++{
++
++  grub_efi_status_t status;
++
++  status = efi_call_4 (dev->ip6_config->set_data, dev->ip6_config,
++		GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
++		sizeof (address->ip6), &address->ip6);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++  return 1;
++}
++
++grub_efi_net_ip_config_t *efi_net_ip6_config = &(grub_efi_net_ip_config_t)
++  {
++    .get_hw_address = grub_efi_ip6_interface_hw_address,
++    .get_address = grub_efi_ip6_interface_address,
++    .get_route_table = grub_efi_ip6_interface_route_table,
++    .best_interface = grub_efi_ip6_interface_match,
++    .set_address = grub_efi_ip6_interface_set_manual_address,
++    .set_gateway = grub_efi_ip6_interface_set_gateway,
++    .set_dns = grub_efi_ip6_interface_set_dns
++  };
+diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c
+new file mode 100644
+index 0000000..3154c55
+--- /dev/null
++++ b/grub-core/net/efi/net.c
+@@ -0,0 +1,1440 @@
++#include <grub/net.h>
++#include <grub/env.h>
++#include <grub/mm.h>
++#include <grub/misc.h>
++#include <grub/dl.h>
++#include <grub/command.h>
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/i18n.h>
++#include <grub/bufio.h>
++#include <grub/efi/http.h>
++#include <grub/efi/dhcp.h>
++#include <grub/net/efi.h>
++#include <grub/charset.h>
++#include <grub/safemath.h>
++
++GRUB_MOD_LICENSE ("GPLv3+");
++
++#define GRUB_EFI_IP6_PREFIX_LENGTH 64
++
++static grub_efi_guid_t ip4_config_guid = GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID;
++static grub_efi_guid_t ip6_config_guid = GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID;
++static grub_efi_guid_t http_service_binding_guid = GRUB_EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID;
++static grub_efi_guid_t http_guid = GRUB_EFI_HTTP_PROTOCOL_GUID;
++static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID;
++static grub_efi_guid_t dhcp4_service_binding_guid = GRUB_EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID;
++static grub_efi_guid_t dhcp4_guid = GRUB_EFI_DHCP4_PROTOCOL_GUID;
++static grub_efi_guid_t dhcp6_service_binding_guid = GRUB_EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID;
++static grub_efi_guid_t dhcp6_guid = GRUB_EFI_DHCP6_PROTOCOL_GUID;
++
++struct grub_efi_net_device *net_devices;
++
++static char *default_server;
++static grub_efi_net_interface_t *net_interface;
++static grub_efi_net_interface_t *net_default_interface;
++
++#define efi_net_interface_configure(inf) inf->io->configure (inf->dev, inf->prefer_ip6)
++#define efi_net_interface_open(inf, file, name) inf->io->open (inf->dev, inf->prefer_ip6, file, name, inf->io_type)
++#define efi_net_interface_read(inf, file, buf, sz) inf->io->read (inf->dev, inf->prefer_ip6, file, buf, sz)
++#define efi_net_interface_close(inf, file) inf->io->close (inf->dev, inf->prefer_ip6, file)
++#define efi_net_interface(m,...) efi_net_interface_ ## m (net_interface, ## __VA_ARGS__)
++
++static grub_efi_handle_t
++grub_efi_locate_device_path (grub_efi_guid_t *protocol, grub_efi_device_path_t *device_path,
++                            grub_efi_device_path_t **r_device_path)
++{
++  grub_efi_handle_t handle;
++  grub_efi_status_t status;
++
++  status = efi_call_3 (grub_efi_system_table->boot_services->locate_device_path,
++                      protocol, &device_path, &handle);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return 0;
++
++  if (r_device_path)
++    *r_device_path = device_path;
++
++  return handle;
++}
++
++static int
++url_parse_fields (const char *url, char **proto, char **host, char **path)
++{
++  const char *p, *ps;
++  grub_size_t l;
++
++  *proto = *host = *path = NULL;
++  ps = p = url;
++
++  while ((p = grub_strchr (p, ':')))
++    {
++      if (grub_strlen (p) < sizeof ("://") - 1)
++	break;
++      if (grub_memcmp (p, "://", sizeof ("://") - 1) == 0)
++	{
++	  l = p - ps;
++	  *proto = grub_malloc (l + 1);
++	  if (!*proto)
++	    {
++	      grub_print_error ();
++	      return 0;
++	    }
++
++	  grub_memcpy (*proto, ps, l);
++	  (*proto)[l] = '\0';
++	  p +=  sizeof ("://") - 1;
++	  break;
++	}
++      ++p;
++    }
++
++  if (!*proto)
++    {
++      grub_dprintf ("bootp", "url: %s is not valid, protocol not found\n", url);
++      return 0;
++    }
++
++  ps = p;
++  p = grub_strchr (p, '/');
++
++  if (!p)
++    {
++      grub_dprintf ("bootp", "url: %s is not valid, host/path not found\n", url);
++      grub_free (*proto);
++      *proto = NULL;
++      return 0;
++    }
++
++  l = p - ps;
++
++  if (l > 2 && ps[0] == '[' && ps[l - 1] == ']')
++    {
++      *host = grub_malloc (l - 1);
++      if (!*host)
++	{
++	  grub_print_error ();
++	  grub_free (*proto);
++	  *proto = NULL;
++	  return 0;
++	}
++      grub_memcpy (*host, ps + 1, l - 2);
++      (*host)[l - 2] = 0;
++    }
++  else
++    {
++      *host = grub_malloc (l + 1);
++      if (!*host)
++	{
++	  grub_print_error ();
++	  grub_free (*proto);
++	  *proto = NULL;
++	  return 0;
++	}
++      grub_memcpy (*host, ps, l);
++      (*host)[l] = 0;
++    }
++
++  *path = grub_strdup (p);
++  if (!*path)
++    {
++      grub_print_error ();
++      grub_free (*host);
++      grub_free (*proto);
++      *host = NULL;
++      *proto = NULL;
++      return 0;
++    }
++  return 1;
++}
++
++static void
++url_get_boot_location (const char *url, char **device, char **path, int is_default)
++{
++  char *protocol, *server, *file;
++  char *slash;
++
++  if (!url_parse_fields (url, &protocol, &server, &file))
++    return;
++
++  if ((slash = grub_strrchr (file, '/')))
++    *slash = 0;
++  else
++    *file = 0;
++
++  *device = grub_xasprintf ("%s,%s", protocol, server);
++  *path = grub_strdup(file);
++
++  if (is_default)
++    default_server = server;
++  else
++    grub_free (server);
++
++  grub_free (protocol);
++  grub_free (file);
++}
++
++static void
++pxe_get_boot_location (const struct grub_net_bootp_packet *bp,
++		  char **device,
++		  char **path,
++		  int is_default)
++{
++  char *server = grub_xasprintf ("%d.%d.%d.%d",
++	     ((grub_uint8_t *) &bp->server_ip)[0],
++	     ((grub_uint8_t *) &bp->server_ip)[1],
++	     ((grub_uint8_t *) &bp->server_ip)[2],
++	     ((grub_uint8_t *) &bp->server_ip)[3]);
++
++  *device = grub_xasprintf ("tftp,%s", server);
++
++  *path = grub_strndup (bp->boot_file, sizeof (bp->boot_file));
++
++  if (*path)
++    {
++      char *slash;
++      slash = grub_strrchr (*path, '/');
++      if (slash)
++	*slash = 0;
++      else
++	**path = 0;
++    }
++
++  if (is_default)
++    default_server = server;
++  else
++    grub_free (server);
++}
++
++static void
++pxe_get_boot_location_v6 (const struct grub_net_dhcp6_packet *dp,
++		  grub_size_t dhcp_size,
++		  char **device,
++		  char **path)
++{
++
++  struct grub_net_dhcp6_option *dhcp_opt;
++  grub_size_t dhcp_remain_size;
++  *device = *path = 0;
++
++  if (dhcp_size < sizeof (*dp))
++    {
++      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("DHCPv6 packet size too small"));
++      return;
++    }
++
++  dhcp_remain_size = dhcp_size - sizeof (*dp);
++  dhcp_opt = (struct grub_net_dhcp6_option *)dp->dhcp_options;
++
++  while (dhcp_remain_size)
++    {
++      grub_uint16_t code = grub_be_to_cpu16 (dhcp_opt->code);
++      grub_uint16_t len = grub_be_to_cpu16 (dhcp_opt->len);
++      grub_uint16_t option_size = sizeof (*dhcp_opt) + len;
++
++      if (dhcp_remain_size < option_size || code == 0)
++	break;
++
++      if (code == GRUB_NET_DHCP6_OPTION_BOOTFILE_URL)
++	{
++	  char *url;
++	  grub_size_t sz;
++
++	  if (grub_add (len, 1, &sz))
++	    return;
++
++	  url = grub_malloc (sz);
++	  if (!url)
++	    return;
++
++	  grub_memcpy (url, dhcp_opt->data, len);
++	  url[len] = 0;
++
++	  url_get_boot_location ((const char *)url, device, path, 1);
++	  grub_free (url);
++	  break;
++	}
++
++      dhcp_remain_size -= option_size;
++      dhcp_opt = (struct grub_net_dhcp6_option *)((grub_uint8_t *)dhcp_opt + option_size);
++    }
++}
++
++static grub_efi_net_interface_t *
++grub_efi_net_config_from_device_path (grub_efi_device_path_t *dp,
++		  struct grub_efi_net_device *netdev,
++		  char **device,
++		  char **path)
++{
++  grub_efi_net_interface_t *inf = NULL;
++
++  while (1)
++    {
++      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
++      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
++      grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
++
++      if (type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE)
++	{
++	  if (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)
++	    {
++	      grub_efi_uri_device_path_t *uri_dp;
++	      uri_dp = (grub_efi_uri_device_path_t *) dp;
++	      /* Beware that uri_dp->uri may not be null terminated */
++	      url_get_boot_location ((const char *)uri_dp->uri, device, path, 1);
++	    }
++	  else if (subtype == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE)
++	    {
++	      grub_efi_net_ip_manual_address_t net_ip;
++	      grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) dp;
++
++	      if (inf)
++		continue;
++	      grub_memcpy (net_ip.ip4.address, ipv4->local_ip_address, sizeof (net_ip.ip4.address));
++	      grub_memcpy (net_ip.ip4.subnet_mask, ipv4->subnet_mask, sizeof (net_ip.ip4.subnet_mask));
++	      net_ip.is_ip6 = 0;
++	      inf = grub_efi_net_create_interface (netdev,
++			    netdev->card_name,
++			    &net_ip,
++			    1);
++	    }
++	  else if (subtype == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)
++	    {
++	      grub_efi_net_ip_manual_address_t net_ip;
++	      grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) dp;
++
++	      if (inf)
++		continue;
++	      grub_memcpy (net_ip.ip6.address, ipv6->local_ip_address, sizeof (net_ip.ip6.address));
++	      net_ip.ip6.prefix_length = GRUB_EFI_IP6_PREFIX_LENGTH;
++	      net_ip.ip6.is_anycast = 0;
++	      net_ip.is_ip6 = 1;
++	      inf = grub_efi_net_create_interface (netdev,
++			    netdev->card_name,
++			    &net_ip,
++			    1);
++	    }
++	}
++
++      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
++        break;
++      dp = (grub_efi_device_path_t *) ((char *) dp + len);
++    }
++
++  return inf;
++}
++
++static grub_efi_net_interface_t *
++grub_efi_net_config_from_handle (grub_efi_handle_t *hnd,
++		  struct grub_efi_net_device *netdev,
++		  char **device,
++		  char **path)
++{
++  grub_efi_pxe_t *pxe = NULL;
++
++  if (hnd == netdev->ip4_pxe_handle)
++    pxe = netdev->ip4_pxe;
++  else if (hnd == netdev->ip6_pxe_handle)
++    pxe = netdev->ip6_pxe;
++
++  if (!pxe)
++    return (grub_efi_net_config_from_device_path (
++		grub_efi_get_device_path (hnd),
++		netdev,
++		device,
++		path));
++
++  if (pxe->mode->using_ipv6)
++    {
++      grub_efi_net_ip_manual_address_t net_ip;
++
++      pxe_get_boot_location_v6 (
++	    (const struct grub_net_dhcp6_packet *) &pxe->mode->dhcp_ack,
++	    sizeof (pxe->mode->dhcp_ack),
++	    device,
++	    path);
++
++      grub_memcpy (net_ip.ip6.address, pxe->mode->station_ip.v6.addr, sizeof(net_ip.ip6.address));
++      net_ip.ip6.prefix_length = GRUB_EFI_IP6_PREFIX_LENGTH;
++      net_ip.ip6.is_anycast = 0;
++      net_ip.is_ip6 = 1;
++      return (grub_efi_net_create_interface (netdev,
++		    netdev->card_name,
++		    &net_ip,
++		    1));
++    }
++  else
++    {
++      grub_efi_net_ip_manual_address_t net_ip;
++
++      pxe_get_boot_location (
++		(const struct grub_net_bootp_packet *) &pxe->mode->dhcp_ack,
++		device,
++		path,
++		1);
++
++      grub_memcpy (net_ip.ip4.address, pxe->mode->station_ip.v4.addr, sizeof (net_ip.ip4.address));
++      grub_memcpy (net_ip.ip4.subnet_mask, pxe->mode->subnet_mask.v4.addr, sizeof (net_ip.ip4.subnet_mask));
++      net_ip.is_ip6 = 0;
++      return (grub_efi_net_create_interface (netdev,
++		    netdev->card_name,
++		    &net_ip,
++		    1));
++    }
++}
++
++static const char *
++grub_efi_net_var_get_address (struct grub_env_var *var,
++                   const char *val __attribute__ ((unused)))
++{
++  struct grub_efi_net_device *dev;
++
++  for (dev = net_devices; dev; dev = dev->next)
++    {
++      grub_efi_net_interface_t *inf;
++
++      for (inf = dev->net_interfaces; inf; inf = inf->next)
++	{
++	  char *var_name;
++
++	  var_name = grub_xasprintf ("net_%s_ip", inf->name);
++	  if (grub_strcmp (var_name, var->name) == 0)
++	    return efi_net_interface_get_address (inf);
++	  grub_free (var_name);
++	  var_name = grub_xasprintf ("net_%s_mac", inf->name);
++	  if (grub_strcmp (var_name, var->name) == 0)
++	    return efi_net_interface_get_hw_address (inf);
++	  grub_free (var_name);
++	}
++    }
++
++  return NULL;
++}
++
++static char *
++grub_efi_net_var_set_interface (struct grub_env_var *var __attribute__ ((unused)),
++		   const char *val)
++{
++  struct grub_efi_net_device *dev;
++  grub_efi_net_interface_t *inf;
++
++  for (dev = net_devices; dev; dev = dev->next)
++    for (inf = dev->net_interfaces; inf; inf = inf->next)
++      if (grub_strcmp (inf->name, val) == 0)
++	{
++	  net_default_interface = inf;
++	  return grub_strdup (val);
++	}
++
++  return NULL;
++}
++
++static char *
++grub_efi_net_var_set_server (struct grub_env_var *var __attribute__ ((unused)),
++		   const char *val)
++{
++  grub_free (default_server);
++  default_server = grub_strdup (val);
++  return grub_strdup (val);
++}
++
++static const char *
++grub_efi_net_var_get_server (struct grub_env_var *var __attribute__ ((unused)),
++		   const char *val __attribute__ ((unused)))
++{
++  return default_server ? : "";
++}
++
++static const char *
++grub_efi_net_var_get_ip (struct grub_env_var *var __attribute__ ((unused)),
++	       const char *val __attribute__ ((unused)))
++{
++  const char *intf = grub_env_get ("net_default_interface");
++  const char *ret = NULL;
++  if (intf)
++    {
++      char *buf = grub_xasprintf ("net_%s_ip", intf);
++      if (buf)
++	ret = grub_env_get (buf);
++      grub_free (buf);
++    }
++  return ret;
++}
++
++static const char *
++grub_efi_net_var_get_mac (struct grub_env_var *var __attribute__ ((unused)),
++	       const char *val __attribute__ ((unused)))
++{
++  const char *intf = grub_env_get ("net_default_interface");
++  const char *ret = NULL;
++  if (intf)
++    {
++      char *buf = grub_xasprintf ("net_%s_mac", intf);
++      if (buf)
++	ret = grub_env_get (buf);
++      grub_free (buf);
++    }
++  return ret;
++}
++
++static void
++grub_efi_net_export_interface_vars (void)
++{
++  struct grub_efi_net_device *dev;
++
++  for (dev = net_devices; dev; dev = dev->next)
++    {
++      grub_efi_net_interface_t *inf;
++
++      for (inf = dev->net_interfaces; inf; inf = inf->next)
++	{
++	  char *var;
++
++	  var = grub_xasprintf ("net_%s_ip", inf->name);
++	  grub_register_variable_hook (var, grub_efi_net_var_get_address, 0);
++	  grub_env_export (var);
++	  grub_free (var);
++	  var = grub_xasprintf ("net_%s_mac", inf->name);
++	  grub_register_variable_hook (var, grub_efi_net_var_get_address, 0);
++	  grub_env_export (var);
++	  grub_free (var);
++	}
++    }
++}
++
++static void
++grub_efi_net_unset_interface_vars (void)
++{
++  struct grub_efi_net_device *dev;
++
++  for (dev = net_devices; dev; dev = dev->next)
++    {
++      grub_efi_net_interface_t *inf;
++
++      for (inf = dev->net_interfaces; inf; inf = inf->next)
++	{
++	  char *var;
++
++	  var = grub_xasprintf ("net_%s_ip", inf->name);
++	  grub_register_variable_hook (var, 0, 0);
++	  grub_env_unset (var);
++	  grub_free (var);
++	  var = grub_xasprintf ("net_%s_mac", inf->name);
++	  grub_register_variable_hook (var, 0, 0);
++	  grub_env_unset (var);
++	  grub_free (var);
++	}
++    }
++}
++
++grub_efi_net_interface_t *
++grub_efi_net_create_interface (struct grub_efi_net_device *dev,
++		const char *interface_name,
++		grub_efi_net_ip_manual_address_t *net_ip,
++		int has_subnet)
++{
++  grub_efi_net_interface_t *inf;
++
++  for (inf = dev->net_interfaces; inf; inf = inf->next)
++    {
++      if (inf->prefer_ip6 == net_ip->is_ip6)
++	break;
++    }
++
++  if (!inf)
++    {
++      inf = grub_malloc (sizeof(*inf));
++      inf->name = grub_strdup (interface_name);
++      inf->prefer_ip6 = net_ip->is_ip6;
++      inf->dev = dev;
++      inf->next = dev->net_interfaces;
++      inf->ip_config = (net_ip->is_ip6) ? efi_net_ip6_config : efi_net_ip4_config ;
++      dev->net_interfaces = inf;
++    }
++  else
++    {
++      grub_free (inf->name);
++      inf->name = grub_strdup (interface_name);
++    }
++
++  if (!efi_net_interface_set_address (inf, net_ip, has_subnet))
++    {
++      grub_error (GRUB_ERR_BUG, N_("Set Address Failed"));
++      return NULL;
++    }
++
++  return inf;
++}
++
++static void
++grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
++			  char **path)
++{
++  grub_efi_handle_t config_hnd;
++
++  struct grub_efi_net_device *netdev;
++  grub_efi_net_interface_t *inf;
++
++  config_hnd = grub_efi_locate_device_path (&ip4_config_guid, grub_efi_get_device_path (hnd), NULL);
++
++  if (!config_hnd)
++    return;
++
++  for (netdev = net_devices; netdev; netdev = netdev->next)
++    if (netdev->handle == config_hnd)
++      break;
++
++  if (!netdev)
++    return;
++
++  if (!(inf = grub_efi_net_config_from_handle (hnd, netdev, device, path)))
++    return;
++
++  grub_env_set ("net_default_interface", inf->name);
++  grub_efi_net_export_interface_vars ();
++}
++
++static grub_err_t
++grub_efi_netfs_dir (grub_device_t device, const char *path __attribute__ ((unused)),
++		 grub_fs_dir_hook_t hook __attribute__ ((unused)),
++		 void *hook_data __attribute__ ((unused)))
++{
++  if (!device->net)
++    return grub_error (GRUB_ERR_BUG, "invalid net device");
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_efi_netfs_open (struct grub_file *file_out __attribute__ ((unused)),
++		  const char *name __attribute__ ((unused)))
++{
++  struct grub_file *file, *bufio;
++
++  file = grub_malloc (sizeof (*file));
++  if (!file)
++    return grub_errno;
++
++  grub_memcpy (file, file_out, sizeof (struct grub_file));
++  file->device->net->name = grub_strdup (name);
++
++  if (!file->device->net->name)
++    {
++      grub_free (file);
++      return grub_errno;
++    }
++
++  efi_net_interface(open, file, name);
++  grub_print_error ();
++
++  bufio = grub_bufio_open (file, 32768);
++  if (!bufio)
++    {
++      grub_free (file->device->net->name);
++      grub_free (file);
++      return grub_errno;
++    }
++  grub_memcpy (file_out, bufio, sizeof (struct grub_file));
++  grub_free (bufio);
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_ssize_t
++grub_efihttp_chunk_read (grub_file_t file, char *buf,
++			grub_size_t len, grub_size_t chunk_size)
++{
++  char *chunk = grub_malloc (chunk_size);
++  grub_size_t sum = 0;
++
++  while (len)
++    {
++      grub_ssize_t rd;
++      grub_size_t sz = (len > chunk_size) ? chunk_size : len;
++
++      rd = efi_net_interface (read, file, chunk, sz);
++
++      if (rd <= 0)
++	return rd;
++
++      if (buf)
++	{
++	  grub_memcpy (buf, chunk, rd);
++	  buf += rd;
++	}
++      sum += rd;
++      len -= rd;
++    }
++
++  grub_free (chunk);
++  return sum;
++}
++
++static grub_ssize_t
++grub_efi_netfs_read (grub_file_t file __attribute__ ((unused)),
++		  char *buf __attribute__ ((unused)), grub_size_t len __attribute__ ((unused)))
++{
++  if (file->offset > file->device->net->offset)
++    {
++      grub_efihttp_chunk_read (file, NULL, file->offset - file->device->net->offset, 10240);
++    }
++  else if (file->offset < file->device->net->offset)
++    {
++      efi_net_interface (close, file);
++      efi_net_interface (open, file, file->device->net->name);
++      if (file->offset)
++	grub_efihttp_chunk_read (file, NULL, file->offset, 10240);
++    }
++
++  return efi_net_interface (read, file, buf, len);
++}
++
++static grub_err_t
++grub_efi_netfs_close (grub_file_t file)
++{
++  efi_net_interface (close, file);
++  return GRUB_ERR_NONE;
++}
++
++static grub_efi_handle_t
++grub_efi_service_binding (grub_efi_handle_t dev, grub_efi_guid_t *service_binding_guid)
++{
++  grub_efi_service_binding_t *service;
++  grub_efi_status_t status;
++  grub_efi_handle_t child_dev = NULL;
++
++  service = grub_efi_open_protocol (dev, service_binding_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++  if (!service)
++    {
++      grub_error (GRUB_ERR_IO, N_("couldn't open efi service binding protocol"));
++      return NULL;
++    }
++
++  status = efi_call_2 (service->create_child, service, &child_dev);
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_error (GRUB_ERR_IO, N_("Failed to create child device of http service %" PRIxGRUB_SIZE), status);
++      return NULL;
++    }
++
++  return child_dev;
++}
++
++static grub_err_t
++grub_efi_net_parse_address (const char *address,
++    grub_efi_ip4_config2_manual_address_t *ip4,
++    grub_efi_ip6_config_manual_address_t *ip6,
++    int *is_ip6,
++    int *has_cidr)
++{
++  const char *rest;
++
++  if (grub_efi_string_to_ip4_address (address, &ip4->address, &rest))
++    {
++      *is_ip6 = 0;
++      if (*rest == '/')
++	{
++	  grub_uint32_t subnet_mask_size;
++
++	  subnet_mask_size = grub_strtoul (rest + 1, &rest, 0);
++
++	  if (!grub_errno && subnet_mask_size <= 32 && *rest == 0)
++	    {
++	      grub_uint32_t subnet_mask;
++
++	      subnet_mask = grub_cpu_to_be32 ((0xffffffffU << (32 - subnet_mask_size)));
++	      grub_memcpy (ip4->subnet_mask, &subnet_mask, sizeof (ip4->subnet_mask));
++	      if (has_cidr)
++		*has_cidr = 1;
++	      return GRUB_ERR_NONE;
++	    }
++	}
++      else if (*rest == 0)
++	{
++	  grub_uint32_t subnet_mask = 0xffffffffU;
++	  grub_memcpy (ip4->subnet_mask, &subnet_mask, sizeof (ip4->subnet_mask));
++	  if (has_cidr)
++	    *has_cidr = 0;
++	  return GRUB_ERR_NONE;
++	}
++    }
++  else if (grub_efi_string_to_ip6_address (address, &ip6->address, &rest))
++    {
++      *is_ip6 = 1;
++      if (*rest == '/')
++	{
++	  grub_efi_uint8_t prefix_length;
++
++	  prefix_length = grub_strtoul (rest + 1, &rest, 0);
++	  if (!grub_errno && prefix_length <= 128 && *rest == 0)
++	    {
++	      ip6->prefix_length = prefix_length;
++	      ip6->is_anycast = 0;
++	      if (has_cidr)
++		*has_cidr = 1;
++	      return GRUB_ERR_NONE;
++	    }
++	}
++      else if (*rest == 0)
++	{
++	  ip6->prefix_length = 128;
++	  ip6->is_anycast = 0;
++	  if (has_cidr)
++	    *has_cidr = 0;
++	  return GRUB_ERR_NONE;
++	}
++    }
++
++  return grub_error (GRUB_ERR_NET_BAD_ADDRESS,
++		   N_("unrecognised network address `%s'"),
++		   address);
++}
++
++static grub_efi_net_interface_t *
++match_route (const char *server)
++{
++  grub_err_t err;
++  grub_efi_ip4_config2_manual_address_t ip4;
++  grub_efi_ip6_config_manual_address_t ip6;
++  grub_efi_net_interface_t *inf;
++  int is_ip6 = 0;
++
++  grub_error_push ();
++  err = grub_efi_net_parse_address (server, &ip4, &ip6, &is_ip6, 0);
++
++  if (err)
++    {
++      grub_dprintf ("efinetfs", "error in matching route : %s\n", grub_errmsg);
++      grub_error_pop ();
++      return NULL;
++    }
++  grub_error_pop ();
++
++  if (is_ip6)
++    {
++      struct grub_efi_net_device *dev;
++      grub_efi_net_ip_address_t addr;
++
++      grub_memcpy (addr.ip6, ip6.address, sizeof(ip6.address));
++
++      for (dev = net_devices; dev; dev = dev->next)
++	  if ((inf = efi_net_ip6_config->best_interface (dev, &addr)))
++	    return inf;
++    }
++  else
++    {
++      struct grub_efi_net_device *dev;
++      grub_efi_net_ip_address_t addr;
++
++      grub_memcpy (addr.ip4, ip4.address, sizeof(ip4.address));
++
++      for (dev = net_devices; dev; dev = dev->next)
++	  if ((inf = efi_net_ip4_config->best_interface (dev, &addr)))
++	    return inf;
++    }
++
++  return 0;
++}
++
++static void
++grub_efi_net_add_pxebc_to_cards (void)
++{
++  grub_efi_uintn_t num_handles;
++  grub_efi_handle_t *handles;
++  grub_efi_handle_t *handle;
++
++  handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &pxe_io_guid,
++				    0, &num_handles);
++  if (!handles)
++    return;
++
++  for (handle = handles; num_handles--; handle++)
++    {
++      grub_efi_device_path_t *dp, *ddp, *ldp;
++      grub_efi_pxe_t *pxe;
++      struct grub_efi_net_device *d;
++      int is_ip6 = 0;
++
++      dp = grub_efi_get_device_path (*handle);
++      if (!dp)
++	continue;
++
++      ddp = grub_efi_duplicate_device_path (dp);
++      ldp = grub_efi_find_last_device_path (ddp);
++
++      if (ldp->type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
++	  && ldp->subtype == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE)
++	{
++	  ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++	  ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++	  ldp->length = sizeof (*ldp);
++	}
++      else if (ldp->type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
++	  && ldp->subtype == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)
++	{
++	  is_ip6 = 1;
++	  ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++	  ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++	  ldp->length = sizeof (*ldp);
++	}
++
++      for (d = net_devices; d; d = d->next)
++	if (grub_efi_compare_device_paths (ddp, grub_efi_get_device_path (d->handle)) == 0)
++	  break;
++
++      if (!d)
++	{
++	  grub_free (ddp);
++	  continue;
++	}
++
++      pxe = grub_efi_open_protocol (*handle, &pxe_io_guid,
++				GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++      if (!pxe)
++	{
++	  grub_free (ddp);
++	  continue;
++	}
++
++      if (is_ip6)
++	{
++	  d->ip6_pxe_handle = *handle;
++	  d->ip6_pxe = pxe;
++	}
++      else
++	{
++	  d->ip4_pxe_handle = *handle;
++	  d->ip4_pxe = pxe;
++	}
++
++      grub_free (ddp);
++    }
++
++  grub_free (handles);
++}
++
++static void
++set_ip_policy_to_static (void)
++{
++  struct grub_efi_net_device *dev;
++
++  for (dev = net_devices; dev; dev = dev->next)
++    {
++      grub_efi_ip4_config2_policy_t ip4_policy = GRUB_EFI_IP4_CONFIG2_POLICY_STATIC;
++
++      if (efi_call_4 (dev->ip4_config->set_data, dev->ip4_config,
++		    GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY,
++		    sizeof (ip4_policy), &ip4_policy) != GRUB_EFI_SUCCESS)
++	grub_dprintf ("efinetfs", "could not set GRUB_EFI_IP4_CONFIG2_POLICY_STATIC on dev `%s'", dev->card_name);
++
++      if (dev->ip6_config)
++	{
++	  grub_efi_ip6_config_policy_t ip6_policy = GRUB_EFI_IP6_CONFIG_POLICY_MANUAL;
++
++	  if (efi_call_4 (dev->ip6_config->set_data, dev->ip6_config,
++		    GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY,
++		    sizeof (ip6_policy), &ip6_policy) != GRUB_EFI_SUCCESS)
++	    grub_dprintf ("efinetfs", "could not set GRUB_EFI_IP6_CONFIG_POLICY_MANUAL on dev `%s'", dev->card_name);
++	}
++    }
++}
++
++/* FIXME: Do not fail if the card did not support any of the protocol (Eg http) */
++static void
++grub_efi_net_find_cards (void)
++{
++  grub_efi_uintn_t num_handles;
++  grub_efi_handle_t *handles;
++  grub_efi_handle_t *handle;
++  int id;
++
++  handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &ip4_config_guid,
++				    0, &num_handles);
++  if (!handles)
++    return;
++
++  for (id = 0, handle = handles; num_handles--; handle++, id++)
++    {
++      grub_efi_device_path_t *dp;
++      grub_efi_ip4_config2_protocol_t *ip4_config;
++      grub_efi_ip6_config_protocol_t *ip6_config;
++      grub_efi_handle_t http_handle;
++      grub_efi_http_t *http;
++      grub_efi_handle_t dhcp4_handle;
++      grub_efi_dhcp4_protocol_t *dhcp4;
++      grub_efi_handle_t dhcp6_handle;
++      grub_efi_dhcp6_protocol_t *dhcp6;
++
++      struct grub_efi_net_device *d;
++
++      dp = grub_efi_get_device_path (*handle);
++      if (!dp)
++	continue;
++
++      ip4_config = grub_efi_open_protocol (*handle, &ip4_config_guid,
++				    GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++      if (!ip4_config)
++	continue;
++
++      ip6_config = grub_efi_open_protocol (*handle, &ip6_config_guid,
++				    GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++      http_handle = grub_efi_service_binding (*handle, &http_service_binding_guid);
++      grub_errno = GRUB_ERR_NONE;
++      http = (http_handle)
++	? grub_efi_open_protocol (http_handle, &http_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL)
++	: NULL;
++
++      dhcp4_handle = grub_efi_service_binding (*handle, &dhcp4_service_binding_guid);
++      grub_errno = GRUB_ERR_NONE;
++      dhcp4 = (dhcp4_handle)
++	? grub_efi_open_protocol (dhcp4_handle, &dhcp4_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL)
++	: NULL;
++
++
++      dhcp6_handle = grub_efi_service_binding (*handle, &dhcp6_service_binding_guid);
++      grub_errno = GRUB_ERR_NONE;
++      dhcp6 = (dhcp6_handle)
++	? grub_efi_open_protocol (dhcp6_handle, &dhcp6_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL)
++	: NULL;
++
++      d = grub_malloc (sizeof (*d));
++      if (!d)
++	{
++	  grub_free (handles);
++	  while (net_devices)
++	    {
++	      d = net_devices->next;
++	      grub_free (net_devices);
++	      net_devices = d;
++	    }
++	  return;
++	}
++      d->handle = *handle;
++      d->ip4_config = ip4_config;
++      d->ip6_config = ip6_config;
++      d->http_handle = http_handle;
++      d->http = http;
++      d->dhcp4_handle = dhcp4_handle;
++      d->dhcp4 = dhcp4;
++      d->dhcp6_handle = dhcp6_handle;
++      d->dhcp6 = dhcp6;
++      d->next = net_devices;
++      d->card_name = grub_xasprintf ("efinet%d", id);
++      d->net_interfaces = NULL;
++      net_devices = d;
++    }
++
++  grub_efi_net_add_pxebc_to_cards ();
++  grub_free (handles);
++  set_ip_policy_to_static ();
++}
++
++static void
++listroutes_ip4 (struct grub_efi_net_device *netdev)
++{
++  char **routes;
++
++  routes = NULL;
++
++  if ((routes = efi_net_ip4_config->get_route_table (netdev)))
++    {
++      char **r;
++
++      for (r = routes; *r; ++r)
++	grub_printf ("%s\n", *r);
++    }
++
++  if (routes)
++    {
++      char **r;
++
++      for (r = routes; *r; ++r)
++	grub_free (*r);
++      grub_free (routes);
++    }
++}
++
++static void
++listroutes_ip6 (struct grub_efi_net_device *netdev)
++{
++  char **routes;
++
++  routes = NULL;
++
++  if ((routes = efi_net_ip6_config->get_route_table (netdev)))
++    {
++      char **r;
++
++      for (r = routes; *r; ++r)
++	grub_printf ("%s\n", *r);
++    }
++
++  if (routes)
++    {
++      char **r;
++
++      for (r = routes; *r; ++r)
++	grub_free (*r);
++      grub_free (routes);
++    }
++}
++
++static grub_err_t
++grub_cmd_efi_listroutes (struct grub_command *cmd __attribute__ ((unused)),
++		     int argc __attribute__ ((unused)),
++		     char **args __attribute__ ((unused)))
++{
++  struct grub_efi_net_device *netdev;
++
++  for (netdev = net_devices; netdev; netdev = netdev->next)
++    {
++      listroutes_ip4 (netdev);
++      listroutes_ip6 (netdev);
++    }
++
++  return GRUB_ERR_NONE;
++}
++static grub_err_t
++grub_cmd_efi_listcards (struct grub_command *cmd __attribute__ ((unused)),
++		    int argc __attribute__ ((unused)),
++		    char **args __attribute__ ((unused)))
++{
++  struct grub_efi_net_device *dev;
++
++  for (dev = net_devices; dev; dev = dev->next)
++    {
++      char *hw_addr;
++
++      hw_addr = efi_net_ip4_config->get_hw_address (dev);
++
++      if (hw_addr)
++	{
++	  grub_printf ("%s %s\n", dev->card_name, hw_addr);
++	  grub_free (hw_addr);
++	}
++    }
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_cmd_efi_listaddrs (struct grub_command *cmd __attribute__ ((unused)),
++		    int argc __attribute__ ((unused)),
++		    char **args __attribute__ ((unused)))
++{
++  struct grub_efi_net_device *dev;
++  grub_efi_net_interface_t *inf;
++
++  for (dev = net_devices; dev; dev = dev->next)
++    for (inf = dev->net_interfaces; inf; inf = inf->next)
++      {
++	char *hw_addr = NULL;
++	char *addr = NULL;
++
++	if ((hw_addr = efi_net_interface_get_hw_address (inf))
++	    && (addr = efi_net_interface_get_address (inf)))
++	  grub_printf ("%s %s %s\n", inf->name, hw_addr, addr);
++
++	if (hw_addr)
++	  grub_free (hw_addr);
++	if (addr)
++	  grub_free (addr);
++      }
++
++  return GRUB_ERR_NONE;
++}
++
++/* FIXME: support MAC specifying.  */
++static grub_err_t
++grub_cmd_efi_addaddr (struct grub_command *cmd __attribute__ ((unused)),
++                  int argc, char **args)
++{
++  struct grub_efi_net_device *dev;
++  grub_err_t err;
++  grub_efi_ip4_config2_manual_address_t ip4;
++  grub_efi_ip6_config_manual_address_t ip6;
++  grub_efi_net_ip_manual_address_t net_ip;
++  int is_ip6 = 0;
++  int cidr = 0;
++
++  if (argc != 3)
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected"));
++
++  for (dev = net_devices; dev; dev = dev->next)
++    {
++      if (grub_strcmp (dev->card_name, args[1]) == 0)
++	break;
++    }
++
++  if (!dev)
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found"));
++
++  err = grub_efi_net_parse_address (args[2], &ip4, &ip6, &is_ip6, &cidr);
++
++  if (err)
++    return err;
++
++  net_ip.is_ip6 = is_ip6;
++  if (is_ip6)
++    grub_memcpy (&net_ip.ip6, &ip6, sizeof(net_ip.ip6));
++  else
++    grub_memcpy (&net_ip.ip4, &ip4, sizeof(net_ip.ip4));
++
++  if (!grub_efi_net_create_interface (dev,
++		args[0],
++		&net_ip,
++		cidr))
++    return grub_errno;
++
++  return GRUB_ERR_NONE;
++}
++
++static struct grub_fs grub_efi_netfs;
++
++static grub_net_t
++grub_net_open_real (const char *name __attribute__ ((unused)))
++{
++  grub_size_t protnamelen;
++  const char *protname, *server;
++  grub_net_t ret;
++
++  net_interface = NULL;
++
++  if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
++    {
++      protname = "tftp";
++      protnamelen = sizeof ("tftp") - 1;
++      server = name + sizeof ("pxe:") - 1;
++    }
++  else if (grub_strcmp (name, "pxe") == 0)
++    {
++      protname = "tftp";
++      protnamelen = sizeof ("tftp") - 1;
++      server = default_server;
++    }
++  else
++    {
++      const char *comma;
++
++      comma = grub_strchr (name, ',');
++      if (comma)
++	{
++	  protnamelen = comma - name;
++	  server = comma + 1;
++	  protname = name;
++	}
++      else
++	{
++	  protnamelen = grub_strlen (name);
++	  server = default_server;
++	  protname = name;
++	}
++    }
++
++  if (!server)
++    {
++      grub_error (GRUB_ERR_NET_BAD_ADDRESS,
++		  N_("no server is specified"));
++      return NULL;
++    }
++
++  /*FIXME: Use DNS translate name to address */
++  net_interface = match_route (server);
++
++  /*XXX: should we check device with default gateway ? */
++  if (!net_interface && !(net_interface = net_default_interface))
++    {
++      grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' no route found"),
++		  name);
++      return NULL;
++    }
++
++  if ((protnamelen == (sizeof ("https") - 1)
++	&& grub_memcmp ("https", protname, protnamelen) == 0))
++    {
++      net_interface->io = &io_http;
++      net_interface->io_type = 1;
++    }
++  else if ((protnamelen == (sizeof ("http") - 1)
++	&& grub_memcmp ("http", protname, protnamelen) == 0))
++    {
++      net_interface->io = &io_http;
++      net_interface->io_type = 0;
++    }
++  else if (protnamelen == (sizeof ("tftp") - 1)
++	&& grub_memcmp ("tftp", protname, protnamelen) == 0)
++    {
++      net_interface->io = &io_pxe;
++      net_interface->io_type = 0;
++    }
++  else
++    {
++      grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"),
++		  name);
++      return NULL;
++    }
++
++  /*XXX: Should we try to avoid doing excess "reconfigure" here ??? */
++  efi_net_interface (configure);
++
++  ret = grub_zalloc (sizeof (*ret));
++  if (!ret)
++    return NULL;
++
++  ret->server = grub_strdup (server);
++  if (!ret->server)
++    {
++      grub_free (ret);
++      return NULL;
++    }
++
++  ret->fs = &grub_efi_netfs;
++  return ret;
++}
++#if 0
++static grub_command_t cmd_efi_lsaddr;
++static grub_command_t cmd_efi_lscards;
++static grub_command_t cmd_efi_lsroutes;
++static grub_command_t cmd_efi_addaddr;
++#endif
++
++static struct grub_fs grub_efi_netfs =
++  {
++    .name = "efi netfs",
++    .fs_dir = grub_efi_netfs_dir,
++    .fs_open = grub_efi_netfs_open,
++    .fs_read = grub_efi_netfs_read,
++    .fs_close = grub_efi_netfs_close,
++    .fs_label = NULL,
++    .fs_uuid = NULL,
++    .fs_mtime = NULL,
++  };
++
++int
++grub_efi_net_boot_from_https (void)
++{
++  grub_efi_loaded_image_t *image = NULL;
++  grub_efi_device_path_t *dp;
++
++  image = grub_efi_get_loaded_image (grub_efi_image_handle);
++  if (!image)
++    return 0;
++
++  dp = grub_efi_get_device_path (image->device_handle);
++
++  while (1)
++    {
++      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
++      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
++      grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
++
++      if ((type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE)
++	  && (subtype == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE))
++	{
++	  grub_efi_uri_device_path_t *uri_dp = (grub_efi_uri_device_path_t *) dp;
++	  return (grub_strncmp ((const char*)uri_dp->uri, "https://", sizeof ("https://") - 1) == 0) ? 1 : 0;
++	}
++
++      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
++        break;
++      dp = (grub_efi_device_path_t *) ((char *) dp + len);
++    }
++
++  return 0;
++}
++
++int
++grub_efi_net_boot_from_opa (void)
++{
++  grub_efi_loaded_image_t *image = NULL;
++  grub_efi_device_path_t *dp;
++
++  image = grub_efi_get_loaded_image (grub_efi_image_handle);
++  if (!image)
++    return 0;
++
++  dp = grub_efi_get_device_path (image->device_handle);
++
++  while (1)
++    {
++      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
++      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
++      grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
++
++      if ((type == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE)
++	  && (subtype == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE))
++	{
++	  grub_efi_mac_address_device_path_t *mac_dp  = (grub_efi_mac_address_device_path_t *)dp;
++	  return (mac_dp->if_type == 0xC7) ? 1 : 0;
++	}
++
++      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
++        break;
++      dp = (grub_efi_device_path_t *) ((char *) dp + len);
++    }
++
++  return 0;
++}
++
++static char *
++grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)),
++			 const char *val __attribute__ ((unused)))
++{
++  return NULL;
++}
++
++grub_command_func_t grub_efi_net_list_routes = grub_cmd_efi_listroutes;
++grub_command_func_t grub_efi_net_list_cards = grub_cmd_efi_listcards;
++grub_command_func_t grub_efi_net_list_addrs = grub_cmd_efi_listaddrs;
++grub_command_func_t grub_efi_net_add_addr = grub_cmd_efi_addaddr;
++
++int
++grub_efi_net_fs_init ()
++{
++  grub_efi_net_find_cards ();
++  grub_efi_net_config = grub_efi_net_config_real;
++  grub_net_open = grub_net_open_real;
++  grub_register_variable_hook ("net_default_server", grub_efi_net_var_get_server,
++			       grub_efi_net_var_set_server);
++  grub_env_export ("net_default_server");
++  grub_register_variable_hook ("pxe_default_server", grub_efi_net_var_get_server,
++			       grub_efi_net_var_set_server);
++  grub_env_export ("pxe_default_server");
++  grub_register_variable_hook ("net_default_interface", 0,
++			       grub_efi_net_var_set_interface);
++  grub_env_export ("net_default_interface");
++  grub_register_variable_hook ("net_default_ip", grub_efi_net_var_get_ip,
++			       0);
++  grub_env_export ("net_default_ip");
++  grub_register_variable_hook ("net_default_mac", grub_efi_net_var_get_mac,
++			       0);
++  grub_env_export ("net_default_mac");
++
++  grub_env_set ("grub_netfs_type", "efi");
++  grub_register_variable_hook ("grub_netfs_type", 0, grub_env_write_readonly);
++  grub_env_export ("grub_netfs_type");
++
++  return 1;
++}
++
++void
++grub_efi_net_fs_fini (void)
++{
++  grub_env_unset ("grub_netfs_type");
++  grub_efi_net_unset_interface_vars ();
++  grub_register_variable_hook ("net_default_server", 0, 0);
++  grub_env_unset ("net_default_server");
++  grub_register_variable_hook ("net_default_interface", 0, 0);
++  grub_env_unset ("net_default_interface");
++  grub_register_variable_hook ("pxe_default_server", 0, 0);
++  grub_env_unset ("pxe_default_server");
++  grub_register_variable_hook ("net_default_ip", 0, 0);
++  grub_env_unset ("net_default_ip");
++  grub_register_variable_hook ("net_default_mac", 0, 0);
++  grub_env_unset ("net_default_mac");
++  grub_efi_net_config = NULL;
++  grub_net_open = NULL;
++  grub_fs_unregister (&grub_efi_netfs);
++}
+diff --git a/grub-core/net/efi/pxe.c b/grub-core/net/efi/pxe.c
+new file mode 100644
+index 0000000..f5b661f
+--- /dev/null
++++ b/grub-core/net/efi/pxe.c
+@@ -0,0 +1,424 @@
++
++#include <grub/efi/api.h>
++#include <grub/efi/efi.h>
++#include <grub/misc.h>
++#include <grub/net/efi.h>
++#include <grub/charset.h>
++
++static grub_efi_ip6_config_manual_address_t *
++efi_ip6_config_manual_address (grub_efi_ip6_config_protocol_t *ip6_config)
++{
++  grub_efi_uintn_t sz;
++  grub_efi_status_t status;
++  grub_efi_ip6_config_manual_address_t *manual_address;
++
++  sz = sizeof (*manual_address);
++  manual_address = grub_malloc (sz);
++  if (!manual_address)
++    return NULL;
++
++  status = efi_call_4 (ip6_config->get_data, ip6_config,
++		    GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS,
++		    &sz, manual_address);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (manual_address);
++      return NULL;
++    }
++
++  return manual_address;
++}
++
++static grub_efi_ip4_config2_manual_address_t *
++efi_ip4_config_manual_address (grub_efi_ip4_config2_protocol_t *ip4_config)
++{
++  grub_efi_uintn_t sz;
++  grub_efi_status_t status;
++  grub_efi_ip4_config2_manual_address_t *manual_address;
++
++  sz = sizeof (*manual_address);
++  manual_address = grub_malloc (sz);
++  if (!manual_address)
++    return NULL;
++
++  status = efi_call_4 (ip4_config->get_data, ip4_config,
++		    GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
++		    &sz, manual_address);
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      grub_free (manual_address);
++      return NULL;
++    }
++
++  return manual_address;
++}
++
++static void
++pxe_configure (struct grub_efi_net_device *dev, int prefer_ip6)
++{
++  grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe;
++
++  grub_efi_pxe_mode_t *mode = pxe->mode;
++
++  if (!mode->started)
++    {
++      grub_efi_status_t status;
++      status = efi_call_2 (pxe->start, pxe, prefer_ip6);
++
++      if (status != GRUB_EFI_SUCCESS)
++	  grub_printf ("Couldn't start PXE\n");
++    }
++
++#if 0
++  grub_printf ("PXE STARTED: %u\n", mode->started);
++  grub_printf ("PXE USING IPV6: %u\n", mode->using_ipv6);
++#endif
++
++  if (mode->using_ipv6)
++    {
++      grub_efi_ip6_config_manual_address_t *manual_address;
++      manual_address = efi_ip6_config_manual_address (dev->ip6_config);
++
++      if (manual_address &&
++	  grub_memcmp (manual_address->address, mode->station_ip.v6.addr, sizeof (manual_address->address)) != 0)
++	{
++	  grub_efi_status_t status;
++	  grub_efi_pxe_ip_address_t station_ip;
++
++	  grub_memcpy (station_ip.v6.addr, manual_address->address, sizeof (station_ip.v6.addr));
++	  status = efi_call_3 (pxe->set_station_ip, pxe, &station_ip, NULL);
++
++	  if (status != GRUB_EFI_SUCCESS)
++	      grub_printf ("Couldn't set station ip\n");
++
++	  grub_free (manual_address);
++	}
++    }
++  else
++    {
++      grub_efi_ip4_config2_manual_address_t *manual_address;
++      manual_address = efi_ip4_config_manual_address (dev->ip4_config);
++
++      if (manual_address &&
++	  grub_memcmp (manual_address->address, mode->station_ip.v4.addr, sizeof (manual_address->address)) != 0)
++	{
++	  grub_efi_status_t status;
++	  grub_efi_pxe_ip_address_t station_ip;
++	  grub_efi_pxe_ip_address_t subnet_mask;
++
++	  grub_memcpy (station_ip.v4.addr, manual_address->address, sizeof (station_ip.v4.addr));
++	  grub_memcpy (subnet_mask.v4.addr, manual_address->subnet_mask, sizeof (subnet_mask.v4.addr));
++
++	  status = efi_call_3 (pxe->set_station_ip, pxe, &station_ip, &subnet_mask);
++
++	  if (status != GRUB_EFI_SUCCESS)
++	      grub_printf ("Couldn't set station ip\n");
++
++	  grub_free (manual_address);
++	}
++    }
++
++#if 0
++  if (mode->using_ipv6)
++    {
++      grub_printf ("PXE STATION IP: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
++	mode->station_ip.v6.addr[0],
++	mode->station_ip.v6.addr[1],
++	mode->station_ip.v6.addr[2],
++	mode->station_ip.v6.addr[3],
++	mode->station_ip.v6.addr[4],
++	mode->station_ip.v6.addr[5],
++	mode->station_ip.v6.addr[6],
++	mode->station_ip.v6.addr[7],
++	mode->station_ip.v6.addr[8],
++	mode->station_ip.v6.addr[9],
++	mode->station_ip.v6.addr[10],
++	mode->station_ip.v6.addr[11],
++	mode->station_ip.v6.addr[12],
++	mode->station_ip.v6.addr[13],
++	mode->station_ip.v6.addr[14],
++	mode->station_ip.v6.addr[15]);
++    }
++  else
++    {
++      grub_printf ("PXE STATION IP: %d.%d.%d.%d\n",
++	mode->station_ip.v4.addr[0],
++	mode->station_ip.v4.addr[1],
++	mode->station_ip.v4.addr[2],
++	mode->station_ip.v4.addr[3]);
++      grub_printf ("PXE SUBNET MASK: %d.%d.%d.%d\n",
++	mode->subnet_mask.v4.addr[0],
++	mode->subnet_mask.v4.addr[1],
++	mode->subnet_mask.v4.addr[2],
++	mode->subnet_mask.v4.addr[3]);
++    }
++#endif
++
++  /* TODO: Set The Station IP to the IP2 Config */
++}
++
++static int
++parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
++{
++  grub_uint16_t newip[8];
++  const char *ptr = val;
++  int word, quaddot = -1;
++  int bracketed = 0;
++
++  if (ptr[0] == '[') {
++    bracketed = 1;
++    ptr++;
++  }
++
++  if (ptr[0] == ':' && ptr[1] != ':')
++    return 0;
++  if (ptr[0] == ':')
++    ptr++;
++
++  for (word = 0; word < 8; word++)
++    {
++      unsigned long t;
++      if (*ptr == ':')
++	{
++	  quaddot = word;
++	  word--;
++	  ptr++;
++	  continue;
++	}
++      t = grub_strtoul (ptr, &ptr, 16);
++      if (grub_errno)
++	{
++	  grub_errno = GRUB_ERR_NONE;
++	  break;
++	}
++      if (t & ~0xffff)
++	return 0;
++      newip[word] = grub_cpu_to_be16 (t);
++      if (*ptr != ':')
++	break;
++      ptr++;
++    }
++  if (quaddot == -1 && word < 7)
++    return 0;
++  if (quaddot != -1)
++    {
++      grub_memmove (&newip[quaddot + 7 - word], &newip[quaddot],
++		    (word - quaddot + 1) * sizeof (newip[0]));
++      grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0]));
++    }
++  grub_memcpy (ip, newip, 16);
++  if (bracketed && *ptr == ']') {
++    ptr++;
++  }
++  if (rest)
++    *rest = ptr;
++  return 1;
++}
++
++static grub_err_t
++pxe_open (struct grub_efi_net_device *dev,
++	  int prefer_ip6,
++	  grub_file_t file,
++	  const char *filename,
++	  int type __attribute__((unused)))
++{
++  int i;
++  const char *p;
++  grub_efi_status_t status;
++  grub_efi_pxe_ip_address_t server_ip;
++  grub_efi_uint64_t file_size = 0;
++  grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe;
++
++  if (pxe->mode->using_ipv6)
++    {
++      const char *rest;
++      grub_uint64_t ip6[2];
++      if (parse_ip6 (file->device->net->server, ip6, &rest) && *rest == 0)
++	grub_memcpy (server_ip.v6.addr, ip6, sizeof (server_ip.v6.addr));
++      /* TODO: ERROR Handling Here */
++#if 0
++      grub_printf ("PXE SERVER IP: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
++	server_ip.v6.addr[0],
++	server_ip.v6.addr[1],
++	server_ip.v6.addr[2],
++	server_ip.v6.addr[3],
++	server_ip.v6.addr[4],
++	server_ip.v6.addr[5],
++	server_ip.v6.addr[6],
++	server_ip.v6.addr[7],
++	server_ip.v6.addr[8],
++	server_ip.v6.addr[9],
++	server_ip.v6.addr[10],
++	server_ip.v6.addr[11],
++	server_ip.v6.addr[12],
++	server_ip.v6.addr[13],
++	server_ip.v6.addr[14],
++	server_ip.v6.addr[15]);
++#endif
++    }
++  else
++    {
++      for (i = 0, p = file->device->net->server; i < 4; ++i, ++p)
++	server_ip.v4.addr[i] = grub_strtoul (p, &p, 10);
++    }
++
++  status = efi_call_10 (pxe->mtftp,
++	    pxe,
++	    GRUB_EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
++	    NULL,
++	    0,
++	    &file_size,
++	    NULL,
++	    &server_ip,
++	    (grub_efi_char8_t *)filename,
++	    NULL,
++	    0);
++
++  if (status != GRUB_EFI_SUCCESS)
++    return grub_error (GRUB_ERR_IO, "Couldn't get file size");
++
++  file->size = (grub_off_t)file_size;
++  file->not_easily_seekable = 0;
++  file->data = 0;
++  file->device->net->offset = 0;
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++pxe_close (struct grub_efi_net_device *dev __attribute__((unused)),
++	  int prefer_ip6 __attribute__((unused)),
++	  grub_file_t file __attribute__((unused)))
++{
++  file->offset = 0;
++  file->size = 0;
++  file->device->net->offset = 0;
++
++  if (file->data)
++    {
++      grub_free (file->data);
++      file->data = NULL;
++    }
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_ssize_t
++pxe_read (struct grub_efi_net_device *dev,
++	  int prefer_ip6,
++	  grub_file_t file,
++	  char *buf,
++	  grub_size_t len)
++{
++  int i;
++  const char *p;
++  grub_efi_status_t status;
++  grub_efi_pxe_t *pxe = (prefer_ip6) ? dev->ip6_pxe : dev->ip4_pxe;
++  grub_efi_uint64_t bufsz = len;
++  grub_efi_pxe_ip_address_t server_ip;
++  char *buf2 = NULL;
++
++  if (file->data)
++    {
++      /* TODO: RANGE Check for offset and file size */
++      grub_memcpy (buf, (char*)file->data + file->device->net->offset, len);
++      file->device->net->offset += len;
++      return len;
++    }
++
++  if (file->device->net->offset)
++    {
++      grub_error (GRUB_ERR_BUG, "No Offet Read Possible");
++      grub_print_error ();
++      return 0;
++    }
++
++  if (pxe->mode->using_ipv6)
++    {
++      const char *rest;
++      grub_uint64_t ip6[2];
++      if (parse_ip6 (file->device->net->server, ip6, &rest) && *rest == 0)
++	grub_memcpy (server_ip.v6.addr, ip6, sizeof (server_ip.v6.addr));
++      /* TODO: ERROR Handling Here */
++    }
++  else
++    {
++      for (i = 0, p = file->device->net->server; i < 4; ++i, ++p)
++	server_ip.v4.addr[i] = grub_strtoul (p, &p, 10);
++    }
++
++  status = efi_call_10 (pxe->mtftp,
++	    pxe,
++	    GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE,
++	    buf,
++	    0,
++	    &bufsz,
++	    NULL,
++	    &server_ip,
++	    (grub_efi_char8_t *)file->device->net->name,
++	    NULL,
++	    0);
++
++  if (bufsz != file->size)
++    {
++      grub_error (GRUB_ERR_BUG, "Short read should not happen here");
++      grub_print_error ();
++      return 0;
++    }
++
++  if (status == GRUB_EFI_BUFFER_TOO_SMALL)
++    {
++
++      buf2 = grub_malloc (bufsz);
++
++      if (!buf2)
++	{
++	  grub_error (GRUB_ERR_OUT_OF_MEMORY, "ERROR OUT OF MEMORY");
++	  grub_print_error ();
++	  return 0;
++	}
++
++      status = efi_call_10 (pxe->mtftp,
++		pxe,
++		GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE,
++		buf2,
++		0,
++		&bufsz,
++		NULL,
++		&server_ip,
++		(grub_efi_char8_t *)file->device->net->name,
++		NULL,
++		0);
++    }
++
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      if (buf2)
++	grub_free (buf2);
++
++      grub_error (GRUB_ERR_IO, "Failed to Read File");
++      grub_print_error ();
++      return 0;
++    }
++
++  if (buf2)
++    grub_memcpy (buf, buf2, len);
++
++  file->device->net->offset = len;
++
++  if (buf2)
++    file->data = buf2;
++
++  return len;
++}
++
++struct grub_efi_net_io io_pxe =
++  {
++    .configure = pxe_configure,
++    .open = pxe_open,
++    .read = pxe_read,
++    .close = pxe_close
++  };
++
+diff --git a/grub-core/net/net.c b/grub-core/net/net.c
+index 15a2f29..34bf04f 100644
+--- a/grub-core/net/net.c
++++ b/grub-core/net/net.c
+@@ -32,6 +32,9 @@
+ #include <grub/loader.h>
+ #include <grub/bufio.h>
+ #include <grub/kernel.h>
++#ifdef GRUB_MACHINE_EFI
++#include <grub/net/efi.h>
++#endif
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -1959,8 +1962,49 @@ static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute;
+ static grub_command_t cmd_lsroutes, cmd_lscards;
+ static grub_command_t cmd_lsaddr, cmd_slaac;
+ 
++#ifdef GRUB_MACHINE_EFI
++
++static enum {
++  INIT_MODE_NONE,
++  INIT_MODE_GRUB,
++  INIT_MODE_EFI
++} init_mode;
++
++static grub_command_t cmd_bootp, cmd_bootp6;
++
++#endif
++
+ GRUB_MOD_INIT(net)
+ {
++#ifdef GRUB_MACHINE_EFI
++  if (grub_net_open)
++    return;
++
++  if ((grub_efi_net_boot_from_https () || grub_efi_net_boot_from_opa ())
++      && grub_efi_net_fs_init ())
++    {
++      cmd_lsroutes = grub_register_command ("net_ls_routes", grub_efi_net_list_routes,
++					    "", N_("list network routes"));
++      cmd_lscards = grub_register_command ("net_ls_cards", grub_efi_net_list_cards,
++					   "", N_("list network cards"));
++      cmd_lsaddr = grub_register_command ("net_ls_addr", grub_efi_net_list_addrs,
++					  "", N_("list network addresses"));
++      cmd_addaddr = grub_register_command ("net_add_addr", grub_efi_net_add_addr,
++					    /* TRANSLATORS: HWADDRESS stands for
++					       "hardware address".  */
++					  N_("SHORTNAME CARD ADDRESS [HWADDRESS]"),
++					  N_("Add a network address."));
++      cmd_bootp = grub_register_command ("net_bootp", grub_efi_net_bootp,
++					 N_("[CARD]"),
++					 N_("perform a bootp autoconfiguration"));
++      cmd_bootp6 = grub_register_command ("net_bootp6", grub_efi_net_bootp6,
++					 N_("[CARD]"),
++					 N_("perform a bootp autoconfiguration"));
++      init_mode = INIT_MODE_EFI;
++      return;
++    }
++#endif
++
+   grub_register_variable_hook ("net_default_server", defserver_get_env,
+ 			       defserver_set_env);
+   grub_env_export ("net_default_server");
+@@ -2008,10 +2052,37 @@ GRUB_MOD_INIT(net)
+ 						grub_net_restore_hw,
+ 						GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
+   grub_net_poll_cards_idle = grub_net_poll_cards_idle_real;
++
++#ifdef GRUB_MACHINE_EFI
++  grub_env_set ("grub_netfs_type", "grub");
++  grub_register_variable_hook ("grub_netfs_type", 0, grub_env_write_readonly);
++  grub_env_export ("grub_netfs_type");
++  init_mode = INIT_MODE_GRUB;
++#endif
++
+ }
+ 
+ GRUB_MOD_FINI(net)
+ {
++
++#ifdef GRUB_MACHINE_EFI
++  if (init_mode == INIT_MODE_NONE)
++    return;
++
++  if (init_mode == INIT_MODE_EFI)
++    {
++      grub_unregister_command (cmd_lsroutes);
++      grub_unregister_command (cmd_lscards);
++      grub_unregister_command (cmd_lsaddr);
++      grub_unregister_command (cmd_addaddr);
++      grub_unregister_command (cmd_bootp);
++      grub_unregister_command (cmd_bootp6);
++      grub_efi_net_fs_fini ();
++      init_mode = INIT_MODE_NONE;
++      return;
++    }
++#endif
++
+   grub_register_variable_hook ("net_default_server", 0, 0);
+   grub_register_variable_hook ("pxe_default_server", 0, 0);
+ 
+@@ -2030,4 +2101,7 @@ GRUB_MOD_FINI(net)
+   grub_net_fini_hw (0);
+   grub_loader_unregister_preboot_hook (fini_hnd);
+   grub_net_poll_cards_idle = grub_net_poll_cards_idle_real;
++#ifdef GRUB_MACHINE_EFI
++  init_mode = INIT_MODE_NONE;
++#endif
+ }
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index 479c2a8..3211f04 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -613,6 +613,23 @@ typedef grub_uint16_t grub_efi_ipv6_address_t[8];
+ typedef grub_uint8_t grub_efi_ip_address_t[8] __attribute__ ((aligned(4)));
+ typedef grub_efi_uint64_t grub_efi_physical_address_t;
+ typedef grub_efi_uint64_t grub_efi_virtual_address_t;
++typedef struct {
++  grub_uint8_t addr[4];
++} grub_efi_pxe_ipv4_address_t;
++
++typedef struct {
++  grub_uint8_t addr[16];
++} grub_efi_pxe_ipv6_address_t;
++
++typedef struct {
++  grub_uint8_t addr[32];
++} grub_efi_pxe_mac_address_t;
++
++typedef union {
++    grub_uint32_t addr[4];
++    grub_efi_pxe_ipv4_address_t v4;
++    grub_efi_pxe_ipv6_address_t v6;
++} grub_efi_pxe_ip_address_t;
+ 
+ struct grub_efi_guid
+ {
+@@ -880,6 +897,8 @@ struct grub_efi_ipv6_device_path
+   grub_efi_uint16_t remote_port;
+   grub_efi_uint16_t protocol;
+   grub_efi_uint8_t static_ip_address;
++  grub_efi_uint8_t prefix_length;
++  grub_efi_ipv6_address_t gateway_ip_address;
+ } GRUB_PACKED;
+ typedef struct grub_efi_ipv6_device_path grub_efi_ipv6_device_path_t;
+ 
+@@ -929,6 +948,15 @@ struct grub_efi_uri_device_path
+ } GRUB_PACKED;
+ typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t;
+ 
++#define GRUB_EFI_DNS_DEVICE_PATH_SUBTYPE                31
++struct grub_efi_dns_device_path
++{
++  grub_efi_device_path_t header;
++  grub_efi_uint8_t is_ipv6;
++  grub_efi_pxe_ip_address_t dns_server_ip[0];
++} GRUB_PACKED;
++typedef struct grub_efi_dns_device_path grub_efi_dns_device_path_t;
++
+ #define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE	10
+ 
+ /* Media Device Path.  */
+@@ -1011,6 +1039,23 @@ struct grub_efi_bios_device_path
+ } GRUB_PACKED;
+ typedef struct grub_efi_bios_device_path grub_efi_bios_device_path_t;
+ 
++/* Service Binding definitions */
++struct grub_efi_service_binding;
++
++typedef grub_efi_status_t
++(*grub_efi_service_binding_create_child) (struct grub_efi_service_binding *this,
++                                          grub_efi_handle_t *child_handle);
++
++typedef grub_efi_status_t
++(*grub_efi_service_binding_destroy_child) (struct grub_efi_service_binding *this,
++                                           grub_efi_handle_t *child_handle);
++
++typedef struct grub_efi_service_binding
++{
++  grub_efi_service_binding_create_child create_child;
++  grub_efi_service_binding_destroy_child destroy_child;
++} grub_efi_service_binding_t;
++
+ struct grub_efi_open_protocol_information_entry
+ {
+   grub_efi_handle_t agent_handle;
+@@ -1502,23 +1547,28 @@ typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output
+ 
+ typedef grub_uint8_t grub_efi_pxe_packet_t[1472];
+ 
+-typedef struct {
+-  grub_uint8_t addr[4];
+-} grub_efi_pxe_ipv4_address_t;
++typedef grub_efi_uint16_t grub_efi_pxe_base_code_udp_port_t;
+ 
+-typedef struct {
+-  grub_uint8_t addr[16];
+-} grub_efi_pxe_ipv6_address_t;
++typedef enum {
++  GRUB_EFI_PXE_BASE_CODE_TFTP_FIRST,
++  GRUB_EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
++  GRUB_EFI_PXE_BASE_CODE_TFTP_READ_FILE,
++  GRUB_EFI_PXE_BASE_CODE_TFTP_WRITE_FILE,
++  GRUB_EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY,
++  GRUB_EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE,
++  GRUB_EFI_PXE_BASE_CODE_MTFTP_READ_FILE,
++  GRUB_EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY,
++  GRUB_EFI_PXE_BASE_CODE_MTFTP_LAST
++} grub_efi_pxe_base_code_tftp_opcode_t;
+ 
+-typedef struct {
+-  grub_uint8_t addr[32];
+-} grub_efi_pxe_mac_address_t;
+ 
+-typedef union {
+-    grub_uint32_t addr[4];
+-    grub_efi_pxe_ipv4_address_t v4;
+-    grub_efi_pxe_ipv6_address_t v6;
+-} grub_efi_pxe_ip_address_t;
++typedef struct {
++  grub_efi_ip_address_t mcast_ip;
++  grub_efi_pxe_base_code_udp_port_t c_port;
++  grub_efi_pxe_base_code_udp_port_t s_port;
++  grub_efi_uint16_t listen_timeout;
++  grub_efi_uint16_t transmit_timeout;
++} grub_efi_pxe_base_code_mtftp_info_t;
+ 
+ #define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8
+ typedef struct {
+@@ -1568,17 +1618,31 @@ typedef struct grub_efi_pxe_mode
+ typedef struct grub_efi_pxe
+ {
+   grub_uint64_t rev;
+-  void (*start) (void);
++  grub_efi_status_t (*start) (struct grub_efi_pxe *this, grub_efi_boolean_t use_ipv6);
+   void (*stop) (void);
+-  void (*dhcp) (void);
++  grub_efi_status_t (*dhcp) (struct grub_efi_pxe *this,
++			    grub_efi_boolean_t sort_offers);
+   void (*discover) (void);
+-  void (*mftp) (void);
++  grub_efi_status_t (*mtftp) (struct grub_efi_pxe *this,
++			    grub_efi_pxe_base_code_tftp_opcode_t operation,
++			    void *buffer_ptr,
++			    grub_efi_boolean_t overwrite,
++			    grub_efi_uint64_t *buffer_size,
++			    grub_efi_uintn_t *block_size,
++			    grub_efi_pxe_ip_address_t *server_ip,
++			    //grub_efi_ip_address_t *server_ip,
++			    grub_efi_char8_t *filename,
++			    grub_efi_pxe_base_code_mtftp_info_t *info,
++			    grub_efi_boolean_t dont_use_buffer);
+   void (*udpwrite) (void);
+   void (*udpread) (void);
+   void (*setipfilter) (void);
+   void (*arp) (void);
+   void (*setparams) (void);
+-  void (*setstationip) (void);
++  grub_efi_status_t (*set_station_ip) (struct grub_efi_pxe *this,
++			    grub_efi_pxe_ip_address_t *new_station_ip,
++			    grub_efi_pxe_ip_address_t *new_subnet_mask);
++  //void (*setstationip) (void);
+   void (*setpackets) (void);
+   struct grub_efi_pxe_mode *mode;
+ } grub_efi_pxe_t;
+@@ -1850,6 +1914,44 @@ struct grub_efi_ip4_config2_protocol
+ };
+ typedef struct grub_efi_ip4_config2_protocol grub_efi_ip4_config2_protocol_t;
+ 
++struct grub_efi_ip4_route_table {
++  grub_efi_ipv4_address_t subnet_address;
++  grub_efi_ipv4_address_t subnet_mask;
++  grub_efi_ipv4_address_t gateway_address;
++};
++
++typedef struct grub_efi_ip4_route_table grub_efi_ip4_route_table_t;
++
++#define GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE 32
++
++struct grub_efi_ip4_config2_interface_info {
++  grub_efi_char16_t name[GRUB_EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE];
++  grub_efi_uint8_t if_type;
++  grub_efi_uint32_t hw_address_size;
++  grub_efi_mac_address_t hw_address;
++  grub_efi_ipv4_address_t station_address;
++  grub_efi_ipv4_address_t subnet_mask;
++  grub_efi_uint32_t route_table_size;
++  grub_efi_ip4_route_table_t *route_table;
++};
++
++typedef struct grub_efi_ip4_config2_interface_info grub_efi_ip4_config2_interface_info_t;
++
++enum grub_efi_ip4_config2_policy {
++  GRUB_EFI_IP4_CONFIG2_POLICY_STATIC,
++  GRUB_EFI_IP4_CONFIG2_POLICY_DHCP,
++  GRUB_EFI_IP4_CONFIG2_POLICY_MAX
++};
++
++typedef enum grub_efi_ip4_config2_policy grub_efi_ip4_config2_policy_t;
++
++struct grub_efi_ip4_config2_manual_address {
++  grub_efi_ipv4_address_t address;
++  grub_efi_ipv4_address_t subnet_mask;
++};
++
++typedef struct grub_efi_ip4_config2_manual_address grub_efi_ip4_config2_manual_address_t;
++
+ enum grub_efi_ip6_config_data_type {
+   GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO,
+   GRUB_EFI_IP6_CONFIG_DATA_TYPE_ALT_INTERFACEID,
+@@ -1884,6 +1986,49 @@ struct grub_efi_ip6_config_protocol
+ };
+ typedef struct grub_efi_ip6_config_protocol grub_efi_ip6_config_protocol_t;
+ 
++enum grub_efi_ip6_config_policy {
++  GRUB_EFI_IP6_CONFIG_POLICY_MANUAL,
++  GRUB_EFI_IP6_CONFIG_POLICY_AUTOMATIC
++};
++typedef enum grub_efi_ip6_config_policy grub_efi_ip6_config_policy_t;
++
++struct grub_efi_ip6_address_info {
++  grub_efi_ipv6_address_t address;
++  grub_efi_uint8_t prefix_length;
++};
++typedef struct grub_efi_ip6_address_info grub_efi_ip6_address_info_t;
++
++struct grub_efi_ip6_route_table {
++  grub_efi_pxe_ipv6_address_t gateway;
++  grub_efi_pxe_ipv6_address_t destination;
++  grub_efi_uint8_t prefix_length;
++};
++typedef struct grub_efi_ip6_route_table grub_efi_ip6_route_table_t;
++
++struct grub_efi_ip6_config_interface_info {
++  grub_efi_char16_t name[32];
++  grub_efi_uint8_t if_type;
++  grub_efi_uint32_t hw_address_size;
++  grub_efi_mac_address_t hw_address;
++  grub_efi_uint32_t address_info_count;
++  grub_efi_ip6_address_info_t *address_info;
++  grub_efi_uint32_t route_count;
++  grub_efi_ip6_route_table_t *route_table;
++};
++typedef struct grub_efi_ip6_config_interface_info grub_efi_ip6_config_interface_info_t;
++
++struct grub_efi_ip6_config_dup_addr_detect_transmits {
++  grub_efi_uint32_t dup_addr_detect_transmits;
++};
++typedef struct grub_efi_ip6_config_dup_addr_detect_transmits grub_efi_ip6_config_dup_addr_detect_transmits_t;
++
++struct grub_efi_ip6_config_manual_address {
++  grub_efi_ipv6_address_t address;
++  grub_efi_boolean_t is_anycast;
++  grub_efi_uint8_t prefix_length;
++};
++typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_address_t;
++
+ #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
+   || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \
+   || defined(__riscv)
+diff --git a/include/grub/efi/dhcp.h b/include/grub/efi/dhcp.h
+new file mode 100644
+index 0000000..fdb88eb
+--- /dev/null
++++ b/include/grub/efi/dhcp.h
+@@ -0,0 +1,343 @@
++#ifndef GRUB_EFI_DHCP_HEADER
++#define GRUB_EFI_DHCP_HEADER	1
++
++#define GRUB_EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID \
++  { 0x9d9a39d8, 0xbd42, 0x4a73, \
++    { 0xa4, 0xd5, 0x8e, 0xe9, 0x4b, 0xe1, 0x13, 0x80 } \
++  }
++
++#define GRUB_EFI_DHCP4_PROTOCOL_GUID \
++  { 0x8a219718, 0x4ef5, 0x4761, \
++    { 0x91, 0xc8, 0xc0, 0xf0, 0x4b, 0xda, 0x9e, 0x56 } \
++  }
++
++#define GRUB_EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID \
++  { 0x9fb9a8a1, 0x2f4a, 0x43a6, \
++    { 0x88, 0x9c, 0xd0, 0xf7, 0xb6, 0xc4 ,0x7a, 0xd5 } \
++  }
++
++#define GRUB_EFI_DHCP6_PROTOCOL_GUID \
++  { 0x87c8bad7, 0x595, 0x4053, \
++    { 0x82, 0x97, 0xde, 0xde, 0x39, 0x5f, 0x5d, 0x5b } \
++  }
++
++typedef struct grub_efi_dhcp4_protocol grub_efi_dhcp4_protocol_t;
++
++enum grub_efi_dhcp4_state {
++  GRUB_EFI_DHCP4_STOPPED,
++  GRUB_EFI_DHCP4_INIT,
++  GRUB_EFI_DHCP4_SELECTING,
++  GRUB_EFI_DHCP4_REQUESTING,
++  GRUB_EFI_DHCP4_BOUND,
++  GRUB_EFI_DHCP4_RENEWING,
++  GRUB_EFI_DHCP4_REBINDING,
++  GRUB_EFI_DHCP4_INIT_REBOOT,
++  GRUB_EFI_DHCP4_REBOOTING
++};
++
++typedef enum grub_efi_dhcp4_state grub_efi_dhcp4_state_t;
++
++struct grub_efi_dhcp4_header {
++  grub_efi_uint8_t op_code;
++  grub_efi_uint8_t hw_type;
++  grub_efi_uint8_t hw_addr_len;
++  grub_efi_uint8_t hops;
++  grub_efi_uint32_t xid;
++  grub_efi_uint16_t seconds;
++  grub_efi_uint16_t reserved;
++  grub_efi_ipv4_address_t client_addr;
++  grub_efi_ipv4_address_t your_addr;
++  grub_efi_ipv4_address_t server_addr;
++  grub_efi_ipv4_address_t gateway_addr;
++  grub_efi_uint8_t client_hw_addr[16];
++  grub_efi_char8_t server_name[64];
++  grub_efi_char8_t boot_file_name[128];
++} GRUB_PACKED;
++
++typedef struct grub_efi_dhcp4_header grub_efi_dhcp4_header_t;
++
++struct grub_efi_dhcp4_packet {
++  grub_efi_uint32_t size;
++  grub_efi_uint32_t length;
++  struct {
++    grub_efi_dhcp4_header_t header;
++    grub_efi_uint32_t magik;
++    grub_efi_uint8_t option[1];
++  } dhcp4;
++} GRUB_PACKED;
++
++typedef struct grub_efi_dhcp4_packet grub_efi_dhcp4_packet_t;
++
++struct grub_efi_dhcp4_listen_point {
++  grub_efi_ipv4_address_t listen_address;
++  grub_efi_ipv4_address_t subnet_mask;
++  grub_efi_uint16_t listen_port;
++};
++
++typedef struct grub_efi_dhcp4_listen_point grub_efi_dhcp4_listen_point_t;
++
++struct grub_efi_dhcp4_transmit_receive_token {
++  grub_efi_status_t status;
++  grub_efi_event_t completion_event;
++  grub_efi_ipv4_address_t remote_address;
++  grub_efi_uint16_t remote_port;
++  grub_efi_ipv4_address_t gateway_address;
++  grub_efi_uint32_t listen_point_count;
++  grub_efi_dhcp4_listen_point_t *listen_points;
++  grub_efi_uint32_t timeout_value;
++  grub_efi_dhcp4_packet_t *packet;
++  grub_efi_uint32_t response_count;
++  grub_efi_dhcp4_packet_t *response_list;
++};
++
++typedef struct grub_efi_dhcp4_transmit_receive_token grub_efi_dhcp4_transmit_receive_token_t;
++
++enum grub_efi_dhcp4_event {
++  GRUB_EFI_DHCP4_SEND_DISCOVER = 0X01,
++  GRUB_EFI_DHCP4_RCVD_OFFER,
++  GRUB_EFI_DHCP4_SELECT_OFFER,
++  GRUB_EFI_DHCP4_SEND_REQUEST,
++  GRUB_EFI_DHCP4_RCVD_ACK,
++  GRUB_EFI_DHCP4_RCVD_NAK,
++  GRUB_EFI_DHCP4_SEND_DECLINE,
++  GRUB_EFI_DHCP4_BOUND_COMPLETED,
++  GRUB_EFI_DHCP4_ENTER_RENEWING,
++  GRUB_EFI_DHCP4_ENTER_REBINDING,
++  GRUB_EFI_DHCP4_ADDRESS_LOST,
++  GRUB_EFI_DHCP4_FAIL
++};
++
++typedef enum grub_efi_dhcp4_event grub_efi_dhcp4_event_t;
++
++struct grub_efi_dhcp4_packet_option {
++  grub_efi_uint8_t op_code;
++  grub_efi_uint8_t length;
++  grub_efi_uint8_t data[1];
++} GRUB_PACKED;
++
++typedef struct grub_efi_dhcp4_packet_option grub_efi_dhcp4_packet_option_t;
++
++struct grub_efi_dhcp4_config_data {
++  grub_efi_uint32_t discover_try_count;
++  grub_efi_uint32_t *discover_timeout;
++  grub_efi_uint32_t request_try_count;
++  grub_efi_uint32_t *request_timeout;
++  grub_efi_ipv4_address_t client_address;
++  grub_efi_status_t (*dhcp4_callback) (
++    grub_efi_dhcp4_protocol_t *this,
++    void *context,
++    grub_efi_dhcp4_state_t current_state,
++    grub_efi_dhcp4_event_t dhcp4_event,
++    grub_efi_dhcp4_packet_t *packet,
++    grub_efi_dhcp4_packet_t **new_packet
++  );
++  void *callback_context;
++  grub_efi_uint32_t option_count;
++  grub_efi_dhcp4_packet_option_t **option_list;
++};
++
++typedef struct grub_efi_dhcp4_config_data grub_efi_dhcp4_config_data_t;
++
++struct grub_efi_dhcp4_mode_data {
++  grub_efi_dhcp4_state_t state;
++  grub_efi_dhcp4_config_data_t config_data;
++  grub_efi_ipv4_address_t client_address;
++  grub_efi_mac_address_t client_mac_address;
++  grub_efi_ipv4_address_t server_address;
++  grub_efi_ipv4_address_t router_address;
++  grub_efi_ipv4_address_t subnet_mask;
++  grub_efi_uint32_t lease_time;
++  grub_efi_dhcp4_packet_t *reply_packet;
++};
++
++typedef struct grub_efi_dhcp4_mode_data grub_efi_dhcp4_mode_data_t;
++
++struct grub_efi_dhcp4_protocol {
++  grub_efi_status_t (*get_mode_data) (grub_efi_dhcp4_protocol_t *this,
++	      grub_efi_dhcp4_mode_data_t *dhcp4_mode_data);
++  grub_efi_status_t (*configure) (grub_efi_dhcp4_protocol_t *this,
++	      grub_efi_dhcp4_config_data_t *dhcp4_cfg_data);
++  grub_efi_status_t (*start) (grub_efi_dhcp4_protocol_t *this,
++	      grub_efi_event_t completion_event);
++  grub_efi_status_t (*renew_rebind) (grub_efi_dhcp4_protocol_t *this,
++	      grub_efi_boolean_t rebind_request,
++	      grub_efi_event_t completion_event);
++  grub_efi_status_t (*release) (grub_efi_dhcp4_protocol_t *this);
++  grub_efi_status_t (*stop) (grub_efi_dhcp4_protocol_t *this);
++  grub_efi_status_t (*build) (grub_efi_dhcp4_protocol_t *this,
++	      grub_efi_dhcp4_packet_t *seed_packet,
++	      grub_efi_uint32_t delete_count,
++	      grub_efi_uint8_t *delete_list,
++	      grub_efi_uint32_t append_count,
++	      grub_efi_dhcp4_packet_option_t *append_list[],
++	      grub_efi_dhcp4_packet_t **new_packet);
++  grub_efi_status_t (*transmit_receive) (grub_efi_dhcp4_protocol_t *this,
++	      grub_efi_dhcp4_transmit_receive_token_t *token);
++  grub_efi_status_t (*parse) (grub_efi_dhcp4_protocol_t *this,
++	      grub_efi_dhcp4_packet_t *packet,
++	      grub_efi_uint32_t *option_count,
++	      grub_efi_dhcp4_packet_option_t *packet_option_list[]);
++};
++
++typedef struct grub_efi_dhcp6_protocol grub_efi_dhcp6_protocol_t;
++
++struct grub_efi_dhcp6_retransmission {
++  grub_efi_uint32_t irt;
++  grub_efi_uint32_t mrc;
++  grub_efi_uint32_t mrt;
++  grub_efi_uint32_t mrd;
++};
++
++typedef struct grub_efi_dhcp6_retransmission grub_efi_dhcp6_retransmission_t;
++
++enum grub_efi_dhcp6_event {
++  GRUB_EFI_DHCP6_SEND_SOLICIT,
++  GRUB_EFI_DHCP6_RCVD_ADVERTISE,
++  GRUB_EFI_DHCP6_SELECT_ADVERTISE,
++  GRUB_EFI_DHCP6_SEND_REQUEST,
++  GRUB_EFI_DHCP6_RCVD_REPLY,
++  GRUB_EFI_DHCP6_RCVD_RECONFIGURE,
++  GRUB_EFI_DHCP6_SEND_DECLINE,
++  GRUB_EFI_DHCP6_SEND_CONFIRM,
++  GRUB_EFI_DHCP6_SEND_RELEASE,
++  GRUB_EFI_DHCP6_SEND_RENEW,
++  GRUB_EFI_DHCP6_SEND_REBIND
++};
++
++typedef enum grub_efi_dhcp6_event grub_efi_dhcp6_event_t;
++
++struct grub_efi_dhcp6_packet_option {
++  grub_efi_uint16_t op_code;
++  grub_efi_uint16_t op_len;
++  grub_efi_uint8_t data[1];
++} GRUB_PACKED;
++
++typedef struct grub_efi_dhcp6_packet_option grub_efi_dhcp6_packet_option_t;
++
++struct grub_efi_dhcp6_header {
++  grub_efi_uint32_t transaction_id:24;
++  grub_efi_uint32_t message_type:8;
++} GRUB_PACKED;
++
++typedef struct grub_efi_dhcp6_header grub_efi_dhcp6_header_t;
++
++struct grub_efi_dhcp6_packet {
++  grub_efi_uint32_t size;
++  grub_efi_uint32_t length;
++  struct {
++    grub_efi_dhcp6_header_t header;
++    grub_efi_uint8_t option[1];
++  } dhcp6;
++} GRUB_PACKED;
++
++typedef struct grub_efi_dhcp6_packet grub_efi_dhcp6_packet_t;
++
++struct grub_efi_dhcp6_ia_address {
++  grub_efi_ipv6_address_t ip_address;
++  grub_efi_uint32_t preferred_lifetime;
++  grub_efi_uint32_t valid_lifetime;
++};
++
++typedef struct grub_efi_dhcp6_ia_address grub_efi_dhcp6_ia_address_t;
++
++enum grub_efi_dhcp6_state {
++  GRUB_EFI_DHCP6_INIT,
++  GRUB_EFI_DHCP6_SELECTING,
++  GRUB_EFI_DHCP6_REQUESTING,
++  GRUB_EFI_DHCP6_DECLINING,
++  GRUB_EFI_DHCP6_CONFIRMING,
++  GRUB_EFI_DHCP6_RELEASING,
++  GRUB_EFI_DHCP6_BOUND,
++  GRUB_EFI_DHCP6_RENEWING,
++  GRUB_EFI_DHCP6_REBINDING
++};
++
++typedef enum grub_efi_dhcp6_state grub_efi_dhcp6_state_t;
++
++#define GRUB_EFI_DHCP6_IA_TYPE_NA 3
++#define GRUB_EFI_DHCP6_IA_TYPE_TA 4
++
++struct grub_efi_dhcp6_ia_descriptor {
++  grub_efi_uint16_t type;
++  grub_efi_uint32_t ia_id;
++};
++
++typedef struct grub_efi_dhcp6_ia_descriptor grub_efi_dhcp6_ia_descriptor_t;
++
++struct grub_efi_dhcp6_ia {
++  grub_efi_dhcp6_ia_descriptor_t descriptor;
++  grub_efi_dhcp6_state_t state;
++  grub_efi_dhcp6_packet_t *reply_packet;
++  grub_efi_uint32_t ia_address_count;
++  grub_efi_dhcp6_ia_address_t ia_address[1];
++};
++
++typedef struct grub_efi_dhcp6_ia grub_efi_dhcp6_ia_t;
++
++struct grub_efi_dhcp6_duid {
++  grub_efi_uint16_t length;
++  grub_efi_uint8_t duid[1];
++};
++
++typedef struct grub_efi_dhcp6_duid grub_efi_dhcp6_duid_t;
++
++struct grub_efi_dhcp6_mode_data {
++  grub_efi_dhcp6_duid_t *client_id;
++  grub_efi_dhcp6_ia_t *ia;
++};
++
++typedef struct grub_efi_dhcp6_mode_data grub_efi_dhcp6_mode_data_t;
++
++struct grub_efi_dhcp6_config_data {
++  grub_efi_status_t (*dhcp6_callback) (grub_efi_dhcp6_protocol_t this,
++		void *context,
++		grub_efi_dhcp6_state_t current_state,
++		grub_efi_dhcp6_event_t dhcp6_event,
++		grub_efi_dhcp6_packet_t *packet,
++		grub_efi_dhcp6_packet_t **new_packet);
++  void *callback_context;
++  grub_efi_uint32_t option_count;
++  grub_efi_dhcp6_packet_option_t **option_list;
++  grub_efi_dhcp6_ia_descriptor_t ia_descriptor;
++  grub_efi_event_t ia_info_event;
++  grub_efi_boolean_t reconfigure_accept;
++  grub_efi_boolean_t rapid_commit;
++  grub_efi_dhcp6_retransmission_t *solicit_retransmission;
++};
++
++typedef struct grub_efi_dhcp6_config_data grub_efi_dhcp6_config_data_t;
++
++struct grub_efi_dhcp6_protocol {
++  grub_efi_status_t (*get_mode_data) (grub_efi_dhcp6_protocol_t *this,
++	    grub_efi_dhcp6_mode_data_t *dhcp6_mode_data,
++	    grub_efi_dhcp6_config_data_t *dhcp6_config_data);
++  grub_efi_status_t (*configure) (grub_efi_dhcp6_protocol_t *this,
++	    grub_efi_dhcp6_config_data_t *dhcp6_cfg_data);
++  grub_efi_status_t (*start) (grub_efi_dhcp6_protocol_t *this);
++  grub_efi_status_t (*info_request) (grub_efi_dhcp6_protocol_t *this,
++	    grub_efi_boolean_t send_client_id,
++	    grub_efi_dhcp6_packet_option_t *option_request,
++	    grub_efi_uint32_t option_count,
++	    grub_efi_dhcp6_packet_option_t *option_list[],
++	    grub_efi_dhcp6_retransmission_t *retransmission,
++	    grub_efi_event_t timeout_event,
++	    grub_efi_status_t (*reply_callback) (grub_efi_dhcp6_protocol_t *this,
++		    void *context,
++		    grub_efi_dhcp6_packet_t *packet),
++	    void *callback_context);
++  grub_efi_status_t (*renew_rebind) (grub_efi_dhcp6_protocol_t *this,
++	    grub_efi_boolean_t rebind_request);
++  grub_efi_status_t (*decline) (grub_efi_dhcp6_protocol_t *this,
++	    grub_efi_uint32_t address_count,
++	    grub_efi_ipv6_address_t *addresses);
++  grub_efi_status_t (*release) (grub_efi_dhcp6_protocol_t *this,
++	    grub_efi_uint32_t address_count,
++	    grub_efi_ipv6_address_t *addresses);
++  grub_efi_status_t (*stop) (grub_efi_dhcp6_protocol_t *this);
++  grub_efi_status_t (*parse) (grub_efi_dhcp6_protocol_t *this,
++	    grub_efi_dhcp6_packet_t *packet,
++	    grub_efi_uint32_t *option_count,
++	    grub_efi_dhcp6_packet_option_t *packet_option_list[]);
++};
++
++#endif /* ! GRUB_EFI_DHCP_HEADER */
+diff --git a/include/grub/efi/http.h b/include/grub/efi/http.h
+new file mode 100644
+index 0000000..c5e9a89
+--- /dev/null
++++ b/include/grub/efi/http.h
+@@ -0,0 +1,215 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2006,2007,2008  Free Software Foundation, Inc.
++ *
++ *  GRUB is free software: you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation, either version 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef GRUB_EFI_HTTP_HEADER
++#define GRUB_EFI_HTTP_HEADER	1
++
++#include <grub/symbol.h>
++#include <grub/net.h>
++#include <grub/efi/api.h>
++
++#define GRUB_EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID \
++  { 0xbdc8e6af, 0xd9bc, 0x4379, \
++      { 0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } \
++  }
++
++#define GRUB_EFI_HTTP_PROTOCOL_GUID \
++  { 0x7A59B29B, 0x910B, 0x4171, \
++      { 0x82, 0x42, 0xA8, 0x5A, 0x0D, 0xF2, 0x5B, 0x5B } \
++  }
++
++#define EFIHTTP_WAIT_TIME 10000 // 10000ms = 10s
++#define EFIHTTP_RX_BUF_LEN 10240
++
++//******************************************
++// Protocol Interface Structure
++//******************************************
++struct grub_efi_http;
++
++//******************************************
++// EFI_HTTP_VERSION
++//******************************************
++typedef enum {
++  GRUB_EFI_HTTPVERSION10,
++  GRUB_EFI_HTTPVERSION11,
++  GRUB_EFI_HTTPVERSIONUNSUPPORTED
++} grub_efi_http_version_t;
++
++//******************************************
++// EFI_HTTPv4_ACCESS_POINT
++//******************************************
++typedef struct {
++  grub_efi_boolean_t use_default_address;
++  grub_efi_ipv4_address_t local_address;
++  grub_efi_ipv4_address_t local_subnet;
++  grub_efi_uint16_t local_port;
++} grub_efi_httpv4_access_point_t;
++
++//******************************************
++// EFI_HTTPv6_ACCESS_POINT
++//******************************************
++typedef struct {
++  grub_efi_ipv6_address_t local_address;
++  grub_efi_uint16_t local_port;
++} grub_efi_httpv6_access_point_t;
++
++//******************************************
++// EFI_HTTP_CONFIG_DATA
++//******************************************
++typedef struct {
++  grub_efi_http_version_t http_version;
++  grub_efi_uint32_t timeout_millisec;
++  grub_efi_boolean_t local_address_is_ipv6;
++  union {
++    grub_efi_httpv4_access_point_t *ipv4_node;
++    grub_efi_httpv6_access_point_t *ipv6_node;
++  } access_point;
++} grub_efi_http_config_data_t;
++
++//******************************************
++// EFI_HTTP_METHOD
++//******************************************
++typedef enum {
++  GRUB_EFI_HTTPMETHODGET,
++  GRUB_EFI_HTTPMETHODPOST,
++  GRUB_EFI_HTTPMETHODPATCH,
++  GRUB_EFI_HTTPMETHODOPTIONS,
++  GRUB_EFI_HTTPMETHODCONNECT,
++  GRUB_EFI_HTTPMETHODHEAD,
++  GRUB_EFI_HTTPMETHODPUT,
++  GRUB_EFI_HTTPMETHODDELETE,
++  GRUB_EFI_HTTPMETHODTRACE,
++} grub_efi_http_method_t;
++
++//******************************************
++// EFI_HTTP_REQUEST_DATA
++//******************************************
++typedef struct {
++  grub_efi_http_method_t method;
++  grub_efi_char16_t *url;
++} grub_efi_http_request_data_t;
++
++typedef enum {
++  GRUB_EFI_HTTP_STATUS_UNSUPPORTED_STATUS = 0,
++  GRUB_EFI_HTTP_STATUS_100_CONTINUE,
++  GRUB_EFI_HTTP_STATUS_101_SWITCHING_PROTOCOLS,
++  GRUB_EFI_HTTP_STATUS_200_OK,
++  GRUB_EFI_HTTP_STATUS_201_CREATED,
++  GRUB_EFI_HTTP_STATUS_202_ACCEPTED,
++  GRUB_EFI_HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION,
++  GRUB_EFI_HTTP_STATUS_204_NO_CONTENT,
++  GRUB_EFI_HTTP_STATUS_205_RESET_CONTENT,
++  GRUB_EFI_HTTP_STATUS_206_PARTIAL_CONTENT,
++  GRUB_EFI_HTTP_STATUS_300_MULTIPLE_CHIOCES,
++  GRUB_EFI_HTTP_STATUS_301_MOVED_PERMANENTLY,
++  GRUB_EFI_HTTP_STATUS_302_FOUND,
++  GRUB_EFI_HTTP_STATUS_303_SEE_OTHER,
++  GRUB_EFI_HTTP_STATUS_304_NOT_MODIFIED,
++  GRUB_EFI_HTTP_STATUS_305_USE_PROXY,
++  GRUB_EFI_HTTP_STATUS_307_TEMPORARY_REDIRECT,
++  GRUB_EFI_HTTP_STATUS_400_BAD_REQUEST,
++  GRUB_EFI_HTTP_STATUS_401_UNAUTHORIZED,
++  GRUB_EFI_HTTP_STATUS_402_PAYMENT_REQUIRED,
++  GRUB_EFI_HTTP_STATUS_403_FORBIDDEN,
++  GRUB_EFI_HTTP_STATUS_404_NOT_FOUND,
++  GRUB_EFI_HTTP_STATUS_405_METHOD_NOT_ALLOWED,
++  GRUB_EFI_HTTP_STATUS_406_NOT_ACCEPTABLE,
++  GRUB_EFI_HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED,
++  GRUB_EFI_HTTP_STATUS_408_REQUEST_TIME_OUT,
++  GRUB_EFI_HTTP_STATUS_409_CONFLICT,
++  GRUB_EFI_HTTP_STATUS_410_GONE,
++  GRUB_EFI_HTTP_STATUS_411_LENGTH_REQUIRED,
++  GRUB_EFI_HTTP_STATUS_412_PRECONDITION_FAILED,
++  GRUB_EFI_HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE,
++  GRUB_EFI_HTTP_STATUS_414_REQUEST_URI_TOO_LARGE,
++  GRUB_EFI_HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE,
++  GRUB_EFI_HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED,
++  GRUB_EFI_HTTP_STATUS_417_EXPECTATION_FAILED,
++  GRUB_EFI_HTTP_STATUS_500_INTERNAL_SERVER_ERROR,
++  GRUB_EFI_HTTP_STATUS_501_NOT_IMPLEMENTED,
++  GRUB_EFI_HTTP_STATUS_502_BAD_GATEWAY,
++  GRUB_EFI_HTTP_STATUS_503_SERVICE_UNAVAILABLE,
++  GRUB_EFI_HTTP_STATUS_504_GATEWAY_TIME_OUT,
++  GRUB_EFI_HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED
++} grub_efi_http_status_code_t;
++
++//******************************************
++// EFI_HTTP_RESPONSE_DATA
++//******************************************
++typedef struct {
++  grub_efi_http_status_code_t status_code;
++} grub_efi_http_response_data_t;
++
++//******************************************
++// EFI_HTTP_HEADER
++//******************************************
++typedef struct {
++  grub_efi_char8_t *field_name;
++  grub_efi_char8_t *field_value;
++} grub_efi_http_header_t;
++
++//******************************************
++// EFI_HTTP_MESSAGE
++//******************************************
++typedef struct {
++  union {
++    grub_efi_http_request_data_t *request;
++    grub_efi_http_response_data_t *response;
++  } data;
++  grub_efi_uint32_t header_count;
++  grub_efi_http_header_t *headers;
++  grub_efi_uint32_t body_length;
++  void *body;
++} grub_efi_http_message_t;
++
++//******************************************
++// EFI_HTTP_TOKEN
++//******************************************
++typedef struct {
++  grub_efi_event_t event;
++  grub_efi_status_t status;
++  grub_efi_http_message_t *message;
++} grub_efi_http_token_t;
++
++struct grub_efi_http {
++  grub_efi_status_t
++  (*get_mode_data) (struct grub_efi_http *this,
++                    grub_efi_http_config_data_t *http_config_data);
++
++  grub_efi_status_t
++  (*configure) (struct grub_efi_http *this,
++                grub_efi_http_config_data_t *http_config_data);
++
++  grub_efi_status_t
++  (*request) (struct grub_efi_http *this,
++              grub_efi_http_token_t *token);
++
++  grub_efi_status_t
++  (*cancel) (struct grub_efi_http *this,
++             grub_efi_http_token_t *token);
++
++  grub_efi_status_t
++  (*response) (struct grub_efi_http *this,
++               grub_efi_http_token_t *token);
++
++  grub_efi_status_t
++  (*poll) (struct grub_efi_http *this);
++};
++typedef struct grub_efi_http grub_efi_http_t;
++
++#endif /* !GRUB_EFI_HTTP_HEADER */
+diff --git a/include/grub/net/efi.h b/include/grub/net/efi.h
+new file mode 100644
+index 0000000..de90d22
+--- /dev/null
++++ b/include/grub/net/efi.h
+@@ -0,0 +1,144 @@
++#ifndef GRUB_NET_EFI_HEADER
++#define GRUB_NET_EFI_HEADER	1
++
++#include <grub/efi/api.h>
++#include <grub/efi/http.h>
++#include <grub/efi/dhcp.h>
++#include <grub/command.h>
++
++typedef struct grub_efi_net_interface grub_efi_net_interface_t;
++typedef struct grub_efi_net_ip_config grub_efi_net_ip_config_t;
++typedef union grub_efi_net_ip_address grub_efi_net_ip_address_t;
++typedef struct grub_efi_net_ip_manual_address grub_efi_net_ip_manual_address_t;
++
++struct grub_efi_net_interface
++{
++  char *name;
++  int prefer_ip6;
++  struct grub_efi_net_device *dev;
++  struct grub_efi_net_io *io;
++  grub_efi_net_ip_config_t *ip_config;
++  int io_type;
++  struct grub_efi_net_interface *next;
++};
++
++#define efi_net_interface_get_hw_address(inf) inf->ip_config->get_hw_address (inf->dev)
++#define efi_net_interface_get_address(inf) inf->ip_config->get_address (inf->dev)
++#define efi_net_interface_get_route_table(inf) inf->ip_config->get_route_table (inf->dev)
++#define efi_net_interface_set_address(inf, addr, with_subnet) inf->ip_config->set_address (inf->dev, addr, with_subnet)
++#define efi_net_interface_set_gateway(inf, addr) inf->ip_config->set_gateway (inf->dev, addr)
++#define efi_net_interface_set_dns(inf, addr) inf->ip_config->set_dns (inf->dev, addr)
++
++struct grub_efi_net_ip_config
++{
++  char * (*get_hw_address) (struct grub_efi_net_device *dev);
++  char * (*get_address) (struct grub_efi_net_device *dev);
++  char ** (*get_route_table) (struct grub_efi_net_device *dev);
++  grub_efi_net_interface_t * (*best_interface) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *address);
++  int (*set_address) (struct grub_efi_net_device *dev, grub_efi_net_ip_manual_address_t *net_ip, int with_subnet);
++  int (*set_gateway) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *address);
++  int (*set_dns) (struct grub_efi_net_device *dev, grub_efi_net_ip_address_t *dns);
++};
++
++union grub_efi_net_ip_address
++{
++  grub_efi_ipv4_address_t ip4;
++  grub_efi_ipv6_address_t ip6;
++};
++
++struct grub_efi_net_ip_manual_address
++{
++  int is_ip6;
++  union
++  {
++    grub_efi_ip4_config2_manual_address_t ip4;
++    grub_efi_ip6_config_manual_address_t ip6;
++  };
++};
++
++struct grub_efi_net_device
++{
++  grub_efi_handle_t handle;
++  grub_efi_ip4_config2_protocol_t *ip4_config;
++  grub_efi_ip6_config_protocol_t *ip6_config;
++  grub_efi_handle_t http_handle;
++  grub_efi_http_t *http;
++  grub_efi_handle_t ip4_pxe_handle;
++  grub_efi_pxe_t *ip4_pxe;
++  grub_efi_handle_t ip6_pxe_handle;
++  grub_efi_pxe_t *ip6_pxe;
++  grub_efi_handle_t dhcp4_handle;
++  grub_efi_dhcp4_protocol_t *dhcp4;
++  grub_efi_handle_t dhcp6_handle;
++  grub_efi_dhcp6_protocol_t *dhcp6;
++  char *card_name;
++  grub_efi_net_interface_t *net_interfaces;
++  struct grub_efi_net_device *next;
++};
++
++struct grub_efi_net_io
++{
++  void (*configure) (struct grub_efi_net_device *dev, int prefer_ip6);
++  grub_err_t (*open) (struct grub_efi_net_device *dev,
++		    int prefer_ip6,
++		    grub_file_t file,
++		    const char *filename,
++		    int type);
++  grub_ssize_t (*read) (struct grub_efi_net_device *dev,
++			int prefer_ip6,
++			grub_file_t file,
++			char *buf,
++			grub_size_t len);
++  grub_err_t (*close) (struct grub_efi_net_device *dev,
++		      int prefer_ip6,
++		      grub_file_t file);
++};
++
++extern struct grub_efi_net_device *net_devices;
++
++extern struct grub_efi_net_io io_http;
++extern struct grub_efi_net_io io_pxe;
++
++extern grub_efi_net_ip_config_t *efi_net_ip4_config;
++extern grub_efi_net_ip_config_t *efi_net_ip6_config;
++
++char *
++grub_efi_ip4_address_to_string (grub_efi_ipv4_address_t *address);
++
++char *
++grub_efi_ip6_address_to_string (grub_efi_pxe_ipv6_address_t *address);
++
++char *
++grub_efi_hw_address_to_string (grub_efi_uint32_t hw_address_size, grub_efi_mac_address_t hw_address);
++
++int
++grub_efi_string_to_ip4_address (const char *val, grub_efi_ipv4_address_t *address, const char **rest);
++
++int
++grub_efi_string_to_ip6_address (const char *val, grub_efi_ipv6_address_t *address, const char **rest);
++
++char *
++grub_efi_ip6_interface_name (struct grub_efi_net_device *dev);
++
++char *
++grub_efi_ip4_interface_name (struct grub_efi_net_device *dev);
++
++grub_efi_net_interface_t *
++grub_efi_net_create_interface (struct grub_efi_net_device *dev,
++		const char *interface_name,
++		grub_efi_net_ip_manual_address_t *net_ip,
++		int has_subnet);
++
++int grub_efi_net_fs_init (void);
++void grub_efi_net_fs_fini (void);
++int grub_efi_net_boot_from_https (void);
++int grub_efi_net_boot_from_opa (void);
++
++extern grub_command_func_t grub_efi_net_list_routes;
++extern grub_command_func_t grub_efi_net_list_cards;
++extern grub_command_func_t grub_efi_net_list_addrs;
++extern grub_command_func_t grub_efi_net_add_addr;
++extern grub_command_func_t grub_efi_net_bootp;
++extern grub_command_func_t grub_efi_net_bootp6;
++
++#endif /* ! GRUB_NET_EFI_HEADER */
diff -pruN 2.06-2/debian/patches/suse-AUDIT-0-http-boot-tracker-bug.patch 2.06-2ubuntu16/debian/patches/suse-AUDIT-0-http-boot-tracker-bug.patch
--- 2.06-2/debian/patches/suse-AUDIT-0-http-boot-tracker-bug.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/suse-AUDIT-0-http-boot-tracker-bug.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,68 @@
+From: Sebastian Krahmer <krahmer@suse.com>
+Date: Tue, 28 Nov 2017 17:24:38 +0800
+Subject: AUDIT-0: http boot tracker bug
+
+Fixing a memory leak in case of error, and a integer overflow, leading to a
+heap overflow due to overly large chunk sizes.
+
+We need to check against some maximum value, otherwise values like 0xffffffff
+will eventually lead in the allocation functions to small sized buffers, since
+the len is rounded up to the next reasonable alignment. The following memcpy
+will then smash the heap, leading to RCE.
+
+This is no big issue for pure http boot, since its going to execute an
+untrusted kernel anyway, but it will break trusted boot scenarios, where only
+signed code is allowed to be executed.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+
+Origin: SUSE
+UEFI HTTP and related network protocol support (FATE#320130)
+Patch420:       0001-add-support-for-UEFI-network-protocols.patch
+Patch421:       0002-AUDIT-0-http-boot-tracker-bug.patch
+
+Patch-Name: suse-AUDIT-0-http-boot-tracker-bug.patch
+---
+ grub-core/net/efi/net.c | 4 +++-
+ grub-core/net/http.c    | 5 ++++-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c
+index 3154c55..9b7a218 100644
+--- a/grub-core/net/efi/net.c
++++ b/grub-core/net/efi/net.c
+@@ -654,8 +654,10 @@ grub_efihttp_chunk_read (grub_file_t file, char *buf,
+ 
+       rd = efi_net_interface (read, file, chunk, sz);
+ 
+-      if (rd <= 0)
++      if (rd <= 0) {
++	grub_free (chunk);
+ 	return rd;
++      }
+ 
+       if (buf)
+ 	{
+diff --git a/grub-core/net/http.c b/grub-core/net/http.c
+index 3fe155f..bf83866 100644
+--- a/grub-core/net/http.c
++++ b/grub-core/net/http.c
+@@ -31,7 +31,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+ enum
+   {
+-    HTTP_PORT = 80
++    HTTP_PORT = 80,
++    HTTP_MAX_CHUNK_SIZE = 0x80000000
+   };
+ 
+ 
+@@ -78,6 +79,8 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len)
+   if (data->in_chunk_len == 2)
+     {
+       data->chunk_rem = grub_strtoul (ptr, 0, 16);
++      if (data->chunk_rem > HTTP_MAX_CHUNK_SIZE)
++	  return GRUB_ERR_NET_PACKET_TOO_BIG;
+       grub_errno = GRUB_ERR_NONE;
+       if (data->chunk_rem == 0)
+ 	{
diff -pruN 2.06-2/debian/patches/suse-grub.texi-add-net_bootp6-document.patch 2.06-2ubuntu16/debian/patches/suse-grub.texi-add-net_bootp6-document.patch
--- 2.06-2/debian/patches/suse-grub.texi-add-net_bootp6-document.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/suse-grub.texi-add-net_bootp6-document.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,49 @@
+From: Michael Chang <mchang@suse.com>
+Date: Tue, 5 May 2015 14:19:24 +0800
+Subject: grub.texi: Add net_bootp6 document
+
+Update grub documentation for net_bootp6 command.
+
+Signed-off-by: Michael Chang <mchang@suse.com>
+Signed-off-by: Ken Lin <ken.lin@hpe.com>
+
+Patch-Name: suse-grub.texi-add-net_bootp6-document.patch
+---
+ docs/grub.texi | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/docs/grub.texi b/docs/grub.texi
+index 0cc2f24..33cde16 100644
+--- a/docs/grub.texi
++++ b/docs/grub.texi
+@@ -5514,6 +5514,7 @@ This command is only available on AArch64 systems.
+ * net_add_dns::                 Add a DNS server
+ * net_add_route::               Add routing entry
+ * net_bootp::                   Perform a bootp/DHCP autoconfiguration
++* net_bootp6::                  Perform a DHCPv6 autoconfiguration
+ * net_del_addr::                Remove IP address from interface
+ * net_del_dns::                 Remove a DNS server
+ * net_del_route::               Remove a route entry
+@@ -5638,6 +5639,22 @@ Sets environment variable @samp{net_}@var{<card>}@samp{_boot_file}
+ 
+ @end deffn
+ 
++@node net_bootp6
++@subsection net_bootp6
++
++@deffn Command net_bootp6 [@var{card}]
++Perform configuration of @var{card} using DHCPv6 protocol. If no card name is
++specified, try to configure all existing cards. If configuration was
++successful, interface with name @var{card}@samp{:dhcp6} and configured address
++is added to @var{card}.
++
++@table @samp
++@item 1 (Domain Name Server)
++Adds all servers from option value to the list of servers used during name
++resolution.
++@end table
++
++@end deffn
+ 
+ @node net_get_dhcp_option
+ @subsection net_get_dhcp_option
diff -pruN 2.06-2/debian/patches/tests-ahci-update-qemu-device-name.patch 2.06-2ubuntu16/debian/patches/tests-ahci-update-qemu-device-name.patch
--- 2.06-2/debian/patches/tests-ahci-update-qemu-device-name.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/tests-ahci-update-qemu-device-name.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,4 +1,3 @@
-From 1a1c93cd19a9ec67d6237d5a537976ff9297ab78 Mon Sep 17 00:00:00 2001
 From: Marius Bakke <marius@gnu.org>
 Date: Sun, 13 Jun 2021 15:11:51 +0200
 Subject: tests/ahci: Change "ide-drive" deprecated QEMU device name to
@@ -20,7 +19,7 @@ Patch-Name: tests-ahci-update-qemu-devic
  1 file changed, 1 insertion(+), 1 deletion(-)
 
 diff --git a/tests/ahci_test.in b/tests/ahci_test.in
-index 7df560462..d844fe680 100644
+index 7df5604..d844fe6 100644
 --- a/tests/ahci_test.in
 +++ b/tests/ahci_test.in
 @@ -41,7 +41,7 @@ echo "hello" > "$outfile"
diff -pruN 2.06-2/debian/patches/tests-Explicitly-unset-SOURCE_DATE_EPOCH-before-running-f.patch 2.06-2ubuntu16/debian/patches/tests-Explicitly-unset-SOURCE_DATE_EPOCH-before-running-f.patch
--- 2.06-2/debian/patches/tests-Explicitly-unset-SOURCE_DATE_EPOCH-before-running-f.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/tests-Explicitly-unset-SOURCE_DATE_EPOCH-before-running-f.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,30 @@
+From: Steve McIntyre <steve@einval.com>
+Date: Sun, 18 Sep 2022 23:12:02 +0100
+Subject: tests: Explicitly unset SOURCE_DATE_EPOCH before running fs tests
+
+In some filesystem utils like mksquashfs, they will silently change
+behaviour and cause timestamps to unexpectedly change. Build
+environments like Debian's set SOURCE_DATE_EPOCH in the environment,
+so remove it. Reproducible builds are good and useful for shipped
+artifacts, but this causes build-time tests to fail.
+
+Signed-off-by: Steve McIntyre <steve@einval.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ tests/util/grub-fs-tester.in | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/tests/util/grub-fs-tester.in b/tests/util/grub-fs-tester.in
+index bfc425e..f69d4e1 100644
+--- a/tests/util/grub-fs-tester.in
++++ b/tests/util/grub-fs-tester.in
+@@ -2,6 +2,9 @@
+ 
+ set -e
+ 
++# We can't have this set, or filesystem tests will fail.
++unset SOURCE_DATE_EPOCH
++
+ fs="$1"
+ 
+ GRUBFSTEST="@builddir@/grub-fstest"
diff -pruN 2.06-2/debian/patches/tpm-unknown-error-non-fatal.patch 2.06-2ubuntu16/debian/patches/tpm-unknown-error-non-fatal.patch
--- 2.06-2/debian/patches/tpm-unknown-error-non-fatal.patch	2021-11-29 00:10:09.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/tpm-unknown-error-non-fatal.patch	2022-12-09 16:11:44.000000000 +0000
@@ -1,8 +1,7 @@
-From ba3a0d4b6c0b56f6d7935911b53a02a7d0504da5 Mon Sep 17 00:00:00 2001
 From: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
 Date: Sat, 10 Jul 2021 22:32:00 +0100
-Subject: tpm: Pass unknown error as non-fatal, but debug print the error we
- got
+Subject: tpm: Pass unknown error as non-fatal,
+ but debug print the error we got
 
 Signed-off-by: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
 
@@ -16,7 +15,7 @@ Patch-Name: tpm-unknown-error-non-fatal.
  1 file changed, 2 insertions(+), 1 deletion(-)
 
 diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c
-index a97d85368..e73bd5561 100644
+index a97d853..e73bd55 100644
 --- a/grub-core/commands/efi/tpm.c
 +++ b/grub-core/commands/efi/tpm.c
 @@ -145,7 +145,8 @@ grub_efi_log_event_status (grub_efi_status_t status)
diff -pruN 2.06-2/debian/patches/ubuntu-add-devicetree-command-support.patch 2.06-2ubuntu16/debian/patches/ubuntu-add-devicetree-command-support.patch
--- 2.06-2/debian/patches/ubuntu-add-devicetree-command-support.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-add-devicetree-command-support.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,51 @@
+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 ac6226f..2dc026b 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 -pruN 2.06-2/debian/patches/ubuntu-add-initrd-less-boot-fallback.patch 2.06-2ubuntu16/debian/patches/ubuntu-add-initrd-less-boot-fallback.patch
--- 2.06-2/debian/patches/ubuntu-add-initrd-less-boot-fallback.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-add-initrd-less-boot-fallback.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,214 @@
+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 | 14 +++++++++
+ util/grub.d/00_header.in     | 27 ++++++++++++++++++
+ util/grub.d/10_linux.in      | 68 +++++++++++++++++++++++++++++++++-----------
+ 5 files changed, 106 insertions(+), 16 deletions(-)
+ create mode 100644 grub-initrd-fallback.service
+
+diff --git a/Makefile.am b/Makefile.am
+index bf9c1ba..353061e 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 a29beb9..15a2a50 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -314,6 +314,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 0000000..1a0a4e5
+--- /dev/null
++++ b/grub-initrd-fallback.service
+@@ -0,0 +1,14 @@
++[Unit]
++Description=GRUB failed boot detection
++After=local-fs.target
++After=grub-common.service
++After=sleep.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 sleep.target
+diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in
+index b7135b6..2642f66 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 dade627..ac6226f 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 -pruN 2.06-2/debian/patches/ubuntu-add-initrd-less-boot-messages.patch 2.06-2ubuntu16/debian/patches/ubuntu-add-initrd-less-boot-messages.patch
--- 2.06-2/debian/patches/ubuntu-add-initrd-less-boot-messages.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-add-initrd-less-boot-messages.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,68 @@
+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
+---
+ grub-initrd-fallback.service |  1 +
+ util/grub.d/10_linux.in      | 10 ++++++++++
+ 2 files changed, 11 insertions(+)
+
+diff --git a/grub-initrd-fallback.service b/grub-initrd-fallback.service
+index 1a0a4e5..59d1a62 100644
+--- a/grub-initrd-fallback.service
++++ b/grub-initrd-fallback.service
+@@ -3,6 +3,7 @@ Description=GRUB failed boot detection
+ After=local-fs.target
+ After=grub-common.service
+ After=sleep.target
++ConditionPathExists=/boot/grub/grub.cfg
+ 
+ [Service]
+ Type=oneshot
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index 4988009..8f2cf82 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 -pruN 2.06-2/debian/patches/ubuntu-boot-from-multipath-dependent-symlink.patch 2.06-2ubuntu16/debian/patches/ubuntu-boot-from-multipath-dependent-symlink.patch
--- 2.06-2/debian/patches/ubuntu-boot-from-multipath-dependent-symlink.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-boot-from-multipath-dependent-symlink.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,68 @@
+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 2dc026b..41a2876 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 -pruN 2.06-2/debian/patches/ubuntu-disable-LOAD-FILE2-protocol-for-initrd-on-ARM.patch 2.06-2ubuntu16/debian/patches/ubuntu-disable-LOAD-FILE2-protocol-for-initrd-on-ARM.patch
--- 2.06-2/debian/patches/ubuntu-disable-LOAD-FILE2-protocol-for-initrd-on-ARM.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-disable-LOAD-FILE2-protocol-for-initrd-on-ARM.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,63 @@
+From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+Date: Wed, 13 Apr 2022 18:51:37 +0200
+Subject: ubuntu: disable LOAD FILE2 protocol for initrd on ARM
+
+RISC-V cannot load the initrd without the LOAD FILE2 protocol.
+
+Currently the LOAD FILE2 protocol does not work with PXE due to a preboot
+hook invoking grub_net_fini_hw().
+
+So let's disable this for ARM until a solution has been agreed on with
+upstream.
+
+Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+---
+ grub-core/loader/efi/linux.c | 18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
+index 24abc0c..6dd3196 100644
+--- a/grub-core/loader/efi/linux.c
++++ b/grub-core/loader/efi/linux.c
+@@ -67,8 +67,10 @@ struct grub_arm64_linux_pe_header
+ grub_err_t
+ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
+ {
++#ifdef __riscv
+   struct grub_pe32_coff_header *coff_header;
+   struct grub_pe32_optional_header *optional_header;
++#endif
+ 
+   if (lh->magic != GRUB_LINUX_ARCH_MAGIC_SIGNATURE)
+     return grub_error(GRUB_ERR_BAD_OS, "invalid magic number");
+@@ -80,17 +82,27 @@ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
+   grub_dprintf ("linux", "UEFI stub kernel:\n");
+   grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset);
+ 
+-  coff_header = (struct grub_pe32_coff_header *)((unsigned long)lh + lh->hdr_offset);
+-  optional_header = (struct grub_pe32_optional_header *)(coff_header + 1);
+-
+   /*
+    * Linux kernels built for any architecture are guaranteed to support the
+    * LoadFile2 based initrd loading protocol if the image version is >= 1.
+    */
++#ifdef __riscv
++  /*
++   * RISC-V cannot load the initrd without the LOAD FILE2 protocol.
++   *
++   * Currently the LOAD FILE2 protocol does not work with PXE due to a preboot
++   * hook invoking grub_net_fini_hw().
++   *
++   * TODO: clarify if the preboot hook is needed
++   */
++  coff_header = (struct grub_pe32_coff_header *)((unsigned long)lh + lh->hdr_offset);
++  optional_header = (struct grub_pe32_optional_header *)(coff_header + 1);
++
+   if (optional_header->major_image_version >= 1)
+     initrd_use_loadfile2 = 1;
+    else
+     initrd_use_loadfile2 = 0;
++#endif
+ 
+   grub_dprintf ("linux", "LoadFile2 initrd loading %sabled\n",
+ 		initrd_use_loadfile2 ? "en" : "dis");
diff -pruN 2.06-2/debian/patches/ubuntu-dont-verify-loopback-images.patch 2.06-2ubuntu16/debian/patches/ubuntu-dont-verify-loopback-images.patch
--- 2.06-2/debian/patches/ubuntu-dont-verify-loopback-images.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-dont-verify-loopback-images.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,36 @@
+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 99f4792..6ca3012 100644
+--- a/grub-core/disk/loopback.c
++++ b/grub-core/disk/loopback.c
+@@ -91,7 +91,8 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name already exists");
+ 
+   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 -pruN 2.06-2/debian/patches/ubuntu-efi-allow-loopmount-chainload.patch 2.06-2ubuntu16/debian/patches/ubuntu-efi-allow-loopmount-chainload.patch
--- 2.06-2/debian/patches/ubuntu-efi-allow-loopmount-chainload.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-efi-allow-loopmount-chainload.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,126 @@
+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 41bebd1..99f4792 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 c3144de..2b74d79 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>
+@@ -905,6 +906,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;
+@@ -962,6 +964,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)
+@@ -1091,6 +1102,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 0000000..3b9a9e3
+--- /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 -pruN 2.06-2/debian/patches/ubuntu-efi-loader-code.patch 2.06-2ubuntu16/debian/patches/ubuntu-efi-loader-code.patch
--- 2.06-2/debian/patches/ubuntu-efi-loader-code.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-efi-loader-code.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,36 @@
+From: Julian Andres Klode <julian.klode@canonical.com>
+Date: Fri, 9 Dec 2022 16:00:25 +0100
+Subject: Allocate executables as CODE, not DATA in chainloader and arm64
+
+Other places seem patched already.
+---
+ grub-core/loader/efi/chainloader.c | 2 +-
+ grub-core/loader/efi/peimage.c     | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index fbd14eb..7e00117 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -596,7 +596,7 @@ handle_image (struct grub_secureboot_chainloader_context *load_context)
+   grub_dprintf ("chain", "image size is %08" PRIuGRUB_UINT64_T ", datasize is %08x\n",
+ 	       context.image_size, datasize);
+ 
+-  efi_status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA,
++  efi_status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_CODE,
+ 			   buffer_size, (void**)&buffer);
+ 
+   if (efi_status != GRUB_EFI_SUCCESS)
+diff --git a/grub-core/loader/efi/peimage.c b/grub-core/loader/efi/peimage.c
+index fffdf65..46cb7cd 100644
+--- a/grub-core/loader/efi/peimage.c
++++ b/grub-core/loader/efi/peimage.c
+@@ -243,7 +243,7 @@ static grub_efi_status_t load_sections(struct image_info *info)
+ 
+ 	info->alloc_addr = grub_efi_allocate_pages_real(
+ 			GRUB_EFI_MAX_USABLE_ADDRESS, info->alloc_pages,
+-			GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA);
++			GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_CODE);
+ 	if (!info->alloc_addr)
+ 		return GRUB_EFI_OUT_OF_RESOURCES;
+ 
diff -pruN 2.06-2/debian/patches/ubuntu-fix-lzma-decompressor-objcopy.patch 2.06-2ubuntu16/debian/patches/ubuntu-fix-lzma-decompressor-objcopy.patch
--- 2.06-2/debian/patches/ubuntu-fix-lzma-decompressor-objcopy.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-fix-lzma-decompressor-objcopy.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,29 @@
+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 f252725..0b5b4e7 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -550,7 +550,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 -pruN 2.06-2/debian/patches/ubuntu-flavour-order.patch 2.06-2ubuntu16/debian/patches/ubuntu-flavour-order.patch
--- 2.06-2/debian/patches/ubuntu-flavour-order.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-flavour-order.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,60 @@
+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 58002c0..a8c247a 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -266,7 +266,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 b6a1d7d..1e69d5b 100644
+--- a/util/grub-mkconfig_lib.in
++++ b/util/grub-mkconfig_lib.in
+@@ -274,6 +274,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 -pruN 2.06-2/debian/patches/ubuntu-fuse3.patch 2.06-2ubuntu16/debian/patches/ubuntu-fuse3.patch
--- 2.06-2/debian/patches/ubuntu-fuse3.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-fuse3.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,108 @@
+From: Julian Andres Klode <julian.klode@canonical.com>
+Date: Wed, 16 Feb 2022 16:52:41 +0100
+Subject: UBUNTU: Build with fuse3
+
+Origin: vendor,
+https://raw.githubusercontent.com/OpenMandrivaAssociation/grub2/master/grub-2.02-fuse3.patch
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1935659
+---
+ Makefile.util.def |  4 ++--
+ configure.ac      | 10 +++++-----
+ util/grub-mount.c | 10 +++++-----
+ 3 files changed, 12 insertions(+), 12 deletions(-)
+
+diff --git a/Makefile.util.def b/Makefile.util.def
+index a6204f6..9241b3e 100644
+--- a/Makefile.util.def
++++ b/Makefile.util.def
+@@ -196,7 +196,7 @@ program = {
+   common = util/config.c;
+ 
+   extra_dist = util/grub-mkimagexx.c;
+-
++  cppflags = '-I/usr/include/fuse3';
+   ldadd = libgrubmods.a;
+   ldadd = libgrubgcry.a;
+   ldadd = libgrubkern.a;
+@@ -313,7 +313,7 @@ program = {
+   ldadd = libgrubgcry.a;
+   ldadd = libgrubkern.a;
+   ldadd = grub-core/lib/gnulib/libgnu.a;
+-  ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM) -lfuse';
++  ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM) -lfuse3';
+   condition = COND_GRUB_MOUNT;
+ };
+ 
+diff --git a/configure.ac b/configure.ac
+index 15a2a50..aafb733 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1799,16 +1799,16 @@ if test x"$enable_grub_mount" = xno ; then
+ fi
+ 
+ if test x"$grub_mount_excuse" = x ; then
+-  AC_CHECK_LIB([fuse], [fuse_main_real], [],
+-               [grub_mount_excuse="need FUSE library"])
++  AC_CHECK_LIB([fuse3], [fuse_main_real], [],
++               [grub_mount_excuse="need FUSE3 library"])
+ fi
+ 
+ if test x"$grub_mount_excuse" = x ; then
+   # Check for fuse headers.
+   SAVED_CPPFLAGS="$CPPFLAGS"
+-  CPPFLAGS="$CPPFLAGS -DFUSE_USE_VERSION=26"
+-  AC_CHECK_HEADERS([fuse/fuse.h], [],
+-  	[grub_mount_excuse=["need FUSE headers"]])
++  CPPFLAGS="$CPPFLAGS -I/usr/include/fuse3 -DFUSE_USE_VERSION=30"
++  AC_CHECK_HEADERS([fuse3/fuse.h], [],
++  	[grub_mount_excuse=["need FUSE3 headers"]])
+   CPPFLAGS="$SAVED_CPPFLAGS"
+ fi
+ 
+diff --git a/util/grub-mount.c b/util/grub-mount.c
+index d7be2a4..b7fd04d 100644
+--- a/util/grub-mount.c
++++ b/util/grub-mount.c
+@@ -16,7 +16,7 @@
+  *  You should have received a copy of the GNU General Public License
+  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+  */
+-#define FUSE_USE_VERSION 26
++#define FUSE_USE_VERSION 30
+ #include <config.h>
+ #include <grub/types.h>
+ #include <grub/emu/misc.h>
+@@ -34,7 +34,7 @@
+ #include <grub/command.h>
+ #include <grub/zfs/zfs.h>
+ #include <grub/i18n.h>
+-#include <fuse/fuse.h>
++#include <fuse3/fuse.h>
+ 
+ #include <stdio.h>
+ #include <unistd.h>
+@@ -147,7 +147,7 @@ fuse_getattr_find_file (const char *cur_filename,
+ }
+ 
+ static int
+-fuse_getattr (const char *path, struct stat *st)
++fuse_getattr (const char *path, struct stat *st, struct fuse_file_info *fi)
+ {
+   struct fuse_getattr_ctx ctx;
+   char *pathname, *path2;
+@@ -330,13 +330,13 @@ fuse_readdir_call_fill (const char *filename,
+   st.st_blocks = (st.st_size + 511) >> 9;
+   st.st_atime = st.st_mtime = st.st_ctime
+     = info->mtimeset ? info->mtime : 0;
+-  ctx->fill (ctx->buf, filename, &st, 0);
++  ctx->fill (ctx->buf, filename, &st, 0, 0);
+   return 0;
+ }
+ 
+ static int 
+ fuse_readdir (const char *path, void *buf,
+-	      fuse_fill_dir_t fill, off_t off, struct fuse_file_info *fi)
++	      fuse_fill_dir_t fill, off_t off, struct fuse_file_info *fi, enum fuse_readdir_flags fl)
+ {
+   struct fuse_readdir_ctx ctx = {
+     .path = path,
diff -pruN 2.06-2/debian/patches/ubuntu-grub-install-extra-removable.patch 2.06-2ubuntu16/debian/patches/ubuntu-grub-install-extra-removable.patch
--- 2.06-2/debian/patches/ubuntu-grub-install-extra-removable.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-grub-install-extra-removable.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,227 @@
+From: Steve McIntyre <93sam@debian.org>
+Date: Wed, 3 Dec 2014 01:25:12 +0000
+Subject: UBUNTU: Add support for forcing EFI installation to the removable
+ media path
+
+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: ubuntu-grub-install-extra-removable.patch
+---
+ 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 65277ea..29651bb 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -56,6 +56,7 @@
+ 
+ static char *target;
+ static int removable = 0;
++static int no_extra_removable = 0;
+ static int recheck = 0;
+ static int update_nvram = 1;
+ static char *install_device = NULL;
+@@ -113,7 +114,8 @@ enum
+     OPTION_LABEL_BGCOLOR,
+     OPTION_PRODUCT_VERSION,
+     OPTION_UEFI_SECURE_BOOT,
+-    OPTION_NO_UEFI_SECURE_BOOT
++    OPTION_NO_UEFI_SECURE_BOOT,
++    OPTION_NO_EXTRA_REMOVABLE
+   };
+ 
+ static int fs_probe = 1;
+@@ -216,6 +218,10 @@ argp_parser (int key, char *arg, struct argp_state *state)
+       removable = 1;
+       return 0;
+ 
++    case OPTION_NO_EXTRA_REMOVABLE:
++      no_extra_removable = 1;
++      return 0;
++
+     case OPTION_ALLOW_FLOPPY:
+       allow_floppy = 1;
+       return 0;
+@@ -322,6 +328,9 @@ static struct argp_option options[] = {
+    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},
++  {"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}
+ };
+ 
+@@ -847,6 +856,116 @@ fill_core_services (const char *core_services)
+   free (sysv_plist);
+ }
+ 
++/* Helper routine for also_install_removable() below. Walk through the
++   specified dir, looking to see if there is a file/dir that matches
++   the search string exactly, but in a case-insensitive manner. If so,
++   return a copy of the exact file/dir that *does* exist. If not,
++   return NULL */
++static char *
++check_component_exists(const char *dir,
++		       const char *search)
++{
++  grub_util_fd_dir_t d;
++  grub_util_fd_dirent_t de;
++  char *found = NULL;
++
++  d = grub_util_fd_opendir (dir);
++  if (!d)
++    grub_util_error (_("cannot open directory `%s': %s"),
++		     dir, grub_util_fd_strerror ());
++
++  while ((de = grub_util_fd_readdir (d)))
++    {
++      if (strcasecmp (de->d_name, search) == 0)
++	{
++	  found = xstrdup (de->d_name);
++	  break;
++	}
++    }
++  grub_util_fd_closedir (d);
++  return found;
++}
++
++/* Some complex directory-handling stuff in here, to cope with
++ * case-insensitive FAT/VFAT filesystem semantics. Ugh. */
++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
++   * component at a time, checking for existing matches each time. */
++
++  /* Look for "EFI" in base_efidir. Make it if it does not exist in
++   * some form. */
++  found = check_component_exists(base_efidir, "EFI");
++  if (found == NULL)
++    found = xstrdup("EFI");
++  dst = grub_util_path_concat (2, base_efidir, found);
++  cur = xstrdup (dst);
++  free (dst);
++  free (found);
++  grub_install_mkdir_p (cur);
++
++  /* Now BOOT */
++  found = check_component_exists(cur, "BOOT");
++  if (found == NULL)
++    found = xstrdup("BOOT");
++  dst = grub_util_path_concat (2, cur, found);
++  free (cur);
++  free (found);
++  grub_install_mkdir_p (dst);
++  generic_efidir = xstrdup (dst);
++  free (dst);
++
++  /* Now $efi_file */
++  found = check_component_exists(generic_efidir, efi_file);
++  if (found == NULL)
++    found = xstrdup(efi_file);
++  dst = grub_util_path_concat (2, generic_efidir, found);
++  free (found);
++  grub_install_copy_file (src, dst, 1);
++  free (efi_file);
++  free (dst);
++
++  /* 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[])
+ {
+@@ -864,6 +983,7 @@ main (int argc, char *argv[])
+   char *relative_grubdir;
+   char **efidir_device_names = NULL;
+   grub_device_t efidir_grub_dev = NULL;
++  char *base_efidir = NULL;
+   char *efidir_grub_devname;
+   int efidir_is_mac = 0;
+   int is_prep = 0;
+@@ -896,6 +1016,9 @@ main (int argc, char *argv[])
+       bootloader_id = xstrdup ("grub");
+     }
+ 
++  if (removable && no_extra_removable)
++    grub_util_error (_("Invalid to use both --removable and --no_extra_removable"));
++
+   if (!grub_install_source_directory)
+     {
+       if (!target)
+@@ -1115,6 +1238,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);
+ 
++      base_efidir = xstrdup(efidir);
++
+       /* 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
+@@ -2051,9 +2176,15 @@ main (int argc, char *argv[])
+ 	    fprintf (config_dst_f, "configfile $prefix/grub.cfg\n");
+ 	    fclose (config_dst_f);
+ 	    free (config_dst);
++	    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 (!removable && !no_extra_removable)
++	      also_install_removable(imgfile, base_efidir, efi_suffix, efi_suffix_upper);
++	  }
+ 
+ 	grub_set_install_backup_ponr ();
+ 
diff -pruN 2.06-2/debian/patches/ubuntu-install-signed.patch 2.06-2ubuntu16/debian/patches/ubuntu-install-signed.patch
--- 2.06-2/debian/patches/ubuntu-install-signed.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-install-signed.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,313 @@
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Mon, 13 Jan 2014 12:13:22 +0000
+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
+
+Author: Stéphane Graber <stgraber@ubuntu.com>
+Author: Steve Langasek <steve.langasek@ubuntu.com>
+Author: Linn Crosetto <linn@hpe.com>
+Author: Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>
+Forwarded: no
+Last-Update: 2016-11-01
+
+Patch-Name: ubuntu-install-signed.patch
+---
+ 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 48e2d37..5ddd028 100644
+--- a/util/grub-install.c
++++ b/util/grub-install.c
+@@ -80,6 +80,7 @@ static char *label_color;
+ static char *label_bgcolor;
+ static char *product_version;
+ static int add_rs_codes = 1;
++static int uefi_secure_boot = 1;
+ 
+ enum
+   {
+@@ -110,7 +111,9 @@ enum
+     OPTION_LABEL_FONT,
+     OPTION_LABEL_COLOR,
+     OPTION_LABEL_BGCOLOR,
+-    OPTION_PRODUCT_VERSION
++    OPTION_PRODUCT_VERSION,
++    OPTION_UEFI_SECURE_BOOT,
++    OPTION_NO_UEFI_SECURE_BOOT
+   };
+ 
+ static int fs_probe = 1;
+@@ -234,6 +237,14 @@ argp_parser (int key, char *arg, struct argp_state *state)
+       bootloader_id = xstrdup (arg);
+       return 0;
+ 
++    case OPTION_UEFI_SECURE_BOOT:
++      uefi_secure_boot = 1;
++      return 0;
++
++    case OPTION_NO_UEFI_SECURE_BOOT:
++      uefi_secure_boot = 0;
++      return 0;
++
+     case ARGP_KEY_ARG:
+       if (install_device)
+ 	grub_util_error ("%s", _("More than one install device?"));
+@@ -303,6 +314,14 @@ static struct argp_option options[] = {
+   {"label-color", OPTION_LABEL_COLOR, N_("COLOR"), 0, N_("use COLOR for label"), 2},
+   {"label-bgcolor", OPTION_LABEL_BGCOLOR, N_("COLOR"), 0, N_("use COLOR for label background"), 2},
+   {"product-version", OPTION_PRODUCT_VERSION, N_("STRING"), 0, N_("use STRING as product version"), 2},
++  {"uefi-secure-boot", OPTION_UEFI_SECURE_BOOT, 0, 0,
++   N_("install an image usable with UEFI Secure Boot. "
++      "This option is only available on EFI and if the grub-efi-amd64-signed "
++      "package is installed."), 2},
++  {"no-uefi-secure-boot", OPTION_NO_UEFI_SECURE_BOOT, 0, 0,
++   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},
+   {0, 0, 0, 0, 0, 0}
+ };
+ 
+@@ -833,7 +852,8 @@ main (int argc, char *argv[])
+ {
+   int is_efi = 0;
+   const char *efi_distributor = NULL;
+-  const char *efi_file = NULL;
++  const char *efi_suffix = NULL, *efi_suffix_upper = NULL;
++  char *efi_file = NULL;
+   char **grub_devices;
+   grub_fs_t grub_fs;
+   grub_device_t grub_dev = NULL;
+@@ -1103,6 +1123,39 @@ main (int argc, char *argv[])
+       */
+       char *t;
+       efi_distributor = bootloader_id;
++      switch (platform)
++	{
++	case GRUB_INSTALL_PLATFORM_I386_EFI:
++	  efi_suffix = "ia32";
++	  efi_suffix_upper = "IA32";
++	  break;
++	case GRUB_INSTALL_PLATFORM_X86_64_EFI:
++	  efi_suffix = "x64";
++	  efi_suffix_upper = "X64";
++	  break;
++	case GRUB_INSTALL_PLATFORM_IA64_EFI:
++	  efi_suffix = "ia64";
++	  efi_suffix_upper = "IA64";
++	  break;
++	case GRUB_INSTALL_PLATFORM_ARM_EFI:
++	  efi_suffix = "arm";
++	  efi_suffix_upper = "ARM";
++	  break;
++	case GRUB_INSTALL_PLATFORM_ARM64_EFI:
++	  efi_suffix = "aa64";
++	  efi_suffix_upper = "AA64";
++	  break;
++	case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
++	  efi_suffix = "riscv32";
++	  efi_suffix_upper = "RISCV32";
++	  break;
++	case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
++	  efi_suffix = "riscv64";
++	  efi_suffix_upper = "RISCV64";
++	  break;
++	default:
++	  break;
++	}
+       if (removable)
+ 	{
+ 	  /* The specification makes stricter requirements of removable
+@@ -1111,66 +1164,16 @@ main (int argc, char *argv[])
+ 	     must have a specific file name depending on the architecture.
+ 	  */
+ 	  efi_distributor = "BOOT";
+-	  switch (platform)
+-	    {
+-	    case GRUB_INSTALL_PLATFORM_I386_EFI:
+-	      efi_file = "BOOTIA32.EFI";
+-	      break;
+-	    case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+-	      efi_file = "BOOTX64.EFI";
+-	      break;
+-	    case GRUB_INSTALL_PLATFORM_IA64_EFI:
+-	      efi_file = "BOOTIA64.EFI";
+-	      break;
+-	    case GRUB_INSTALL_PLATFORM_ARM_EFI:
+-	      efi_file = "BOOTARM.EFI";
+-	      break;
+-	    case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+-	      efi_file = "BOOTAA64.EFI";
+-	      break;
+-	    case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+-	      efi_file = "BOOTRISCV32.EFI";
+-	      break;
+-	    case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
+-	      efi_file = "BOOTRISCV64.EFI";
+-	      break;
+-	    default:
+-	      grub_util_error ("%s", _("You've found a bug"));
+-	      break;
+-	    }
++	  if (!efi_suffix)
++	    grub_util_error ("%s", _("You've found a bug"));
++	  efi_file = xasprintf ("BOOT%s.EFI", efi_suffix_upper);
+ 	}
+       else
+ 	{
+ 	  /* It is convenient for each architecture to have a different
+ 	     efi_file, so that different versions can be installed in parallel.
+ 	  */
+-	  switch (platform)
+-	    {
+-	    case GRUB_INSTALL_PLATFORM_I386_EFI:
+-	      efi_file = "grubia32.efi";
+-	      break;
+-	    case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+-	      efi_file = "grubx64.efi";
+-	      break;
+-	    case GRUB_INSTALL_PLATFORM_IA64_EFI:
+-	      efi_file = "grubia64.efi";
+-	      break;
+-	    case GRUB_INSTALL_PLATFORM_ARM_EFI:
+-	      efi_file = "grubarm.efi";
+-	      break;
+-	    case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+-	      efi_file = "grubaa64.efi";
+-	      break;
+-	    case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+-	      efi_file = "grubriscv32.efi";
+-	      break;
+-	    case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
+-	      efi_file = "grubriscv64.efi";
+-	      break;
+-	    default:
+-	      efi_file = "grub.efi";
+-	      break;
+-	    }
++	  efi_file = xasprintf ("grub%s.efi", efi_suffix);
+ 	}
+       t = grub_util_path_concat (3, efidir, "EFI", efi_distributor);
+       free (efidir);
+@@ -1376,14 +1379,41 @@ main (int argc, char *argv[])
+ 	}
+     }
+ 
+-  if (!have_abstractions)
++  char *efi_signed = NULL;
++  switch (platform)
++    {
++    case GRUB_INSTALL_PLATFORM_I386_EFI:
++    case GRUB_INSTALL_PLATFORM_X86_64_EFI:
++    case GRUB_INSTALL_PLATFORM_ARM_EFI:
++    case GRUB_INSTALL_PLATFORM_ARM64_EFI:
++    case GRUB_INSTALL_PLATFORM_IA64_EFI:
++      {
++	char *dir = xasprintf ("%s-signed", grub_install_source_directory);
++	char *signed_image;
++	if (removable)
++	  signed_image = xasprintf ("gcd%s.efi.signed", efi_suffix);
++	else
++	  signed_image = xasprintf ("grub%s.efi.signed", efi_suffix);
++	efi_signed = grub_util_path_concat (2, dir, signed_image);
++	break;
++      }
++
++    default:
++      break;
++    }
++
++  if (!efi_signed || !grub_util_is_regular (efi_signed))
++    uefi_secure_boot = 0;
++
++  if (!have_abstractions || uefi_secure_boot)
+     {
+       if ((disk_module && grub_strcmp (disk_module, "biosdisk") != 0)
+ 	  || grub_drives[1]
+ 	  || (!install_drive
+ 	      && platform != GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275)
+ 	  || (install_drive && !is_same_disk (grub_drives[0], install_drive))
+-	  || !have_bootdev (platform))
++	  || !have_bootdev (platform)
++	  || uefi_secure_boot)
+ 	{
+ 	  char *uuid = NULL;
+ 	  /*  generic method (used on coreboot and ata mod).  */
+@@ -1941,7 +1971,74 @@ main (int argc, char *argv[])
+     case GRUB_INSTALL_PLATFORM_IA64_EFI:
+       {
+ 	char *dst = grub_util_path_concat (2, efidir, efi_file);
+-	grub_install_copy_file (imgfile, dst, 1);
++	if (uefi_secure_boot)
++	  {
++	    char *shim_signed = 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_file = xasprintf ("mm%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, *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);
++		    efi_file = xasprintf ("shim%s.efi", efi_suffix);
++		    free (dst);
++		    dst = grub_util_path_concat (2, efidir, efi_file);
++		  }
++		grub_install_copy_file (shim_signed, dst, 1);
++		free (efi_signed);
++		efi_signed = xstrdup (shim_signed);
++
++		/* 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_file);
++		mok_dst = grub_util_path_concat (2, efidir,
++						    mok_file);
++		grub_install_copy_file (mok_src,
++					mok_dst, 0);
++		free (mok_src);
++		free (mok_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);
++
++	    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);
++	  }
++	else
++	  grub_install_copy_file (imgfile, dst, 1);
+ 
+ 	grub_set_install_backup_ponr ();
+ 
diff -pruN 2.06-2/debian/patches/ubuntu-linuxefi-arm64.patch 2.06-2ubuntu16/debian/patches/ubuntu-linuxefi-arm64.patch
--- 2.06-2/debian/patches/ubuntu-linuxefi-arm64.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-linuxefi-arm64.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,171 @@
+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/efi/linux.c | 101 ++++++++++++++++++++++---------------------
+ 1 file changed, 51 insertions(+), 50 deletions(-)
+
+diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
+index d81e7be..93e4cfc 100644
+--- a/grub-core/loader/efi/linux.c
++++ b/grub-core/loader/efi/linux.c
+@@ -42,6 +42,7 @@ static int loaded;
+ 
+ static void *kernel_addr;
+ static grub_uint64_t kernel_size;
++static grub_uint32_t handover_offset;
+ 
+ static char *linux_args;
+ static grub_uint32_t cmdline_size;
+@@ -99,7 +100,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 = NULL;
+ 
+@@ -134,6 +136,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:
+@@ -141,62 +164,36 @@ failure:
+   return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
+ }
+ 
+-grub_err_t
+-grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
++static void
++free_params (void)
+ {
+-  grub_efi_memory_mapped_device_path_t *mempath;
+-  grub_efi_handle_t image_handle;
+-  grub_efi_boot_services_t *b;
+-  grub_efi_status_t status;
+-  grub_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;
+-
+-  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);
++  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;
++    }
++}
+ 
+-  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");
++grub_err_t
++grub_arch_efi_linux_boot_image (grub_addr_t addr __attribute__((unused)),
++				grub_size_t size __attribute__((unused)),
++				char *args)
++{
++  grub_err_t retval;
+ 
+   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);
+-
+-  grub_dprintf ("linux", "starting image %p\n", image_handle);
+-  status = b->start_image (image_handle, 0, NULL);
++  retval = grub_efi_linux_boot (kernel_addr, handover_offset, kernel_addr);
+ 
+   /* 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));
+-
+-  return grub_errno;
++  free_params();
++  return retval;
+ }
+ 
+ static grub_err_t
+@@ -411,6 +408,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;
+ 
+@@ -464,6 +462,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
++  pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
++  handover_offset = pe->opt.entry_addr;
++
+   cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
+   linux_args = grub_malloc (cmdline_size);
+   if (!linux_args)
diff -pruN 2.06-2/debian/patches/ubuntu-linuxefi-arm64-set-base-addr.patch 2.06-2ubuntu16/debian/patches/ubuntu-linuxefi-arm64-set-base-addr.patch
--- 2.06-2/debian/patches/ubuntu-linuxefi-arm64-set-base-addr.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-linuxefi-arm64-set-base-addr.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,68 @@
+From: Javier Martinez Canillas <javierm@redhat.com>
+Date: Thu, 23 Apr 2020 15:06:46 +0200
+Subject: efi: Set image base address before jumping to the PE/COFF entry
+ point
+
+Upstream GRUB uses the EFI LoadImage() and StartImage() to boot the Linux
+kernel. But our custom EFI loader that supports Secure Boot instead uses
+the EFI handover protocol (for x86) or jumping directly to the PE/COFF
+entry point (for aarch64).
+
+This is done to allow the bootloader to verify the images using the shim
+lock protocol to avoid booting untrusted binaries.
+
+Since the bootloader loads the kernel from the boot media instead of using
+LoadImage(), it is responsible to set the Loaded Image base address before
+booting the kernel.
+
+Otherwise the kernel EFI stub will complain that it was not set correctly
+and print the following warning message:
+
+EFI stub: ERROR: FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value
+
+Resolves: rhbz#1825411
+
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+[ dannf: Offset adjustment to apply to Ubuntu's GRUB ]
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1900774
+Origin: https://github.com/rhboot/grub2/commit/1d5ef08216edec4d31d0e10cfdb30b5ebfef7a45
+Last-Updated: 2020-11-09
+Patch-Name: ubuntu-linuxefi-arm64-set-base-addr.patch
+---
+ grub-core/loader/efi/linux_sb.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/grub-core/loader/efi/linux_sb.c b/grub-core/loader/efi/linux_sb.c
+index e372b26..73a7196 100644
+--- a/grub-core/loader/efi/linux_sb.c
++++ b/grub-core/loader/efi/linux_sb.c
+@@ -71,6 +71,7 @@ grub_err_t
+ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
+ 		     void *kernel_params)
+ {
++  grub_efi_loaded_image_t *loaded_image = NULL;
+   handover_func hf;
+   int offset = 0;
+ 
+@@ -79,6 +80,20 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
+   offset = 512;
+ #endif
+ 
++  /*
++   * Since the EFI loader is not calling the LoadImage() and StartImage()
++   * services for loading the kernel and booting respectively, it has to
++   * set the Loaded Image base address.
++   */
++  loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
++  if (loaded_image)
++    loaded_image->image_base = kernel_addr;
++  else
++    grub_dprintf ("linux", "Loaded Image base address could not be set\n");
++
++  grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n",
++		kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params);
++
+   hf = (handover_func)((char *)kernel_addr + handover_offset + offset);
+   hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
+ 
diff -pruN 2.06-2/debian/patches/ubuntu-linuxefi.patch 2.06-2ubuntu16/debian/patches/ubuntu-linuxefi.patch
--- 2.06-2/debian/patches/ubuntu-linuxefi.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-linuxefi.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,2606 @@
+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/97c97a2e9a95a29c42569952c8be7be1fdb5b4cf
+Forwarded: no
+Last-Update: 2019-02-27
+
+Rework linux16 command
+
+We want a single buffer that contains the entire kernel image in order to
+perform a TPM measurement. Allocate one and copy the entire kernel int it
+before pulling out the individual blocks later on.
+
+Origin: vendor, https://github.com/rhboot/grub2/commit/78d85625026497d96a06e5b7880a1d4785af9d1f
+Forwarded: no
+Last-Update: 2019-02-27
+
+Re-work some intricacies of PE loading.
+
+The PE spec is not a well written document, and awesomely every place
+where there's an ambiguous way to read something, Windows' bootmgfw.efi
+takes a different read than either of them.
+
+Origin: vendor, https://github.com/rhboot/grub2/commit/3f023d25a1ceb6d23c1bb17b754fbc1f8321427d
+Forwarded: no
+Last-Update: 2019-02-27
+
+Rework even more of efi chainload so non-sb cases work right.
+
+This ensures that if shim protocol is not loaded, or is loaded but shim
+is disabled, we will fall back to a correct load method for the efi
+chain loader.
+
+Here's what I tested with this version:
+
+results                             expected    actual
+------------------------------------------------------------
+sb + enabled + shim + fedora        success     success
+sb + enabled + shim + win           success     success
+sb + enabled + grub + fedora        fail        fail
+sb + enabled + grub + win           fail        fail
+
+sb + mokdisabled + shim + fedora    success     success
+sb + mokdisabled + shim + win       success     success
+sb + mokdisabled + grub + fedora    fail        fail
+sb + mokdisabled + grub + win       fail        fail
+
+sb disabled + shim + fedora         success     success*
+sb disabled + shim + win            success     success*
+sb disabled + grub + fedora         success     success
+sb disabled + grub + win            success     success
+
+nosb + shim + fedora                success     success*
+nosb + shim + win                   success     success*
+nosb + grub + fedora                success     success
+nosb + grub + win                   success     success
+
+* for some reason shim protocol is being installed in these cases, and I
+  can't see why, but I think it may be this firmware build returning an
+  erroneous value.  But this effectively falls back to the mokdisabled
+  behavior, which works correctly, and the presence of the "grub" (i.e.
+  no shim) tests effectively tests the desired behavior here.
+
+Resolves: rhbz#1344512
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+Origin: vendor, https://github.com/rhboot/grub2/commit/149cdec4f9e5fd039a698ef20530bad588b6aeeb
+Forwarded: no
+Last-Update: 2019-02-27
+
+Add some grub_dprintf() in the linuxefi path.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+Origin: vendor, https://github.com/rhboot/grub2/commit/527a427a8edf05d8994f679a16d0dc98106563f4
+Forwarded: no
+Last-Update: 2019-02-27
+
+linuxefi: minor cleanups
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+Origin: vendor, https://github.com/rhboot/grub2/commit/2c9a6edf8abbc7397174ec2696fce28822996a12
+Forwarded: no
+Last-Update: 2019-02-27
+
+Handle multi-arch (64-on-32) boot in linuxefi loader.
+
+Allow booting 64-bit kernels on 32-bit EFI on x86.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+Origin: vendor, https://github.com/rhboot/grub2/commit/1c88c700148acf02863a350055a43eb87e16bbe5
+Forwarded: no
+Last-Update: 2019-02-27
+
+Clean up some errors in the linuxefi loader
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+Origin: vendor, https://github.com/rhboot/grub2/commit/df0d3873162dd7e9352e1d4fbd589aa60e722f2e
+Forwarded: no
+Last-Update: 2019-02-27
+
+efi/chainloader: fix wrong sanity check in relocate_coff()
+
+In relocate_coff(), the relocation entries are parsed from the original
+image (not the section-wise copied image). The original image is
+pointed-to by the "orig" pointer. The current check
+
+  (void *)reloc_end < data
+
+compares the addresses of independent memory allocations. "data" is a typo
+here, it should be "orig".
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1347291
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+Tested-by: Bogdan Costescu <bcostescu@gmail.com>
+Tested-by: Juan Orti <j.orti.alcaine@gmail.com>
+
+Last-Update: 2019-02-27
+
+efi/chainloader: truncate overlong relocation section
+
+The UEFI Windows 7 boot loader ("EFI/Microsoft/Boot/bootmgfw.efi", SHA1
+31b410e029bba87d2068c65a80b88882f9f8ea25) has inconsistent headers.
+
+Compare:
+
+> The Data Directory
+> ...
+> Entry 5 00000000000d9000 00000574 Base Relocation Directory [.reloc]
+
+Versus:
+
+> Sections:
+> Idx Name      Size      VMA               LMA               File off ...
+> ...
+>  10 .reloc    00000e22  00000000100d9000  00000000100d9000  000a1800 ...
+
+That is, the size reported by the RelocDir entry (0x574) is smaller than
+the virtual size of the .reloc section (0xe22).
+
+Quoting the grub2 debug log for the same:
+
+> chainloader.c:595: reloc_dir: 0xd9000 reloc_size: 0x00000574
+> chainloader.c:603: reloc_base: 0x7d208000 reloc_base_end: 0x7d208573
+> ...
+> chainloader.c:620: Section 10 ".reloc" at 0x7d208000..0x7d208e21
+> chainloader.c:661:  section is not reloc section?
+> chainloader.c:663:  rds: 0x00001000, vs: 00000e22
+> chainloader.c:664:  base: 0x7d208000 end: 0x7d208e21
+> chainloader.c:666:  reloc_base: 0x7d208000 reloc_base_end: 0x7d208573
+> chainloader.c:671:  Section characteristics are 42000040
+> chainloader.c:673:  Section virtual size: 00000e22
+> chainloader.c:675:  Section raw_data size: 00001000
+> chainloader.c:678:  Discarding section
+
+After hexdumping "bootmgfw.efi" and manually walking its relocation blocks
+(yes, really), I determined that the (smaller) RelocDir value is correct.
+The remaining area that extends up to the .reloc section size (== 0xe22 -
+0x574 == 0x8ae bytes) exists as zero padding in the file.
+
+This zero padding shouldn't be passed to relocate_coff() for parsing. In
+order to cope with it, split the handling of .reloc sections into the
+following branches:
+
+- original case (equal size): original behavior (--> relocation
+  attempted),
+
+- overlong .reloc section (longer than reported by RelocDir): truncate the
+  section to the RelocDir size for the purposes of relocate_coff(), and
+  attempt relocation,
+
+- .reloc section is too short, or other checks fail: original behavior
+  (--> relocation not attempted).
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1347291
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+Last-Update: 2019-02-27
+
+i386/efi: update loader to new interfaces
+
+This updates the non-upstream loader/i386/efi/linux.c to build
+correctly with the patches in this branch appled.
+
+Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
+
+Bug-Debian: https://bugs.debian.org/907596
+Bug-Debian: https://bugs.debian.org/909420
+Bug-Debian: https://bugs.debian.org/915091
+Last-Update: 2018-12-06
+
+If running under UEFI secure boot, attempt to use linuxefi loader
+
+Forwarded: no
+Last-Update: 2019-02-27
+
+Disallow unsigned kernels if UEFI Secure Boot is enabled
+
+If UEFI Secure Boot is enabled and kernel signature verification fails, do not
+boot the kernel. Before this change, if kernel signature verification failed
+then GRUB would fall back to calling ExitBootServices() and continuing the
+boot.
+
+Signed-off-by: Linn Crosetto <linn@hpe.com>
+
+Move include for efi/sb.h in i386/linux loader
+
+It really should be EFI-specific.
+
+Signed-off-by: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
+Last-Update: 2019-02-22
+
+Fix various format/cast errors in Secure Boot code
+
+Signed-off-by: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
+Last-Update: 2019-02-22
+
+Temporarily re-enable the generic linux loader
+
+We're currently relying on it and an automatic hand-off to linuxefi for EFI
+booting; so we need the linux command to start to be able to do the hand-off
+correctly.
+
+This is a temporary measure until we switch to calling linuxefi directly.
+
+Forwarded: no
+Last-Update: 2019-02-27
+
+linuxefi: Don't enforce Shim signature validation if Secure Boot is disabled
+
+The linuxefi command fails if used on a system without shim, even if
+Secure Boot is disabled. There's no need to do the validation if we're
+not in Secure Boot mode (an attacker could just boot a modified grub),
+so skip this to make it easier to use the Linux EFI entry point even on
+non-Secure Boot systems.
+
+Last-Update: 2018-12-07
+
+Updated 2021-12-13: If we cannot allocate kernel at preferred address,
+reset errno so that we do not fail erroneously with out of memory.
+---
+ grub-core/Makefile.core.def            |  17 +-
+ grub-core/commands/iorw.c              |   7 +
+ grub-core/commands/memrw.c             |   7 +
+ grub-core/kern/arm/coreboot/coreboot.S |   6 +
+ grub-core/kern/dl.c                    |   1 +
+ grub-core/kern/efi/mm.c                |  32 ++
+ grub-core/loader/efi/appleloader.c     |   7 +
+ grub-core/loader/efi/chainloader.c     | 815 ++++++++++++++++++++++++++++++---
+ grub-core/loader/efi/fdt.c             |   1 +
+ grub-core/loader/efi/linux.c           |  16 +
+ grub-core/loader/efi/linux_sb.c        |  86 ++++
+ grub-core/loader/i386/bsd.c            |   7 +
+ grub-core/loader/i386/efi/linux.c      | 382 +++++++++++++++
+ grub-core/loader/i386/linux.c          |  78 +++-
+ grub-core/loader/i386/pc/linux.c       |  40 +-
+ grub-core/loader/multiboot.c           |   7 +
+ grub-core/loader/xnu.c                 |   7 +
+ include/grub/arm64/linux.h             |   2 +
+ include/grub/efi/efi.h                 |   3 +
+ include/grub/efi/linux.h               |  31 ++
+ include/grub/efi/pe32.h                |  52 ++-
+ include/grub/i386/linux.h              |   7 +-
+ include/grub/ia64/linux.h              |   0
+ include/grub/mips/linux.h              |   0
+ include/grub/powerpc/linux.h           |   0
+ include/grub/sparc64/linux.h           |   0
+ 26 files changed, 1511 insertions(+), 100 deletions(-)
+ create mode 100644 grub-core/loader/efi/linux_sb.c
+ create mode 100644 grub-core/loader/i386/efi/linux.c
+ create mode 100644 include/grub/efi/linux.h
+ create mode 100644 include/grub/ia64/linux.h
+ create mode 100644 include/grub/mips/linux.h
+ create mode 100644 include/grub/powerpc/linux.h
+ create mode 100644 include/grub/sparc64/linux.h
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 0536575..1a3ead6 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -1807,10 +1807,15 @@ module = {
+   ia64_efi = loader/ia64/efi/linux.c;
+   arm_coreboot = loader/arm/linux.c;
+   arm_efi = loader/efi/linux.c;
++  arm_efi = loader/efi/linux_sb.c;
+   arm_uboot = loader/arm/linux.c;
+   arm64 = loader/efi/linux.c;
++  arm64 = loader/efi/linux_sb.c;
+   riscv32 = loader/efi/linux.c;
++  riscv32 = loader/efi/linux_sb.c;
+   riscv64 = loader/efi/linux.c;
++  riscv64 = loader/efi/linux_sb.c;
++  cflags = '-Wno-error=cast-align';
+   common = loader/linux.c;
+   common = lib/cmdline.c;
+   enable = noemu;
+@@ -1819,7 +1824,7 @@ module = {
+ module = {
+   name = fdt;
+   efi = loader/efi/fdt.c;
+-  common = lib/fdt.c;
++  fdt = lib/fdt.c;
+   enable = fdt;
+ };
+ 
+@@ -1874,12 +1879,22 @@ module = {
+   enable = x86_64_efi;
+ };
+ 
++module = {
++  name = linuxefi;
++  efi = loader/i386/efi/linux.c;
++  efi = loader/efi/linux_sb.c;
++  cflags = '-Wno-error=cast-align';
++  enable = i386_efi;
++  enable = x86_64_efi;
++};
++
+ module = {
+   name = chain;
+   efi = loader/efi/chainloader.c;
+   i386_pc = loader/i386/pc/chainloader.c;
+   i386_coreboot = loader/i386/coreboot/chainloader.c;
+   i386_coreboot = lib/LzmaDec.c;
++  cflags = '-Wno-error=cast-align';
+   enable = i386_pc;
+   enable = i386_coreboot;
+   enable = efi;
+diff --git a/grub-core/commands/iorw.c b/grub-core/commands/iorw.c
+index 584baec..cb3c1b5 100644
+--- a/grub-core/commands/iorw.c
++++ b/grub-core/commands/iorw.c
+@@ -24,6 +24,7 @@
+ #include <grub/cpu/io.h>
+ #include <grub/i18n.h>
+ #include <grub/lockdown.h>
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -119,6 +120,9 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv)
+ 
+ GRUB_MOD_INIT(memrw)
+ {
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    return;
++
+   cmd_read_byte =
+     grub_register_extcmd ("inb", grub_cmd_read, 0,
+ 			  N_("PORT"), N_("Read 8-bit value from PORT."),
+@@ -147,6 +151,9 @@ GRUB_MOD_INIT(memrw)
+ 
+ GRUB_MOD_FINI(memrw)
+ {
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    return;
++
+   grub_unregister_extcmd (cmd_read_byte);
+   grub_unregister_extcmd (cmd_read_word);
+   grub_unregister_extcmd (cmd_read_dword);
+diff --git a/grub-core/commands/memrw.c b/grub-core/commands/memrw.c
+index d401a6d..e4be011 100644
+--- a/grub-core/commands/memrw.c
++++ b/grub-core/commands/memrw.c
+@@ -23,6 +23,7 @@
+ #include <grub/env.h>
+ #include <grub/i18n.h>
+ #include <grub/lockdown.h>
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -121,6 +122,9 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv)
+ 
+ GRUB_MOD_INIT(memrw)
+ {
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    return;
++
+   cmd_read_byte =
+     grub_register_extcmd ("read_byte", grub_cmd_read, 0,
+ 			  N_("ADDR"), N_("Read 8-bit value from ADDR."),
+@@ -149,6 +153,9 @@ GRUB_MOD_INIT(memrw)
+ 
+ GRUB_MOD_FINI(memrw)
+ {
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    return;
++
+   grub_unregister_extcmd (cmd_read_byte);
+   grub_unregister_extcmd (cmd_read_word);
+   grub_unregister_extcmd (cmd_read_dword);
+diff --git a/grub-core/kern/arm/coreboot/coreboot.S b/grub-core/kern/arm/coreboot/coreboot.S
+index a110452..70998c0 100644
+--- a/grub-core/kern/arm/coreboot/coreboot.S
++++ b/grub-core/kern/arm/coreboot/coreboot.S
+@@ -42,3 +42,9 @@ FUNCTION(grub_armv7_get_timer_frequency)
+ 	mrc p15, 0, r0, c14, c0, 0
+ 	bx	lr
+ 
++int
++EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size);
++grub_err_t
++EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
++				  void *kernel_param);
++
+diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
+index 51a800a..1fea604 100644
+--- a/grub-core/kern/dl.c
++++ b/grub-core/kern/dl.c
+@@ -32,6 +32,7 @@
+ #include <grub/env.h>
+ #include <grub/cache.h>
+ #include <grub/i18n.h>
++#include <grub/efi/sb.h>
+ 
+ /* Platforms where modules are in a readonly area of memory.  */
+ #if defined(GRUB_MACHINE_QEMU)
+diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
+index 9838fb2..f6aef0e 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/efi/appleloader.c b/grub-core/loader/efi/appleloader.c
+index 74888c4..07677f0 100644
+--- a/grub-core/loader/efi/appleloader.c
++++ b/grub-core/loader/efi/appleloader.c
+@@ -24,6 +24,7 @@
+ #include <grub/misc.h>
+ #include <grub/efi/api.h>
+ #include <grub/efi/efi.h>
++#include <grub/efi/sb.h>
+ #include <grub/command.h>
+ #include <grub/i18n.h>
+ 
+@@ -227,6 +228,9 @@ static grub_command_t cmd;
+ 
+ GRUB_MOD_INIT(appleloader)
+ {
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    return;
++
+   cmd = grub_register_command ("appleloader", grub_cmd_appleloader,
+ 			       N_("[OPTS]"),
+ 			       /* TRANSLATORS: This command is used on EFI to
+@@ -238,5 +242,8 @@ GRUB_MOD_INIT(appleloader)
+ 
+ GRUB_MOD_FINI(appleloader)
+ {
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    return;
++
+   grub_unregister_command (cmd);
+ }
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 2bd80f4..c3144de 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -32,6 +32,9 @@
+ #include <grub/efi/api.h>
+ #include <grub/efi/efi.h>
+ #include <grub/efi/disk.h>
++#include <grub/efi/pe32.h>
++#include <grub/efi/linux.h>
++#include <grub/efi/sb.h>
+ #include <grub/command.h>
+ #include <grub/i18n.h>
+ #include <grub/net.h>
+@@ -46,9 +49,14 @@ static grub_dl_t my_mod;
+ 
+ static grub_efi_physical_address_t address;
+ static grub_efi_uintn_t pages;
++static grub_ssize_t fsize;
+ static grub_efi_device_path_t *file_path;
+ static grub_efi_handle_t image_handle;
+ static grub_efi_char16_t *cmdline;
++static grub_ssize_t cmdline_len;
++static grub_efi_handle_t dev_handle;
++
++static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table);
+ 
+ static grub_err_t
+ grub_chainloader_unload (void)
+@@ -63,6 +71,7 @@ grub_chainloader_unload (void)
+   grub_free (cmdline);
+   cmdline = 0;
+   file_path = 0;
++  dev_handle = 0;
+ 
+   grub_dl_unref (my_mod);
+   return GRUB_ERR_NONE;
+@@ -213,20 +222,693 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
+   return file_path;
+ }
+ 
++#define SHIM_LOCK_GUID \
++  { 0x605dab50, 0xe046, 0x4300, { 0xab,0xb6,0x3d,0xd8,0x10,0xdd,0x8b,0x23 } }
++
++typedef union
++{
++  struct grub_pe32_header_32 pe32;
++  struct grub_pe32_header_64 pe32plus;
++} grub_pe_header_t;
++
++struct pe_coff_loader_image_context
++{
++  grub_efi_uint64_t image_address;
++  grub_efi_uint64_t image_size;
++  grub_efi_uint64_t entry_point;
++  grub_efi_uintn_t size_of_headers;
++  grub_efi_uint16_t image_type;
++  grub_efi_uint16_t number_of_sections;
++  grub_efi_uint32_t section_alignment;
++  struct grub_pe32_section_table *first_section;
++  struct grub_pe32_data_directory *reloc_dir;
++  struct grub_pe32_data_directory *sec_dir;
++  grub_efi_uint64_t number_of_rva_and_sizes;
++  grub_pe_header_t *pe_hdr;
++};
++
++typedef struct pe_coff_loader_image_context pe_coff_loader_image_context_t;
++
++struct grub_efi_shim_lock
++{
++  grub_efi_status_t (*verify)(void *buffer,
++                              grub_efi_uint32_t size);
++  grub_efi_status_t (*hash)(void *data,
++                            grub_efi_int32_t datasize,
++                            pe_coff_loader_image_context_t *context,
++                            grub_efi_uint8_t *sha256hash,
++                            grub_efi_uint8_t *sha1hash);
++  grub_efi_status_t (*context)(void *data,
++                               grub_efi_uint32_t size,
++                               pe_coff_loader_image_context_t *context);
++};
++
++typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
++
++static grub_efi_boolean_t
++read_header (void *data, grub_efi_uint32_t size,
++	     pe_coff_loader_image_context_t *context)
++{
++  grub_efi_guid_t guid = SHIM_LOCK_GUID;
++  grub_efi_shim_lock_t *shim_lock;
++  grub_efi_status_t status;
++
++  shim_lock = grub_efi_locate_protocol (&guid, NULL);
++  if (!shim_lock)
++    {
++      grub_dprintf ("chain", "no shim lock protocol");
++      return 0;
++    }
++
++  status = shim_lock->context (data, size, context);
++
++  if (status == GRUB_EFI_SUCCESS)
++    {
++      grub_dprintf ("chain", "context success\n");
++      return 1;
++    }
++
++  switch (status)
++    {
++      case GRUB_EFI_UNSUPPORTED:
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "context error unsupported");
++      break;
++      case GRUB_EFI_INVALID_PARAMETER:
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "context error invalid parameter");
++      break;
++      default:
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "context error code");
++      break;
++    }
++
++  return -1;
++}
++
++static void*
++image_address (void *image, grub_efi_uint64_t sz, grub_efi_uint64_t adr)
++{
++  if (adr > sz)
++    return NULL;
++
++  return ((grub_uint8_t*)image + adr);
++}
++
++static int
++image_is_64_bit (grub_pe_header_t *pe_hdr)
++{
++  /* .Magic is the same offset in all cases */
++  if (pe_hdr->pe32plus.optional_header.magic == GRUB_PE32_PE64_MAGIC)
++    return 1;
++  return 0;
++}
++
++static const grub_uint16_t machine_type __attribute__((__unused__)) =
++#if defined(__x86_64__)
++  GRUB_PE32_MACHINE_X86_64;
++#elif defined(__aarch64__)
++  GRUB_PE32_MACHINE_ARM64;
++#elif defined(__arm__)
++  GRUB_PE32_MACHINE_ARMTHUMB_MIXED;
++#elif defined(__i386__) || defined(__i486__) || defined(__i686__)
++  GRUB_PE32_MACHINE_I386;
++#elif defined(__ia64__)
++  GRUB_PE32_MACHINE_IA64;
++#elif defined(__riscv) && __riscv_xlen == 64
++  GRUB_PE32_MACHINE_RISCV64;
++#else
++#error this architecture is not supported by grub2
++#endif
++
++static grub_efi_status_t
++relocate_coff (pe_coff_loader_image_context_t *context,
++	       struct grub_pe32_section_table *section,
++	       void *orig, void *data)
++{
++  struct grub_pe32_data_directory *reloc_base, *reloc_base_end;
++  grub_efi_uint64_t adjust;
++  struct grub_pe32_fixup_block *reloc, *reloc_end;
++  char *fixup, *fixup_base, *fixup_data = NULL;
++  grub_efi_uint16_t *fixup_16;
++  grub_efi_uint32_t *fixup_32;
++  grub_efi_uint64_t *fixup_64;
++  grub_efi_uint64_t size = context->image_size;
++  void *image_end = (char *)orig + size;
++  int n = 0;
++
++  if (image_is_64_bit (context->pe_hdr))
++    context->pe_hdr->pe32plus.optional_header.image_base =
++      (grub_uint64_t)(unsigned long)data;
++  else
++    context->pe_hdr->pe32.optional_header.image_base =
++      (grub_uint32_t)(unsigned long)data;
++
++  /* Alright, so here's how this works:
++   *
++   * context->reloc_dir gives us two things:
++   * - the VA the table of base relocation blocks are (maybe) to be
++   *   mapped at (reloc_dir->rva)
++   * - the virtual size (reloc_dir->size)
++   *
++   * The .reloc section (section here) gives us some other things:
++   * - the name! kind of. (section->name)
++   * - the virtual size (section->virtual_size), which should be the same
++   *   as RelocDir->Size
++   * - the virtual address (section->virtual_address)
++   * - the file section size (section->raw_data_size), which is
++   *   a multiple of optional_header->file_alignment.  Only useful for image
++   *   validation, not really useful for iteration bounds.
++   * - the file address (section->raw_data_offset)
++   * - a bunch of stuff we don't use that's 0 in our binaries usually
++   * - Flags (section->characteristics)
++   *
++   * and then the thing that's actually at the file address is an array
++   * of struct grub_pe32_fixup_block structs with some values packed behind
++   * them.  The block_size field of this structure includes the
++   * structure itself, and adding it to that structure's address will
++   * yield the next entry in the array.
++   */
++
++  reloc_base = image_address (orig, size, section->raw_data_offset);
++  reloc_base_end = image_address (orig, size, section->raw_data_offset
++				  + section->virtual_size);
++
++  grub_dprintf ("chain", "relocate_coff(): reloc_base %p reloc_base_end %p\n",
++		reloc_base, reloc_base_end);
++
++  if (!reloc_base && !reloc_base_end)
++    return GRUB_EFI_SUCCESS;
++
++  if (!reloc_base || !reloc_base_end)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc table overflows binary");
++      return GRUB_EFI_UNSUPPORTED;
++    }
++
++  adjust = (grub_uint64_t)(grub_addr_t)data - context->image_address;
++  if (adjust == 0)
++    return GRUB_EFI_SUCCESS;
++
++  while (reloc_base < reloc_base_end)
++    {
++      grub_uint16_t *entry;
++      reloc = (struct grub_pe32_fixup_block *)reloc_base;
++
++      if ((reloc_base->size == 0) ||
++	  (reloc_base->size > context->reloc_dir->size))
++	{
++	  grub_error (GRUB_ERR_BAD_ARGUMENT,
++		      "Reloc %d block size %d is invalid\n", n,
++		      reloc_base->size);
++	  return GRUB_EFI_UNSUPPORTED;
++	}
++
++      entry = &reloc->entries[0];
++      reloc_end = (struct grub_pe32_fixup_block *)
++	((char *)reloc_base + reloc_base->size);
++
++      if ((void *)reloc_end < orig || (void *)reloc_end > image_end)
++        {
++          grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc entry %d overflows binary",
++		      n);
++          return GRUB_EFI_UNSUPPORTED;
++        }
++
++      fixup_base = image_address(data, size, reloc_base->rva);
++
++      if (!fixup_base)
++        {
++          grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc %d Invalid fixupbase", n);
++          return GRUB_EFI_UNSUPPORTED;
++        }
++
++      while ((void *)entry < (void *)reloc_end)
++        {
++          fixup = fixup_base + (*entry & 0xFFF);
++          switch ((*entry) >> 12)
++            {
++              case GRUB_PE32_REL_BASED_ABSOLUTE:
++                break;
++              case GRUB_PE32_REL_BASED_HIGH:
++                fixup_16 = (grub_uint16_t *)fixup;
++                *fixup_16 = (grub_uint16_t)
++		  (*fixup_16 + ((grub_uint16_t)((grub_uint32_t)adjust >> 16)));
++                if (fixup_data != NULL)
++                  {
++                    *(grub_uint16_t *) fixup_data = *fixup_16;
++                    fixup_data = fixup_data + sizeof (grub_uint16_t);
++                  }
++                break;
++              case GRUB_PE32_REL_BASED_LOW:
++                fixup_16 = (grub_uint16_t *)fixup;
++                *fixup_16 = (grub_uint16_t) (*fixup_16 + (grub_uint16_t)adjust);
++                if (fixup_data != NULL)
++                  {
++                    *(grub_uint16_t *) fixup_data = *fixup_16;
++                    fixup_data = fixup_data + sizeof (grub_uint16_t);
++                  }
++                break;
++              case GRUB_PE32_REL_BASED_HIGHLOW:
++                fixup_32 = (grub_uint32_t *)fixup;
++                *fixup_32 = *fixup_32 + (grub_uint32_t)adjust;
++                if (fixup_data != NULL)
++                  {
++                    fixup_data = (char *)ALIGN_UP ((grub_addr_t)fixup_data, sizeof (grub_uint32_t));
++                    *(grub_uint32_t *) fixup_data = *fixup_32;
++                    fixup_data += sizeof (grub_uint32_t);
++                  }
++                break;
++              case GRUB_PE32_REL_BASED_DIR64:
++                fixup_64 = (grub_uint64_t *)fixup;
++                *fixup_64 = *fixup_64 + (grub_uint64_t)adjust;
++                if (fixup_data != NULL)
++                  {
++                    fixup_data = (char *)ALIGN_UP ((grub_addr_t)fixup_data, sizeof (grub_uint64_t));
++                    *(grub_uint64_t *) fixup_data = *fixup_64;
++                    fixup_data += sizeof (grub_uint64_t);
++                  }
++                break;
++              /* TODO: GRUB_PE32_REL_BASED_RISCV_HI20, GRUB_PE32_REL_BASED_RISCV_LOW12I/S */	
++              default:
++                grub_error (GRUB_ERR_BAD_ARGUMENT,
++			    "Reloc %d unknown relocation type %d",
++			    n, (*entry) >> 12);
++                return GRUB_EFI_UNSUPPORTED;
++            }
++          entry += 1;
++        }
++      reloc_base = (struct grub_pe32_data_directory *)reloc_end;
++      n++;
++    }
++
++  return GRUB_EFI_SUCCESS;
++}
++
++static grub_efi_device_path_t *
++grub_efi_get_media_file_path (grub_efi_device_path_t *dp)
++{
++  while (1)
++    {
++      grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
++      grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
++
++      if (type == GRUB_EFI_END_DEVICE_PATH_TYPE)
++        break;
++      else if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
++            && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
++      return dp;
++
++      dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
++    }
++
++    return NULL;
++}
++
++static grub_efi_boolean_t
++handle_image (void *data, grub_efi_uint32_t datasize)
++{
++  grub_efi_boot_services_t *b;
++  grub_efi_loaded_image_t *li, li_bak;
++  int efi_status;
++  char *buffer = NULL;
++  char *buffer_aligned = NULL;
++  grub_efi_uint32_t i;
++  struct grub_pe32_section_table *section;
++  char *base, *end;
++  pe_coff_loader_image_context_t context;
++  grub_uint32_t section_alignment;
++  grub_uint32_t buffer_size;
++  int found_entry_point = 0;
++  int rc;
++
++  b = grub_efi_system_table->boot_services;
++
++  rc = read_header (data, datasize, &context);
++  if (rc < 0)
++    {
++      grub_dprintf ("chain", "Failed to read header\n");
++      goto error_exit;
++    }
++  else if (rc == 0)
++    {
++      grub_dprintf ("chain", "Secure Boot is not enabled\n");
++      return 0;
++    }
++  else
++    {
++      grub_dprintf ("chain", "Header read without error\n");
++    }
++
++  /*
++   * The spec says, uselessly, of SectionAlignment:
++   * =====
++   * The alignment (in bytes) of sections when they are loaded into
++   * memory. It must be greater than or equal to FileAlignment. The
++   * default is the page size for the architecture.
++   * =====
++   * Which doesn't tell you whose responsibility it is to enforce the
++   * "default", or when.  It implies that the value in the field must
++   * be > FileAlignment (also poorly defined), but it appears visual
++   * studio will happily write 512 for FileAlignment (its default) and
++   * 0 for SectionAlignment, intending to imply PAGE_SIZE.
++   *
++   * We only support one page size, so if it's zero, nerf it to 4096.
++   */
++  section_alignment = context.section_alignment;
++  if (section_alignment == 0)
++    section_alignment = 4096;
++
++  buffer_size = context.image_size + section_alignment;
++  grub_dprintf ("chain", "image size is %08" PRIuGRUB_UINT64_T ", datasize is %08x\n",
++	       context.image_size, datasize);
++
++  efi_status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA,
++			   buffer_size, (void**)&buffer);
++
++  if (efi_status != GRUB_EFI_SUCCESS)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++      goto error_exit;
++    }
++
++  buffer_aligned = (char *)ALIGN_UP ((grub_addr_t)buffer, section_alignment);
++  if (!buffer_aligned)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++      goto error_exit;
++    }
++
++  grub_memcpy (buffer_aligned, data, context.size_of_headers);
++
++  entry_point = image_address (buffer_aligned, context.image_size,
++			       context.entry_point);
++
++  grub_dprintf ("chain", "entry_point: %p\n", entry_point);
++  if (!entry_point)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid entry point");
++      goto error_exit;
++    }
++
++  char *reloc_base, *reloc_base_end;
++  grub_dprintf ("chain", "reloc_dir: %p reloc_size: 0x%08x\n",
++		(void *) ((grub_addr_t)context.reloc_dir->rva),
++		context.reloc_dir->size);
++  reloc_base = image_address (buffer_aligned, context.image_size,
++			      context.reloc_dir->rva);
++  /* RelocBaseEnd here is the address of the last byte of the table */
++  reloc_base_end = image_address (buffer_aligned, context.image_size,
++				  context.reloc_dir->rva
++				  + context.reloc_dir->size - 1);
++  grub_dprintf ("chain", "reloc_base: %p reloc_base_end: %p\n",
++		reloc_base, reloc_base_end);
++
++  struct grub_pe32_section_table *reloc_section = NULL, fake_reloc_section;
++
++  section = context.first_section;
++  for (i = 0; i < context.number_of_sections; i++, section++)
++    {
++      char name[9];
++
++      base = image_address (buffer_aligned, context.image_size,
++			    section->virtual_address);
++      end = image_address (buffer_aligned, context.image_size,
++			   section->virtual_address + section->virtual_size -1);
++
++      grub_strncpy(name, section->name, 9);
++      name[8] = '\0';
++      grub_dprintf ("chain", "Section %d \"%s\" at %p..%p\n", i,
++		   name, base, end);
++
++      if (end < base)
++	{
++	  grub_dprintf ("chain", " base is %p but end is %p... bad.\n",
++		       base, end);
++	  grub_error (GRUB_ERR_BAD_ARGUMENT,
++		      "Image has invalid negative size");
++	  goto error_exit;
++	}
++
++      if (section->virtual_address <= context.entry_point &&
++	  (section->virtual_address + section->raw_data_size - 1)
++	  > context.entry_point)
++	{
++	  found_entry_point++;
++	  grub_dprintf ("chain", " section contains entry point\n");
++	}
++
++      /* We do want to process .reloc, but it's often marked
++       * discardable, so we don't want to memcpy it. */
++      if (grub_memcmp (section->name, ".reloc\0\0", 8) == 0)
++	{
++	  if (reloc_section)
++	    {
++	      grub_error (GRUB_ERR_BAD_ARGUMENT,
++			  "Image has multiple relocation sections");
++	      goto error_exit;
++	    }
++
++	  /* If it has nonzero sizes, and our bounds check
++	   * made sense, and the VA and size match RelocDir's
++	   * versions, then we believe in this section table. */
++	  if (section->raw_data_size && section->virtual_size &&
++	      base && end && reloc_base == base)
++	    {
++	      if (reloc_base_end == end)
++		{
++		  grub_dprintf ("chain", " section is relocation section\n");
++		  reloc_section = section;
++		}
++	      else if (reloc_base_end && reloc_base_end < end)
++	        {
++		  /* Bogus virtual size in the reloc section -- RelocDir
++		   * reported a smaller Base Relocation Directory. Decrease
++		   * the section's virtual size so that it equal RelocDir's
++		   * idea, but only for the purposes of relocate_coff(). */
++		  grub_dprintf ("chain",
++				" section is (overlong) relocation section\n");
++		  grub_memcpy (&fake_reloc_section, section, sizeof *section);
++		  fake_reloc_section.virtual_size -= (end - reloc_base_end);
++		  reloc_section = &fake_reloc_section;
++		}
++	    }
++
++	  if (!reloc_section)
++	    {
++	      grub_dprintf ("chain", " section is not reloc section?\n");
++	      grub_dprintf ("chain", " rds: 0x%08x, vs: %08x\n",
++			    section->raw_data_size, section->virtual_size);
++	      grub_dprintf ("chain", " base: %p end: %p\n", base, end);
++	      grub_dprintf ("chain", " reloc_base: %p reloc_base_end: %p\n",
++			    reloc_base, reloc_base_end);
++	    }
++	}
++
++      grub_dprintf ("chain", " Section characteristics are %08x\n",
++		   section->characteristics);
++      grub_dprintf ("chain", " Section virtual size: %08x\n",
++		   section->virtual_size);
++      grub_dprintf ("chain", " Section raw_data size: %08x\n",
++		   section->raw_data_size);
++      if (section->characteristics & GRUB_PE32_SCN_MEM_DISCARDABLE)
++	{
++	  grub_dprintf ("chain", " Discarding section\n");
++	  continue;
++	}
++
++      if (!base || !end)
++        {
++	  grub_dprintf ("chain", " section is invalid\n");
++          grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid section size");
++          goto error_exit;
++        }
++
++      if (section->characteristics & GRUB_PE32_SCN_CNT_UNINITIALIZED_DATA)
++	{
++	  if (section->raw_data_size != 0)
++	    grub_dprintf ("chain", " UNINITIALIZED_DATA section has data?\n");
++	}
++      else if (section->virtual_address < context.size_of_headers ||
++	       section->raw_data_offset < context.size_of_headers)
++	{
++	  grub_error (GRUB_ERR_BAD_ARGUMENT,
++		      "Section %d is inside image headers", i);
++	  goto error_exit;
++	}
++
++      if (section->raw_data_size > 0)
++	{
++	  grub_dprintf ("chain", " copying 0x%08x bytes to %p\n",
++			section->raw_data_size, base);
++	  grub_memcpy (base,
++		       (grub_efi_uint8_t*)data + section->raw_data_offset,
++		       section->raw_data_size);
++	}
++
++      if (section->raw_data_size < section->virtual_size)
++	{
++	  grub_dprintf ("chain", " padding with 0x%08x bytes at %p\n",
++			section->virtual_size - section->raw_data_size,
++			base + section->raw_data_size);
++	  grub_memset (base + section->raw_data_size, 0,
++		       section->virtual_size - section->raw_data_size);
++	}
++
++      grub_dprintf ("chain", " finished section %s\n", name);
++    }
++
++  /* 5 == EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC */
++  if (context.number_of_rva_and_sizes <= 5)
++    {
++      grub_dprintf ("chain", "image has no relocation entry\n");
++      goto error_exit;
++    }
++
++  if (context.reloc_dir->size && reloc_section)
++    {
++      /* run the relocation fixups */
++      efi_status = relocate_coff (&context, reloc_section, data,
++				  buffer_aligned);
++
++      if (efi_status != GRUB_EFI_SUCCESS)
++	{
++	  grub_error (GRUB_ERR_BAD_ARGUMENT, "relocation failed");
++	  goto error_exit;
++	}
++    }
++
++  if (!found_entry_point)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "entry point is not within sections");
++      goto error_exit;
++    }
++  if (found_entry_point > 1)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "%d sections contain entry point",
++		  found_entry_point);
++      goto error_exit;
++    }
++
++  li = grub_efi_get_loaded_image (grub_efi_image_handle);
++  if (!li)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, "no loaded image available");
++      goto error_exit;
++    }
++
++  grub_memcpy (&li_bak, li, sizeof (grub_efi_loaded_image_t));
++  li->image_base = buffer_aligned;
++  li->image_size = context.image_size;
++  li->load_options = cmdline;
++  li->load_options_size = cmdline_len;
++  li->file_path = grub_efi_get_media_file_path (file_path);
++  li->device_handle = dev_handle;
++  if (!li->file_path)
++    {
++      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found");
++      goto error_exit;
++    }
++
++  grub_dprintf ("chain", "booting via entry point\n");
++  efi_status = efi_call_2 (entry_point, grub_efi_image_handle,
++			   grub_efi_system_table);
++
++  grub_dprintf ("chain", "entry_point returned %d\n", efi_status);
++  grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t));
++  efi_status = efi_call_1 (b->free_pool, buffer);
++
++  return 1;
++
++error_exit:
++  grub_dprintf ("chain", "error_exit: grub_errno: %d\n", grub_errno);
++  if (buffer)
++      efi_call_1 (b->free_pool, buffer);
++
++  return 0;
++}
++
++static grub_err_t
++grub_secureboot_chainloader_unload (void)
++{
++  grub_efi_boot_services_t *b;
++
++  b = grub_efi_system_table->boot_services;
++  efi_call_2 (b->free_pages, address, pages);
++  grub_free (file_path);
++  grub_free (cmdline);
++  cmdline = 0;
++  file_path = 0;
++  dev_handle = 0;
++
++  grub_dl_unref (my_mod);
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_load_and_start_image(void *boot_image)
++{
++  grub_efi_boot_services_t *b;
++  grub_efi_status_t status;
++  grub_efi_loaded_image_t *loaded_image;
++
++  b = grub_efi_system_table->boot_services;
++
++  status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
++		       boot_image, fsize, &image_handle);
++  if (status != GRUB_EFI_SUCCESS)
++    {
++      if (status == GRUB_EFI_OUT_OF_RESOURCES)
++	grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
++      else
++	grub_error (GRUB_ERR_BAD_OS, "cannot load image");
++      return -1;
++    }
++
++  /* LoadImage does not set a device handler when the image is
++     loaded from memory, so it is necessary to set it explicitly here.
++     This is a mess.  */
++  loaded_image = grub_efi_get_loaded_image (image_handle);
++  if (! loaded_image)
++    {
++      grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
++      return -1;
++    }
++  loaded_image->device_handle = dev_handle;
++
++  if (cmdline)
++    {
++      loaded_image->load_options = cmdline;
++      loaded_image->load_options_size = cmdline_len;
++    }
++
++  return 0;
++}
++
++static grub_err_t
++grub_secureboot_chainloader_boot (void)
++{
++  int rc;
++  rc = handle_image ((void *)((grub_addr_t) address), fsize);
++  if (rc == 0)
++    {
++      grub_load_and_start_image((void *)((grub_addr_t) address));
++    }
++
++  grub_loader_unset ();
++  return grub_errno;
++}
++
+ static grub_err_t
+ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ 		      int argc, char *argv[])
+ {
+   grub_file_t file = 0;
+-  grub_ssize_t size;
+   grub_efi_status_t status;
+   grub_efi_boot_services_t *b;
+   grub_device_t dev = 0;
+   grub_efi_device_path_t *dp = 0;
+-  grub_efi_loaded_image_t *loaded_image;
+   char *filename;
+   void *boot_image = 0;
+-  grub_efi_handle_t dev_handle = 0;
++  int rc;
+ 
+   if (argc == 0)
+     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+@@ -238,15 +920,45 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   address = 0;
+   image_handle = 0;
+   file_path = 0;
++  dev_handle = 0;
+ 
+   b = grub_efi_system_table->boot_services;
+ 
++  if (argc > 1)
++    {
++      int i;
++      grub_efi_char16_t *p16;
++
++      for (i = 1, cmdline_len = 0; i < argc; i++)
++        cmdline_len += grub_strlen (argv[i]) + 1;
++
++      cmdline_len *= sizeof (grub_efi_char16_t);
++      cmdline = p16 = grub_malloc (cmdline_len);
++      if (! cmdline)
++        goto fail;
++
++      for (i = 1; i < argc; i++)
++        {
++          char *p8;
++
++          p8 = argv[i];
++          while (*p8)
++            *(p16++) = *(p8++);
++
++          *(p16++) = ' ';
++        }
++      *(--p16) = 0;
++    }
++
+   file = grub_file_open (filename, GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE);
+   if (! file)
+     goto fail;
+ 
+-  /* Get the root device's device path.  */
+-  dev = grub_device_open (0);
++  /* Get the device path from filename. */
++  char *devname = grub_file_get_device_name (filename);
++  dev = grub_device_open (devname);
++  if (devname)
++    grub_free (devname);
+   if (! dev)
+     goto fail;
+ 
+@@ -283,17 +995,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   if (! file_path)
+     goto fail;
+ 
+-  grub_printf ("file path: ");
+-  grub_efi_print_device_path (file_path);
+-
+-  size = grub_file_size (file);
+-  if (!size)
++  fsize = grub_file_size (file);
++  if (!fsize)
+     {
+       grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+ 		  filename);
+       goto fail;
+     }
+-  pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12);
++  pages = (((grub_efi_uintn_t) fsize + ((1 << 12) - 1)) >> 12);
+ 
+   status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES,
+ 			      GRUB_EFI_LOADER_CODE,
+@@ -307,7 +1016,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+     }
+ 
+   boot_image = (void *) ((grub_addr_t) address);
+-  if (grub_file_read (file, boot_image, size) != size)
++  if (grub_file_read (file, boot_image, fsize) != fsize)
+     {
+       if (grub_errno == GRUB_ERR_NONE)
+ 	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+@@ -317,7 +1026,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+     }
+ 
+ #if defined (__i386__) || defined (__x86_64__)
+-  if (size >= (grub_ssize_t) sizeof (struct grub_macho_fat_header))
++  if (fsize >= (grub_ssize_t) sizeof (struct grub_macho_fat_header))
+     {
+       struct grub_macho_fat_header *head = boot_image;
+       if (head->magic
+@@ -326,6 +1035,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ 	  grub_uint32_t i;
+ 	  struct grub_macho_fat_arch *archs
+ 	    = (struct grub_macho_fat_arch *) (head + 1);
++
++	  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++	    {
++	      grub_error (GRUB_ERR_BAD_OS,
++			  "MACHO binaries are forbidden with Secure Boot");
++	      goto fail;
++	    }
++
+ 	  for (i = 0; i < grub_cpu_to_le32 (head->nfat_arch); i++)
+ 	    {
+ 	      if (GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT (archs[i].cputype))
+@@ -340,79 +1057,40 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ 	      > ~grub_cpu_to_le32 (archs[i].size)
+ 	      || grub_cpu_to_le32 (archs[i].offset)
+ 	      + grub_cpu_to_le32 (archs[i].size)
+-	      > (grub_size_t) size)
++	      > (grub_size_t) fsize)
+ 	    {
+ 	      grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+ 			  filename);
+ 	      goto fail;
+ 	    }
+ 	  boot_image = (char *) boot_image + grub_cpu_to_le32 (archs[i].offset);
+-	  size = grub_cpu_to_le32 (archs[i].size);
++	  fsize = grub_cpu_to_le32 (archs[i].size);
+ 	}
+     }
+ #endif
+ 
+-  status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
+-		       boot_image, size,
+-		       &image_handle);
+-  if (status != GRUB_EFI_SUCCESS)
++  rc = grub_linuxefi_secure_validate((void *)((grub_addr_t) address), fsize);
++  grub_dprintf ("chain", "linuxefi_secure_validate: %d\n", rc);
++  if (rc > 0)
+     {
+-      if (status == GRUB_EFI_OUT_OF_RESOURCES)
+-	grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
+-      else
+-	grub_error (GRUB_ERR_BAD_OS, "cannot load image");
+-
+-      goto fail;
+-    }
+-
+-  /* LoadImage does not set a device handler when the image is
+-     loaded from memory, so it is necessary to set it explicitly here.
+-     This is a mess.  */
+-  loaded_image = grub_efi_get_loaded_image (image_handle);
+-  if (! loaded_image)
+-    {
+-      grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
+-      goto fail;
++      grub_file_close (file);
++      grub_loader_set (grub_secureboot_chainloader_boot,
++		       grub_secureboot_chainloader_unload, 0);
++      return 0;
+     }
+-  loaded_image->device_handle = dev_handle;
+-
+-  if (argc > 1)
++  else if (rc == 0)
+     {
+-      int i, len;
+-      grub_efi_char16_t *p16;
+-
+-      for (i = 1, len = 0; i < argc; i++)
+-        len += grub_strlen (argv[i]) + 1;
+-
+-      len *= sizeof (grub_efi_char16_t);
+-      cmdline = p16 = grub_malloc (len);
+-      if (! cmdline)
+-        goto fail;
+-
+-      for (i = 1; i < argc; i++)
+-        {
+-          char *p8;
+-
+-          p8 = argv[i];
+-          while (*p8)
+-            *(p16++) = *(p8++);
+-
+-          *(p16++) = ' ';
+-        }
+-      *(--p16) = 0;
++      grub_load_and_start_image(boot_image);
++      grub_file_close (file);
++      grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
+ 
+-      loaded_image->load_options = cmdline;
+-      loaded_image->load_options_size = len;
++      return 0;
+     }
+ 
+   grub_file_close (file);
+   grub_device_close (dev);
+ 
+-  grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
+-  return 0;
+-
+- fail:
+-
++fail:
+   if (dev)
+     grub_device_close (dev);
+ 
+@@ -424,6 +1102,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+   if (address)
+     efi_call_2 (b->free_pages, address, pages);
+ 
++  if (cmdline)
++    grub_free (cmdline);
++
+   grub_dl_unref (my_mod);
+ 
+   return grub_errno;
+diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c
+index 771d455..971e84d 100644
+--- a/grub-core/loader/efi/fdt.c
++++ b/grub-core/loader/efi/fdt.c
+@@ -26,6 +26,7 @@
+ #include <grub/efi/fdtload.h>
+ #include <grub/efi/memory.h>
+ #include <grub/cpu/efi/memory.h>
++#include <grub/efi/sb.h>
+ 
+ static void *loaded_fdt;
+ static void *fdt;
+diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
+index 3292cab..d81e7be 100644
+--- a/grub-core/loader/efi/linux.c
++++ b/grub-core/loader/efi/linux.c
+@@ -27,6 +27,7 @@
+ #include <grub/types.h>
+ #include <grub/cpu/linux.h>
+ #include <grub/efi/efi.h>
++#include <grub/efi/linux.h>
+ #include <grub/efi/fdtload.h>
+ #include <grub/efi/memory.h>
+ #include <grub/efi/pe32.h>
+@@ -54,6 +55,13 @@ static int initrd_use_loadfile2;
+ static grub_efi_guid_t load_file2_guid = GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID;
+ static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID;
+ 
++struct grub_arm64_linux_pe_header
++{
++  grub_uint32_t magic;
++  struct grub_pe32_coff_header coff;
++  struct grub_pe64_optional_header opt;
++};
++
+ grub_err_t
+ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
+ {
+@@ -404,6 +412,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_file_t file = 0;
+   struct linux_arch_kernel_header lh;
+   grub_err_t err;
++  int rc;
+ 
+   grub_dl_ref (my_mod);
+ 
+@@ -448,6 +457,13 @@ 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)
++    {
++      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);
+   linux_args = grub_malloc (cmdline_size);
+   if (!linux_args)
+diff --git a/grub-core/loader/efi/linux_sb.c b/grub-core/loader/efi/linux_sb.c
+new file mode 100644
+index 0000000..e372b26
+--- /dev/null
++++ b/grub-core/loader/efi/linux_sb.c
+@@ -0,0 +1,86 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2014 Free Software Foundation, Inc.
++ *
++ *  GRUB is free software: you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation, either version 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <grub/err.h>
++#include <grub/mm.h>
++#include <grub/types.h>
++#include <grub/cpu/linux.h>
++#include <grub/efi/efi.h>
++#include <grub/efi/pe32.h>
++#include <grub/efi/linux.h>
++#include <grub/efi/sb.h>
++
++#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;
++
++int
++grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
++{
++  grub_efi_guid_t guid = SHIM_LOCK_GUID;
++  grub_efi_shim_lock_t *shim_lock;
++  int status;
++
++  grub_dprintf ("linuxefi", "Locating shim protocol\n");
++  shim_lock = grub_efi_locate_protocol(&guid, NULL);
++  grub_dprintf ("secureboot", "shim_lock: %p\n", shim_lock);
++  if (!shim_lock)
++    {
++      grub_dprintf ("secureboot", "shim not available\n");
++      return 0;
++    }
++
++  grub_dprintf ("secureboot", "Asking shim to verify kernel signature\n");
++  status = shim_lock->verify (data, size);
++  grub_dprintf ("secureboot", "shim_lock->verify(): %d\n", status);
++  if (status == GRUB_EFI_SUCCESS)
++    {
++      grub_dprintf ("secureboot", "Kernel signature verification passed\n");
++      return 1;
++    }
++
++  grub_dprintf ("secureboot", "Kernel signature verification failed (0x%lx)\n",
++		(unsigned long) status);
++
++  return -1;
++}
++
++typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
++
++grub_err_t
++grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
++		     void *kernel_params)
++{
++  handover_func hf;
++  int offset = 0;
++
++#ifdef __x86_64__
++  /* Offset to startup64 */
++  offset = 512;
++#endif
++
++  hf = (handover_func)((char *)kernel_addr + handover_offset + offset);
++  hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
++
++  return GRUB_ERR_BUG;
++}
+diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c
+index 5f3290c..690e366 100644
+--- a/grub-core/loader/i386/bsd.c
++++ b/grub-core/loader/i386/bsd.c
+@@ -40,6 +40,7 @@
+ #ifdef GRUB_MACHINE_PCBIOS
+ #include <grub/machine/int.h>
+ #endif
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -2137,6 +2138,9 @@ static grub_command_t cmd_netbsd_module_elf, cmd_openbsd_ramdisk;
+ 
+ GRUB_MOD_INIT (bsd)
+ {
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    return;
++
+   /* Net and OpenBSD kernels are often compressed.  */
+   grub_dl_load ("gzio");
+ 
+@@ -2176,6 +2180,9 @@ GRUB_MOD_INIT (bsd)
+ 
+ GRUB_MOD_FINI (bsd)
+ {
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    return;
++
+   grub_unregister_extcmd (cmd_freebsd);
+   grub_unregister_extcmd (cmd_openbsd);
+   grub_unregister_extcmd (cmd_netbsd);
+diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
+new file mode 100644
+index 0000000..382ff52
+--- /dev/null
++++ b/grub-core/loader/i386/efi/linux.c
+@@ -0,0 +1,382 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2012  Free Software Foundation, Inc.
++ *
++ *  GRUB is free software: you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation, either version 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <grub/loader.h>
++#include <grub/file.h>
++#include <grub/err.h>
++#include <grub/types.h>
++#include <grub/mm.h>
++#include <grub/cpu/linux.h>
++#include <grub/command.h>
++#include <grub/i18n.h>
++#include <grub/lib/cmdline.h>
++#include <grub/efi/efi.h>
++#include <grub/efi/linux.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)
++
++static grub_err_t
++grub_linuxefi_boot (void)
++{
++  asm volatile ("cli");
++
++  return grub_efi_linux_boot ((char *)kernel_mem,
++			      handover_offset,
++			      params);
++}
++
++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_file_t *files = 0;
++  int i, nfiles = 0;
++  grub_size_t size = 0;
++  grub_uint8_t *ptr;
++
++  if (argc == 0)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
++      goto fail;
++    }
++
++  if (!loaded)
++    {
++      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
++      goto fail;
++    }
++
++  files = grub_zalloc (argc * sizeof (files[0]));
++  if (!files)
++    goto fail;
++
++  for (i = 0; i < argc; i++)
++    {
++      files[i] = grub_file_open (argv[i], GRUB_FILE_TYPE_LINUX_INITRD | GRUB_FILE_TYPE_NO_DECOMPRESS);
++      if (! files[i])
++        goto fail;
++      nfiles++;
++      size += ALIGN_UP (grub_file_size (files[i]), 4);
++    }
++
++  initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
++
++  if (!initrd_mem)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
++      goto fail;
++    }
++
++  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;
++
++  ptr = initrd_mem;
++
++  for (i = 0; i < nfiles; i++)
++    {
++      grub_ssize_t cursize = grub_file_size (files[i]);
++      if (grub_file_read (files[i], ptr, cursize) != cursize)
++        {
++          if (!grub_errno)
++            grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
++                        argv[i]);
++          goto fail;
++        }
++      ptr += cursize;
++      grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
++      ptr += ALIGN_UP_OVERHEAD (cursize, 4);
++    }
++
++  params->ramdisk_size = size;
++
++ fail:
++  for (i = 0; i < nfiles; i++)
++    grub_file_close (files[i]);
++  grub_free (files);
++
++  if (initrd_mem && grub_errno)
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem,
++			 BYTES_TO_PAGES(size));
++
++  return grub_errno;
++}
++
++#define MIN(a, b) \
++  ({ typeof (a) _a = (a); \
++     typeof (b) _b = (b); \
++     _a < _b ? _a : _b; })
++
++static grub_err_t
++grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
++		int argc, char *argv[])
++{
++  grub_file_t file = 0;
++  struct linux_i386_kernel_header *lh = NULL;
++  grub_ssize_t start, filelen;
++  void *kernel = NULL;
++  int setup_header_end_offset;
++  int rc;
++
++  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;
++    }
++
++  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,
++					BYTES_TO_PAGES(sizeof(*params)));
++  if (! params)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
++      goto fail;
++    }
++
++  grub_dprintf ("linuxefi", "params = %p\n", params);
++
++  grub_memset (params, 0, sizeof(*params));
++
++  setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201);
++  grub_dprintf ("linuxefi", "copying %" PRIuGRUB_SIZE " bytes from %p to %p\n",
++		MIN((grub_size_t)0x202+setup_header_end_offset,
++		    sizeof (*params)) - 0x1f1,
++		(grub_uint8_t *)kernel + 0x1f1,
++		(grub_uint8_t *)params + 0x1f1);
++  grub_memcpy ((grub_uint8_t *)params + 0x1f1,
++	       (grub_uint8_t *)kernel + 0x1f1,
++		MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
++  lh = (struct linux_i386_kernel_header *)params;
++  grub_dprintf ("linuxefi", "lh is at %p\n", lh);
++  grub_dprintf ("linuxefi", "checking lh->boot_flag\n");
++  if (lh->boot_flag != grub_cpu_to_le16 (0xaa55))
++    {
++      grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number"));
++      goto fail;
++    }
++
++  grub_dprintf ("linuxefi", "checking lh->setup_sects\n");
++  if (lh->setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
++    {
++      grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
++      goto fail;
++    }
++
++  grub_dprintf ("linuxefi", "checking lh->version\n");
++  if (lh->version < grub_cpu_to_le16 (0x020b))
++    {
++      grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
++      goto fail;
++    }
++
++  grub_dprintf ("linuxefi", "checking lh->handover_offset\n");
++  if (!lh->handover_offset)
++    {
++      grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
++      goto fail;
++    }
++
++#if defined(__x86_64__) || defined(__aarch64__)
++  grub_dprintf ("linuxefi", "checking lh->xloadflags\n");
++  if (!(lh->xloadflags & LINUX_XLF_KERNEL_64))
++    {
++      grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support 64-bit CPUs"));
++      goto fail;
++    }
++#endif
++
++#if defined(__i386__)
++  if ((lh->xloadflags & LINUX_XLF_KERNEL_64) &&
++      !(lh->xloadflags & LINUX_XLF_EFI_HANDOVER_32))
++    {
++      grub_error (GRUB_ERR_BAD_OS,
++		  N_("kernel doesn't support 32-bit handover"));
++      goto fail;
++    }
++#endif
++
++  grub_dprintf ("linuxefi", "setting up cmdline\n");
++  linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
++					 BYTES_TO_PAGES(lh->cmdline_size + 1));
++  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_create_loader_cmdline (argc, argv,
++                              linux_cmdline + sizeof (LINUX_IMAGE) - 1,
++			      lh->cmdline_size - (sizeof (LINUX_IMAGE) - 1),
++			      GRUB_VERIFY_KERNEL_CMDLINE);
++
++  grub_dprintf ("linuxefi", "setting lh->cmd_line_ptr\n");
++  lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
++
++  grub_dprintf ("linuxefi", "computing handover offset\n");
++  handover_offset = lh->handover_offset;
++
++  start = (lh->setup_sects + 1) * 512;
++
++  kernel_mem = grub_efi_allocate_fixed(lh->pref_address,
++				       BYTES_TO_PAGES(lh->init_size));
++
++  if (!kernel_mem)
++    {
++      grub_error_pop();
++      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);
++
++  grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
++  loaded=1;
++  grub_dprintf ("linuxefi", "setting lh->code32_start to %p\n", kernel_mem);
++  lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
++
++  grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start);
++
++  grub_dprintf ("linuxefi", "setting lh->type_of_loader\n");
++  lh->type_of_loader = 0x6;
++
++  grub_dprintf ("linuxefi", "setting lh->ext_loader_{type,ver}\n");
++  params->ext_loader_type = 0;
++  params->ext_loader_ver = 2;
++  grub_dprintf("linuxefi", "kernel_mem: %p handover_offset: %08x\n",
++	       kernel_mem, handover_offset);
++
++ fail:
++  if (file)
++    grub_file_close (file);
++
++  if (kernel)
++    grub_free (kernel);
++
++  if (grub_errno != GRUB_ERR_NONE)
++    {
++      grub_dl_unref (my_mod);
++      loaded = 0;
++    }
++
++  if (linux_cmdline && lh && !loaded)
++    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
++			 linux_cmdline,
++			 BYTES_TO_PAGES(lh->cmdline_size + 1));
++
++  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,
++			 sizeof(*params));
++
++  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 f30a158..b6c13d7 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -78,6 +78,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;
+@@ -649,16 +651,51 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ {
+   grub_file_t file = 0;
+   struct linux_i386_kernel_header lh;
++  grub_uint8_t *linux_params_ptr;
+   grub_uint8_t setup_sects;
+-  grub_size_t real_size, prot_size, prot_file_size;
++  grub_size_t real_size, prot_size, prot_file_size, kernel_offset;
+   grub_ssize_t len;
+   int i;
+   grub_size_t align, min_align;
+   int relocatable;
+   grub_uint64_t preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
++  grub_uint8_t *kernel = NULL;
+ 
+   grub_dl_ref (my_mod);
+ 
++#ifdef GRUB_MACHINE_EFI
++  using_linuxefi = 0;
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    {
++      /* 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"));
+@@ -669,7 +706,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   if (! file)
+     goto fail;
+ 
+-  if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
++  len = grub_file_size (file);
++  kernel = grub_malloc (len);
++  if (!kernel)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
++      goto fail;
++    }
++
++  if (grub_file_read (file, kernel, len) != len)
+     {
+       if (!grub_errno)
+ 	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+@@ -677,6 +722,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
++  grub_memcpy (&lh, kernel, sizeof (lh));
++  kernel_offset = sizeof (lh);
++
+   if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
+     {
+       grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
+@@ -765,6 +813,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 		      preferred_address))
+     goto fail;
+ 
++
+   grub_memset (&linux_params, 0, sizeof (linux_params));
+ 
+   /*
+@@ -784,14 +833,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   /* We've already read lh so there is no need to read it second time. */
+   len -= sizeof(lh);
+ 
+-  if ((len > 0) &&
+-      (grub_file_read (file, (char *) &linux_params + sizeof (lh), len) != len))
+-    {
+-      if (!grub_errno)
+-	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+-		    argv[0]);
+-      goto fail;
+-    }
++  linux_params_ptr = (void *)&linux_params;
++  grub_memcpy (linux_params_ptr + sizeof (lh), kernel + kernel_offset, len);
++  kernel_offset += len;
+ 
+   linux_params.code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR;
+   linux_params.kernel_alignment = (1 << align);
+@@ -853,7 +897,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+   /* The other parameters are filled when booting.  */
+ 
+-  grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
++  kernel_offset = real_size + GRUB_DISK_SECTOR_SIZE;
+ 
+   grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
+ 		(unsigned) real_size, (unsigned) prot_size);
+@@ -1007,9 +1051,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   }
+ 
+   len = prot_file_size;
+-  if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno)
+-    grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+-		argv[0]);
++  grub_memcpy (prot_mode_mem, kernel + kernel_offset, len);
+ 
+   if (grub_errno == GRUB_ERR_NONE)
+     {
+@@ -1020,6 +1062,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+  fail:
+ 
++  grub_free (kernel);
++
+   if (file)
+     grub_file_close (file);
+ 
+@@ -1042,6 +1086,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/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
+index efeeeb2..69db786 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/safemath.h>
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -124,13 +125,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_file_t file = 0;
+   struct linux_i386_kernel_header lh;
+   grub_uint8_t setup_sects;
+-  grub_size_t real_size;
++  grub_size_t real_size, kernel_offset = 0;
+   grub_ssize_t len;
+   int i;
+   char *grub_linux_prot_chunk;
+   int grub_linux_is_bzimage;
+   grub_addr_t grub_linux_prot_target;
+   grub_err_t err;
++  grub_uint8_t *kernel = NULL;
+ 
+   grub_dl_ref (my_mod);
+ 
+@@ -144,7 +146,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   if (! file)
+     goto fail;
+ 
+-  if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
++  len = grub_file_size (file);
++  kernel = grub_malloc (len);
++  if (!kernel)
++    {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
++      goto fail;
++    }
++
++  if (grub_file_read (file, kernel, len) != len)
+     {
+       if (!grub_errno)
+ 	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+@@ -152,6 +162,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+       goto fail;
+     }
+ 
++  grub_memcpy (&lh, kernel, sizeof (lh));
++  kernel_offset = sizeof (lh);
++
+   if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
+     {
+       grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
+@@ -320,13 +333,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   grub_memmove (grub_linux_real_chunk, &lh, sizeof (lh));
+ 
+   len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh);
+-  if (grub_file_read (file, grub_linux_real_chunk + sizeof (lh), len) != len)
+-    {
+-      if (!grub_errno)
+-	grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+-		    argv[0]);
+-      goto fail;
+-    }
++  grub_memcpy (grub_linux_real_chunk + sizeof (lh), kernel + kernel_offset,
++	       len);
++  kernel_offset += len;
+ 
+   if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
+       || grub_le_to_cpu16 (lh.version) < 0x0200)
+@@ -364,9 +373,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+   }
+ 
+   len = grub_linux16_prot_size;
+-  if (grub_file_read (file, grub_linux_prot_chunk, len) != len && !grub_errno)
+-    grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+-		argv[0]);
++  grub_memcpy (grub_linux_prot_chunk, kernel + kernel_offset, len);
++  kernel_offset += len;
+ 
+   if (grub_errno == GRUB_ERR_NONE)
+     {
+@@ -376,6 +384,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ 
+  fail:
+ 
++  grub_free (kernel);
++
+   if (file)
+     grub_file_close (file);
+ 
+@@ -478,6 +488,9 @@ static grub_command_t cmd_linux, cmd_initrd;
+ 
+ GRUB_MOD_INIT(linux16)
+ {
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    return;
++
+   cmd_linux =
+     grub_register_command ("linux16", grub_cmd_linux,
+ 			   0, N_("Load Linux."));
+@@ -489,6 +502,9 @@ GRUB_MOD_INIT(linux16)
+ 
+ GRUB_MOD_FINI(linux16)
+ {
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    return;
++
+   grub_unregister_command (cmd_linux);
+   grub_unregister_command (cmd_initrd);
+ }
+diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
+index facb13f..3dc0a62 100644
+--- a/grub-core/loader/multiboot.c
++++ b/grub-core/loader/multiboot.c
+@@ -50,6 +50,7 @@
+ #include <grub/video.h>
+ #include <grub/memory.h>
+ #include <grub/i18n.h>
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -444,6 +445,9 @@ static grub_command_t cmd_multiboot, cmd_module;
+ 
+ GRUB_MOD_INIT(multiboot)
+ {
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    return;
++
+   cmd_multiboot =
+ #ifdef GRUB_USE_MULTIBOOT2
+     grub_register_command ("multiboot2", grub_cmd_multiboot,
+@@ -464,6 +468,9 @@ GRUB_MOD_INIT(multiboot)
+ 
+ GRUB_MOD_FINI(multiboot)
+ {
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    return;
++
+   grub_unregister_command (cmd_multiboot);
+   grub_unregister_command (cmd_module);
+ }
+diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
+index 1c0cf6a..c5ba84c 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/safemath.h>
++#include <grub/efi/sb.h>
+ 
+ GRUB_MOD_LICENSE ("GPLv3+");
+ 
+@@ -1497,6 +1498,9 @@ static grub_extcmd_t cmd_splash;
+ 
+ GRUB_MOD_INIT(xnu)
+ {
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    return;
++
+   cmd_kernel = grub_register_command ("xnu_kernel", grub_cmd_xnu_kernel, 0,
+ 				      N_("Load XNU image."));
+   cmd_kernel64 = grub_register_command ("xnu_kernel64", grub_cmd_xnu_kernel64,
+@@ -1540,6 +1544,9 @@ GRUB_MOD_INIT(xnu)
+ 
+ GRUB_MOD_FINI(xnu)
+ {
++  if (grub_efi_get_secureboot() == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
++    return;
++
+ #ifndef GRUB_MACHINE_EMU
+   grub_unregister_command (cmd_resume);
+ #endif
+diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h
+index effd870..9efd37a 100644
+--- a/include/grub/arm64/linux.h
++++ b/include/grub/arm64/linux.h
+@@ -22,6 +22,8 @@
+ #include <grub/types.h>
+ 
+ #define GRUB_LINUX_ARM64_MAGIC_SIGNATURE 0x644d5241 /* 'ARM\x64' */
++#define GRUB_ARM64_LINUX_MAGIC 0x644d5241 /* 'ARM\x64' */
++#define GRUB_EFI_PE_MAGIC	0x5A4D
+ 
+ /* From linux/Documentation/arm64/booting.txt */
+ struct linux_arm64_kernel_header
+diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
+index 83d958f..08f6ee0 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/include/grub/efi/linux.h b/include/grub/efi/linux.h
+new file mode 100644
+index 0000000..0033d93
+--- /dev/null
++++ b/include/grub/efi/linux.h
+@@ -0,0 +1,31 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2014  Free Software Foundation, Inc.
++ *
++ *  GRUB is free software: you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation, either version 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  GRUB is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef GRUB_EFI_LINUX_HEADER
++#define GRUB_EFI_LINUX_HEADER	1
++
++#include <grub/efi/api.h>
++#include <grub/err.h>
++#include <grub/symbol.h>
++
++int
++EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size);
++grub_err_t
++EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
++				  void *kernel_param);
++
++#endif /* ! GRUB_EFI_LINUX_HEADER */
+diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
+index 0ed8781..a43adf2 100644
+--- a/include/grub/efi/pe32.h
++++ b/include/grub/efi/pe32.h
+@@ -223,7 +223,11 @@ struct grub_pe64_optional_header
+ struct grub_pe32_section_table
+ {
+   char name[8];
+-  grub_uint32_t virtual_size;
++  union
++    {
++      grub_uint32_t physical_address;
++      grub_uint32_t virtual_size;
++    };
+   grub_uint32_t virtual_address;
+   grub_uint32_t raw_data_size;
+   grub_uint32_t raw_data_offset;
+@@ -234,12 +238,18 @@ struct grub_pe32_section_table
+   grub_uint32_t characteristics;
+ };
+ 
++#define GRUB_PE32_SCN_TYPE_NO_PAD		0x00000008
+ #define GRUB_PE32_SCN_CNT_CODE			0x00000020
+ #define GRUB_PE32_SCN_CNT_INITIALIZED_DATA	0x00000040
+-#define GRUB_PE32_SCN_MEM_DISCARDABLE		0x02000000
+-#define GRUB_PE32_SCN_MEM_EXECUTE		0x20000000
+-#define GRUB_PE32_SCN_MEM_READ			0x40000000
+-#define GRUB_PE32_SCN_MEM_WRITE			0x80000000
++#define GRUB_PE32_SCN_CNT_UNINITIALIZED_DATA	0x00000080
++#define GRUB_PE32_SCN_LNK_OTHER			0x00000100
++#define GRUB_PE32_SCN_LNK_INFO			0x00000200
++#define GRUB_PE32_SCN_LNK_REMOVE		0x00000800
++#define GRUB_PE32_SCN_LNK_COMDAT		0x00001000
++#define GRUB_PE32_SCN_GPREL			0x00008000
++#define GRUB_PE32_SCN_MEM_16BIT			0x00020000
++#define GRUB_PE32_SCN_MEM_LOCKED		0x00040000
++#define GRUB_PE32_SCN_MEM_PRELOAD		0x00080000
+ 
+ #define GRUB_PE32_SCN_ALIGN_1BYTES		0x00100000
+ #define GRUB_PE32_SCN_ALIGN_2BYTES		0x00200000
+@@ -248,10 +258,28 @@ struct grub_pe32_section_table
+ #define GRUB_PE32_SCN_ALIGN_16BYTES		0x00500000
+ #define GRUB_PE32_SCN_ALIGN_32BYTES		0x00600000
+ #define GRUB_PE32_SCN_ALIGN_64BYTES		0x00700000
++#define GRUB_PE32_SCN_ALIGN_128BYTES		0x00800000
++#define GRUB_PE32_SCN_ALIGN_256BYTES		0x00900000
++#define GRUB_PE32_SCN_ALIGN_512BYTES		0x00A00000
++#define GRUB_PE32_SCN_ALIGN_1024BYTES		0x00B00000
++#define GRUB_PE32_SCN_ALIGN_2048BYTES		0x00C00000
++#define GRUB_PE32_SCN_ALIGN_4096BYTES		0x00D00000
++#define GRUB_PE32_SCN_ALIGN_8192BYTES		0x00E00000
+ 
+ #define GRUB_PE32_SCN_ALIGN_SHIFT		20
+ #define GRUB_PE32_SCN_ALIGN_MASK		7
+ 
++#define GRUB_PE32_SCN_LNK_NRELOC_OVFL		0x01000000
++#define GRUB_PE32_SCN_MEM_DISCARDABLE		0x02000000
++#define GRUB_PE32_SCN_MEM_NOT_CACHED		0x04000000
++#define GRUB_PE32_SCN_MEM_NOT_PAGED		0x08000000
++#define GRUB_PE32_SCN_MEM_SHARED		0x10000000
++#define GRUB_PE32_SCN_MEM_EXECUTE		0x20000000
++#define GRUB_PE32_SCN_MEM_READ			0x40000000
++#define GRUB_PE32_SCN_MEM_WRITE			0x80000000
++
++
++
+ #define GRUB_PE32_SIGNATURE_SIZE 4
+ 
+ struct grub_pe32_header
+@@ -274,6 +302,20 @@ struct grub_pe32_header
+ #endif
+ };
+ 
++struct grub_pe32_header_32
++{
++  char signature[GRUB_PE32_SIGNATURE_SIZE];
++  struct grub_pe32_coff_header coff_header;
++  struct grub_pe32_optional_header optional_header;
++};
++
++struct grub_pe32_header_64
++{
++  char signature[GRUB_PE32_SIGNATURE_SIZE];
++  struct grub_pe32_coff_header coff_header;
++  struct grub_pe64_optional_header optional_header;
++};
++
+ struct grub_pe32_fixup_block
+ {
+   grub_uint32_t page_rva;
+diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
+index eddf925..25ef52c 100644
+--- a/include/grub/i386/linux.h
++++ b/include/grub/i386/linux.h
+@@ -138,7 +138,12 @@ struct linux_i386_kernel_header
+   grub_uint32_t kernel_alignment;
+   grub_uint8_t relocatable;
+   grub_uint8_t min_alignment;
+-  grub_uint8_t pad[2];
++#define LINUX_XLF_KERNEL_64                   (1<<0)
++#define LINUX_XLF_CAN_BE_LOADED_ABOVE_4G      (1<<1)
++#define LINUX_XLF_EFI_HANDOVER_32             (1<<2)
++#define LINUX_XLF_EFI_HANDOVER_64             (1<<3)
++#define LINUX_XLF_EFI_KEXEC                   (1<<4)
++  grub_uint16_t xloadflags;
+   grub_uint32_t cmdline_size;
+   grub_uint32_t hardware_subarch;
+   grub_uint64_t hardware_subarch_data;
+diff --git a/include/grub/ia64/linux.h b/include/grub/ia64/linux.h
+new file mode 100644
+index 0000000..e69de29
+diff --git a/include/grub/mips/linux.h b/include/grub/mips/linux.h
+new file mode 100644
+index 0000000..e69de29
+diff --git a/include/grub/powerpc/linux.h b/include/grub/powerpc/linux.h
+new file mode 100644
+index 0000000..e69de29
+diff --git a/include/grub/sparc64/linux.h b/include/grub/sparc64/linux.h
+new file mode 100644
+index 0000000..e69de29
diff -pruN 2.06-2/debian/patches/ubuntu-mkconfig-leave-breadcrumbs.patch 2.06-2ubuntu16/debian/patches/ubuntu-mkconfig-leave-breadcrumbs.patch
--- 2.06-2/debian/patches/ubuntu-mkconfig-leave-breadcrumbs.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-mkconfig-leave-breadcrumbs.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,28 @@
+From: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
+Date: Fri, 14 Dec 2018 13:46:14 -0500
+Subject: UBUNTU: grub-mkconfig: leave a trace of what files were sourced to
+ generate the config
+
+Patch-Name: ubuntu-mkconfig-leave-breadcrumbs.patch
+Signed-off-by: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
+---
+ util/grub-mkconfig.in | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index 4cf8d19..58002c0 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -158,10 +158,12 @@ if [ "x${GRUB_EARLY_INITRD_LINUX_STOCK}" = "x" ]; then
+ fi
+ 
+ if test -f ${sysconfdir}/default/grub ; then
++  gettext_printf "Sourcing file \`%s'\n" "${sysconfdir}/default/grub" 1>&2
+   . ${sysconfdir}/default/grub
+ fi
+ for x in ${sysconfdir}/default/grub.d/*.cfg ; do
+   if [ -e "${x}" ]; then
++    gettext_printf "Sourcing file \`%s'\n" "${x}" 1>&2
+     . "${x}"
+   fi
+ done
diff -pruN 2.06-2/debian/patches/ubuntu-os-prober-auto.patch 2.06-2ubuntu16/debian/patches/ubuntu-os-prober-auto.patch
--- 2.06-2/debian/patches/ubuntu-os-prober-auto.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.06-2ubuntu16/debian/patches/ubuntu-os-prober-auto.patch	2022-12-09 16:11:44.000000000 +0000
@@ -0,0 +1,51 @@
+From: Julian Andres Klode <julian.klode@canonical.com>
+Date: Wed, 16 Feb 2022 17:19:45 +0100
+Subject: UBUNTU: os-prober: Enable on first run or if last run produced
+ results
+
+To not break existing use cases, if we install alongside another OS
+let's keep running os-prober. For this, introduce an auto mode that
+determines whether we are (a) a new install or (b) have previously
+added any os-prober items.
+
+This patch is not optimal, and it might be nicer to handle this in
+installers and the release upgrader, but that involves touching a
+lot more packages and means we'd also have that policy in multiple
+places, which is detrimental if we want to change it again.
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1955109
+---
+ util/grub-mkconfig.in       | 2 +-
+ util/grub.d/30_os-prober.in | 6 ++++++
+ 2 files changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
+index a8c247a..21d28f1 100644
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -141,7 +141,7 @@ GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`"
+ GRUB_DEVICE_BOOT_UUID="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_uuid 2> /dev/null`" || true
+ 
+ # Disable os-prober by default due to security reasons.
+-GRUB_DISABLE_OS_PROBER="true"
++GRUB_DISABLE_OS_PROBER="auto"
+ 
+ # Filesystem for the device containing our userland.  Used for stuff like
+ # choosing Hurd filesystem module.
+diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
+index 225a3ba..5eb44d1 100644
+--- a/util/grub.d/30_os-prober.in
++++ b/util/grub.d/30_os-prober.in
+@@ -43,6 +43,12 @@ EOF
+ if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
+   grub_warn "$(gettext_printf "os-prober will not be executed to detect other bootable partitions.\nSystems on them will not be added to the GRUB boot configuration.\nCheck GRUB_DISABLE_OS_PROBER documentation entry.")"
+   exit 0
++elif [ "x${GRUB_DISABLE_OS_PROBER}" = "xauto" ]; then
++  # UBUNTU: We do not want to disable os-prober on upgrades if we found items before.
++  if test -e /boot/grub/grub.cfg && ! grep -q osprober /boot/grub/grub.cfg; then
++    grub_warn "$(gettext_printf "os-prober will not be executed to detect other bootable partitions.\nSystems on them will not be added to the G