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

