Package: release.debian.org
Severity: normal
Tags: stretch
User: [email protected]
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                                       [[email protected]]
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 <[email protected]>  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 <[email protected]>
+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 <[email protected]>
+Reviewed-by: Konrad Rzeszutek Wilk <[email protected]>
+Reviewed-by: Vladimir Serbinenko <[email protected]>
+
+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 <[email protected]>
+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 <[email protected]>
+Reviewed-by: Konrad Rzeszutek Wilk <[email protected]>
+Reviewed-by: Vladimir Serbinenko <[email protected]>
+
+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 <[email protected]>
+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 <[email protected]>
+Reviewed-by: Konrad Rzeszutek Wilk <[email protected]>
+Reviewed-by: Vladimir Serbinenko <[email protected]>
+
+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 <[email protected]>
+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 <[email protected]>
+Reviewed-by: Vladimir Serbinenko <[email protected]>
+
+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 <[email protected]>
+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 <[email protected]>
+Reviewed-by: Daniel Kiper <[email protected]>
+
+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 via email to