Bug#930420: stretch-pu: package grub2/2.02~beta3-5+deb9u2
Package: release.debian.org
Severity: normal
Tags: stretch
User: release.debian.org@packages.debian.org
Usertags: pu
I'd like to upload an update to stretch's grub2 which adds support for
booting Xen on UEFI hosts. This consists of four straight cherry-picks
from upstream (somewhat complex, but mostly confined to the multiboot
loader so IMO low-risk for other boot methods) and one cherry-pick of a
an upstream backport that I'd previously done for buster. It was
requested by and has been tested by an upstream Xen developer. The
proposed debdiff is attached.
Thanks,
--
Colin Watson [cjwatson@debian.org]
diff -Nru grub2-2.02~beta3/debian/.git-dpm grub2-2.02~beta3/debian/.git-dpm
--- grub2-2.02~beta3/debian/.git-dpm 2018-10-28 19:18:13.000000000 +0000
+++ grub2-2.02~beta3/debian/.git-dpm 2019-06-12 12:20:28.000000000 +0100
@@ -1,6 +1,6 @@
# see git-dpm(1) from git-dpm package
-f088c5a77750ef243888de09fd8cc979da9244bb
-f088c5a77750ef243888de09fd8cc979da9244bb
+23439d60d742949cee70df3c1b84ac61c9ce2c0d
+23439d60d742949cee70df3c1b84ac61c9ce2c0d
422889f9199d539926099fc5c1ceeeda51ab7f53
422889f9199d539926099fc5c1ceeeda51ab7f53
grub2_2.02~beta3.orig.tar.xz
diff -Nru grub2-2.02~beta3/debian/changelog grub2-2.02~beta3/debian/changelog
--- grub2-2.02~beta3/debian/changelog 2018-10-28 19:18:13.000000000 +0000
+++ grub2-2.02~beta3/debian/changelog 2019-06-12 12:20:51.000000000 +0100
@@ -1,3 +1,16 @@
+grub2 (2.02~beta3-5+deb9u2) stable; urgency=medium
+
+ * Cherry-pick upstream patches for Xen UEFI support (closes: #930028):
+ - i386/relocator: Add grub_relocator64_efi relocator
+ - multiboot2: Add tags used to pass ImageHandle to loaded image
+ - multiboot2: Do not pass memory maps to image if EFI boot services are
+ enabled
+ - multiboot2: Add support for relocatable images
+ - Use grub-file to figure out whether multiboot2 should be used for
+ Xen.gz
+
+ -- Colin Watson <cjwatson@debian.org> Wed, 12 Jun 2019 12:20:51 +0100
+
grub2 (2.02~beta3-5+deb9u1) stable; urgency=medium
* grub-mknetdir: Add support for ARM64 EFI (closes: #871772).
diff -Nru grub2-2.02~beta3/debian/patches/add-grub_relocator64_efi-relocator.patch grub2-2.02~beta3/debian/patches/add-grub_relocator64_efi-relocator.patch
--- grub2-2.02~beta3/debian/patches/add-grub_relocator64_efi-relocator.patch 1970-01-01 01:00:00.000000000 +0100
+++ grub2-2.02~beta3/debian/patches/add-grub_relocator64_efi-relocator.patch 2019-06-12 12:20:28.000000000 +0100
@@ -0,0 +1,360 @@
+From 94f7fe2201bc37170b7cf4f18378386b15c6955c Mon Sep 17 00:00:00 2001
+From: Daniel Kiper <daniel.kiper@oracle.com>
+Date: Fri, 17 Jul 2015 19:43:42 +0200
+Subject: i386/relocator: Add grub_relocator64_efi relocator
+
+Add grub_relocator64_efi relocator. It will be used on EFI 64-bit platforms
+when multiboot2 compatible image requests MULTIBOOT_TAG_TYPE_EFI_BS. Relocator
+will set lower parts of %rax and %rbx accordingly to multiboot2 specification.
+On the other hand processor mode, just before jumping into loaded image, will
+be set accordingly to Unified Extensible Firmware Interface Specification,
+Version 2.4 Errata B, section 2.3.4, x64 Platforms, boot services. This way
+loaded image will be able to use EFI boot services without any issues.
+
+Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
+Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
+
+Origin: upstream, https://git.savannah.gnu.org/cgit/grub.git/commit/?id=9862b241212b25ee23f60f5bcc4277d2289eaaf9
+Bug-Debian: https://bugs.debian.org/930028
+Last-Update: 2019-06-12
+
+Patch-Name: add-grub_relocator64_efi-relocator.patch
+---
+ grub-core/Makefile.core.def | 1 +
+ grub-core/lib/i386/relocator64.S | 11 +++++
+ grub-core/lib/x86_64/efi/relocator.c | 80 ++++++++++++++++++++++++++++++++++++
+ grub-core/loader/multiboot.c | 51 ++++++++++++++++++++---
+ grub-core/loader/multiboot_mbi2.c | 19 +++++++--
+ include/grub/i386/multiboot.h | 11 +++++
+ include/grub/i386/relocator.h | 21 ++++++++++
+ include/multiboot2.h | 1 +
+ 8 files changed, 186 insertions(+), 9 deletions(-)
+ create mode 100644 grub-core/lib/x86_64/efi/relocator.c
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 6b047109b..8052f68d3 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -1540,6 +1540,7 @@ module = {
+ i386_xen = lib/i386/xen/relocator.S;
+ x86_64_xen = lib/x86_64/xen/relocator.S;
+ xen = lib/i386/relocator_common_c.c;
++ x86_64_efi = lib/x86_64/efi/relocator.c;
+
+ extra_dist = lib/i386/relocator_common.S;
+ extra_dist = kern/powerpc/cache_flush.S;
+diff --git a/grub-core/lib/i386/relocator64.S b/grub-core/lib/i386/relocator64.S
+index e4648d818..75725cf75 100644
+--- a/grub-core/lib/i386/relocator64.S
++++ b/grub-core/lib/i386/relocator64.S
+@@ -73,6 +73,14 @@ VARIABLE(grub_relocator64_rsp)
+
+ movq %rax, %rsp
+
++ /*
++ * Here is grub_relocator64_efi_start() entry point.
++ * Following code is shared between grub_relocator64_efi_start()
++ * and grub_relocator64_start().
++ *
++ * Think twice before changing anything below!!!
++ */
++VARIABLE(grub_relocator64_efi_start)
+ /* mov imm64, %rax */
+ .byte 0x48
+ .byte 0xb8
+@@ -120,6 +128,9 @@ LOCAL(jump_addr):
+ VARIABLE(grub_relocator64_rip)
+ .quad 0
+
++ /* Here grub_relocator64_efi_start() ends. Ufff... */
++VARIABLE(grub_relocator64_efi_end)
++
+ #ifndef __x86_64__
+ .p2align 4
+ LOCAL(gdt):
+diff --git a/grub-core/lib/x86_64/efi/relocator.c b/grub-core/lib/x86_64/efi/relocator.c
+new file mode 100644
+index 000000000..3caef7a40
+--- /dev/null
++++ b/grub-core/lib/x86_64/efi/relocator.c
+@@ -0,0 +1,80 @@
++/*
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 2009 Free Software Foundation, Inc.
++ * Copyright (C) 2016 Oracle and/or its affiliates. All rights reserved.
++ *
++ * GRUB is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation, either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GRUB is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <grub/mm.h>
++#include <grub/misc.h>
++
++#include <grub/types.h>
++#include <grub/err.h>
++
++#include <grub/i386/relocator.h>
++#include <grub/relocator_private.h>
++
++extern grub_uint64_t grub_relocator64_rax;
++extern grub_uint64_t grub_relocator64_rbx;
++extern grub_uint64_t grub_relocator64_rcx;
++extern grub_uint64_t grub_relocator64_rdx;
++extern grub_uint64_t grub_relocator64_rip;
++extern grub_uint64_t grub_relocator64_rsi;
++
++extern grub_uint8_t grub_relocator64_efi_start;
++extern grub_uint8_t grub_relocator64_efi_end;
++
++#define RELOCATOR_SIZEOF(x) (&grub_relocator##x##_end - &grub_relocator##x##_start)
++
++grub_err_t
++grub_relocator64_efi_boot (struct grub_relocator *rel,
++ struct grub_relocator64_efi_state state)
++{
++ grub_err_t err;
++ void *relst;
++ grub_relocator_chunk_t ch;
++
++ /*
++ * 64-bit relocator code may live above 4 GiB quite well.
++ * However, I do not want ask for problems. Just in case.
++ */
++ err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
++ 0x100000000 - RELOCATOR_SIZEOF (64_efi),
++ RELOCATOR_SIZEOF (64_efi), 16,
++ GRUB_RELOCATOR_PREFERENCE_NONE, 1);
++ if (err)
++ return err;
++
++ /* Do not touch %rsp! It points to EFI created stack. */
++ grub_relocator64_rax = state.rax;
++ grub_relocator64_rbx = state.rbx;
++ grub_relocator64_rcx = state.rcx;
++ grub_relocator64_rdx = state.rdx;
++ grub_relocator64_rip = state.rip;
++ grub_relocator64_rsi = state.rsi;
++
++ grub_memmove (get_virtual_current_address (ch), &grub_relocator64_efi_start,
++ RELOCATOR_SIZEOF (64_efi));
++
++ err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch),
++ &relst, NULL);
++ if (err)
++ return err;
++
++ ((void (*) (void)) relst) ();
++
++ /* Not reached. */
++ return GRUB_ERR_NONE;
++}
+diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
+index 73aa0aa12..18038fd31 100644
+--- a/grub-core/loader/multiboot.c
++++ b/grub-core/loader/multiboot.c
+@@ -118,6 +118,48 @@ grub_multiboot_set_video_mode (void)
+ return err;
+ }
+
++#ifdef GRUB_MACHINE_EFI
++#ifdef __x86_64__
++#define grub_relocator_efi_boot grub_relocator64_efi_boot
++#define grub_relocator_efi_state grub_relocator64_efi_state
++#endif
++#endif
++
++#ifdef grub_relocator_efi_boot
++static void
++efi_boot (struct grub_relocator *rel,
++ grub_uint32_t target)
++{
++ struct grub_relocator_efi_state state_efi = MULTIBOOT_EFI_INITIAL_STATE;
++
++ state_efi.MULTIBOOT_EFI_ENTRY_REGISTER = grub_multiboot_payload_eip;
++ state_efi.MULTIBOOT_EFI_MBI_REGISTER = target;
++
++ grub_relocator_efi_boot (rel, state_efi);
++}
++#else
++#define grub_efi_is_finished 1
++static void
++efi_boot (struct grub_relocator *rel __attribute__ ((unused)),
++ grub_uint32_t target __attribute__ ((unused)))
++{
++}
++#endif
++
++#if defined (__i386__) || defined (__x86_64__)
++static void
++normal_boot (struct grub_relocator *rel, struct grub_relocator32_state state)
++{
++ grub_relocator32_boot (rel, state, 0);
++}
++#else
++static void
++normal_boot (struct grub_relocator *rel, struct grub_relocator32_state state)
++{
++ grub_relocator32_boot (rel, state);
++}
++#endif
++
+ static grub_err_t
+ grub_multiboot_boot (void)
+ {
+@@ -131,11 +173,10 @@ grub_multiboot_boot (void)
+ if (err)
+ return err;
+
+-#if defined (__i386__) || defined (__x86_64__)
+- grub_relocator32_boot (grub_multiboot_relocator, state, 0);
+-#else
+- grub_relocator32_boot (grub_multiboot_relocator, state);
+-#endif
++ if (grub_efi_is_finished)
++ normal_boot (grub_multiboot_relocator, state);
++ else
++ efi_boot (grub_multiboot_relocator, state.MULTIBOOT_MBI_REGISTER);
+
+ /* Not reached. */
+ return GRUB_ERR_NONE;
+diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
+index f147d674d..a3dca9011 100644
+--- a/grub-core/loader/multiboot_mbi2.c
++++ b/grub-core/loader/multiboot_mbi2.c
+@@ -107,8 +107,8 @@ grub_multiboot_load (grub_file_t file, const char *filename)
+ grub_err_t err;
+ struct multiboot_header_tag *tag;
+ struct multiboot_header_tag_address *addr_tag = NULL;
+- int entry_specified = 0;
+- grub_addr_t entry = 0;
++ int entry_specified = 0, efi_entry_specified = 0;
++ grub_addr_t entry = 0, efi_entry = 0;
+ grub_uint32_t console_required = 0;
+ struct multiboot_header_tag_framebuffer *fbtag = NULL;
+ int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
+@@ -192,6 +192,13 @@ grub_multiboot_load (grub_file_t file, const char *filename)
+ entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
+ break;
+
++ case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64:
++#if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
++ efi_entry_specified = 1;
++ efi_entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
++#endif
++ break;
++
+ case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
+ if (!(((struct multiboot_header_tag_console_flags *) tag)->console_flags
+ & MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED))
+@@ -211,7 +218,9 @@ grub_multiboot_load (grub_file_t file, const char *filename)
+ break;
+
+ case MULTIBOOT_HEADER_TAG_EFI_BS:
++#ifdef GRUB_MACHINE_EFI
+ keep_bs = 1;
++#endif
+ break;
+
+ default:
+@@ -224,7 +233,7 @@ grub_multiboot_load (grub_file_t file, const char *filename)
+ break;
+ }
+
+- if (addr_tag && !entry_specified)
++ if (addr_tag && !entry_specified && !(keep_bs && efi_entry_specified))
+ {
+ grub_free (buffer);
+ return grub_error (GRUB_ERR_UNKNOWN_OS,
+@@ -287,7 +296,9 @@ grub_multiboot_load (grub_file_t file, const char *filename)
+ }
+ }
+
+- if (entry_specified)
++ if (keep_bs && efi_entry_specified)
++ grub_multiboot_payload_eip = efi_entry;
++ else if (entry_specified)
+ grub_multiboot_payload_eip = entry;
+
+ if (fbtag)
+diff --git a/include/grub/i386/multiboot.h b/include/grub/i386/multiboot.h
+index a1b94883d..807a1de27 100644
+--- a/include/grub/i386/multiboot.h
++++ b/include/grub/i386/multiboot.h
+@@ -30,6 +30,17 @@
+ #define MULTIBOOT_MBI_REGISTER ebx
+ #define MULTIBOOT_ARCHITECTURE_CURRENT MULTIBOOT_ARCHITECTURE_I386
+
++#ifdef GRUB_MACHINE_EFI
++#ifdef __x86_64__
++#define MULTIBOOT_EFI_INITIAL_STATE { .rax = MULTIBOOT_BOOTLOADER_MAGIC, \
++ .rcx = 0, \
++ .rdx = 0, \
++ }
++#define MULTIBOOT_EFI_ENTRY_REGISTER rip
++#define MULTIBOOT_EFI_MBI_REGISTER rbx
++#endif
++#endif
++
+ #define MULTIBOOT_ELF32_MACHINE EM_386
+ #define MULTIBOOT_ELF64_MACHINE EM_X86_64
+
+diff --git a/include/grub/i386/relocator.h b/include/grub/i386/relocator.h
+index 5f89a7ec8..2a56c3b54 100644
+--- a/include/grub/i386/relocator.h
++++ b/include/grub/i386/relocator.h
+@@ -65,6 +65,20 @@ struct grub_relocator64_state
+ grub_addr_t cr3;
+ };
+
++#ifdef GRUB_MACHINE_EFI
++#ifdef __x86_64__
++struct grub_relocator64_efi_state
++{
++ grub_uint64_t rax;
++ grub_uint64_t rbx;
++ grub_uint64_t rcx;
++ grub_uint64_t rdx;
++ grub_uint64_t rip;
++ grub_uint64_t rsi;
++};
++#endif
++#endif
++
+ grub_err_t grub_relocator16_boot (struct grub_relocator *rel,
+ struct grub_relocator16_state state);
+
+@@ -76,4 +90,11 @@ grub_err_t grub_relocator64_boot (struct grub_relocator *rel,
+ struct grub_relocator64_state state,
+ grub_addr_t min_addr, grub_addr_t max_addr);
+
++#ifdef GRUB_MACHINE_EFI
++#ifdef __x86_64__
++grub_err_t grub_relocator64_efi_boot (struct grub_relocator *rel,
++ struct grub_relocator64_efi_state state);
++#endif
++#endif
++
+ #endif /* ! GRUB_RELOCATOR_CPU_HEADER */
+diff --git a/include/multiboot2.h b/include/multiboot2.h
+index 9d4862759..d96aa4041 100644
+--- a/include/multiboot2.h
++++ b/include/multiboot2.h
+@@ -69,6 +69,7 @@
+ #define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
+ #define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
+ #define MULTIBOOT_HEADER_TAG_EFI_BS 7
++#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
+
+ #define MULTIBOOT_ARCHITECTURE_I386 0
+ #define MULTIBOOT_ARCHITECTURE_MIPS32 4
diff -Nru grub2-2.02~beta3/debian/patches/multiboot2-add-ImageHandle-tags.patch grub2-2.02~beta3/debian/patches/multiboot2-add-ImageHandle-tags.patch
--- grub2-2.02~beta3/debian/patches/multiboot2-add-ImageHandle-tags.patch 1970-01-01 01:00:00.000000000 +0100
+++ grub2-2.02~beta3/debian/patches/multiboot2-add-ImageHandle-tags.patch 2019-06-12 12:20:28.000000000 +0100
@@ -0,0 +1,128 @@
+From e5f294327082bb3990e81bb6e9a7f64316c7a1ac Mon Sep 17 00:00:00 2001
+From: Daniel Kiper <daniel.kiper@oracle.com>
+Date: Thu, 20 Nov 2014 00:09:54 +0100
+Subject: multiboot2: Add tags used to pass ImageHandle to loaded image
+
+Add tags used to pass ImageHandle to loaded image if requested.
+It is used by at least ExitBootServices() function.
+
+Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
+Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
+
+Origin: upstream, https://git.savannah.gnu.org/cgit/grub.git/commit/?id=ba89c19f4995e01e3b84c6680f12f14bf0f6a38b
+Bug-Debian: https://bugs.debian.org/930028
+Last-Update: 2019-06-12
+
+Patch-Name: multiboot2-add-ImageHandle-tags.patch
+---
+ grub-core/loader/multiboot_mbi2.c | 42 ++++++++++++++++++++++++++++++++-------
+ include/multiboot2.h | 16 +++++++++++++++
+ 2 files changed, 51 insertions(+), 7 deletions(-)
+
+diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
+index a3dca9011..6c044024e 100644
+--- a/grub-core/loader/multiboot_mbi2.c
++++ b/grub-core/loader/multiboot_mbi2.c
+@@ -172,6 +172,8 @@ grub_multiboot_load (grub_file_t file, const char *filename)
+ case MULTIBOOT_TAG_TYPE_NETWORK:
+ case MULTIBOOT_TAG_TYPE_EFI_MMAP:
+ case MULTIBOOT_TAG_TYPE_EFI_BS:
++ case MULTIBOOT_TAG_TYPE_EFI32_IH:
++ case MULTIBOOT_TAG_TYPE_EFI64_IH:
+ break;
+
+ default:
+@@ -407,13 +409,15 @@ grub_multiboot_get_mbi_size (void)
+ + grub_get_multiboot_mmap_count ()
+ * sizeof (struct multiboot_mmap_entry)), MULTIBOOT_TAG_ALIGN)
+ + ALIGN_UP (sizeof (struct multiboot_tag_framebuffer), MULTIBOOT_TAG_ALIGN)
+- + ALIGN_UP (sizeof (struct multiboot_tag_efi32), MULTIBOOT_TAG_ALIGN)
+- + ALIGN_UP (sizeof (struct multiboot_tag_efi64), MULTIBOOT_TAG_ALIGN)
+ + ALIGN_UP (sizeof (struct multiboot_tag_old_acpi)
+ + sizeof (struct grub_acpi_rsdp_v10), MULTIBOOT_TAG_ALIGN)
+ + acpiv2_size ()
+ + net_size ()
+ #ifdef GRUB_MACHINE_EFI
++ + ALIGN_UP (sizeof (struct multiboot_tag_efi32), MULTIBOOT_TAG_ALIGN)
++ + ALIGN_UP (sizeof (struct multiboot_tag_efi32_ih), MULTIBOOT_TAG_ALIGN)
++ + ALIGN_UP (sizeof (struct multiboot_tag_efi64), MULTIBOOT_TAG_ALIGN)
++ + ALIGN_UP (sizeof (struct multiboot_tag_efi64_ih), MULTIBOOT_TAG_ALIGN)
+ + ALIGN_UP (sizeof (struct multiboot_tag_efi_mmap)
+ + efi_mmap_size, MULTIBOOT_TAG_ALIGN)
+ #endif
+@@ -907,11 +911,35 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
+
+ if (keep_bs)
+ {
+- struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
+- tag->type = MULTIBOOT_TAG_TYPE_EFI_BS;
+- tag->size = sizeof (struct multiboot_tag);
+- ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
+- / sizeof (grub_properly_aligned_t);
++ {
++ struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
++ tag->type = MULTIBOOT_TAG_TYPE_EFI_BS;
++ tag->size = sizeof (struct multiboot_tag);
++ ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
++ / sizeof (grub_properly_aligned_t);
++ }
++
++#ifdef __i386__
++ {
++ struct multiboot_tag_efi32_ih *tag = (struct multiboot_tag_efi32_ih *) ptrorig;
++ tag->type = MULTIBOOT_TAG_TYPE_EFI32_IH;
++ tag->size = sizeof (struct multiboot_tag_efi32_ih);
++ tag->pointer = (grub_addr_t) grub_efi_image_handle;
++ ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
++ / sizeof (grub_properly_aligned_t);
++ }
++#endif
++
++#ifdef __x86_64__
++ {
++ struct multiboot_tag_efi64_ih *tag = (struct multiboot_tag_efi64_ih *) ptrorig;
++ tag->type = MULTIBOOT_TAG_TYPE_EFI64_IH;
++ tag->size = sizeof (struct multiboot_tag_efi64_ih);
++ tag->pointer = (grub_addr_t) grub_efi_image_handle;
++ ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
++ / sizeof (grub_properly_aligned_t);
++ }
++#endif
+ }
+ #endif
+
+diff --git a/include/multiboot2.h b/include/multiboot2.h
+index d96aa4041..36a174fd0 100644
+--- a/include/multiboot2.h
++++ b/include/multiboot2.h
+@@ -60,6 +60,8 @@
+ #define MULTIBOOT_TAG_TYPE_NETWORK 16
+ #define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
+ #define MULTIBOOT_TAG_TYPE_EFI_BS 18
++#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
++#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
+
+ #define MULTIBOOT_HEADER_TAG_END 0
+ #define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
+@@ -371,6 +373,20 @@ struct multiboot_tag_efi_mmap
+ multiboot_uint8_t efi_mmap[0];
+ };
+
++struct multiboot_tag_efi32_ih
++{
++ multiboot_uint32_t type;
++ multiboot_uint32_t size;
++ multiboot_uint32_t pointer;
++};
++
++struct multiboot_tag_efi64_ih
++{
++ multiboot_uint32_t type;
++ multiboot_uint32_t size;
++ multiboot_uint64_t pointer;
++};
++
+ #endif /* ! ASM_FILE */
+
+ #endif /* ! MULTIBOOT_HEADER */
diff -Nru grub2-2.02~beta3/debian/patches/multiboot2-do-not-pass-mmaps-if-efi-boot-services.patch grub2-2.02~beta3/debian/patches/multiboot2-do-not-pass-mmaps-if-efi-boot-services.patch
--- grub2-2.02~beta3/debian/patches/multiboot2-do-not-pass-mmaps-if-efi-boot-services.patch 1970-01-01 01:00:00.000000000 +0100
+++ grub2-2.02~beta3/debian/patches/multiboot2-do-not-pass-mmaps-if-efi-boot-services.patch 2019-06-12 12:20:28.000000000 +0100
@@ -0,0 +1,135 @@
+From be9fee51de2cff287aeff055e2eb2fd98a0d187e Mon Sep 17 00:00:00 2001
+From: Daniel Kiper <daniel.kiper@oracle.com>
+Date: Sat, 18 Jul 2015 00:09:31 +0200
+Subject: multiboot2: Do not pass memory maps to image if EFI boot services are
+ enabled
+
+If image requested EFI boot services then skip multiboot2 memory maps.
+Main reason for not providing maps is because they will likely be
+invalid. We do a few allocations after filling them, e.g. for relocator
+needs. Usually we do not care as we would have finished boot services.
+If we keep boot services then it is easier/safer to not provide maps.
+However, if image needs memory maps and they are not provided by bootloader
+then it should get itself just before ExitBootServices() call.
+
+Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
+Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
+
+Origin: upstream, https://git.savannah.gnu.org/cgit/grub.git/commit/?id=f2b6c20a258b328ae8717cd5624d7b039328bcc0
+Bug-Debian: https://bugs.debian.org/930028
+Last-Update: 2019-06-12
+
+Patch-Name: multiboot2-do-not-pass-mmaps-if-efi-boot-services.patch
+---
+ grub-core/loader/multiboot_mbi2.c | 73 +++++++++++++++++++--------------------
+ 1 file changed, 36 insertions(+), 37 deletions(-)
+
+diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
+index 6c044024e..ad1553ba7 100644
+--- a/grub-core/loader/multiboot_mbi2.c
++++ b/grub-core/loader/multiboot_mbi2.c
+@@ -390,7 +390,7 @@ static grub_size_t
+ grub_multiboot_get_mbi_size (void)
+ {
+ #ifdef GRUB_MACHINE_EFI
+- if (!efi_mmap_size)
++ if (!keep_bs && !efi_mmap_size)
+ find_efi_mmap_size ();
+ #endif
+ return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag)
+@@ -755,12 +755,13 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
+ }
+ }
+
+- {
+- struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig;
+- grub_fill_multiboot_mmap (tag);
+- ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
+- / sizeof (grub_properly_aligned_t);
+- }
++ if (!keep_bs)
++ {
++ struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig;
++ grub_fill_multiboot_mmap (tag);
++ ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
++ / sizeof (grub_properly_aligned_t);
++ }
+
+ {
+ struct multiboot_tag_elf_sections *tag
+@@ -776,18 +777,19 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
+ / sizeof (grub_properly_aligned_t);
+ }
+
+- {
+- struct multiboot_tag_basic_meminfo *tag
+- = (struct multiboot_tag_basic_meminfo *) ptrorig;
+- tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
+- tag->size = sizeof (struct multiboot_tag_basic_meminfo);
+-
+- /* Convert from bytes to kilobytes. */
+- tag->mem_lower = grub_mmap_get_lower () / 1024;
+- tag->mem_upper = grub_mmap_get_upper () / 1024;
+- ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
+- / sizeof (grub_properly_aligned_t);
+- }
++ if (!keep_bs)
++ {
++ struct multiboot_tag_basic_meminfo *tag
++ = (struct multiboot_tag_basic_meminfo *) ptrorig;
++ tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
++ tag->size = sizeof (struct multiboot_tag_basic_meminfo);
++
++ /* Convert from bytes to kilobytes. */
++ tag->mem_lower = grub_mmap_get_lower () / 1024;
++ tag->mem_upper = grub_mmap_get_upper () / 1024;
++ ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
++ / sizeof (grub_properly_aligned_t);
++ }
+
+ {
+ struct grub_net_network_level_interface *net;
+@@ -886,27 +888,24 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
+ grub_efi_uintn_t efi_desc_size;
+ grub_efi_uint32_t efi_desc_version;
+
+- tag->type = MULTIBOOT_TAG_TYPE_EFI_MMAP;
+- tag->size = sizeof (*tag) + efi_mmap_size;
+-
+ if (!keep_bs)
+- err = grub_efi_finish_boot_services (&efi_mmap_size, tag->efi_mmap, NULL,
+- &efi_desc_size, &efi_desc_version);
+- else
+ {
+- if (grub_efi_get_memory_map (&efi_mmap_size, (void *) tag->efi_mmap,
+- NULL,
+- &efi_desc_size, &efi_desc_version) <= 0)
+- err = grub_error (GRUB_ERR_IO, "couldn't retrieve memory map");
+- }
+- if (err)
+- return err;
+- tag->descr_size = efi_desc_size;
+- tag->descr_vers = efi_desc_version;
+- tag->size = sizeof (*tag) + efi_mmap_size;
++ tag->type = MULTIBOOT_TAG_TYPE_EFI_MMAP;
++ tag->size = sizeof (*tag) + efi_mmap_size;
+
+- ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
+- / sizeof (grub_properly_aligned_t);
++ err = grub_efi_finish_boot_services (&efi_mmap_size, tag->efi_mmap, NULL,
++ &efi_desc_size, &efi_desc_version);
++
++ if (err)
++ return err;
++
++ tag->descr_size = efi_desc_size;
++ tag->descr_vers = efi_desc_version;
++ tag->size = sizeof (*tag) + efi_mmap_size;
++
++ ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
++ / sizeof (grub_properly_aligned_t);
++ }
+ }
+
+ if (keep_bs)
diff -Nru grub2-2.02~beta3/debian/patches/multiboot2-relocatable-images.patch grub2-2.02~beta3/debian/patches/multiboot2-relocatable-images.patch
--- grub2-2.02~beta3/debian/patches/multiboot2-relocatable-images.patch 1970-01-01 01:00:00.000000000 +0100
+++ grub2-2.02~beta3/debian/patches/multiboot2-relocatable-images.patch 2019-06-12 12:20:28.000000000 +0100
@@ -0,0 +1,683 @@
+From 87c062a404117dfdca46a2210e6791012199a25b Mon Sep 17 00:00:00 2001
+From: Daniel Kiper <daniel.kiper@oracle.com>
+Date: Fri, 17 Jul 2015 21:02:09 +0200
+Subject: multiboot2: Add support for relocatable images
+
+Currently multiboot2 protocol loads image exactly at address specified in
+ELF or multiboot2 header. This solution works quite well on legacy BIOS
+platforms. It is possible because memory regions are placed at predictable
+addresses (though I was not able to find any spec which says that it is
+strong requirement, so, it looks that it is just a goodwill of hardware
+designers). However, EFI platforms are more volatile. Even if required
+memory regions live at specific addresses then they are sometimes simply
+not free (e.g. used by boot/runtime services on Dell PowerEdge R820 and
+OVMF). This means that you are not able to just set up final image
+destination on build time. You have to provide method to relocate image
+contents to real load address which is usually different than load address
+specified in ELF and multiboot2 headers.
+
+This patch provides all needed machinery to do self relocation in image code.
+First of all GRUB2 reads min_addr (min. load addr), max_addr (max. load addr),
+align (required image alignment), preference (it says which memory regions are
+preferred by image, e.g. none, low, high) from multiboot_header_tag_relocatable
+header tag contained in binary (at this stage load addresses from multiboot2
+and/or ELF headers are ignored). Later loader tries to fulfill request (not only
+that one) and if it succeeds then it informs image about real load address via
+multiboot_tag_load_base_addr tag. At this stage GRUB2 role is finished. Starting
+from now executable must cope with relocations itself using whole static and
+dynamic knowledge provided by boot loader.
+
+This patch does not provide functionality which could do relocations using
+ELF relocation data. However, I was asked by Konrad Rzeszutek Wilk and Vladimir
+'phcoder' Serbinenko to investigate that thing. It looks that relevant machinery
+could be added to existing code (including this patch) without huge effort.
+Additionally, ELF relocation could live in parallel with self relocation provided
+by this patch. However, during research I realized that first of all we should
+establish the details how ELF relocatable image should look like and how it should
+be build. At least to build proper test/example files.
+
+So, this patch just provides support for self relocatable images. If ELF file
+with relocs is loaded then GRUB2 complains loudly and ignores it. Support for
+such files will be added later.
+
+This patch was tested with Xen image which uses that functionality. However, this Xen
+feature is still under development and new patchset will be released in about 2-3 weeks.
+
+Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
+Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
+
+Origin: upstream, https://git.savannah.gnu.org/cgit/grub.git/commit/?id=a620876e3b32e4ea0c9a7b3541fcb9a4dd4fb9eb
+Bug-Debian: https://bugs.debian.org/930028
+Last-Update: 2019-06-12
+
+Patch-Name: multiboot2-relocatable-images.patch
+---
+ grub-core/loader/i386/multiboot_mbi.c | 13 +++-
+ grub-core/loader/multiboot.c | 11 ++-
+ grub-core/loader/multiboot_elfxx.c | 131 +++++++++++++++++++++-------------
+ grub-core/loader/multiboot_mbi2.c | 122 +++++++++++++++++++++++++------
+ include/grub/multiboot.h | 22 +++++-
+ include/multiboot2.h | 24 +++++++
+ 6 files changed, 244 insertions(+), 79 deletions(-)
+
+diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c
+index f60b70234..fd7b41b0c 100644
+--- a/grub-core/loader/i386/multiboot_mbi.c
++++ b/grub-core/loader/i386/multiboot_mbi.c
+@@ -70,9 +70,18 @@ load_kernel (grub_file_t file, const char *filename,
+ char *buffer, struct multiboot_header *header)
+ {
+ grub_err_t err;
++ mbi_load_data_t mld;
++
++ mld.file = file;
++ mld.filename = filename;
++ mld.buffer = buffer;
++ mld.mbi_ver = 1;
++ mld.relocatable = 0;
++ mld.avoid_efi_boot_services = 0;
++
+ if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE)
+ {
+- err = grub_multiboot_load_elf (file, filename, buffer);
++ err = grub_multiboot_load_elf (&mld);
+ if (err == GRUB_ERR_NONE) {
+ return GRUB_ERR_NONE;
+ }
+@@ -121,7 +130,7 @@ load_kernel (grub_file_t file, const char *filename,
+ return GRUB_ERR_NONE;
+ }
+
+- return grub_multiboot_load_elf (file, filename, buffer);
++ return grub_multiboot_load_elf (&mld);
+ }
+
+ static struct multiboot_header *
+diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
+index 18038fd31..bd9d5b3e6 100644
+--- a/grub-core/loader/multiboot.c
++++ b/grub-core/loader/multiboot.c
+@@ -207,13 +207,12 @@ static grub_uint64_t highest_load;
+
+ /* Load ELF32 or ELF64. */
+ grub_err_t
+-grub_multiboot_load_elf (grub_file_t file, const char *filename,
+- void *buffer)
++grub_multiboot_load_elf (mbi_load_data_t *mld)
+ {
+- if (grub_multiboot_is_elf32 (buffer))
+- return grub_multiboot_load_elf32 (file, filename, buffer);
+- else if (grub_multiboot_is_elf64 (buffer))
+- return grub_multiboot_load_elf64 (file, filename, buffer);
++ if (grub_multiboot_is_elf32 (mld->buffer))
++ return grub_multiboot_load_elf32 (mld);
++ else if (grub_multiboot_is_elf64 (mld->buffer))
++ return grub_multiboot_load_elf64 (mld);
+
+ return grub_error (GRUB_ERR_UNKNOWN_OS, N_("invalid arch-dependent ELF magic"));
+ }
+diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c
+index e3a39b609..5e649ed25 100644
+--- a/grub-core/loader/multiboot_elfxx.c
++++ b/grub-core/loader/multiboot_elfxx.c
+@@ -51,11 +51,15 @@ CONCAT(grub_multiboot_is_elf, XX) (void *buffer)
+ }
+
+ static grub_err_t
+-CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, void *buffer)
++CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
+ {
+- Elf_Ehdr *ehdr = (Elf_Ehdr *) buffer;
++ Elf_Ehdr *ehdr = (Elf_Ehdr *) mld->buffer;
+ char *phdr_base;
++ grub_err_t err;
++ grub_relocator_chunk_t ch;
++ grub_uint32_t load_offset, load_size;
+ int i;
++ void *source;
+
+ if (ehdr->e_ident[EI_MAG0] != ELFMAG0
+ || ehdr->e_ident[EI_MAG1] != ELFMAG1
+@@ -75,54 +79,86 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
+ if (ehdr->e_phoff + (grub_uint32_t) ehdr->e_phnum * ehdr->e_phentsize > MULTIBOOT_SEARCH)
+ return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
+
+- phdr_base = (char *) buffer + ehdr->e_phoff;
++ phdr_base = (char *) mld->buffer + ehdr->e_phoff;
+ #define phdr(i) ((Elf_Phdr *) (phdr_base + (i) * ehdr->e_phentsize))
+
++ mld->link_base_addr = ~0;
++
++ /* Calculate lowest and highest load address. */
++ for (i = 0; i < ehdr->e_phnum; i++)
++ if (phdr(i)->p_type == PT_LOAD)
++ {
++ mld->link_base_addr = grub_min (mld->link_base_addr, phdr(i)->p_paddr);
++ highest_load = grub_max (highest_load, phdr(i)->p_paddr + phdr(i)->p_memsz);
++ }
++
++#ifdef MULTIBOOT_LOAD_ELF64
++ if (highest_load >= 0x100000000)
++ return grub_error (GRUB_ERR_BAD_OS, "segment crosses 4 GiB border");
++#endif
++
++ load_size = highest_load - mld->link_base_addr;
++
++ if (mld->relocatable)
++ {
++ if (load_size > mld->max_addr || mld->min_addr > mld->max_addr - load_size)
++ return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
++
++ err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
++ mld->min_addr, mld->max_addr - load_size,
++ load_size, mld->align ? mld->align : 1,
++ mld->preference, mld->avoid_efi_boot_services);
++ }
++ else
++ err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, &ch,
++ mld->link_base_addr, load_size);
++
++ if (err)
++ {
++ grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n");
++ return err;
++ }
++
++ mld->load_base_addr = get_physical_target_address (ch);
++ source = get_virtual_current_address (ch);
++
++ grub_dprintf ("multiboot_loader", "link_base_addr=0x%x, load_base_addr=0x%x, "
++ "load_size=0x%x, relocatable=%d\n", mld->link_base_addr,
++ mld->load_base_addr, load_size, mld->relocatable);
++
++ if (mld->relocatable)
++ grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, avoid_efi_boot_services=%d\n",
++ (long) mld->align, mld->preference, mld->avoid_efi_boot_services);
++
+ /* Load every loadable segment in memory. */
+ for (i = 0; i < ehdr->e_phnum; i++)
+ {
+ if (phdr(i)->p_type == PT_LOAD)
+ {
+- grub_err_t err;
+- void *source;
+-
+- if (phdr(i)->p_paddr + phdr(i)->p_memsz > highest_load)
+- highest_load = phdr(i)->p_paddr + phdr(i)->p_memsz;
+
+ grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, memsz=0x%lx, vaddr=0x%lx\n",
+ i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long) phdr(i)->p_vaddr);
+
+- {
+- grub_relocator_chunk_t ch;
+- err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator,
+- &ch, phdr(i)->p_paddr,
+- phdr(i)->p_memsz);
+- if (err)
+- {
+- grub_dprintf ("multiboot_loader", "Error loading phdr %d\n", i);
+- return err;
+- }
+- source = get_virtual_current_address (ch);
+- }
++ load_offset = phdr(i)->p_paddr - mld->link_base_addr;
+
+ if (phdr(i)->p_filesz != 0)
+ {
+- if (grub_file_seek (file, (grub_off_t) phdr(i)->p_offset)
++ if (grub_file_seek (mld->file, (grub_off_t) phdr(i)->p_offset)
+ == (grub_off_t) -1)
+ return grub_errno;
+
+- if (grub_file_read (file, source, phdr(i)->p_filesz)
++ if (grub_file_read (mld->file, (grub_uint8_t *) source + load_offset, phdr(i)->p_filesz)
+ != (grub_ssize_t) phdr(i)->p_filesz)
+ {
+ if (!grub_errno)
+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
+- filename);
++ mld->filename);
+ return grub_errno;
+ }
+ }
+
+ if (phdr(i)->p_filesz < phdr(i)->p_memsz)
+- grub_memset ((grub_uint8_t *) source + phdr(i)->p_filesz, 0,
++ grub_memset ((grub_uint8_t *) source + load_offset + phdr(i)->p_filesz, 0,
+ phdr(i)->p_memsz - phdr(i)->p_filesz);
+ }
+ }
+@@ -168,18 +204,18 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
+ if (!shdr)
+ return grub_errno;
+
+- if (grub_file_seek (file, ehdr->e_shoff) == (grub_off_t) -1)
++ if (grub_file_seek (mld->file, ehdr->e_shoff) == (grub_off_t) -1)
+ {
+ grub_free (shdr);
+ return grub_errno;
+ }
+
+- if (grub_file_read (file, shdr, (grub_uint32_t) ehdr->e_shnum * ehdr->e_shentsize)
++ if (grub_file_read (mld->file, shdr, (grub_uint32_t) ehdr->e_shnum * ehdr->e_shentsize)
+ != (grub_ssize_t) ehdr->e_shnum * ehdr->e_shentsize)
+ {
+ if (!grub_errno)
+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
+- filename);
++ mld->filename);
+ return grub_errno;
+ }
+
+@@ -189,7 +225,9 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
+ Elf_Shdr *sh = (Elf_Shdr *) shdrptr;
+ void *src;
+ grub_addr_t target;
+- grub_err_t err;
++
++ if (mld->mbi_ver >= 2 && (sh->sh_type == SHT_REL || sh->sh_type == SHT_RELA))
++ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ELF files with relocs are not supported yet");
+
+ /* This section is a loaded section,
+ so we don't care. */
+@@ -200,33 +238,28 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
+ if (sh->sh_size == 0)
+ continue;
+
+- {
+- grub_relocator_chunk_t ch;
+- err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator,
+- &ch, 0,
+- (0xffffffff - sh->sh_size)
+- + 1, sh->sh_size,
+- sh->sh_addralign,
+- GRUB_RELOCATOR_PREFERENCE_NONE,
+- 0);
+- if (err)
+- {
+- grub_dprintf ("multiboot_loader", "Error loading shdr %d\n", i);
+- return err;
+- }
+- src = get_virtual_current_address (ch);
+- target = get_physical_target_address (ch);
+- }
+-
+- if (grub_file_seek (file, sh->sh_offset) == (grub_off_t) -1)
++ err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, 0,
++ (0xffffffff - sh->sh_size) + 1,
++ sh->sh_size, sh->sh_addralign,
++ GRUB_RELOCATOR_PREFERENCE_NONE,
++ mld->avoid_efi_boot_services);
++ if (err)
++ {
++ grub_dprintf ("multiboot_loader", "Error loading shdr %d\n", i);
++ return err;
++ }
++ src = get_virtual_current_address (ch);
++ target = get_physical_target_address (ch);
++
++ if (grub_file_seek (mld->file, sh->sh_offset) == (grub_off_t) -1)
+ return grub_errno;
+
+- if (grub_file_read (file, src, sh->sh_size)
++ if (grub_file_read (mld->file, src, sh->sh_size)
+ != (grub_ssize_t) sh->sh_size)
+ {
+ if (!grub_errno)
+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
+- filename);
++ mld->filename);
+ return grub_errno;
+ }
+ sh->sh_addr = target;
+diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
+index ad1553ba7..b0679a9f6 100644
+--- a/grub-core/loader/multiboot_mbi2.c
++++ b/grub-core/loader/multiboot_mbi2.c
+@@ -68,6 +68,7 @@ static grub_size_t elf_sec_num, elf_sec_entsize;
+ static unsigned elf_sec_shstrndx;
+ static void *elf_sections;
+ static int keep_bs = 0;
++static grub_uint32_t load_base_addr;
+
+ void
+ grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize,
+@@ -101,36 +102,40 @@ find_header (grub_properly_aligned_t *buffer, grub_ssize_t len)
+ grub_err_t
+ grub_multiboot_load (grub_file_t file, const char *filename)
+ {
+- grub_properly_aligned_t *buffer;
+ grub_ssize_t len;
+ struct multiboot_header *header;
+ grub_err_t err;
+ struct multiboot_header_tag *tag;
+ struct multiboot_header_tag_address *addr_tag = NULL;
++ struct multiboot_header_tag_relocatable *rel_tag;
+ int entry_specified = 0, efi_entry_specified = 0;
+ grub_addr_t entry = 0, efi_entry = 0;
+ grub_uint32_t console_required = 0;
+ struct multiboot_header_tag_framebuffer *fbtag = NULL;
+ int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
++ mbi_load_data_t mld;
+
+- buffer = grub_malloc (MULTIBOOT_SEARCH);
+- if (!buffer)
++ mld.mbi_ver = 2;
++ mld.relocatable = 0;
++
++ mld.buffer = grub_malloc (MULTIBOOT_SEARCH);
++ if (!mld.buffer)
+ return grub_errno;
+
+- len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
++ len = grub_file_read (file, mld.buffer, MULTIBOOT_SEARCH);
+ if (len < 32)
+ {
+- grub_free (buffer);
++ grub_free (mld.buffer);
+ return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), filename);
+ }
+
+ COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0);
+
+- header = find_header (buffer, len);
++ header = find_header (mld.buffer, len);
+
+ if (header == 0)
+ {
+- grub_free (buffer);
++ grub_free (mld.buffer);
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
+ }
+
+@@ -174,10 +179,11 @@ grub_multiboot_load (grub_file_t file, const char *filename)
+ case MULTIBOOT_TAG_TYPE_EFI_BS:
+ case MULTIBOOT_TAG_TYPE_EFI32_IH:
+ case MULTIBOOT_TAG_TYPE_EFI64_IH:
++ case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
+ break;
+
+ default:
+- grub_free (buffer);
++ grub_free (mld.buffer);
+ return grub_error (GRUB_ERR_UNKNOWN_OS,
+ "unsupported information tag: 0x%x",
+ request_tag->requests[i]);
+@@ -215,6 +221,27 @@ grub_multiboot_load (grub_file_t file, const char *filename)
+ accepted_consoles |= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER;
+ break;
+
++ case MULTIBOOT_HEADER_TAG_RELOCATABLE:
++ mld.relocatable = 1;
++ rel_tag = (struct multiboot_header_tag_relocatable *) tag;
++ mld.min_addr = rel_tag->min_addr;
++ mld.max_addr = rel_tag->max_addr;
++ mld.align = rel_tag->align;
++ switch (rel_tag->preference)
++ {
++ case MULTIBOOT_LOAD_PREFERENCE_LOW:
++ mld.preference = GRUB_RELOCATOR_PREFERENCE_LOW;
++ break;
++
++ case MULTIBOOT_LOAD_PREFERENCE_HIGH:
++ mld.preference = GRUB_RELOCATOR_PREFERENCE_HIGH;
++ break;
++
++ default:
++ mld.preference = GRUB_RELOCATOR_PREFERENCE_NONE;
++ }
++ break;
++
+ /* GRUB always page-aligns modules. */
+ case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
+ break;
+@@ -228,7 +255,7 @@ grub_multiboot_load (grub_file_t file, const char *filename)
+ default:
+ if (! (tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL))
+ {
+- grub_free (buffer);
++ grub_free (mld.buffer);
+ return grub_error (GRUB_ERR_UNKNOWN_OS,
+ "unsupported tag: 0x%x", tag->type);
+ }
+@@ -237,7 +264,7 @@ grub_multiboot_load (grub_file_t file, const char *filename)
+
+ if (addr_tag && !entry_specified && !(keep_bs && efi_entry_specified))
+ {
+- grub_free (buffer);
++ grub_free (mld.buffer);
+ return grub_error (GRUB_ERR_UNKNOWN_OS,
+ "load address tag without entry address tag");
+ }
+@@ -246,8 +273,8 @@ grub_multiboot_load (grub_file_t file, const char *filename)
+ {
+ grub_uint64_t load_addr = (addr_tag->load_addr + 1)
+ ? addr_tag->load_addr : (addr_tag->header_addr
+- - ((char *) header - (char *) buffer));
+- int offset = ((char *) header - (char *) buffer -
++ - ((char *) header - (char *) mld.buffer));
++ int offset = ((char *) header - (char *) mld.buffer -
+ (addr_tag->header_addr - load_addr));
+ int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset :
+ addr_tag->load_end_addr - addr_tag->load_addr);
+@@ -260,27 +287,50 @@ grub_multiboot_load (grub_file_t file, const char *filename)
+ else
+ code_size = load_size;
+
+- err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator,
+- &ch, load_addr,
+- code_size);
++ if (mld.relocatable)
++ {
++ if (code_size > mld.max_addr || mld.min_addr > mld.max_addr - code_size)
++ {
++ grub_free (mld.buffer);
++ return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
++ }
++
++ err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
++ mld.min_addr, mld.max_addr - code_size,
++ code_size, mld.align ? mld.align : 1,
++ mld.preference, keep_bs);
++ }
++ else
++ err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator,
++ &ch, load_addr, code_size);
+ if (err)
+ {
+ grub_dprintf ("multiboot_loader", "Error loading aout kludge\n");
+- grub_free (buffer);
++ grub_free (mld.buffer);
+ return err;
+ }
++ mld.link_base_addr = load_addr;
++ mld.load_base_addr = get_physical_target_address (ch);
+ source = get_virtual_current_address (ch);
+
++ grub_dprintf ("multiboot_loader", "link_base_addr=0x%x, load_base_addr=0x%x, "
++ "load_size=0x%lx, relocatable=%d\n", mld.link_base_addr,
++ mld.load_base_addr, (long) code_size, mld.relocatable);
++
++ if (mld.relocatable)
++ grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, avoid_efi_boot_services=%d\n",
++ (long) mld.align, mld.preference, keep_bs);
++
+ if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
+ {
+- grub_free (buffer);
++ grub_free (mld.buffer);
+ return grub_errno;
+ }
+
+ grub_file_read (file, source, load_size);
+ if (grub_errno)
+ {
+- grub_free (buffer);
++ grub_free (mld.buffer);
+ return grub_errno;
+ }
+
+@@ -290,19 +340,41 @@ grub_multiboot_load (grub_file_t file, const char *filename)
+ }
+ else
+ {
+- err = grub_multiboot_load_elf (file, filename, buffer);
++ mld.file = file;
++ mld.filename = filename;
++ mld.avoid_efi_boot_services = keep_bs;
++ err = grub_multiboot_load_elf (&mld);
+ if (err)
+ {
+- grub_free (buffer);
++ grub_free (mld.buffer);
+ return err;
+ }
+ }
+
++ load_base_addr = mld.load_base_addr;
++
+ if (keep_bs && efi_entry_specified)
+ grub_multiboot_payload_eip = efi_entry;
+ else if (entry_specified)
+ grub_multiboot_payload_eip = entry;
+
++ if (mld.relocatable)
++ {
++ /*
++ * Both branches are mathematically equivalent. However, it looks
++ * that real life (C?) is more complicated. I am trying to avoid
++ * wrap around here if mld.load_base_addr < mld.link_base_addr.
++ * If you look at C operator precedence then everything should work.
++ * However, I am not 100% sure that a given compiler will not
++ * optimize/break this stuff. So, maybe we should use signed
++ * 64-bit int here.
++ */
++ if (mld.load_base_addr >= mld.link_base_addr)
++ grub_multiboot_payload_eip += mld.load_base_addr - mld.link_base_addr;
++ else
++ grub_multiboot_payload_eip -= mld.link_base_addr - mld.load_base_addr;
++ }
++
+ if (fbtag)
+ err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
+ accepted_consoles,
+@@ -411,6 +483,7 @@ grub_multiboot_get_mbi_size (void)
+ + ALIGN_UP (sizeof (struct multiboot_tag_framebuffer), MULTIBOOT_TAG_ALIGN)
+ + ALIGN_UP (sizeof (struct multiboot_tag_old_acpi)
+ + sizeof (struct grub_acpi_rsdp_v10), MULTIBOOT_TAG_ALIGN)
++ + ALIGN_UP (sizeof (struct multiboot_tag_load_base_addr), MULTIBOOT_TAG_ALIGN)
+ + acpiv2_size ()
+ + net_size ()
+ #ifdef GRUB_MACHINE_EFI
+@@ -694,6 +767,15 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
+ ptrorig += (2 * sizeof (grub_uint32_t)) / sizeof (grub_properly_aligned_t);
+
+ {
++ struct multiboot_tag_load_base_addr *tag = (struct multiboot_tag_load_base_addr *) ptrorig;
++ tag->type = MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR;
++ tag->size = sizeof (struct multiboot_tag_load_base_addr);
++ tag->load_base_addr = load_base_addr;
++ ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
++ / sizeof (grub_properly_aligned_t);
++ }
++
++ {
+ struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
+ tag->type = MULTIBOOT_TAG_TYPE_CMDLINE;
+ tag->size = sizeof (struct multiboot_tag_string) + cmdline_size;
+diff --git a/include/grub/multiboot.h b/include/grub/multiboot.h
+index e13c0843b..c96492bb5 100644
+--- a/include/grub/multiboot.h
++++ b/include/grub/multiboot.h
+@@ -91,10 +91,28 @@ grub_multiboot_set_console (int console_type, int accepted_consoles,
+ int console_required);
+ grub_err_t
+ grub_multiboot_load (grub_file_t file, const char *filename);
++
++struct mbi_load_data
++{
++ grub_file_t file;
++ const char *filename;
++ void *buffer;
++ unsigned int mbi_ver;
++ int relocatable;
++ grub_uint32_t min_addr;
++ grub_uint32_t max_addr;
++ grub_size_t align;
++ grub_uint32_t preference;
++ grub_uint32_t link_base_addr;
++ grub_uint32_t load_base_addr;
++ int avoid_efi_boot_services;
++};
++typedef struct mbi_load_data mbi_load_data_t;
++
+ /* Load ELF32 or ELF64. */
+ grub_err_t
+-grub_multiboot_load_elf (grub_file_t file, const char *filename,
+- void *buffer);
++grub_multiboot_load_elf (mbi_load_data_t *mld);
++
+ extern grub_size_t grub_multiboot_pure_size;
+ extern grub_size_t grub_multiboot_alloc_mbi;
+ extern grub_uint32_t grub_multiboot_payload_eip;
+diff --git a/include/multiboot2.h b/include/multiboot2.h
+index 36a174fd0..b93fba46d 100644
+--- a/include/multiboot2.h
++++ b/include/multiboot2.h
+@@ -62,6 +62,7 @@
+ #define MULTIBOOT_TAG_TYPE_EFI_BS 18
+ #define MULTIBOOT_TAG_TYPE_EFI32_IH 19
+ #define MULTIBOOT_TAG_TYPE_EFI64_IH 20
++#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
+
+ #define MULTIBOOT_HEADER_TAG_END 0
+ #define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
+@@ -72,11 +73,16 @@
+ #define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
+ #define MULTIBOOT_HEADER_TAG_EFI_BS 7
+ #define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
++#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
+
+ #define MULTIBOOT_ARCHITECTURE_I386 0
+ #define MULTIBOOT_ARCHITECTURE_MIPS32 4
+ #define MULTIBOOT_HEADER_TAG_OPTIONAL 1
+
++#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
++#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
++#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
++
+ #define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
+ #define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
+
+@@ -161,6 +167,17 @@ struct multiboot_header_tag_module_align
+ multiboot_uint32_t size;
+ };
+
++struct multiboot_header_tag_relocatable
++{
++ multiboot_uint16_t type;
++ multiboot_uint16_t flags;
++ multiboot_uint32_t size;
++ multiboot_uint32_t min_addr;
++ multiboot_uint32_t max_addr;
++ multiboot_uint32_t align;
++ multiboot_uint32_t preference;
++};
++
+ struct multiboot_color
+ {
+ multiboot_uint8_t red;
+@@ -387,6 +404,13 @@ struct multiboot_tag_efi64_ih
+ multiboot_uint64_t pointer;
+ };
+
++struct multiboot_tag_load_base_addr
++{
++ multiboot_uint32_t type;
++ multiboot_uint32_t size;
++ multiboot_uint32_t load_base_addr;
++};
++
+ #endif /* ! ASM_FILE */
+
+ #endif /* ! MULTIBOOT_HEADER */
diff -Nru grub2-2.02~beta3/debian/patches/series grub2-2.02~beta3/debian/patches/series
--- grub2-2.02~beta3/debian/patches/series 2018-10-28 19:18:13.000000000 +0000
+++ grub2-2.02~beta3/debian/patches/series 2019-06-12 12:20:28.000000000 +0100
@@ -59,3 +59,8 @@
grub-install-efibootmgr-check.patch
mknetdir_arm64.patch
tsc_efi_default_to_pmtimer.patch
+add-grub_relocator64_efi-relocator.patch
+multiboot2-add-ImageHandle-tags.patch
+multiboot2-do-not-pass-mmaps-if-efi-boot-services.patch
+multiboot2-relocatable-images.patch
+xen-multiboot2.patch
diff -Nru grub2-2.02~beta3/debian/patches/xen-multiboot2.patch grub2-2.02~beta3/debian/patches/xen-multiboot2.patch
--- grub2-2.02~beta3/debian/patches/xen-multiboot2.patch 1970-01-01 01:00:00.000000000 +0100
+++ grub2-2.02~beta3/debian/patches/xen-multiboot2.patch 2019-06-12 12:20:28.000000000 +0100
@@ -0,0 +1,61 @@
+From 23439d60d742949cee70df3c1b84ac61c9ce2c0d Mon Sep 17 00:00:00 2001
+From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Date: Tue, 29 Aug 2017 16:40:53 -0400
+Subject: Use grub-file to figure out whether multiboot2 should be used for
+ Xen.gz
+
+The multiboot2 is much more preferable than multiboot. Especially
+if booting under EFI where multiboot does not have the functionality
+to pass ImageHandler.
+
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+
+Origin: backport, https://git.savannah.gnu.org/cgit/grub.git/commit/?id=b4d709b6ee789cdaf3fa7a80fd90c721a16f48c2
+Bug-Debian: https://bugs.debian.org/898947
+Bug-Debian: https://bugs.debian.org/930028
+Last-Update: 2019-06-12
+
+Patch-Name: xen-multiboot2.patch
+---
+ util/grub.d/20_linux_xen.in | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
+index 6fd17f1e9..d726ee7d2 100644
+--- a/util/grub.d/20_linux_xen.in
++++ b/util/grub.d/20_linux_xen.in
+@@ -130,16 +130,16 @@ linux_entry ()
+ else
+ xen_rm_opts="no-real-mode edd=off"
+ fi
+- multiboot ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
++ ${xen_loader} ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
+ echo '$(echo "$lmessage" | grub_quote)'
+- module ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
++ ${module_loader} ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
+ EOF
+ if test -n "${initrd}" ; then
+ # TRANSLATORS: ramdisk isn't identifier. Should be translated.
+ message="$(gettext_printf "Loading initial ramdisk ...")"
+ sed "s/^/$submenu_indentation/" << EOF
+ echo '$(echo "$message" | grub_quote)'
+- module --nounzip ${rel_dirname}/${initrd}
++ ${module_loader} --nounzip ${rel_dirname}/${initrd}
+ EOF
+ fi
+ sed "s/^/$submenu_indentation/" << EOF
+@@ -214,6 +214,13 @@ while [ "x${xen_list}" != "x" ] ; do
+ if [ "x$is_top_level" != xtrue ]; then
+ echo " submenu '$(gettext_printf "Xen hypervisor, version %s" "${xen_version}" | grub_quote)' \$menuentry_id_option 'xen-hypervisor-$xen_version-$boot_device_id' {"
+ fi
++ if ($grub_file --is-x86-multiboot2 $current_xen); then
++ xen_loader="multiboot2"
++ module_loader="module2"
++ else
++ xen_loader="multiboot"
++ module_loader="module"
++ fi
+ while [ "x$list" != "x" ] ; do
+ linux=`version_find_latest $list`
+ gettext_printf "Found linux image: %s\n" "$linux" >&2
Reply to: