[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: