diff -Nru grub2-2.02~beta2/debian/changelog grub2-2.02~beta2/debian/changelog --- grub2-2.02~beta2/debian/changelog 2017-05-20 19:59:17.000000000 +0000 +++ grub2-2.02~beta2/debian/changelog 2017-06-08 17:16:17.000000000 +0000 @@ -1,3 +1,34 @@ +grub2 (2.02~beta2-36ubuntu3.12) xenial; urgency=medium + + * debian/patches: Rework linuxefi/SecureBoot support and sync with upstream + SB patch set: (LP: #1696599) + - linuxefi_backport_arm64.patch: backport basic arm64 chainload/linux + command support from 17.04. + - linuxefi_arm_sb_support.patch: add Secure Boot support for arm for its + chainloader. + - linuxefi_fix_validation_race.patch: Fix a race in validating images. + - linuxefi_chainloader_path.patch: honor the starting path for grub, so + images do not need to be started from $root. + - linuxefi_chainloader_sb.patch: Fix some more issues in chainloader use + when Secure Boot is enabled. + - linuxefi_loaders_enforce_sb.patch: Enforce Secure Boot policy for all + loaders: don't load the commands when Secure Boot is enabled. + - linuxefi_re-enable_linux_cmd.patch: Since we rely on the linux and + initrd commands to automatically hand-off to linuxefi/initrdefi; re- + enable the linux loader. + - linuxefi_chainloader_pe_fixes.patch: PE parsing fixes for chainloading + "special" PE images, such as Windows'. + - linuxefi_rework_non-sb_cases.patch: rework cases where Secure Boot is + disabled or shim validation is disabled so loading works as EFI binaries + when it is supposed to. + - Removed linuxefi_require_shim.patch; superseded by the above. + (LP: #1689687) + * debian/patches/git_tsc_use_alt_delay_sources_d43a5ee6.patch: refreshed. + * debian/patches/arm64-set-correct-length-of-device-path-end-entry.patch: + dropped; included in linuxefi_backport_arm64.patch. + + -- Mathieu Trudel-Lapierre Thu, 08 Jun 2017 10:16:17 -0700 + grub2 (2.02~beta2-36ubuntu3.11) xenial; urgency=medium * Fix syntax error in debian/postinst.in. (LP #1692181) diff -Nru grub2-2.02~beta2/debian/patches/git_tsc_use_alt_delay_sources_d43a5ee6.patch grub2-2.02~beta2/debian/patches/git_tsc_use_alt_delay_sources_d43a5ee6.patch --- grub2-2.02~beta2/debian/patches/git_tsc_use_alt_delay_sources_d43a5ee6.patch 2016-09-15 17:56:55.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/git_tsc_use_alt_delay_sources_d43a5ee6.patch 2017-06-08 17:16:17.000000000 +0000 @@ -29,7 +29,7 @@ =================================================================== --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am -@@ -98,6 +98,7 @@ if COND_i386_efi +@@ -99,6 +99,7 @@ if COND_i386_efi KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h @@ -37,7 +37,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h endif -@@ -109,10 +110,12 @@ KERNEL_HEADER_FILES += $(top_srcdir)/inc +@@ -110,10 +111,12 @@ KERNEL_HEADER_FILES += $(top_srcdir)/inc KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h @@ -50,7 +50,7 @@ endif if COND_i386_qemu -@@ -151,11 +154,13 @@ KERNEL_HEADER_FILES += $(top_srcdir)/inc +@@ -152,11 +155,13 @@ KERNEL_HEADER_FILES += $(top_srcdir)/inc KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h @@ -64,7 +64,7 @@ endif if COND_mips -@@ -230,11 +235,13 @@ KERNEL_HEADER_FILES += $(top_srcdir)/inc +@@ -231,11 +236,13 @@ KERNEL_HEADER_FILES += $(top_srcdir)/inc KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h @@ -82,7 +82,7 @@ =================================================================== --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def -@@ -174,8 +174,20 @@ kernel = { +@@ -174,9 +174,21 @@ kernel = { efi = kern/efi/init.c; efi = kern/efi/mm.c; efi = term/efi/console.c; @@ -92,6 +92,7 @@ + i386_multiboot = kern/i386/pc/acpi.c; + i386_coreboot = kern/acpi.c; + i386_multiboot = kern/acpi.c; + common = kern/efi/sb.c; x86 = kern/i386/tsc.c; + x86 = kern/i386/tsc_pit.c; @@ -103,7 +104,7 @@ i386_efi = kern/i386/efi/init.c; i386_efi = bus/pci.c; -@@ -187,6 +199,7 @@ kernel = { +@@ -188,6 +200,7 @@ kernel = { x86_64_efi = bus/pci.c; xen = kern/i386/tsc.c; @@ -111,7 +112,7 @@ x86_64_xen = kern/x86_64/xen/hypercall.S; i386_xen = kern/i386/xen/hypercall.S; xen = kern/xen/init.c; -@@ -685,10 +698,8 @@ module = { +@@ -686,10 +699,8 @@ module = { name = acpi; common = commands/acpi.c; diff -Nru grub2-2.02~beta2/debian/patches/linuxefi_arm_sb_support.patch grub2-2.02~beta2/debian/patches/linuxefi_arm_sb_support.patch --- grub2-2.02~beta2/debian/patches/linuxefi_arm_sb_support.patch 1970-01-01 00:00:00.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/linuxefi_arm_sb_support.patch 2017-06-08 17:16:17.000000000 +0000 @@ -0,0 +1,438 @@ +From 69cfd0fbd4838c43f0cc34324372bbc23b68b418 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 18 Sep 2014 11:26:14 -0400 +Subject: [PATCH] Load arm with SB enabled. + +Make sure we actually try to validate secure boot on this platform (even +though we're not shipping it enabled by default.) + +This means giving the kernel grub's loaded image as the vehicle for the +kernel command line, because we can't call systab->bs->LoadImage() if SB +is enabled. +--- + grub-core/Makefile.core.def | 3 + grub-core/loader/arm/linux.c | 1 + grub-core/loader/arm64/linux.c | 117 ++++++++++++++++++++------------------ + grub-core/loader/efi/linux.c | 66 +++++++++++++++++++++ + grub-core/loader/i386/efi/linux.c | 39 ------------ + include/grub/arm64/linux.h | 8 ++ + include/grub/efi/linux.h | 31 ++++++++++ + 7 files changed, 175 insertions(+), 90 deletions(-) + create mode 100644 grub-core/loader/efi/linux.c + create mode 100644 include/grub/efi/linux.h + +Index: b/grub-core/Makefile.core.def +=================================================================== +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1673,6 +1673,8 @@ module = { + ia64_efi = loader/ia64/efi/linux.c; + arm = loader/arm/linux.c; + arm64 = loader/arm64/linux.c; ++ arm64 = loader/efi/linux.c; ++ fdt = lib/fdt.c; + common = loader/linux.c; + common = lib/cmdline.c; + enable = noemu; +@@ -1715,6 +1717,7 @@ module = { + name = linuxefi; + efi = loader/i386/efi/linux.c; + efi = lib/cmdline.c; ++ efi = loader/efi/linux.c; + enable = i386_efi; + enable = x86_64_efi; + }; +Index: b/grub-core/loader/arm64/linux.c +=================================================================== +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -39,6 +40,7 @@ static int loaded; + + static void *kernel_addr; + static grub_uint64_t kernel_size; ++static grub_uint32_t handover_offset; + + static char *linux_args; + static grub_uint32_t cmdline_size; +@@ -67,7 +69,8 @@ grub_arm64_uefi_check_image (struct grub + static grub_err_t + finalize_params_linux (void) + { +- int node, retval; ++ grub_efi_loaded_image_t *loaded_image = NULL; ++ int node, retval, len; + + void *fdt; + +@@ -102,6 +105,26 @@ finalize_params_linux (void) + if (grub_fdt_install() != GRUB_ERR_NONE) + goto failure; + ++ grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n", ++ fdt); ++ ++ /* Convert command line to UCS-2 */ ++ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); ++ if (!loaded_image) ++ goto failure; ++ ++ loaded_image->load_options_size = len = ++ (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t); ++ loaded_image->load_options = ++ grub_efi_allocate_pages (0, ++ GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size)); ++ if (!loaded_image->load_options) ++ return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters"); ++ ++ loaded_image->load_options_size = ++ 2 * grub_utf8_to_utf16 (loaded_image->load_options, len, ++ (grub_uint8_t *) linux_args, len, NULL); ++ + return GRUB_ERR_NONE; + + failure: +@@ -109,73 +132,49 @@ failure: + return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); + } + ++static void ++free_params (void) ++{ ++ grub_efi_loaded_image_t *loaded_image = NULL; ++ ++ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle); ++ if (loaded_image) ++ { ++ if (loaded_image->load_options) ++ grub_efi_free_pages ((grub_efi_physical_address_t) ++ loaded_image->load_options, ++ GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size)); ++ loaded_image->load_options = NULL; ++ loaded_image->load_options_size = 0; ++ } ++} ++ + grub_err_t + grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args) + { +- grub_efi_memory_mapped_device_path_t *mempath; +- grub_efi_handle_t image_handle; +- grub_efi_boot_services_t *b; +- grub_efi_status_t status; +- grub_efi_loaded_image_t *loaded_image; +- int len; ++ grub_err_t retval; + +- mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t)); +- if (!mempath) ++ retval = finalize_params_linux (); ++ if (retval != GRUB_ERR_NONE) + return grub_errno; + +- mempath[0].header.type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE; +- mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE; +- mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath)); +- mempath[0].memory_type = GRUB_EFI_LOADER_DATA; +- mempath[0].start_address = addr; +- mempath[0].end_address = addr + size; +- +- mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE; +- mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; +- mempath[1].header.length = sizeof (grub_efi_device_path_t); +- +- b = grub_efi_system_table->boot_services; +- status = b->load_image (0, grub_efi_image_handle, +- (grub_efi_device_path_t *) mempath, +- (void *) addr, size, &image_handle); +- if (status != GRUB_EFI_SUCCESS) +- return grub_error (GRUB_ERR_BAD_OS, "cannot load image"); +- + grub_dprintf ("linux", "linux command line: '%s'\n", args); ++ grub_dprintf ("linux", "using kernel addr %p (was 0x%08lx); offset 0x%08x (size %zd)", ++ kernel_addr, addr, handover_offset, size); + +- /* Convert command line to UCS-2 */ +- loaded_image = grub_efi_get_loaded_image (image_handle); +- loaded_image->load_options_size = len = +- (grub_strlen (args) + 1) * sizeof (grub_efi_char16_t); +- loaded_image->load_options = +- grub_efi_allocate_pages (0, +- GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size)); +- if (!loaded_image->load_options) +- return grub_errno; +- +- loaded_image->load_options_size = +- 2 * grub_utf8_to_utf16 (loaded_image->load_options, len, +- (grub_uint8_t *) args, len, NULL); ++ retval = grub_efi_linux_boot ((char *)kernel_addr, handover_offset, ++ kernel_addr); + +- grub_dprintf ("linux", "starting image %p\n", image_handle); +- status = b->start_image (image_handle, 0, NULL); +- +- /* When successful, not reached */ +- b->unload_image (image_handle); +- grub_efi_free_pages ((grub_efi_physical_address_t) loaded_image->load_options, +- GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size)); +- +- return grub_errno; ++ /* Never reached... */ ++ free_params(); ++ return retval; + } + + static grub_err_t + grub_linux_boot (void) + { +- if (finalize_params_linux () != GRUB_ERR_NONE) +- return grub_errno; +- +- return (grub_arm64_uefi_boot_image((grub_addr_t)kernel_addr, +- kernel_size, linux_args)); ++ return grub_arm64_uefi_boot_image ((grub_addr_t)kernel_addr, ++ kernel_size, linux_args); + } + + static grub_err_t +@@ -253,6 +252,7 @@ grub_cmd_linux (grub_command_t cmd __att + { + grub_file_t file = 0; + struct grub_arm64_linux_kernel_header lh; ++ struct grub_arm64_linux_pe_header *pe; + + grub_dl_ref (my_mod); + +@@ -297,6 +297,15 @@ grub_cmd_linux (grub_command_t cmd __att + + grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); + ++ if (!grub_linuxefi_secure_validate (kernel_addr, kernel_size)) ++ { ++ grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); ++ goto fail; ++ } ++ ++ pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset); ++ handover_offset = pe->opt.entry_addr; ++ + cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE); + linux_args = grub_malloc (cmdline_size); + if (!linux_args) +Index: b/grub-core/loader/efi/linux.c +=================================================================== +--- /dev/null ++++ b/grub-core/loader/efi/linux.c +@@ -0,0 +1,66 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2014 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SHIM_LOCK_GUID \ ++ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} } ++ ++struct grub_efi_shim_lock ++{ ++ grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size); ++}; ++typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; ++ ++grub_efi_boolean_t ++grub_linuxefi_secure_validate (void *data, grub_uint32_t size) ++{ ++ grub_efi_guid_t guid = SHIM_LOCK_GUID; ++ grub_efi_shim_lock_t *shim_lock; ++ ++ shim_lock = grub_efi_locate_protocol(&guid, NULL); ++ ++ if (!shim_lock) ++ return 1; ++ ++ if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS) ++ return 1; ++ ++ return 0; ++} ++ ++typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *); ++ ++grub_err_t ++grub_efi_linux_boot (void *kernel_addr, grub_off_t offset, ++ void *kernel_params) ++{ ++ handover_func hf; ++ ++ hf = (handover_func)((char *)kernel_addr + offset); ++ hf (grub_efi_image_handle, grub_efi_system_table, kernel_params); ++ ++ return GRUB_ERR_BUG; ++} ++ +Index: b/grub-core/loader/i386/efi/linux.c +=================================================================== +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -40,52 +41,18 @@ static char *linux_cmdline; + + #define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) + +-#define SHIM_LOCK_GUID \ +- { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} } +- +-struct grub_efi_shim_lock +-{ +- grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size); +-}; +-typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; +- +-static grub_efi_boolean_t +-grub_linuxefi_secure_validate (void *data, grub_uint32_t size) +-{ +- grub_efi_guid_t guid = SHIM_LOCK_GUID; +- grub_efi_shim_lock_t *shim_lock; +- +- shim_lock = grub_efi_locate_protocol(&guid, NULL); +- +- if (!shim_lock) +- return 1; +- +- if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS) +- return 1; +- +- return 0; +-} +- +-typedef void(*handover_func)(void *, grub_efi_system_table_t *, struct linux_kernel_params *); +- + static grub_err_t + grub_linuxefi_boot (void) + { +- handover_func hf; + int offset = 0; + + #ifdef __x86_64__ + offset = 512; + #endif +- +- hf = (handover_func)((char *)kernel_mem + handover_offset + offset); +- + asm volatile ("cli"); + +- hf (grub_efi_image_handle, grub_efi_system_table, params); +- +- /* Not reached */ +- return GRUB_ERR_NONE; ++ return grub_efi_linux_boot ((char *)kernel_mem, handover_offset + offset, ++ params); + } + + static grub_err_t +Index: b/include/grub/arm64/linux.h +=================================================================== +--- a/include/grub/arm64/linux.h ++++ b/include/grub/arm64/linux.h +@@ -20,6 +20,7 @@ + #define GRUB_LINUX_CPU_HEADER 1 + + #include ++#include + + #define GRUB_ARM64_LINUX_MAGIC 0x644d5241 /* 'ARM\x64' */ + +@@ -45,4 +46,11 @@ grub_err_t grub_arm64_uefi_check_image ( + grub_err_t grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, + char *args); + ++struct grub_arm64_linux_pe_header ++{ ++ grub_uint32_t magic; ++ struct grub_pe32_coff_header coff; ++ struct grub_pe64_optional_header opt; ++}; ++ + #endif /* ! GRUB_LINUX_CPU_HEADER */ +Index: b/include/grub/efi/linux.h +=================================================================== +--- /dev/null ++++ b/include/grub/efi/linux.h +@@ -0,0 +1,31 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2014 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++#ifndef GRUB_EFI_LINUX_HEADER ++#define GRUB_EFI_LINUX_HEADER 1 ++ ++#include ++#include ++#include ++ ++grub_efi_boolean_t ++EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size); ++grub_err_t ++EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset, ++ void *kernel_param); ++ ++#endif /* ! GRUB_EFI_LINUX_HEADER */ +Index: b/grub-core/loader/arm/linux.c +=================================================================== +--- a/grub-core/loader/arm/linux.c ++++ b/grub-core/loader/arm/linux.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + diff -Nru grub2-2.02~beta2/debian/patches/linuxefi_backport_arm64.patch grub2-2.02~beta2/debian/patches/linuxefi_backport_arm64.patch --- grub2-2.02~beta2/debian/patches/linuxefi_backport_arm64.patch 1970-01-01 00:00:00.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/linuxefi_backport_arm64.patch 2017-06-08 17:16:17.000000000 +0000 @@ -0,0 +1,1189 @@ +--- + grub-core/Makefile.core.def | 8 + grub-core/lib/fdt.c | 3 + grub-core/loader/arm64/fdt.c | 185 ++++++++++++++ + grub-core/loader/arm64/linux.c | 219 +++------------- + grub-core/loader/arm64/xen_boot.c | 499 ++++++++++++++++++++++++++++++++++++++ + include/grub/arm64/fdtload.h | 35 ++ + include/grub/arm64/linux.h | 7 + 7 files changed, 779 insertions(+), 177 deletions(-) + +Index: b/grub-core/loader/arm64/linux.c +=================================================================== +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -33,12 +34,6 @@ + + GRUB_MOD_LICENSE ("GPLv3+"); + +-#define GRUB_EFI_PAGE_SHIFT 12 +-#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> GRUB_EFI_PAGE_SHIFT) +-#define GRUB_EFI_PE_MAGIC 0x5A4D +- +-static grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID; +- + static grub_dl_t my_mod; + static int loaded; + +@@ -51,76 +46,15 @@ static grub_uint32_t cmdline_size; + static grub_addr_t initrd_start; + static grub_addr_t initrd_end; + +-static void *loaded_fdt; +-static void *fdt; +- +-static void * +-get_firmware_fdt (void) +-{ +- grub_efi_configuration_table_t *tables; +- void *firmware_fdt = NULL; +- unsigned int i; +- +- /* Look for FDT in UEFI config tables. */ +- tables = grub_efi_system_table->configuration_table; +- +- for (i = 0; i < grub_efi_system_table->num_table_entries; i++) +- if (grub_memcmp (&tables[i].vendor_guid, &fdt_guid, sizeof (fdt_guid)) == 0) +- { +- firmware_fdt = tables[i].vendor_table; +- grub_dprintf ("linux", "found registered FDT @ 0x%p\n", firmware_fdt); +- break; +- } +- +- return firmware_fdt; +-} +- +-static void +-get_fdt (void) +-{ +- void *raw_fdt; +- grub_size_t size; +- +- if (fdt) +- { +- size = BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt)); +- grub_efi_free_pages ((grub_efi_physical_address_t) fdt, size); +- } +- +- if (loaded_fdt) +- raw_fdt = loaded_fdt; +- else +- raw_fdt = get_firmware_fdt(); +- +- size = +- raw_fdt ? grub_fdt_get_totalsize (raw_fdt) : GRUB_FDT_EMPTY_TREE_SZ; +- size += 0x400; +- +- grub_dprintf ("linux", "allocating %ld bytes for fdt\n", size); +- fdt = grub_efi_allocate_pages (0, BYTES_TO_PAGES (size)); +- if (!fdt) +- return; +- +- if (raw_fdt) +- { +- grub_memmove (fdt, raw_fdt, size); +- grub_fdt_set_totalsize (fdt, size); +- } +- else +- { +- grub_fdt_create_empty_tree (fdt, size); +- } +-} +- +-static grub_err_t +-check_kernel (struct grub_arm64_linux_kernel_header *lh) ++grub_err_t ++grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header * lh) + { + if (lh->magic != GRUB_ARM64_LINUX_MAGIC) + return grub_error(GRUB_ERR_BAD_OS, "invalid magic number"); + + if ((lh->code0 & 0xffff) != GRUB_EFI_PE_MAGIC) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, +- N_("plain Image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled")); ++ N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled")); + + grub_dprintf ("linux", "UEFI stub kernel:\n"); + grub_dprintf ("linux", "text_offset = 0x%012llx\n", +@@ -131,13 +65,14 @@ check_kernel (struct grub_arm64_linux_ke + } + + static grub_err_t +-finalize_params (void) ++finalize_params_linux (void) + { +- grub_efi_boot_services_t *b; +- grub_efi_status_t status; + int node, retval; + +- get_fdt (); ++ void *fdt; ++ ++ fdt = grub_fdt_load (0x400); ++ + if (!fdt) + goto failure; + +@@ -164,97 +99,26 @@ finalize_params (void) + goto failure; + } + +- b = grub_efi_system_table->boot_services; +- status = b->install_configuration_table (&fdt_guid, fdt); +- if (status != GRUB_EFI_SUCCESS) ++ if (grub_fdt_install() != GRUB_ERR_NONE) + goto failure; + +- grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n", +- fdt); +- + return GRUB_ERR_NONE; + + failure: +- grub_efi_free_pages ((grub_efi_physical_address_t) fdt, +- BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt))); +- fdt = NULL; ++ grub_fdt_unload(); + return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT"); + } + +-static grub_err_t +-grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)), +- int argc, char *argv[]) +-{ +- grub_file_t dtb; +- void *blob = NULL; +- int size; +- +- if (!loaded) +- { +- grub_error (GRUB_ERR_BAD_ARGUMENT, +- N_("you need to load the kernel first")); +- return GRUB_ERR_BAD_OS; +- } +- +- if (argc != 1) +- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +- +- if (loaded_fdt) +- grub_free (loaded_fdt); +- loaded_fdt = NULL; +- +- dtb = grub_file_open (argv[0]); +- if (!dtb) +- goto out; +- +- size = grub_file_size (dtb); +- blob = grub_malloc (size); +- if (!blob) +- goto out; +- +- if (grub_file_read (dtb, blob, size) < size) +- { +- if (!grub_errno) +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]); +- goto out; +- } +- +- if (grub_fdt_check_header (blob, size) != 0) +- { +- grub_error (GRUB_ERR_BAD_OS, N_("invalid device tree")); +- goto out; +- } +- +-out: +- if (dtb) +- grub_file_close (dtb); +- +- if (blob) +- { +- if (grub_errno == GRUB_ERR_NONE) +- loaded_fdt = blob; +- else +- grub_free (blob); +- } +- +- return grub_errno; +-} +- +-static grub_err_t +-grub_linux_boot (void) ++grub_err_t ++grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args) + { + grub_efi_memory_mapped_device_path_t *mempath; + grub_efi_handle_t image_handle; + grub_efi_boot_services_t *b; + grub_efi_status_t status; +- grub_err_t retval; + grub_efi_loaded_image_t *loaded_image; + int len; + +- retval = finalize_params(); +- if (retval != GRUB_ERR_NONE) +- return retval; +- + mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t)); + if (!mempath) + return grub_errno; +@@ -263,64 +127,71 @@ grub_linux_boot (void) + mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE; + mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath)); + mempath[0].memory_type = GRUB_EFI_LOADER_DATA; +- mempath[0].start_address = (grub_addr_t) kernel_addr; +- mempath[0].end_address = (grub_addr_t) kernel_addr + kernel_size; ++ mempath[0].start_address = addr; ++ mempath[0].end_address = addr + size; + + mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE; + mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; +- mempath[1].header.length = 0; ++ mempath[1].header.length = sizeof (grub_efi_device_path_t); + + b = grub_efi_system_table->boot_services; + status = b->load_image (0, grub_efi_image_handle, + (grub_efi_device_path_t *) mempath, +- kernel_addr, kernel_size, &image_handle); ++ (void *) addr, size, &image_handle); + if (status != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_BAD_OS, "cannot load image"); + +- grub_dprintf ("linux", "linux command line: '%s'\n", linux_args); ++ grub_dprintf ("linux", "linux command line: '%s'\n", args); + + /* Convert command line to UCS-2 */ + loaded_image = grub_efi_get_loaded_image (image_handle); + loaded_image->load_options_size = len = +- (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t); ++ (grub_strlen (args) + 1) * sizeof (grub_efi_char16_t); + loaded_image->load_options = + grub_efi_allocate_pages (0, +- BYTES_TO_PAGES (loaded_image->load_options_size)); ++ GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size)); + if (!loaded_image->load_options) + return grub_errno; + + loaded_image->load_options_size = + 2 * grub_utf8_to_utf16 (loaded_image->load_options, len, +- (grub_uint8_t *) linux_args, len, NULL); ++ (grub_uint8_t *) args, len, NULL); + +- grub_dprintf("linux", "starting image %p\n", image_handle); ++ grub_dprintf ("linux", "starting image %p\n", image_handle); + status = b->start_image (image_handle, 0, NULL); + + /* When successful, not reached */ + b->unload_image (image_handle); + grub_efi_free_pages ((grub_efi_physical_address_t) loaded_image->load_options, +- BYTES_TO_PAGES (loaded_image->load_options_size)); ++ GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size)); + + return grub_errno; + } + + static grub_err_t ++grub_linux_boot (void) ++{ ++ if (finalize_params_linux () != GRUB_ERR_NONE) ++ return grub_errno; ++ ++ return (grub_arm64_uefi_boot_image((grub_addr_t)kernel_addr, ++ kernel_size, linux_args)); ++} ++ ++static grub_err_t + grub_linux_unload (void) + { + grub_dl_unref (my_mod); + loaded = 0; + if (initrd_start) + grub_efi_free_pages ((grub_efi_physical_address_t) initrd_start, +- BYTES_TO_PAGES (initrd_end - initrd_start)); ++ GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start)); + initrd_start = initrd_end = 0; + grub_free (linux_args); + if (kernel_addr) + grub_efi_free_pages ((grub_efi_physical_address_t) kernel_addr, +- BYTES_TO_PAGES (kernel_size)); +- if (fdt) +- grub_efi_free_pages ((grub_efi_physical_address_t) fdt, +- BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt))); +- ++ GRUB_EFI_BYTES_TO_PAGES (kernel_size)); ++ grub_fdt_unload (); + return GRUB_ERR_NONE; + } + +@@ -328,7 +199,7 @@ static grub_err_t + grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { +- struct grub_linux_initrd_context initrd_ctx; ++ struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 }; + int initrd_size, initrd_pages; + void *initrd_mem = NULL; + +@@ -351,7 +222,7 @@ grub_cmd_initrd (grub_command_t cmd __at + initrd_size = grub_get_initrd_size (&initrd_ctx); + grub_dprintf ("linux", "Loading initrd\n"); + +- initrd_pages = (BYTES_TO_PAGES (initrd_size)); ++ initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size)); + initrd_mem = grub_efi_allocate_pages (0, initrd_pages); + if (!initrd_mem) + { +@@ -400,15 +271,15 @@ grub_cmd_linux (grub_command_t cmd __att + if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh)) + return grub_errno; + +- if (check_kernel (&lh) != GRUB_ERR_NONE) ++ if (grub_arm64_uefi_check_image (&lh) != GRUB_ERR_NONE) + goto fail; + + grub_loader_unset(); + + grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size); +- kernel_addr = grub_efi_allocate_pages (0, BYTES_TO_PAGES (kernel_size)); ++ kernel_addr = grub_efi_allocate_pages (0, GRUB_EFI_BYTES_TO_PAGES (kernel_size)); + grub_dprintf ("linux", "kernel numpages: %lld\n", +- (long long) BYTES_TO_PAGES (kernel_size)); ++ (long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size)); + if (!kernel_addr) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); +@@ -459,13 +330,13 @@ fail: + + if (kernel_addr && !loaded) + grub_efi_free_pages ((grub_efi_physical_address_t) kernel_addr, +- BYTES_TO_PAGES (kernel_size)); ++ GRUB_EFI_BYTES_TO_PAGES (kernel_size)); + + return grub_errno; + } + + +-static grub_command_t cmd_linux, cmd_initrd, cmd_devicetree; ++static grub_command_t cmd_linux, cmd_initrd; + + GRUB_MOD_INIT (linux) + { +@@ -473,9 +344,6 @@ GRUB_MOD_INIT (linux) + N_("Load Linux.")); + cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0, + N_("Load initrd.")); +- cmd_devicetree = +- grub_register_command ("devicetree", grub_cmd_devicetree, 0, +- N_("Load DTB file.")); + my_mod = mod; + } + +@@ -483,5 +351,4 @@ GRUB_MOD_FINI (linux) + { + grub_unregister_command (cmd_linux); + grub_unregister_command (cmd_initrd); +- grub_unregister_command (cmd_devicetree); + } +Index: b/include/grub/arm64/linux.h +=================================================================== +--- a/include/grub/arm64/linux.h ++++ b/include/grub/arm64/linux.h +@@ -23,6 +23,8 @@ + + #define GRUB_ARM64_LINUX_MAGIC 0x644d5241 /* 'ARM\x64' */ + ++#define GRUB_EFI_PE_MAGIC 0x5A4D ++ + /* From linux/Documentation/arm64/booting.txt */ + struct grub_arm64_linux_kernel_header + { +@@ -38,4 +40,9 @@ struct grub_arm64_linux_kernel_header + grub_uint32_t hdr_offset; /* Offset of PE/COFF header */ + }; + ++grub_err_t grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header ++ *lh); ++grub_err_t grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, ++ char *args); ++ + #endif /* ! GRUB_LINUX_CPU_HEADER */ +Index: b/grub-core/loader/arm64/fdt.c +=================================================================== +--- /dev/null ++++ b/grub-core/loader/arm64/fdt.c +@@ -0,0 +1,185 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2013-2015 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static void *loaded_fdt; ++static void *fdt; ++ ++static void * ++get_firmware_fdt (void) ++{ ++ grub_efi_configuration_table_t *tables; ++ grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID; ++ void *firmware_fdt = NULL; ++ unsigned int i; ++ ++ /* Look for FDT in UEFI config tables. */ ++ tables = grub_efi_system_table->configuration_table; ++ ++ for (i = 0; i < grub_efi_system_table->num_table_entries; i++) ++ if (grub_memcmp (&tables[i].vendor_guid, &fdt_guid, sizeof (fdt_guid)) == 0) ++ { ++ firmware_fdt = tables[i].vendor_table; ++ grub_dprintf ("linux", "found registered FDT @ %p\n", firmware_fdt); ++ break; ++ } ++ ++ return firmware_fdt; ++} ++ ++void * ++grub_fdt_load (grub_size_t additional_size) ++{ ++ void *raw_fdt; ++ grub_size_t size; ++ ++ if (fdt) ++ { ++ size = GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt)); ++ grub_efi_free_pages ((grub_efi_physical_address_t) fdt, size); ++ } ++ ++ if (loaded_fdt) ++ raw_fdt = loaded_fdt; ++ else ++ raw_fdt = get_firmware_fdt(); ++ ++ size = ++ raw_fdt ? grub_fdt_get_totalsize (raw_fdt) : GRUB_FDT_EMPTY_TREE_SZ; ++ size += additional_size; ++ ++ grub_dprintf ("linux", "allocating %ld bytes for fdt\n", size); ++ fdt = grub_efi_allocate_pages (0, GRUB_EFI_BYTES_TO_PAGES (size)); ++ if (!fdt) ++ return NULL; ++ ++ if (raw_fdt) ++ { ++ grub_memmove (fdt, raw_fdt, size); ++ grub_fdt_set_totalsize (fdt, size); ++ } ++ else ++ { ++ grub_fdt_create_empty_tree (fdt, size); ++ } ++ return fdt; ++} ++ ++grub_err_t ++grub_fdt_install (void) ++{ ++ grub_efi_boot_services_t *b; ++ grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID; ++ grub_efi_status_t status; ++ ++ b = grub_efi_system_table->boot_services; ++ status = b->install_configuration_table (&fdt_guid, fdt); ++ if (status != GRUB_EFI_SUCCESS) ++ return grub_error (GRUB_ERR_IO, "failed to install FDT"); ++ ++ grub_dprintf ("fdt", "Installed/updated FDT configuration table @ %p\n", ++ fdt); ++ return GRUB_ERR_NONE; ++} ++ ++void ++grub_fdt_unload (void) { ++ if (!fdt) { ++ return; ++ } ++ grub_efi_free_pages ((grub_efi_physical_address_t) fdt, ++ GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt))); ++ fdt = NULL; ++} ++ ++static grub_err_t ++grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char *argv[]) ++{ ++ grub_file_t dtb; ++ void *blob = NULL; ++ int size; ++ ++ if (loaded_fdt) ++ grub_free (loaded_fdt); ++ loaded_fdt = NULL; ++ ++ /* No arguments means "use firmware FDT". */ ++ if (argc == 0) ++ { ++ return GRUB_ERR_NONE; ++ } ++ ++ dtb = grub_file_open (argv[0]); ++ if (!dtb) ++ goto out; ++ ++ size = grub_file_size (dtb); ++ blob = grub_malloc (size); ++ if (!blob) ++ goto out; ++ ++ if (grub_file_read (dtb, blob, size) < size) ++ { ++ if (!grub_errno) ++ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]); ++ goto out; ++ } ++ ++ if (grub_fdt_check_header (blob, size) != 0) ++ { ++ grub_error (GRUB_ERR_BAD_OS, N_("invalid device tree")); ++ goto out; ++ } ++ ++out: ++ if (dtb) ++ grub_file_close (dtb); ++ ++ if (blob) ++ { ++ if (grub_errno == GRUB_ERR_NONE) ++ loaded_fdt = blob; ++ else ++ grub_free (blob); ++ } ++ ++ return grub_errno; ++} ++ ++static grub_command_t cmd_devicetree; ++ ++GRUB_MOD_INIT (fdt) ++{ ++ cmd_devicetree = ++ grub_register_command ("devicetree", grub_cmd_devicetree, 0, ++ N_("Load DTB file.")); ++} ++ ++GRUB_MOD_FINI (fdt) ++{ ++ grub_unregister_command (cmd_devicetree); ++} +Index: b/grub-core/loader/arm64/xen_boot.c +=================================================================== +--- /dev/null ++++ b/grub-core/loader/arm64/xen_boot.c +@@ -0,0 +1,499 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2014 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* required by struct xen_hypervisor_header */ ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++#define XEN_HYPERVISOR_NAME "xen_hypervisor" ++#define MODULE_CUSTOM_COMPATIBLE "multiboot,module" ++ ++/* This maximum size is defined in Power.org ePAPR V1.1 ++ * https://www.power.org/documentation/epapr-version-1-1/ ++ * 2.2.1.1 Node Name Requirements ++ * node-name@unit-address ++ * 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49 ++ */ ++#define FDT_NODE_NAME_MAX_SIZE (49) ++ ++struct compat_string_struct ++{ ++ grub_size_t size; ++ const char *compat_string; ++}; ++typedef struct compat_string_struct compat_string_struct_t; ++#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)} ++ ++enum module_type ++{ ++ MODULE_IMAGE, ++ MODULE_INITRD, ++ MODULE_XSM, ++ MODULE_CUSTOM ++}; ++typedef enum module_type module_type_t; ++ ++struct xen_hypervisor_header ++{ ++ struct grub_arm64_linux_kernel_header efi_head; ++ ++ /* This is always PE\0\0. */ ++ grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE]; ++ /* The COFF file header. */ ++ struct grub_pe32_coff_header coff_header; ++ /* The Optional header. */ ++ struct grub_pe64_optional_header optional_header; ++}; ++ ++struct xen_boot_binary ++{ ++ struct xen_boot_binary *next; ++ struct xen_boot_binary **prev; ++ int is_hypervisor; ++ ++ grub_addr_t start; ++ grub_size_t size; ++ grub_size_t align; ++ ++ char *cmdline; ++ int cmdline_size; ++}; ++ ++static grub_dl_t my_mod; ++ ++static int loaded; ++ ++static struct xen_boot_binary *xen_hypervisor; ++static struct xen_boot_binary *module_head; ++ ++static __inline grub_addr_t ++xen_boot_address_align (grub_addr_t start, grub_size_t align) ++{ ++ return (align ? (ALIGN_UP (start, align)) : start); ++} ++ ++static grub_err_t ++prepare_xen_hypervisor_params (void *xen_boot_fdt) ++{ ++ int chosen_node = 0; ++ int retval; ++ ++ chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen"); ++ if (chosen_node < 0) ++ chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen"); ++ if (chosen_node < 1) ++ return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT"); ++ ++ grub_dprintf ("xen_loader", ++ "Xen Hypervisor cmdline : %s @ %p size:%d\n", ++ xen_hypervisor->cmdline, xen_hypervisor->cmdline, ++ xen_hypervisor->cmdline_size); ++ ++ retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs", ++ xen_hypervisor->cmdline, ++ xen_hypervisor->cmdline_size); ++ if (retval) ++ return grub_error (GRUB_ERR_IO, "failed to install/update FDT"); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++prepare_xen_module_params (struct xen_boot_binary *module, void *xen_boot_fdt) ++{ ++ int retval, chosen_node = 0, module_node = 0; ++ char module_name[FDT_NODE_NAME_MAX_SIZE]; ++ ++ retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx", ++ xen_boot_address_align (module->start, ++ module->align)); ++ grub_dprintf ("xen_loader", "Module node name %s \n", module_name); ++ ++ if (retval < (int) sizeof ("module@")) ++ return grub_error (GRUB_ERR_IO, N_("failed to get FDT")); ++ ++ chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen"); ++ if (chosen_node < 0) ++ chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen"); ++ if (chosen_node < 1) ++ return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT"); ++ ++ module_node = ++ grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name); ++ if (module_node < 0) ++ module_node = ++ grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name); ++ ++ retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible", ++ MODULE_CUSTOM_COMPATIBLE, sizeof(MODULE_CUSTOM_COMPATIBLE) - 1); ++ if (retval) ++ return grub_error (GRUB_ERR_IO, "failed to update FDT"); ++ ++ grub_dprintf ("xen_loader", "Module\n"); ++ ++ retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node, ++ xen_boot_address_align (module->start, ++ module->align), ++ module->size); ++ if (retval) ++ return grub_error (GRUB_ERR_IO, "failed to update FDT"); ++ ++ if (module->cmdline && module->cmdline_size > 0) ++ { ++ grub_dprintf ("xen_loader", ++ "Module cmdline : %s @ %p size:%d\n", ++ module->cmdline, module->cmdline, module->cmdline_size); ++ ++ retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs", ++ module->cmdline, module->cmdline_size + 1); ++ if (retval) ++ return grub_error (GRUB_ERR_IO, "failed to update FDT"); ++ } ++ else ++ { ++ grub_dprintf ("xen_loader", "Module has no bootargs!\n"); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++finalize_params_xen_boot (void) ++{ ++ struct xen_boot_binary *module; ++ void *xen_boot_fdt; ++ grub_size_t additional_size = 0x1000; ++ ++ /* Hypervisor. */ ++ additional_size += FDT_NODE_NAME_MAX_SIZE + xen_hypervisor->cmdline_size; ++ FOR_LIST_ELEMENTS (module, module_head) ++ { ++ additional_size += 6 * FDT_NODE_NAME_MAX_SIZE + sizeof(MODULE_CUSTOM_COMPATIBLE) - 1 ++ + module->cmdline_size; ++ } ++ ++ xen_boot_fdt = grub_fdt_load (additional_size); ++ if (!xen_boot_fdt) ++ return grub_error (GRUB_ERR_IO, "failed to get FDT"); ++ ++ if (xen_hypervisor) ++ { ++ if (prepare_xen_hypervisor_params (xen_boot_fdt) != GRUB_ERR_NONE) ++ goto fail; ++ } ++ else ++ { ++ grub_dprintf ("xen_loader", "Failed to get Xen Hypervisor info!\n"); ++ goto fail; ++ } ++ ++ /* Set module params info */ ++ FOR_LIST_ELEMENTS (module, module_head) ++ { ++ if (module->start && module->size > 0) ++ { ++ grub_dprintf ("xen_loader", "Module @ 0x%lx size:0x%lx\n", ++ xen_boot_address_align (module->start, module->align), ++ module->size); ++ if (prepare_xen_module_params (module, xen_boot_fdt) != GRUB_ERR_NONE) ++ goto fail; ++ } ++ else ++ { ++ grub_dprintf ("xen_loader", "Module info error!\n"); ++ goto fail; ++ } ++ } ++ ++ if (grub_fdt_install() == GRUB_ERR_NONE) ++ return GRUB_ERR_NONE; ++ ++fail: ++ grub_fdt_unload (); ++ ++ return grub_error (GRUB_ERR_IO, "failed to install/update FDT"); ++} ++ ++ ++static grub_err_t ++xen_boot (void) ++{ ++ grub_err_t err = finalize_params_xen_boot (); ++ if (err) ++ return err; ++ ++ return grub_arm64_uefi_boot_image (xen_hypervisor->start, ++ xen_hypervisor->size, ++ xen_hypervisor->cmdline); ++} ++ ++static void ++single_binary_unload (struct xen_boot_binary *binary) ++{ ++ if (!binary) ++ return; ++ ++ if (binary->start && binary->size > 0) ++ { ++ grub_efi_free_pages ((grub_efi_physical_address_t) binary->start, ++ GRUB_EFI_BYTES_TO_PAGES (binary->size + binary->align)); ++ } ++ ++ if (binary->cmdline && binary->cmdline_size > 0) ++ { ++ grub_free (binary->cmdline); ++ grub_dprintf ("xen_loader", ++ "Module cmdline memory free @ %p size: %d\n", ++ binary->cmdline, binary->cmdline_size); ++ } ++ ++ if (!binary->is_hypervisor) ++ grub_list_remove (GRUB_AS_LIST (binary)); ++ ++ grub_dprintf ("xen_loader", ++ "Module struct memory free @ %p size: 0x%lx\n", ++ binary, sizeof (binary)); ++ grub_free (binary); ++ ++ return; ++} ++ ++static void ++all_binaries_unload (void) ++{ ++ struct xen_boot_binary *binary; ++ ++ FOR_LIST_ELEMENTS (binary, module_head) ++ { ++ single_binary_unload (binary); ++ } ++ ++ if (xen_hypervisor) ++ single_binary_unload (xen_hypervisor); ++ ++ return; ++} ++ ++static grub_err_t ++xen_unload (void) ++{ ++ loaded = 0; ++ all_binaries_unload (); ++ grub_fdt_unload (); ++ grub_dl_unref (my_mod); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static void ++xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file, ++ int argc, char *argv[]) ++{ ++ binary->size = grub_file_size (file); ++ grub_dprintf ("xen_loader", "Xen_boot file size: 0x%lx\n", binary->size); ++ ++ binary->start ++ = (grub_addr_t) grub_efi_allocate_pages (0, ++ GRUB_EFI_BYTES_TO_PAGES ++ (binary->size + ++ binary->align)); ++ if (!binary->start) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ return; ++ } ++ ++ grub_dprintf ("xen_loader", "Xen_boot numpages: 0x%lx\n", ++ GRUB_EFI_BYTES_TO_PAGES (binary->size + binary->align)); ++ ++ if (grub_file_read (file, (void *) xen_boot_address_align (binary->start, ++ binary->align), ++ binary->size) != (grub_ssize_t) binary->size) ++ { ++ single_binary_unload (binary); ++ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]); ++ return; ++ } ++ ++ if (argc > 1) ++ { ++ binary->cmdline_size = grub_loader_cmdline_size (argc - 1, argv + 1); ++ binary->cmdline = grub_zalloc (binary->cmdline_size); ++ if (!binary->cmdline) ++ { ++ single_binary_unload (binary); ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ return; ++ } ++ grub_create_loader_cmdline (argc - 1, argv + 1, binary->cmdline, ++ binary->cmdline_size); ++ grub_dprintf ("xen_loader", ++ "Xen_boot cmdline @ %p %s, size: %d\n", ++ binary->cmdline, binary->cmdline, binary->cmdline_size); ++ } ++ else ++ { ++ binary->cmdline_size = 0; ++ binary->cmdline = NULL; ++ } ++ ++ grub_errno = GRUB_ERR_NONE; ++ return; ++} ++ ++static grub_err_t ++grub_cmd_xen_module (grub_command_t cmd __attribute__((unused)), ++ int argc, char *argv[]) ++{ ++ ++ struct xen_boot_binary *module = NULL; ++ grub_file_t file = 0; ++ ++ if (!argc) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ goto fail; ++ } ++ ++ if (!loaded) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("you need to load the Xen Hypervisor first")); ++ goto fail; ++ } ++ ++ module = ++ (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary)); ++ if (!module) ++ return grub_errno; ++ ++ module->is_hypervisor = 0; ++ module->align = 4096; ++ ++ grub_dprintf ("xen_loader", "Init module and node info\n"); ++ ++ file = grub_file_open (argv[0]); ++ if (!file) ++ goto fail; ++ ++ xen_boot_binary_load (module, file, argc, argv); ++ if (grub_errno == GRUB_ERR_NONE) ++ grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module)); ++ ++ fail: ++ if (file) ++ grub_file_close (file); ++ if (grub_errno != GRUB_ERR_NONE) ++ single_binary_unload (module); ++ ++ return grub_errno; ++} ++ ++static grub_err_t ++grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char *argv[]) ++{ ++ struct xen_hypervisor_header sh; ++ grub_file_t file = NULL; ++ ++ grub_dl_ref (my_mod); ++ ++ if (!argc) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); ++ goto fail; ++ } ++ ++ file = grub_file_open (argv[0]); ++ if (!file) ++ goto fail; ++ ++ if (grub_file_read (file, &sh, sizeof (sh)) != (long) sizeof (sh)) ++ goto fail; ++ if (grub_arm64_uefi_check_image ++ ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE) ++ goto fail; ++ grub_file_seek (file, 0); ++ ++ /* if another module has called grub_loader_set, ++ we need to make sure that another module is unloaded properly */ ++ grub_loader_unset (); ++ ++ xen_hypervisor = ++ (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary)); ++ if (!xen_hypervisor) ++ return grub_errno; ++ ++ xen_hypervisor->is_hypervisor = 1; ++ xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment; ++ ++ xen_boot_binary_load (xen_hypervisor, file, argc, argv); ++ if (grub_errno == GRUB_ERR_NONE) ++ { ++ grub_loader_set (xen_boot, xen_unload, 0); ++ loaded = 1; ++ } ++ ++fail: ++ if (file) ++ grub_file_close (file); ++ if (grub_errno != GRUB_ERR_NONE) ++ { ++ loaded = 0; ++ all_binaries_unload (); ++ grub_dl_unref (my_mod); ++ } ++ ++ return grub_errno; ++} ++ ++static grub_command_t cmd_xen_hypervisor; ++static grub_command_t cmd_xen_module; ++ ++GRUB_MOD_INIT (xen_boot) ++{ ++ cmd_xen_hypervisor = ++ grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0, ++ N_("Load a xen hypervisor.")); ++ cmd_xen_module = ++ grub_register_command ("xen_module", grub_cmd_xen_module, 0, ++ N_("Load a xen module.")); ++ my_mod = mod; ++} ++ ++GRUB_MOD_FINI (xen_boot) ++{ ++ grub_unregister_command (cmd_xen_hypervisor); ++ grub_unregister_command (cmd_xen_module); ++} +Index: b/include/grub/arm64/fdtload.h +=================================================================== +--- /dev/null ++++ b/include/grub/arm64/fdtload.h +@@ -0,0 +1,35 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2013-2015 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_FDTLOAD_CPU_HEADER ++#define GRUB_FDTLOAD_CPU_HEADER 1 ++ ++#include ++#include ++ ++void * ++grub_fdt_load (grub_size_t additional_size); ++void ++grub_fdt_unload (void); ++grub_err_t ++grub_fdt_install (void); ++ ++#define GRUB_EFI_PAGE_SHIFT 12 ++#define GRUB_EFI_BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> GRUB_EFI_PAGE_SHIFT) ++ ++#endif +Index: b/grub-core/Makefile.core.def +=================================================================== +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1673,13 +1673,19 @@ module = { + ia64_efi = loader/ia64/efi/linux.c; + arm = loader/arm/linux.c; + arm64 = loader/arm64/linux.c; +- fdt = lib/fdt.c; + common = loader/linux.c; + common = lib/cmdline.c; + enable = noemu; + }; + + module = { ++ name = fdt; ++ arm64 = loader/arm64/fdt.c; ++ common = lib/fdt.c; ++ enable = fdt; ++}; ++ ++module = { + name = xnu; + x86 = loader/xnu_resume.c; + x86 = loader/i386/xnu.c; +Index: b/grub-core/lib/fdt.c +=================================================================== +--- a/grub-core/lib/fdt.c ++++ b/grub-core/lib/fdt.c +@@ -19,6 +19,9 @@ + #include + #include + #include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); + + #define FDT_SUPPORTED_VERSION 17 + diff -Nru grub2-2.02~beta2/debian/patches/linuxefi_chainloader_path.patch grub2-2.02~beta2/debian/patches/linuxefi_chainloader_path.patch --- grub2-2.02~beta2/debian/patches/linuxefi_chainloader_path.patch 1970-01-01 00:00:00.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/linuxefi_chainloader_path.patch 2017-06-08 17:16:17.000000000 +0000 @@ -0,0 +1,34 @@ +From 4b30b1a7b7eac0981b91fd76b21e8bd674b4d7fc Mon Sep 17 00:00:00 2001 +From: Raymund Will +Date: Fri, 10 Apr 2015 01:45:02 -0400 +Subject: [PATCH] Use device part of chainloader target, if present. + +Otherwise chainloading is restricted to '$root', which might not even +be readable by EFI! + +v1. use grub_file_get_device_name() to get device name + +Signed-off-by: Michael Chang +Signed-off-by: Peter Jones +--- + grub-core/loader/efi/chainloader.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +Index: b/grub-core/loader/efi/chainloader.c +=================================================================== +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -219,8 +219,11 @@ grub_cmd_chainloader (grub_command_t cmd + if (! file) + goto fail; + +- /* Get the root device's device path. */ +- dev = grub_device_open (0); ++ /* Get the device path from filename. */ ++ char *devname = grub_file_get_device_name (filename); ++ dev = grub_device_open (devname); ++ if (devname) ++ grub_free (devname); + if (! dev) + goto fail; + diff -Nru grub2-2.02~beta2/debian/patches/linuxefi_chainloader_pe_fixes.patch grub2-2.02~beta2/debian/patches/linuxefi_chainloader_pe_fixes.patch --- grub2-2.02~beta2/debian/patches/linuxefi_chainloader_pe_fixes.patch 1970-01-01 00:00:00.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/linuxefi_chainloader_pe_fixes.patch 2017-06-08 17:16:17.000000000 +0000 @@ -0,0 +1,350 @@ +From 8170e902e9c48cee1dc727445656a1c4b802b70e Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 9 Jun 2016 12:22:29 -0400 +Subject: [PATCH] Re-work some intricacies of PE loading. + +The PE spec is not a well written document, and awesomely every place +where there's an ambiguous way to read something, Windows' bootmgfw.efi +takes a different read than either of them. +--- + grub-core/loader/efi/chainloader.c | 156 +++++++++++++++++++++++++++++-------- + include/grub/efi/pe32.h | 32 ++++++- + 2 files changed, 152 insertions(+), 36 deletions(-) + +Index: b/grub-core/loader/efi/chainloader.c +=================================================================== +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -297,7 +297,7 @@ image_is_64_bit (grub_pe_header_t *pe_hd + return 0; + } + +-static const grub_uint16_t machine_type = ++static const grub_uint16_t machine_type __attribute__((__unused__)) = + #if defined(__x86_64__) + GRUB_PE32_MACHINE_X86_64; + #elif defined(__aarch64__) +@@ -363,10 +363,10 @@ relocate_coff (pe_coff_loader_image_cont + + reloc_base = image_address (orig, size, section->raw_data_offset); + reloc_base_end = image_address (orig, size, section->raw_data_offset +- + section->virtual_size - 1); ++ + section->virtual_size); + +- grub_dprintf ("chain", "reloc_base %p reloc_base_end %p\n", reloc_base, +- reloc_base_end); ++ grub_dprintf ("chain", "relocate_coff(): reloc_base %p reloc_base_end %p\n", ++ reloc_base, reloc_base_end); + + if (!reloc_base && !reloc_base_end) + return GRUB_EFI_SUCCESS; +@@ -503,12 +503,13 @@ handle_image (void *data, grub_efi_uint3 + grub_efi_status_t efi_status; + char *buffer = NULL; + char *buffer_aligned = NULL; +- grub_efi_uint32_t i, size; ++ grub_efi_uint32_t i; + struct grub_pe32_section_table *section; + char *base, *end; + pe_coff_loader_image_context_t context; + grub_uint32_t section_alignment; + grub_uint32_t buffer_size; ++ int found_entry_point = 0; + + b = grub_efi_system_table->boot_services; + +@@ -522,8 +523,28 @@ handle_image (void *data, grub_efi_uint3 + goto error_exit; + } + ++ /* ++ * The spec says, uselessly, of SectionAlignment: ++ * ===== ++ * The alignment (in bytes) of sections when they are loaded into ++ * memory. It must be greater than or equal to FileAlignment. The ++ * default is the page size for the architecture. ++ * ===== ++ * Which doesn't tell you whose responsibility it is to enforce the ++ * "default", or when. It implies that the value in the field must ++ * be > FileAlignment (also poorly defined), but it appears visual ++ * studio will happily write 512 for FileAlignment (its default) and ++ * 0 for SectionAlignment, intending to imply PAGE_SIZE. ++ * ++ * We only support one page size, so if it's zero, nerf it to 4096. ++ */ + section_alignment = context.section_alignment; ++ if (section_alignment == 0) ++ section_alignment = 4096; ++ + buffer_size = context.image_size + section_alignment; ++ grub_dprintf ("chain", "image size is %08lx, datasize is %08x\n", ++ context.image_size, datasize); + + efi_status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA, + buffer_size, (void **) &buffer); +@@ -535,7 +556,6 @@ handle_image (void *data, grub_efi_uint3 + } + + buffer_aligned = (char *)ALIGN_UP ((grub_addr_t)buffer, section_alignment); +- + if (!buffer_aligned) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); +@@ -544,27 +564,62 @@ handle_image (void *data, grub_efi_uint3 + + grub_memcpy (buffer_aligned, data, context.size_of_headers); + ++ entry_point = image_address (buffer_aligned, context.image_size, ++ context.entry_point); ++ ++ grub_dprintf ("chain", "entry_point: %p\n", entry_point); ++ if (!entry_point) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid entry point"); ++ goto error_exit; ++ } ++ + char *reloc_base, *reloc_base_end; +- reloc_base = image_address (buffer_aligned, datasize, ++ grub_dprintf ("chain", "reloc_dir: %p reloc_size: 0x%08x\n", ++ context.reloc_dir->rva, ++ context.reloc_dir->size); ++ reloc_base = image_address (buffer_aligned, context.image_size, + context.reloc_dir->rva); + /* RelocBaseEnd here is the address of the last byte of the table */ +- reloc_base_end = image_address (buffer_aligned, datasize, ++ reloc_base_end = image_address (buffer_aligned, context.image_size, + context.reloc_dir->rva + + context.reloc_dir->size - 1); ++ grub_dprintf ("chain", "reloc_base: %p reloc_base_end: %p\n", ++ reloc_base, reloc_base_end); ++ + struct grub_pe32_section_table *reloc_section = NULL; + + section = context.first_section; + for (i = 0; i < context.number_of_sections; i++, section++) + { +- size = section->virtual_size; +- if (size > section->raw_data_size) +- size = section->raw_data_size; ++ char name[9]; + + base = image_address (buffer_aligned, context.image_size, + section->virtual_address); + end = image_address (buffer_aligned, context.image_size, +- section->virtual_address + size - 1); ++ section->virtual_address + section->virtual_size -1); + ++ grub_strncpy(name, section->name, 9); ++ name[8] = '\0'; ++ grub_dprintf ("chain", "Section %d \"%s\" at %p..%p\n", i, ++ name, base, end); ++ ++ if (end < base) ++ { ++ grub_dprintf ("chain", " base is %p but end is %p... bad.\n", ++ base, end); ++ grub_error (GRUB_ERR_BAD_ARGUMENT, ++ "Image has invalid negative size"); ++ goto error_exit; ++ } ++ ++ if (section->virtual_address <= context.entry_point && ++ (section->virtual_address + section->raw_data_size - 1) ++ > context.entry_point) ++ { ++ found_entry_point++; ++ grub_dprintf ("chain", " section contains entry point\n"); ++ } + + /* We do want to process .reloc, but it's often marked + * discardable, so we don't want to memcpy it. */ +@@ -583,21 +638,46 @@ handle_image (void *data, grub_efi_uint3 + if (section->raw_data_size && section->virtual_size && + base && end && reloc_base == base && reloc_base_end == end) + { ++ grub_dprintf ("chain", " section is relocation section\n"); + reloc_section = section; + } ++ else ++ { ++ grub_dprintf ("chain", " section is not reloc section?\n"); ++ grub_dprintf ("chain", " rds: 0x%08x, vs: %08x\n", ++ section->raw_data_size, section->virtual_size); ++ grub_dprintf ("chain", " base: %p end: %p\n", base, end); ++ grub_dprintf ("chain", " reloc_base: %p reloc_base_end: %p\n", ++ reloc_base, reloc_base_end); ++ } + } + +- if (section->characteristics && GRUB_PE32_SCN_MEM_DISCARDABLE) +- continue; ++ grub_dprintf ("chain", " Section characteristics are %08x\n", ++ section->characteristics); ++ grub_dprintf ("chain", " Section virtual size: %08x\n", ++ section->virtual_size); ++ grub_dprintf ("chain", " Section raw_data size: %08x\n", ++ section->raw_data_size); ++ if (section->characteristics & GRUB_PE32_SCN_MEM_DISCARDABLE) ++ { ++ grub_dprintf ("chain", " Discarding section\n"); ++ continue; ++ } + + if (!base || !end) + { ++ grub_dprintf ("chain", " section is invalid\n"); + grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid section size"); + goto error_exit; + } + +- if (section->virtual_address < context.size_of_headers || +- section->raw_data_offset < context.size_of_headers) ++ if (section->characteristics & GRUB_PE32_SCN_CNT_UNINITIALIZED_DATA) ++ { ++ if (section->raw_data_size != 0) ++ grub_dprintf ("chain", " UNINITIALIZED_DATA section has data?\n"); ++ } ++ else if (section->virtual_address < context.size_of_headers || ++ section->raw_data_offset < context.size_of_headers) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + "Section %d is inside image headers", i); +@@ -605,13 +685,24 @@ handle_image (void *data, grub_efi_uint3 + } + + if (section->raw_data_size > 0) +- grub_memcpy (base, (grub_efi_uint8_t*)data + section->raw_data_offset, +- size); ++ { ++ grub_dprintf ("chain", " copying 0x%08x bytes to %p\n", ++ section->raw_data_size, base); ++ grub_memcpy (base, ++ (grub_efi_uint8_t*)data + section->raw_data_offset, ++ section->raw_data_size); ++ } + +- if (size < section->virtual_size) +- grub_memset (base + size, 0, section->virtual_size - size); ++ if (section->raw_data_size < section->virtual_size) ++ { ++ grub_dprintf ("chain", " padding with 0x%08x bytes at %p\n", ++ section->virtual_size - section->raw_data_size, ++ base + section->raw_data_size); ++ grub_memset (base + section->raw_data_size, 0, ++ section->virtual_size - section->raw_data_size); ++ } + +- grub_dprintf ("chain", "copied section %s\n", section->name); ++ grub_dprintf ("chain", " finished section %s\n", name); + } + + /* 5 == EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC */ +@@ -634,12 +725,15 @@ handle_image (void *data, grub_efi_uint3 + } + } + +- entry_point = image_address (buffer_aligned, context.image_size, +- context.entry_point); +- +- if (!entry_point) ++ if (!found_entry_point) + { +- grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid entry point"); ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "entry point is not within sections"); ++ goto error_exit; ++ } ++ if (found_entry_point > 1) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "%d sections contain entry point", ++ found_entry_point); + goto error_exit; + } + +@@ -657,26 +751,24 @@ handle_image (void *data, grub_efi_uint3 + li->load_options_size = cmdline_len; + li->file_path = grub_efi_get_media_file_path (file_path); + li->device_handle = dev_handle; +- if (li->file_path) +- { +- grub_printf ("file path: "); +- grub_efi_print_device_path (li->file_path); +- } +- else ++ if (!li->file_path) + { + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found"); + goto error_exit; + } + ++ grub_dprintf ("chain", "booting via entry point\n"); + efi_status = efi_call_2 (entry_point, grub_efi_image_handle, + grub_efi_system_table); + ++ grub_dprintf ("chain", "entry_point returned %ld\n", efi_status); + grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t)); + efi_status = efi_call_1 (b->free_pool, buffer); + + return 1; + + error_exit: ++ grub_dprintf ("chain", "error_exit: grub_errno: %d\n", grub_errno); + if (buffer) + efi_call_1 (b->free_pool, buffer); + +Index: b/include/grub/efi/pe32.h +=================================================================== +--- a/include/grub/efi/pe32.h ++++ b/include/grub/efi/pe32.h +@@ -227,12 +227,18 @@ struct grub_pe32_section_table + grub_uint32_t characteristics; + }; + ++#define GRUB_PE32_SCN_TYPE_NO_PAD 0x00000008 + #define GRUB_PE32_SCN_CNT_CODE 0x00000020 + #define GRUB_PE32_SCN_CNT_INITIALIZED_DATA 0x00000040 +-#define GRUB_PE32_SCN_MEM_DISCARDABLE 0x02000000 +-#define GRUB_PE32_SCN_MEM_EXECUTE 0x20000000 +-#define GRUB_PE32_SCN_MEM_READ 0x40000000 +-#define GRUB_PE32_SCN_MEM_WRITE 0x80000000 ++#define GRUB_PE32_SCN_CNT_UNINITIALIZED_DATA 0x00000080 ++#define GRUB_PE32_SCN_LNK_OTHER 0x00000100 ++#define GRUB_PE32_SCN_LNK_INFO 0x00000200 ++#define GRUB_PE32_SCN_LNK_REMOVE 0x00000800 ++#define GRUB_PE32_SCN_LNK_COMDAT 0x00001000 ++#define GRUB_PE32_SCN_GPREL 0x00008000 ++#define GRUB_PE32_SCN_MEM_16BIT 0x00020000 ++#define GRUB_PE32_SCN_MEM_LOCKED 0x00040000 ++#define GRUB_PE32_SCN_MEM_PRELOAD 0x00080000 + + #define GRUB_PE32_SCN_ALIGN_1BYTES 0x00100000 + #define GRUB_PE32_SCN_ALIGN_2BYTES 0x00200000 +@@ -241,10 +247,28 @@ struct grub_pe32_section_table + #define GRUB_PE32_SCN_ALIGN_16BYTES 0x00500000 + #define GRUB_PE32_SCN_ALIGN_32BYTES 0x00600000 + #define GRUB_PE32_SCN_ALIGN_64BYTES 0x00700000 ++#define GRUB_PE32_SCN_ALIGN_128BYTES 0x00800000 ++#define GRUB_PE32_SCN_ALIGN_256BYTES 0x00900000 ++#define GRUB_PE32_SCN_ALIGN_512BYTES 0x00A00000 ++#define GRUB_PE32_SCN_ALIGN_1024BYTES 0x00B00000 ++#define GRUB_PE32_SCN_ALIGN_2048BYTES 0x00C00000 ++#define GRUB_PE32_SCN_ALIGN_4096BYTES 0x00D00000 ++#define GRUB_PE32_SCN_ALIGN_8192BYTES 0x00E00000 + + #define GRUB_PE32_SCN_ALIGN_SHIFT 20 + #define GRUB_PE32_SCN_ALIGN_MASK 7 + ++#define GRUB_PE32_SCN_LNK_NRELOC_OVFL 0x01000000 ++#define GRUB_PE32_SCN_MEM_DISCARDABLE 0x02000000 ++#define GRUB_PE32_SCN_MEM_NOT_CACHED 0x04000000 ++#define GRUB_PE32_SCN_MEM_NOT_PAGED 0x08000000 ++#define GRUB_PE32_SCN_MEM_SHARED 0x10000000 ++#define GRUB_PE32_SCN_MEM_EXECUTE 0x20000000 ++#define GRUB_PE32_SCN_MEM_READ 0x40000000 ++#define GRUB_PE32_SCN_MEM_WRITE 0x80000000 ++ ++ ++ + #define GRUB_PE32_SIGNATURE_SIZE 4 + + struct grub_pe32_header diff -Nru grub2-2.02~beta2/debian/patches/linuxefi_chainloader_sb.patch grub2-2.02~beta2/debian/patches/linuxefi_chainloader_sb.patch --- grub2-2.02~beta2/debian/patches/linuxefi_chainloader_sb.patch 1970-01-01 00:00:00.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/linuxefi_chainloader_sb.patch 2017-06-08 17:16:17.000000000 +0000 @@ -0,0 +1,820 @@ +From 6cb5703868e185c60b3cb5e78bd84288dd41f275 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 6 Oct 2015 13:04:37 -0400 +Subject: [PATCH] Add secureboot support on efi chainloader + +Expand the chainloader to be able to verify the image by means of shim +lock protocol. The PE/COFF image is loaded and relocated by the +chainloader instead of calling LoadImage and StartImage UEFI boot +Service as they require positive verification result from keys enrolled +in KEK or DB. The shim will use MOK in addition to firmware enrolled +keys to verify the image. + +The chainloader module could be used to load other UEFI bootloaders, +such as xen.efi, and could be signed by any of MOK, KEK or DB. + +Based on https://build.opensuse.org/package/view_file/openSUSE:Factory/grub2/grub2-secureboot-chainloader.patch + +Signed-off-by: Peter Jones +--- + grub-core/Makefile.core.def | 3 + grub-core/loader/efi/chainloader.c | 612 ++++++++++++++++++++++++++++++++++--- + include/grub/efi/pe32.h | 20 + + 3 files changed, 598 insertions(+), 37 deletions(-) + +Index: b/grub-core/loader/efi/chainloader.c +=================================================================== +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -32,6 +32,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -46,9 +48,14 @@ static grub_dl_t my_mod; + + static grub_efi_physical_address_t address; + static grub_efi_uintn_t pages; ++static grub_ssize_t fsize; + static grub_efi_device_path_t *file_path; + static grub_efi_handle_t image_handle; + static grub_efi_char16_t *cmdline; ++static grub_ssize_t cmdline_len; ++static grub_efi_handle_t dev_handle; ++ ++static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table); + + static grub_err_t + grub_chainloader_unload (void) +@@ -63,6 +70,7 @@ grub_chainloader_unload (void) + grub_free (cmdline); + cmdline = 0; + file_path = 0; ++ dev_handle = 0; + + grub_dl_unref (my_mod); + return GRUB_ERR_NONE; +@@ -187,12 +195,523 @@ make_file_path (grub_efi_device_path_t * + return file_path; + } + ++#define SHIM_LOCK_GUID \ ++ { 0x605dab50, 0xe046, 0x4300, { 0xab,0xb6,0x3d,0xd8,0x10,0xdd,0x8b,0x23 } } ++ ++typedef union ++{ ++ struct grub_pe32_header_32 pe32; ++ struct grub_pe32_header_64 pe32plus; ++} grub_pe_header_t; ++ ++struct pe_coff_loader_image_context ++{ ++ grub_efi_uint64_t image_address; ++ grub_efi_uint64_t image_size; ++ grub_efi_uint64_t entry_point; ++ grub_efi_uintn_t size_of_headers; ++ grub_efi_uint16_t image_type; ++ grub_efi_uint16_t number_of_sections; ++ grub_efi_uint32_t section_alignment; ++ struct grub_pe32_section_table *first_section; ++ struct grub_pe32_data_directory *reloc_dir; ++ struct grub_pe32_data_directory *sec_dir; ++ grub_efi_uint64_t number_of_rva_and_sizes; ++ grub_pe_header_t *pe_hdr; ++}; ++ ++typedef struct pe_coff_loader_image_context pe_coff_loader_image_context_t; ++ ++struct grub_efi_shim_lock ++{ ++ grub_efi_status_t (*verify)(void *buffer, ++ grub_efi_uint32_t size); ++ grub_efi_status_t (*hash)(void *data, ++ grub_efi_int32_t datasize, ++ pe_coff_loader_image_context_t *context, ++ grub_efi_uint8_t *sha256hash, ++ grub_efi_uint8_t *sha1hash); ++ grub_efi_status_t (*context)(void *data, ++ grub_efi_uint32_t size, ++ pe_coff_loader_image_context_t *context); ++}; ++ ++typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; ++ ++static grub_efi_boolean_t ++read_header (void *data, grub_efi_uint32_t size, ++ pe_coff_loader_image_context_t *context) ++{ ++ grub_efi_guid_t guid = SHIM_LOCK_GUID; ++ grub_efi_shim_lock_t *shim_lock; ++ grub_efi_status_t status; ++ ++ shim_lock = grub_efi_locate_protocol (&guid, NULL); ++ ++ if (!shim_lock) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "no shim lock protocol"); ++ return 0; ++ } ++ ++ status = shim_lock->context (data, size, context); ++ ++ if (status == GRUB_EFI_SUCCESS) ++ { ++ grub_dprintf ("chain", "context success\n"); ++ return 1; ++ } ++ ++ switch (status) ++ { ++ case GRUB_EFI_UNSUPPORTED: ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "context error unsupported"); ++ break; ++ case GRUB_EFI_INVALID_PARAMETER: ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "context error invalid parameter"); ++ break; ++ default: ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "context error code"); ++ break; ++ } ++ ++ return 0; ++} ++ ++static void* ++image_address (void *image, grub_efi_uint64_t sz, grub_efi_uint64_t adr) ++{ ++ if (adr > sz) ++ return NULL; ++ ++ return ((grub_uint8_t*)image + adr); ++} ++ ++static int ++image_is_64_bit (grub_pe_header_t *pe_hdr) ++{ ++ /* .Magic is the same offset in all cases */ ++ if (pe_hdr->pe32plus.optional_header.magic == GRUB_PE32_PE64_MAGIC) ++ return 1; ++ return 0; ++} ++ ++static const grub_uint16_t machine_type = ++#if defined(__x86_64__) ++ GRUB_PE32_MACHINE_X86_64; ++#elif defined(__aarch64__) ++ GRUB_PE32_MACHINE_ARM64; ++#elif defined(__arm__) ++ GRUB_PE32_MACHINE_ARMTHUMB_MIXED; ++#elif defined(__i386__) || defined(__i486__) || defined(__i686__) ++ GRUB_PE32_MACHINE_I386; ++#elif defined(__ia64__) ++ GRUB_PE32_MACHINE_IA64; ++#else ++#error this architecture is not supported by grub2 ++#endif ++ ++static grub_efi_status_t ++relocate_coff (pe_coff_loader_image_context_t *context, ++ struct grub_pe32_section_table *section, ++ void *orig, void *data) ++{ ++ struct grub_pe32_data_directory *reloc_base, *reloc_base_end; ++ grub_efi_uint64_t adjust; ++ struct grub_pe32_fixup_block *reloc, *reloc_end; ++ char *fixup, *fixup_base, *fixup_data = NULL; ++ grub_efi_uint16_t *fixup_16; ++ grub_efi_uint32_t *fixup_32; ++ grub_efi_uint64_t *fixup_64; ++ grub_efi_uint64_t size = context->image_size; ++ void *image_end = (char *)orig + size; ++ int n = 0; ++ ++ if (image_is_64_bit (context->pe_hdr)) ++ context->pe_hdr->pe32plus.optional_header.image_base = ++ (grub_uint64_t)(unsigned long)data; ++ else ++ context->pe_hdr->pe32.optional_header.image_base = ++ (grub_uint32_t)(unsigned long)data; ++ ++ /* Alright, so here's how this works: ++ * ++ * context->reloc_dir gives us two things: ++ * - the VA the table of base relocation blocks are (maybe) to be ++ * mapped at (reloc_dir->rva) ++ * - the virtual size (reloc_dir->size) ++ * ++ * The .reloc section (section here) gives us some other things: ++ * - the name! kind of. (section->name) ++ * - the virtual size (section->virtual_size), which should be the same ++ * as RelocDir->Size ++ * - the virtual address (section->virtual_address) ++ * - the file section size (section->raw_data_size), which is ++ * a multiple of optional_header->file_alignment. Only useful for image ++ * validation, not really useful for iteration bounds. ++ * - the file address (section->raw_data_offset) ++ * - a bunch of stuff we don't use that's 0 in our binaries usually ++ * - Flags (section->characteristics) ++ * ++ * and then the thing that's actually at the file address is an array ++ * of struct grub_pe32_fixup_block structs with some values packed behind ++ * them. The block_size field of this structure includes the ++ * structure itself, and adding it to that structure's address will ++ * yield the next entry in the array. ++ */ ++ ++ reloc_base = image_address (orig, size, section->raw_data_offset); ++ reloc_base_end = image_address (orig, size, section->raw_data_offset ++ + section->virtual_size - 1); ++ ++ grub_dprintf ("chain", "reloc_base %p reloc_base_end %p\n", reloc_base, ++ reloc_base_end); ++ ++ if (!reloc_base && !reloc_base_end) ++ return GRUB_EFI_SUCCESS; ++ ++ if (!reloc_base || !reloc_base_end) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc table overflows binary"); ++ return GRUB_EFI_UNSUPPORTED; ++ } ++ ++ adjust = (grub_uint64_t)(unsigned long)data - context->image_address; ++ if (adjust == 0) ++ return GRUB_EFI_SUCCESS; ++ ++ while (reloc_base < reloc_base_end) ++ { ++ grub_uint16_t *entry; ++ reloc = (struct grub_pe32_fixup_block *)((char*)reloc_base); ++ ++ if ((reloc_base->size == 0) || ++ (reloc_base->size > context->reloc_dir->size)) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, ++ "Reloc %d block size %d is invalid\n", n, ++ reloc_base->size); ++ return GRUB_EFI_UNSUPPORTED; ++ } ++ ++ entry = &reloc->entries[0]; ++ reloc_end = (struct grub_pe32_fixup_block *) ++ ((char *)reloc_base + reloc_base->size); ++ ++ if ((void *)reloc_end < data || (void *)reloc_end > image_end) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc entry %d overflows binary", ++ n); ++ return GRUB_EFI_UNSUPPORTED; ++ } ++ ++ fixup_base = image_address(data, size, reloc_base->rva); ++ ++ if (!fixup_base) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc %d Invalid fixupbase", n); ++ return GRUB_EFI_UNSUPPORTED; ++ } ++ ++ while ((void *)entry < (void *)reloc_end) ++ { ++ fixup = fixup_base + (*entry & 0xFFF); ++ switch ((*entry) >> 12) ++ { ++ case GRUB_PE32_REL_BASED_ABSOLUTE: ++ break; ++ case GRUB_PE32_REL_BASED_HIGH: ++ fixup_16 = (grub_uint16_t *)fixup; ++ *fixup_16 = (grub_uint16_t) ++ (*fixup_16 + ((grub_uint16_t)((grub_uint32_t)adjust >> 16))); ++ if (fixup_data != NULL) ++ { ++ *(grub_uint16_t *) fixup_data = *fixup_16; ++ fixup_data = fixup_data + sizeof (grub_uint16_t); ++ } ++ break; ++ case GRUB_PE32_REL_BASED_LOW: ++ fixup_16 = (grub_uint16_t *)fixup; ++ *fixup_16 = (grub_uint16_t) (*fixup_16 + (grub_uint16_t)adjust); ++ if (fixup_data != NULL) ++ { ++ *(grub_uint16_t *) fixup_data = *fixup_16; ++ fixup_data = fixup_data + sizeof (grub_uint16_t); ++ } ++ break; ++ case GRUB_PE32_REL_BASED_HIGHLOW: ++ fixup_32 = (grub_uint32_t *)fixup; ++ *fixup_32 = *fixup_32 + (grub_uint32_t)adjust; ++ if (fixup_data != NULL) ++ { ++ fixup_data = (char *)ALIGN_UP ((grub_addr_t)fixup_data, sizeof (grub_uint32_t)); ++ *(grub_uint32_t *) fixup_data = *fixup_32; ++ fixup_data += sizeof (grub_uint32_t); ++ } ++ break; ++ case GRUB_PE32_REL_BASED_DIR64: ++ fixup_64 = (grub_uint64_t *)fixup; ++ *fixup_64 = *fixup_64 + (grub_uint64_t)adjust; ++ if (fixup_data != NULL) ++ { ++ fixup_data = (char *)ALIGN_UP ((grub_addr_t)fixup_data, sizeof (grub_uint64_t)); ++ *(grub_uint64_t *) fixup_data = *fixup_64; ++ fixup_data += sizeof (grub_uint64_t); ++ } ++ break; ++ default: ++ grub_error (GRUB_ERR_BAD_ARGUMENT, ++ "Reloc %d unknown relocation type %d", ++ n, (*entry) >> 12); ++ return GRUB_EFI_UNSUPPORTED; ++ } ++ entry += 1; ++ } ++ reloc_base = (struct grub_pe32_data_directory *)reloc_end; ++ n++; ++ } ++ ++ return GRUB_EFI_SUCCESS; ++} ++ ++static grub_efi_device_path_t * ++grub_efi_get_media_file_path (grub_efi_device_path_t *dp) ++{ ++ while (1) ++ { ++ grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); ++ grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); ++ ++ if (type == GRUB_EFI_END_DEVICE_PATH_TYPE) ++ break; ++ else if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE ++ && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE) ++ return dp; ++ ++ dp = GRUB_EFI_NEXT_DEVICE_PATH (dp); ++ } ++ ++ return NULL; ++} ++ ++static grub_efi_boolean_t ++handle_image (void *data, grub_efi_uint32_t datasize) ++{ ++ grub_efi_boot_services_t *b; ++ grub_efi_loaded_image_t *li, li_bak; ++ grub_efi_status_t efi_status; ++ char *buffer = NULL; ++ char *buffer_aligned = NULL; ++ grub_efi_uint32_t i, size; ++ struct grub_pe32_section_table *section; ++ char *base, *end; ++ pe_coff_loader_image_context_t context; ++ grub_uint32_t section_alignment; ++ grub_uint32_t buffer_size; ++ ++ b = grub_efi_system_table->boot_services; ++ ++ if (read_header (data, datasize, &context)) ++ { ++ grub_dprintf ("chain", "Succeed to read header\n"); ++ } ++ else ++ { ++ grub_dprintf ("chain", "Failed to read header\n"); ++ goto error_exit; ++ } ++ ++ section_alignment = context.section_alignment; ++ buffer_size = context.image_size + section_alignment; ++ ++ efi_status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA, ++ buffer_size, (void **) &buffer); ++ ++ if (efi_status != GRUB_EFI_SUCCESS) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto error_exit; ++ } ++ ++ buffer_aligned = (char *)ALIGN_UP ((grub_addr_t)buffer, section_alignment); ++ ++ if (!buffer_aligned) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ goto error_exit; ++ } ++ ++ grub_memcpy (buffer_aligned, data, context.size_of_headers); ++ ++ char *reloc_base, *reloc_base_end; ++ reloc_base = image_address (buffer_aligned, datasize, ++ context.reloc_dir->rva); ++ /* RelocBaseEnd here is the address of the last byte of the table */ ++ reloc_base_end = image_address (buffer_aligned, datasize, ++ context.reloc_dir->rva ++ + context.reloc_dir->size - 1); ++ struct grub_pe32_section_table *reloc_section = NULL; ++ ++ section = context.first_section; ++ for (i = 0; i < context.number_of_sections; i++, section++) ++ { ++ size = section->virtual_size; ++ if (size > section->raw_data_size) ++ size = section->raw_data_size; ++ ++ base = image_address (buffer_aligned, context.image_size, ++ section->virtual_address); ++ end = image_address (buffer_aligned, context.image_size, ++ section->virtual_address + size - 1); ++ ++ ++ /* We do want to process .reloc, but it's often marked ++ * discardable, so we don't want to memcpy it. */ ++ if (grub_memcmp (section->name, ".reloc\0\0", 8) == 0) ++ { ++ if (reloc_section) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, ++ "Image has multiple relocation sections"); ++ goto error_exit; ++ } ++ ++ /* If it has nonzero sizes, and our bounds check ++ * made sense, and the VA and size match RelocDir's ++ * versions, then we believe in this section table. */ ++ if (section->raw_data_size && section->virtual_size && ++ base && end && reloc_base == base && reloc_base_end == end) ++ { ++ reloc_section = section; ++ } ++ } ++ ++ if (section->characteristics && GRUB_PE32_SCN_MEM_DISCARDABLE) ++ continue; ++ ++ if (!base || !end) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid section size"); ++ goto error_exit; ++ } ++ ++ if (section->virtual_address < context.size_of_headers || ++ section->raw_data_offset < context.size_of_headers) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, ++ "Section %d is inside image headers", i); ++ goto error_exit; ++ } ++ ++ if (section->raw_data_size > 0) ++ grub_memcpy (base, (grub_efi_uint8_t*)data + section->raw_data_offset, ++ size); ++ ++ if (size < section->virtual_size) ++ grub_memset (base + size, 0, section->virtual_size - size); ++ ++ grub_dprintf ("chain", "copied section %s\n", section->name); ++ } ++ ++ /* 5 == EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC */ ++ if (context.number_of_rva_and_sizes <= 5) ++ { ++ grub_dprintf ("chain", "image has no relocation entry\n"); ++ goto error_exit; ++ } ++ ++ if (context.reloc_dir->size && reloc_section) ++ { ++ /* run the relocation fixups */ ++ efi_status = relocate_coff (&context, reloc_section, data, ++ buffer_aligned); ++ ++ if (efi_status != GRUB_EFI_SUCCESS) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "relocation failed"); ++ goto error_exit; ++ } ++ } ++ ++ entry_point = image_address (buffer_aligned, context.image_size, ++ context.entry_point); ++ ++ if (!entry_point) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid entry point"); ++ goto error_exit; ++ } ++ ++ li = grub_efi_get_loaded_image (grub_efi_image_handle); ++ if (!li) ++ { ++ grub_error (GRUB_ERR_BAD_ARGUMENT, "no loaded image available"); ++ goto error_exit; ++ } ++ ++ grub_memcpy (&li_bak, li, sizeof (grub_efi_loaded_image_t)); ++ li->image_base = buffer_aligned; ++ li->image_size = context.image_size; ++ li->load_options = cmdline; ++ li->load_options_size = cmdline_len; ++ li->file_path = grub_efi_get_media_file_path (file_path); ++ li->device_handle = dev_handle; ++ if (li->file_path) ++ { ++ grub_printf ("file path: "); ++ grub_efi_print_device_path (li->file_path); ++ } ++ else ++ { ++ grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found"); ++ goto error_exit; ++ } ++ ++ efi_status = efi_call_2 (entry_point, grub_efi_image_handle, ++ grub_efi_system_table); ++ ++ grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t)); ++ efi_status = efi_call_1 (b->free_pool, buffer); ++ ++ return 1; ++ ++error_exit: ++ if (buffer) ++ efi_call_1 (b->free_pool, buffer); ++ ++ return 0; ++} ++ ++static grub_err_t ++grub_secureboot_chainloader_unload (void) ++{ ++ grub_efi_boot_services_t *b; ++ ++ b = grub_efi_system_table->boot_services; ++ efi_call_2 (b->free_pages, address, pages); ++ grub_free (file_path); ++ grub_free (cmdline); ++ cmdline = 0; ++ file_path = 0; ++ dev_handle = 0; ++ ++ grub_dl_unref (my_mod); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_secureboot_chainloader_boot (void) ++{ ++ handle_image ((void *)address, fsize); ++ grub_loader_unset (); ++ return grub_errno; ++} ++ + static grub_err_t + grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { + grub_file_t file = 0; +- grub_ssize_t size; + grub_efi_status_t status; + grub_efi_boot_services_t *b; + grub_device_t dev = 0; +@@ -200,7 +719,6 @@ grub_cmd_chainloader (grub_command_t cmd + grub_efi_loaded_image_t *loaded_image; + char *filename; + void *boot_image = 0; +- grub_efi_handle_t dev_handle = 0; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +@@ -212,9 +730,36 @@ grub_cmd_chainloader (grub_command_t cmd + address = 0; + image_handle = 0; + file_path = 0; ++ dev_handle = 0; + + b = grub_efi_system_table->boot_services; + ++ if (argc > 1) ++ { ++ int i; ++ grub_efi_char16_t *p16; ++ ++ for (i = 1, cmdline_len = 0; i < argc; i++) ++ cmdline_len += grub_strlen (argv[i]) + 1; ++ ++ cmdline_len *= sizeof (grub_efi_char16_t); ++ cmdline = p16 = grub_malloc (cmdline_len); ++ if (! cmdline) ++ goto fail; ++ ++ for (i = 1; i < argc; i++) ++ { ++ char *p8; ++ ++ p8 = argv[i]; ++ while (*p8) ++ *(p16++) = *(p8++); ++ ++ *(p16++) = ' '; ++ } ++ *(--p16) = 0; ++ } ++ + file = grub_file_open (filename); + if (! file) + goto fail; +@@ -263,14 +808,14 @@ grub_cmd_chainloader (grub_command_t cmd + grub_printf ("file path: "); + grub_efi_print_device_path (file_path); + +- size = grub_file_size (file); +- if (!size) ++ fsize = grub_file_size (file); ++ if (!fsize) + { + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + goto fail; + } +- pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12); ++ pages = (((grub_efi_uintn_t) fsize + ((1 << 12) - 1)) >> 12); + + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, + GRUB_EFI_LOADER_CODE, +@@ -284,7 +829,7 @@ grub_cmd_chainloader (grub_command_t cmd + } + + boot_image = (void *) ((grub_addr_t) address); +- if (grub_file_read (file, boot_image, size) != size) ++ if (grub_file_read (file, boot_image, fsize) != fsize) + { + if (grub_errno == GRUB_ERR_NONE) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +@@ -294,7 +839,7 @@ grub_cmd_chainloader (grub_command_t cmd + } + + #if defined (__i386__) || defined (__x86_64__) +- if (size >= (grub_ssize_t) sizeof (struct grub_macho_fat_header)) ++ if (fsize >= (grub_ssize_t) sizeof (struct grub_macho_fat_header)) + { + struct grub_macho_fat_header *head = boot_image; + if (head->magic +@@ -303,6 +848,14 @@ grub_cmd_chainloader (grub_command_t cmd + grub_uint32_t i; + struct grub_macho_fat_arch *archs + = (struct grub_macho_fat_arch *) (head + 1); ++ ++ if (grub_efi_secure_boot()) ++ { ++ grub_error (GRUB_ERR_BAD_OS, ++ "MACHO binaries are forbidden with Secure Boot"); ++ goto fail; ++ } ++ + for (i = 0; i < grub_cpu_to_le32 (head->nfat_arch); i++) + { + if (GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT (archs[i].cputype)) +@@ -317,21 +870,28 @@ grub_cmd_chainloader (grub_command_t cmd + > ~grub_cpu_to_le32 (archs[i].size) + || grub_cpu_to_le32 (archs[i].offset) + + grub_cpu_to_le32 (archs[i].size) +- > (grub_size_t) size) ++ > (grub_size_t) fsize) + { + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + goto fail; + } + boot_image = (char *) boot_image + grub_cpu_to_le32 (archs[i].offset); +- size = grub_cpu_to_le32 (archs[i].size); ++ fsize = grub_cpu_to_le32 (archs[i].size); + } + } + #endif + ++ if (grub_linuxefi_secure_validate((void *)address, fsize)) ++ { ++ grub_file_close (file); ++ grub_loader_set (grub_secureboot_chainloader_boot, ++ grub_secureboot_chainloader_unload, 0); ++ return 0; ++ } ++ + status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path, +- boot_image, size, +- &image_handle); ++ boot_image, fsize, &image_handle); + if (status != GRUB_EFI_SUCCESS) + { + if (status == GRUB_EFI_OUT_OF_RESOURCES) +@@ -355,33 +915,10 @@ grub_cmd_chainloader (grub_command_t cmd + + grub_file_close (file); + +- if (argc > 1) ++ if (cmdline) + { +- int i, len; +- grub_efi_char16_t *p16; +- +- for (i = 1, len = 0; i < argc; i++) +- len += grub_strlen (argv[i]) + 1; +- +- len *= sizeof (grub_efi_char16_t); +- cmdline = p16 = grub_malloc (len); +- if (! cmdline) +- goto fail; +- +- for (i = 1; i < argc; i++) +- { +- char *p8; +- +- p8 = argv[i]; +- while (*p8) +- *(p16++) = *(p8++); +- +- *(p16++) = ' '; +- } +- *(--p16) = 0; +- + loaded_image->load_options = cmdline; +- loaded_image->load_options_size = len; ++ loaded_image->load_options_size = cmdline_len; + } + + grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); +@@ -400,6 +937,9 @@ grub_cmd_chainloader (grub_command_t cmd + if (address) + efi_call_2 (b->free_pages, address, pages); + ++ if (cmdline) ++ grub_free (cmdline); ++ + grub_dl_unref (my_mod); + + return grub_errno; +Index: b/include/grub/efi/pe32.h +=================================================================== +--- a/include/grub/efi/pe32.h ++++ b/include/grub/efi/pe32.h +@@ -212,7 +212,11 @@ struct grub_pe64_optional_header + struct grub_pe32_section_table + { + char name[8]; +- grub_uint32_t virtual_size; ++ union ++ { ++ grub_uint32_t physical_address; ++ grub_uint32_t virtual_size; ++ }; + grub_uint32_t virtual_address; + grub_uint32_t raw_data_size; + grub_uint32_t raw_data_offset; +@@ -263,6 +267,20 @@ struct grub_pe32_header + #endif + }; + ++struct grub_pe32_header_32 ++{ ++ char signature[GRUB_PE32_SIGNATURE_SIZE]; ++ struct grub_pe32_coff_header coff_header; ++ struct grub_pe32_optional_header optional_header; ++}; ++ ++struct grub_pe32_header_64 ++{ ++ char signature[GRUB_PE32_SIGNATURE_SIZE]; ++ struct grub_pe32_coff_header coff_header; ++ struct grub_pe64_optional_header optional_header; ++}; ++ + struct grub_pe32_fixup_block + { + grub_uint32_t page_rva; +Index: b/grub-core/Makefile.core.def +=================================================================== +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -1708,6 +1708,7 @@ module = { + + module = { + name = linuxefi; ++ cflags = '-Wno-error=format= -Wno-error=cast-align -Wno-error=int-to-pointer-cast -Wno-error=pointer-to-int-cast -Wno-error=unused-parameter'; + efi = loader/i386/efi/linux.c; + efi = lib/cmdline.c; + efi = loader/efi/linux.c; +@@ -1717,7 +1718,9 @@ module = { + + module = { + name = chain; ++ cflags = '-Wno-error=format= -Wno-error=cast-align -Wno-error=int-to-pointer-cast -Wno-error=pointer-to-int-cast -Wno-error=unused-parameter'; + efi = loader/efi/chainloader.c; ++ efi = loader/efi/linux.c; + i386_pc = loader/i386/pc/chainloader.c; + i386_coreboot = loader/i386/coreboot/chainloader.c; + i386_coreboot = lib/LzmaDec.c; diff -Nru grub2-2.02~beta2/debian/patches/linuxefi_debug.patch grub2-2.02~beta2/debian/patches/linuxefi_debug.patch --- grub2-2.02~beta2/debian/patches/linuxefi_debug.patch 2016-03-15 18:08:17.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/linuxefi_debug.patch 2017-06-08 17:16:17.000000000 +0000 @@ -1,18 +1,19 @@ -From a8f1ec0423c5dc99485e2a2db538b2c89f9f415d Mon Sep 17 00:00:00 2001 +From 519c28e1053a5d5e398120a577384d5162b48c77 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 13 Jan 2014 12:13:18 +0000 Subject: Add more debugging to linuxefi Forwarded: no -Last-Update: 2013-01-29 +Last-Update: 2016-09-19 Patch-Name: linuxefi_debug.patch --- - grub-core/loader/i386/efi/linux.c | 28 +++++++++++++++++++++++++--- - 1 file changed, 25 insertions(+), 3 deletions(-) + grub-core/loader/efi/linux.c | 15 +++++++++++++-- + grub-core/loader/i386/efi/linux.c | 8 ++++++++ + 2 files changed, 21 insertions(+), 2 deletions(-) -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index ebaf1db..2bf38fa 100644 +Index: b/grub-core/loader/i386/efi/linux.c +=================================================================== --- a/grub-core/loader/i386/efi/linux.c +++ b/grub-core/loader/i386/efi/linux.c @@ -19,6 +19,7 @@ @@ -23,38 +24,7 @@ #include #include #include -@@ -54,15 +55,27 @@ grub_linuxefi_secure_validate (void *data, grub_uint32_t size) - { - grub_efi_guid_t guid = SHIM_LOCK_GUID; - grub_efi_shim_lock_t *shim_lock; -+ grub_efi_status_t status; - -+ grub_dprintf ("linuxefi", "Locating shim protocol\n"); - shim_lock = grub_efi_locate_protocol(&guid, NULL); - - if (!shim_lock) -- return 1; -+ { -+ grub_dprintf ("linuxefi", "shim not available\n"); -+ return 1; -+ } - -- if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS) -- return 1; -+ grub_dprintf ("linuxefi", "Asking shim to verify kernel signature\n"); -+ status = shim_lock->verify(data, size); -+ if (status == GRUB_EFI_SUCCESS) -+ { -+ grub_dprintf ("linuxefi", "Kernel signature verification passed\n"); -+ return 1; -+ } - -+ grub_dprintf ("linuxefi", "Kernel signature verification failed (0x%lx)\n", -+ (unsigned long) status); - return 0; - } - -@@ -147,6 +160,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), +@@ -114,6 +115,8 @@ grub_cmd_initrd (grub_command_t cmd __at goto fail; } @@ -63,16 +33,16 @@ params->ramdisk_size = size; params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem; -@@ -236,6 +251,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), +@@ -201,6 +204,8 @@ grub_cmd_linux (grub_command_t cmd __att goto fail; } + grub_dprintf ("linuxefi", "params = %lx\n", (unsigned long) params); + - memset (params, 0, 16384); + grub_memset (params, 0, 16384); - if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) -@@ -279,6 +296,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_memcpy (&lh, kernel, sizeof (lh)); +@@ -238,6 +243,9 @@ grub_cmd_linux (grub_command_t cmd __att goto fail; } @@ -82,12 +52,36 @@ grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); grub_create_loader_cmdline (argc, argv, linux_cmdline + sizeof (LINUX_IMAGE) - 1, -@@ -304,6 +324,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - goto fail; - } +Index: b/grub-core/loader/efi/linux.c +=================================================================== +--- a/grub-core/loader/efi/linux.c ++++ b/grub-core/loader/efi/linux.c +@@ -40,15 +40,26 @@ grub_linuxefi_secure_validate (void *dat + grub_efi_shim_lock_t *shim_lock; + grub_efi_status_t status; + ++ grub_dprintf ("linuxefi", "Locating shim protocol\n"); + shim_lock = grub_efi_locate_protocol(&guid, NULL); + grub_dprintf ("secureboot", "shim_lock: %p\n", shim_lock); + if (!shim_lock) +- return 0; ++ { ++ grub_dprintf ("linuxefi", "shim not available\n"); ++ return 0; ++ } -+ grub_dprintf ("linuxefi", "kernel_mem = %lx\n", (unsigned long) kernel_mem); ++ grub_dprintf ("linuxefi", "Asking shim to verify kernel signature\n"); + status = shim_lock->verify(data, size); + grub_dprintf ("secureboot", "shim_lock->verify(): %ld\n", status); + if (status == GRUB_EFI_SUCCESS) +- return 1; ++ { ++ grub_dprintf ("linuxefi", "Kernel signature verification passed\n"); ++ return 1; ++ } + - if (grub_file_seek (file, start) == (grub_off_t) -1) - { - grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), ++ grub_dprintf ("linuxefi", "Kernel signature verification failed (0x%lx)\n", ++ (unsigned long) status); + + return -1; + } diff -Nru grub2-2.02~beta2/debian/patches/linuxefi_fix_validation_race.patch grub2-2.02~beta2/debian/patches/linuxefi_fix_validation_race.patch --- grub2-2.02~beta2/debian/patches/linuxefi_fix_validation_race.patch 1970-01-01 00:00:00.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/linuxefi_fix_validation_race.patch 2017-06-08 17:16:17.000000000 +0000 @@ -0,0 +1,89 @@ +From 93ff3333a3fbd26e07cd425166b7d7fb243f033f Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Tue, 14 Jul 2015 16:58:51 -0700 +Subject: [PATCH] Fix race in EFI validation + +--- + grub-core/loader/i386/efi/linux.c | 40 ++++++++------------------------------ + 1 file changed, 9 insertions(+), 31 deletions(-) + +Index: b/grub-core/loader/i386/efi/linux.c +=================================================================== +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -154,7 +154,7 @@ grub_cmd_linux (grub_command_t cmd __att + grub_file_t file = 0; + struct linux_kernel_header lh; + grub_ssize_t len, start, filelen; +- void *kernel; ++ void *kernel = NULL; + + grub_dl_ref (my_mod); + +@@ -190,10 +190,6 @@ grub_cmd_linux (grub_command_t cmd __att + goto fail; + } + +- grub_file_seek (file, 0); +- +- grub_free(kernel); +- + params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384)); + + if (! params) +@@ -204,13 +200,7 @@ grub_cmd_linux (grub_command_t cmd __att + + grub_memset (params, 0, 16384); + +- if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) +- { +- if (!grub_errno) +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +- argv[0]); +- goto fail; +- } ++ grub_memcpy (&lh, kernel, sizeof (lh)); + + if (lh.boot_flag != grub_cpu_to_le16 (0xaa55)) + { +@@ -270,26 +260,11 @@ grub_cmd_linux (grub_command_t cmd __att + goto fail; + } + +- if (grub_file_seek (file, start) == (grub_off_t) -1) +- { +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +- argv[0]); +- goto fail; +- } +- +- if (grub_file_read (file, kernel_mem, len) != len && !grub_errno) +- { +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +- argv[0]); +- } +- +- if (grub_errno == GRUB_ERR_NONE) +- { +- grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); +- loaded = 1; +- lh.code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem; +- } ++ grub_memcpy (kernel_mem, (char *)kernel + start, len); ++ grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); ++ loaded=1; + ++ lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem; + grub_memcpy (params, &lh, 2 * 512); + + params->type_of_loader = 0x21; +@@ -299,6 +274,9 @@ grub_cmd_linux (grub_command_t cmd __att + if (file) + grub_file_close (file); + ++ if (kernel) ++ grub_free (kernel); ++ + if (grub_errno != GRUB_ERR_NONE) + { + grub_dl_unref (my_mod); diff -Nru grub2-2.02~beta2/debian/patches/linuxefi_loaders_enforce_sb.patch grub2-2.02~beta2/debian/patches/linuxefi_loaders_enforce_sb.patch --- grub2-2.02~beta2/debian/patches/linuxefi_loaders_enforce_sb.patch 1970-01-01 00:00:00.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/linuxefi_loaders_enforce_sb.patch 2017-06-08 17:16:17.000000000 +0000 @@ -0,0 +1,531 @@ +From e9ed48bb0a655886f26dfa5f4b8aa318513b7a51 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 6 Oct 2015 16:09:25 -0400 +Subject: [PATCH] Make any of the loaders that link in efi mode honor secure + boot. + +And in this case "honor" means "even if somebody does link this in, they +won't register commands if SB is enabled." + +Signed-off-by: Peter Jones +--- + grub-core/Makefile.am | 1 + + grub-core/Makefile.core.def | 1 + + grub-core/commands/iorw.c | 7 +++++ + grub-core/commands/memrw.c | 7 +++++ + grub-core/kern/dl.c | 1 + + grub-core/kern/efi/efi.c | 28 ------------------ + grub-core/kern/efi/sb.c | 58 ++++++++++++++++++++++++++++++++++++++ + grub-core/loader/efi/appleloader.c | 7 +++++ + grub-core/loader/efi/chainloader.c | 1 + + grub-core/loader/i386/bsd.c | 7 +++++ + grub-core/loader/i386/linux.c | 7 +++++ + grub-core/loader/i386/pc/linux.c | 7 +++++ + grub-core/loader/multiboot.c | 7 +++++ + grub-core/loader/xnu.c | 7 +++++ + include/grub/efi/efi.h | 1 - + include/grub/efi/sb.h | 29 +++++++++++++++++++ + include/grub/ia64/linux.h | 0 + include/grub/mips/linux.h | 0 + include/grub/powerpc/linux.h | 0 + include/grub/sparc64/linux.h | 0 + grub-core/Makefile.am | 1 + grub-core/Makefile.core.def | 1 + grub-core/commands/iorw.c | 7 ++++ + grub-core/commands/memrw.c | 7 ++++ + grub-core/kern/dl.c | 1 + grub-core/kern/efi/efi.c | 28 ----------------- + grub-core/kern/efi/sb.c | 58 +++++++++++++++++++++++++++++++++++++ + grub-core/loader/efi/appleloader.c | 7 ++++ + grub-core/loader/efi/chainloader.c | 1 + grub-core/loader/i386/bsd.c | 7 ++++ + grub-core/loader/i386/linux.c | 7 ++++ + grub-core/loader/i386/pc/linux.c | 7 ++++ + grub-core/loader/multiboot.c | 7 ++++ + grub-core/loader/xnu.c | 7 ++++ + include/grub/efi/efi.h | 1 + include/grub/efi/sb.h | 29 ++++++++++++++++++ + include/grub/powerpc/linux.h | 19 ++++++++++++ + 17 files changed, 166 insertions(+), 29 deletions(-) + create mode 100644 grub-core/kern/efi/sb.c + create mode 100644 include/grub/efi/sb.h + create mode 100644 include/grub/ia64/linux.h + create mode 100644 include/grub/mips/linux.h + create mode 100644 include/grub/powerpc/linux.h + create mode 100644 include/grub/sparc64/linux.h + +Index: b/grub-core/Makefile.am +=================================================================== +--- a/grub-core/Makefile.am ++++ b/grub-core/Makefile.am +@@ -65,6 +65,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/inc + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/device.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/disk.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dl.h ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/sb.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env_private.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/err.h +Index: b/grub-core/Makefile.core.def +=================================================================== +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -173,6 +173,7 @@ kernel = { + efi = kern/efi/init.c; + efi = kern/efi/mm.c; + efi = term/efi/console.c; ++ common = kern/efi/sb.c; + + x86 = kern/i386/tsc.c; + +Index: b/grub-core/commands/iorw.c +=================================================================== +--- a/grub-core/commands/iorw.c ++++ b/grub-core/commands/iorw.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -118,6 +119,9 @@ grub_cmd_write (grub_command_t cmd, int + + GRUB_MOD_INIT(memrw) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + cmd_read_byte = + grub_register_extcmd ("inb", grub_cmd_read, 0, + N_("PORT"), N_("Read 8-bit value from PORT."), +@@ -146,6 +150,9 @@ GRUB_MOD_INIT(memrw) + + GRUB_MOD_FINI(memrw) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + grub_unregister_extcmd (cmd_read_byte); + grub_unregister_extcmd (cmd_read_word); + grub_unregister_extcmd (cmd_read_dword); +Index: b/grub-core/commands/memrw.c +=================================================================== +--- a/grub-core/commands/memrw.c ++++ b/grub-core/commands/memrw.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -120,6 +121,9 @@ grub_cmd_write (grub_command_t cmd, int + + GRUB_MOD_INIT(memrw) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + cmd_read_byte = + grub_register_extcmd ("read_byte", grub_cmd_read, 0, + N_("ADDR"), N_("Read 8-bit value from ADDR."), +@@ -148,6 +152,9 @@ GRUB_MOD_INIT(memrw) + + GRUB_MOD_FINI(memrw) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + grub_unregister_extcmd (cmd_read_byte); + grub_unregister_extcmd (cmd_read_word); + grub_unregister_extcmd (cmd_read_dword); +Index: b/grub-core/kern/dl.c +=================================================================== +--- a/grub-core/kern/dl.c ++++ b/grub-core/kern/dl.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + /* Platforms where modules are in a readonly area of memory. */ + #if defined(GRUB_MACHINE_QEMU) +Index: b/grub-core/kern/efi/sb.c +=================================================================== +--- /dev/null ++++ b/grub-core/kern/efi/sb.c +@@ -0,0 +1,58 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2014 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++int ++grub_efi_secure_boot (void) ++{ ++#ifdef GRUB_MACHINE_EFI ++ grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID; ++ grub_size_t datasize; ++ char *secure_boot = NULL; ++ char *setup_mode = NULL; ++ grub_efi_boolean_t ret = 0; ++ ++ secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize); ++ ++ if (datasize != 1 || !secure_boot) ++ goto out; ++ ++ setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize); ++ ++ if (datasize != 1 || !setup_mode) ++ goto out; ++ ++ if (*secure_boot && !*setup_mode) ++ ret = 1; ++ ++ out: ++ grub_free (secure_boot); ++ grub_free (setup_mode); ++ return ret; ++#else ++ return 0; ++#endif ++} +Index: b/grub-core/loader/efi/appleloader.c +=================================================================== +--- a/grub-core/loader/efi/appleloader.c ++++ b/grub-core/loader/efi/appleloader.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -227,6 +228,9 @@ static grub_command_t cmd; + + GRUB_MOD_INIT(appleloader) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + cmd = grub_register_command ("appleloader", grub_cmd_appleloader, + N_("[OPTS]"), + /* TRANSLATORS: This command is used on EFI to +@@ -238,5 +242,8 @@ GRUB_MOD_INIT(appleloader) + + GRUB_MOD_FINI(appleloader) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + grub_unregister_command (cmd); + } +Index: b/grub-core/loader/efi/chainloader.c +=================================================================== +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include + #include + #include +Index: b/grub-core/loader/i386/bsd.c +=================================================================== +--- a/grub-core/loader/i386/bsd.c ++++ b/grub-core/loader/i386/bsd.c +@@ -38,6 +38,7 @@ + #ifdef GRUB_MACHINE_PCBIOS + #include + #endif ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -2101,6 +2102,9 @@ static grub_command_t cmd_netbsd_module_ + + GRUB_MOD_INIT (bsd) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + /* Net and OpenBSD kernels are often compressed. */ + grub_dl_load ("gzio"); + +@@ -2140,6 +2144,9 @@ GRUB_MOD_INIT (bsd) + + GRUB_MOD_FINI (bsd) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + grub_unregister_extcmd (cmd_freebsd); + grub_unregister_extcmd (cmd_openbsd); + grub_unregister_extcmd (cmd_netbsd); +Index: b/grub-core/loader/i386/linux.c +=================================================================== +--- a/grub-core/loader/i386/linux.c ++++ b/grub-core/loader/i386/linux.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -1137,6 +1138,9 @@ static grub_command_t cmd_linux, cmd_ini + + GRUB_MOD_INIT(linux) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + cmd_linux = grub_register_command ("linux", grub_cmd_linux, + 0, N_("Load Linux.")); + cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, +@@ -1146,6 +1150,9 @@ GRUB_MOD_INIT(linux) + + GRUB_MOD_FINI(linux) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + grub_unregister_command (cmd_linux); + grub_unregister_command (cmd_initrd); + } +Index: b/grub-core/loader/i386/pc/linux.c +=================================================================== +--- a/grub-core/loader/i386/pc/linux.c ++++ b/grub-core/loader/i386/pc/linux.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -469,6 +470,9 @@ static grub_command_t cmd_linux, cmd_ini + + GRUB_MOD_INIT(linux16) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + cmd_linux = + grub_register_command ("linux16", grub_cmd_linux, + 0, N_("Load Linux.")); +@@ -480,6 +484,9 @@ GRUB_MOD_INIT(linux16) + + GRUB_MOD_FINI(linux16) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + grub_unregister_command (cmd_linux); + grub_unregister_command (cmd_initrd); + } +Index: b/grub-core/loader/multiboot.c +=================================================================== +--- a/grub-core/loader/multiboot.c ++++ b/grub-core/loader/multiboot.c +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -383,6 +384,9 @@ static grub_command_t cmd_multiboot, cmd + + GRUB_MOD_INIT(multiboot) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + cmd_multiboot = + #ifdef GRUB_USE_MULTIBOOT2 + grub_register_command ("multiboot2", grub_cmd_multiboot, +@@ -403,6 +407,9 @@ GRUB_MOD_INIT(multiboot) + + GRUB_MOD_FINI(multiboot) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + grub_unregister_command (cmd_multiboot); + grub_unregister_command (cmd_module); + } +Index: b/grub-core/loader/xnu.c +=================================================================== +--- a/grub-core/loader/xnu.c ++++ b/grub-core/loader/xnu.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -1466,6 +1467,9 @@ static grub_extcmd_t cmd_splash; + + GRUB_MOD_INIT(xnu) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + cmd_kernel = grub_register_command ("xnu_kernel", grub_cmd_xnu_kernel, 0, + N_("Load XNU image.")); + cmd_kernel64 = grub_register_command ("xnu_kernel64", grub_cmd_xnu_kernel64, +@@ -1506,6 +1510,9 @@ GRUB_MOD_INIT(xnu) + + GRUB_MOD_FINI(xnu) + { ++ if (grub_efi_secure_boot()) ++ return; ++ + #ifndef GRUB_MACHINE_EMU + grub_unregister_command (cmd_resume); + #endif +Index: b/include/grub/efi/efi.h +=================================================================== +--- a/include/grub/efi/efi.h ++++ b/include/grub/efi/efi.h +@@ -72,7 +72,6 @@ EXPORT_FUNC (grub_efi_set_variable) (con + const grub_efi_guid_t *guid, + void *data, + grub_size_t datasize); +-grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void); + int + EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1, + const grub_efi_device_path_t *dp2); +Index: b/include/grub/efi/sb.h +=================================================================== +--- /dev/null ++++ b/include/grub/efi/sb.h +@@ -0,0 +1,29 @@ ++/* sb.h - declare functions for EFI Secure Boot support */ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_EFI_SB_HEADER ++#define GRUB_EFI_SB_HEADER 1 ++ ++#include ++#include ++ ++/* Functions. */ ++int EXPORT_FUNC (grub_efi_secure_boot) (void); ++ ++#endif /* ! GRUB_EFI_SB_HEADER */ +Index: b/include/grub/powerpc/linux.h +=================================================================== +--- /dev/null ++++ b/include/grub/powerpc/linux.h +@@ -0,0 +1,19 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2008 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++/* sb.c (via dl.c) requires grub/cpu/linux.h */ +Index: b/grub-core/kern/efi/efi.c +=================================================================== +--- a/grub-core/kern/efi/efi.c ++++ b/grub-core/kern/efi/efi.c +@@ -259,34 +259,6 @@ grub_efi_get_variable (const char *var, + return NULL; + } + +-grub_efi_boolean_t +-grub_efi_secure_boot (void) +-{ +- grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID; +- grub_size_t datasize; +- char *secure_boot = NULL; +- char *setup_mode = NULL; +- grub_efi_boolean_t ret = 0; +- +- secure_boot = grub_efi_get_variable ("SecureBoot", &efi_var_guid, &datasize); +- +- if (datasize != 1 || !secure_boot) +- goto out; +- +- setup_mode = grub_efi_get_variable ("SetupMode", &efi_var_guid, &datasize); +- +- if (datasize != 1 || !setup_mode) +- goto out; +- +- if (*secure_boot && !*setup_mode) +- ret = 1; +- +- out: +- grub_free (secure_boot); +- grub_free (setup_mode); +- return ret; +-} +- + #pragma GCC diagnostic ignored "-Wcast-align" + + /* Search the mods section from the PE32/PE32+ image. This code uses diff -Nru grub2-2.02~beta2/debian/patches/linuxefi_non_sb_fallback.patch grub2-2.02~beta2/debian/patches/linuxefi_non_sb_fallback.patch --- grub2-2.02~beta2/debian/patches/linuxefi_non_sb_fallback.patch 2016-03-15 18:08:17.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/linuxefi_non_sb_fallback.patch 2017-06-08 17:16:17.000000000 +0000 @@ -1,4 +1,4 @@ -From bbee35754c088eca0ffada3ed7457a2fe674de69 Mon Sep 17 00:00:00 2001 +From e022bb4a1aef299debfbb9dbe85413303d71e77f Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 13 Jan 2014 12:13:20 +0000 Subject: If running under UEFI secure boot, attempt to use linuxefi loader @@ -9,28 +9,28 @@ Patch-Name: linuxefi_non_sb_fallback.patch --- - grub-core/loader/i386/efi/linux.c | 2 +- - grub-core/loader/i386/linux.c | 43 +++++++++++++++++++++++++++++++++++++++ + grub-core/loader/i386/efi/linux.c | 2 - + grub-core/loader/i386/linux.c | 43 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index f764f49..88e2d34 100644 +Index: b/grub-core/loader/i386/efi/linux.c +=================================================================== --- a/grub-core/loader/i386/efi/linux.c +++ b/grub-core/loader/i386/efi/linux.c -@@ -234,7 +234,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - - if (! grub_linuxefi_secure_validate (kernel, filelen)) +@@ -192,7 +192,7 @@ grub_cmd_linux (grub_command_t cmd __att + rc = grub_linuxefi_secure_validate (kernel, filelen); + if (rc < 0) { - grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); + grub_error (GRUB_ERR_ACCESS_DENIED, N_("%s has invalid signature"), argv[0]); - grub_free (kernel); goto fail; } -diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c -index 31fb91e..2380642 100644 + +Index: b/grub-core/loader/i386/linux.c +=================================================================== --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c -@@ -76,6 +76,8 @@ static grub_size_t maximal_cmdline_size; +@@ -77,6 +77,8 @@ static grub_size_t maximal_cmdline_size; static struct linux_kernel_params linux_params; static char *linux_cmdline; #ifdef GRUB_MACHINE_EFI @@ -39,7 +39,7 @@ static grub_efi_uintn_t efi_mmap_size; #else static const grub_size_t efi_mmap_size = 0; -@@ -690,6 +692,41 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), +@@ -691,6 +693,41 @@ grub_cmd_linux (grub_command_t cmd __att grub_dl_ref (my_mod); @@ -81,7 +81,7 @@ if (argc == 0) { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); -@@ -1052,6 +1089,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), +@@ -1053,6 +1090,12 @@ grub_cmd_initrd (grub_command_t cmd __at grub_err_t err; struct grub_linux_initrd_context initrd_ctx; diff -Nru grub2-2.02~beta2/debian/patches/linuxefi.patch grub2-2.02~beta2/debian/patches/linuxefi.patch --- grub2-2.02~beta2/debian/patches/linuxefi.patch 2016-03-15 18:08:17.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/linuxefi.patch 2017-06-08 17:16:17.000000000 +0000 @@ -1,27 +1,27 @@ -From 275e1976bb46405ac6fc7e1da7d769dfebba9576 Mon Sep 17 00:00:00 2001 +From 5cd20151112bfde11cf3ed8b9920797d7cabe325 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Mon, 13 Jan 2014 12:13:15 +0000 Subject: Add "linuxefi" loader which avoids ExitBootServices Origin: vendor, http://pkgs.fedoraproject.org/cgit/grub2.git/tree/grub2-linuxefi.patch Forwarded: no -Last-Update: 2014-11-18 +Last-Update: 2016-09-19 Patch-Name: linuxefi.patch --- - grub-core/Makefile.core.def | 8 + - grub-core/kern/efi/mm.c | 32 ++++ - grub-core/loader/i386/efi/linux.c | 371 ++++++++++++++++++++++++++++++++++++++ - include/grub/efi/efi.h | 3 + - include/grub/i386/linux.h | 1 + - 5 files changed, 415 insertions(+) + grub-core/Makefile.core.def | 8 + grub-core/kern/efi/mm.c | 32 +++ + grub-core/loader/i386/efi/linux.c | 370 ++++++++++++++++++++++++++++++++++++++ + include/grub/efi/efi.h | 3 + include/grub/i386/linux.h | 1 + 5 files changed, 414 insertions(+) create mode 100644 grub-core/loader/i386/efi/linux.c -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index c916246..8c246c6 100644 +Index: b/grub-core/Makefile.core.def +=================================================================== --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def -@@ -1706,6 +1706,14 @@ module = { +@@ -1731,6 +1731,14 @@ module = { }; module = { @@ -36,11 +36,11 @@ name = chain; efi = loader/efi/chainloader.c; i386_pc = loader/i386/pc/chainloader.c; -diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c -index be37afd..ddeca60 100644 +Index: b/grub-core/kern/efi/mm.c +=================================================================== --- a/grub-core/kern/efi/mm.c +++ b/grub-core/kern/efi/mm.c -@@ -49,6 +49,38 @@ static grub_efi_uintn_t finish_desc_size; +@@ -49,6 +49,38 @@ static grub_efi_uintn_t finish_desc_size static grub_efi_uint32_t finish_desc_version; int grub_efi_is_finished = 0; @@ -79,12 +79,11 @@ /* Allocate pages. Return the pointer to the first of allocated pages. */ void * grub_efi_allocate_pages (grub_efi_physical_address_t address, -diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -new file mode 100644 -index 0000000..ebaf1db +Index: b/grub-core/loader/i386/efi/linux.c +=================================================================== --- /dev/null +++ b/grub-core/loader/i386/efi/linux.c -@@ -0,0 +1,371 @@ +@@ -0,0 +1,370 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 Free Software Foundation, Inc. @@ -307,7 +306,6 @@ + if (! grub_linuxefi_secure_validate (kernel, filelen)) + { + grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); -+ grub_free (kernel); + goto fail; + } + @@ -323,7 +321,7 @@ + goto fail; + } + -+ memset (params, 0, 16384); ++ grub_memset (params, 0, 16384); + + if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) + { @@ -411,7 +409,7 @@ + lh.code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem; + } + -+ memcpy(params, &lh, 2 * 512); ++ grub_memcpy (params, &lh, 2 * 512); + + params->type_of_loader = 0x21; + @@ -456,11 +454,11 @@ + grub_unregister_command (cmd_linux); + grub_unregister_command (cmd_initrd); +} -diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h -index db2169e..a000c38 100644 +Index: b/include/grub/efi/efi.h +=================================================================== --- a/include/grub/efi/efi.h +++ b/include/grub/efi/efi.h -@@ -40,6 +40,9 @@ void EXPORT_FUNC(grub_efi_stall) (grub_efi_uintn_t microseconds); +@@ -40,6 +40,9 @@ void EXPORT_FUNC(grub_efi_stall) (grub_e void * EXPORT_FUNC(grub_efi_allocate_pages) (grub_efi_physical_address_t address, grub_efi_uintn_t pages); @@ -470,8 +468,8 @@ void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address, grub_efi_uintn_t pages); int -diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h -index da0ca3b..fc36bda 100644 +Index: b/include/grub/i386/linux.h +=================================================================== --- a/include/grub/i386/linux.h +++ b/include/grub/i386/linux.h @@ -139,6 +139,7 @@ struct linux_kernel_header diff -Nru grub2-2.02~beta2/debian/patches/linuxefi_re-enable_linux_cmd.patch grub2-2.02~beta2/debian/patches/linuxefi_re-enable_linux_cmd.patch --- grub2-2.02~beta2/debian/patches/linuxefi_re-enable_linux_cmd.patch 1970-01-01 00:00:00.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/linuxefi_re-enable_linux_cmd.patch 2017-06-08 17:16:17.000000000 +0000 @@ -0,0 +1,37 @@ +From: Mathieu Trudel-Lapierre +Subject: Temporarily re-enable the generic linux loader + +We're currently relying on it and an automatic hand-off to linuxefi for EFI +booting; so we need the linux command to start to be able to do the hand-off +correctly. + +This is a temporary measure until we switch to calling linuxefi directly. + +--- + grub-core/loader/i386/linux.c | 6 ------ + 1 file changed, 6 deletions(-) + +Index: b/grub-core/loader/i386/linux.c +=================================================================== +--- a/grub-core/loader/i386/linux.c ++++ b/grub-core/loader/i386/linux.c +@@ -1138,9 +1138,6 @@ static grub_command_t cmd_linux, cmd_ini + + GRUB_MOD_INIT(linux) + { +- if (grub_efi_secure_boot()) +- return; +- + cmd_linux = grub_register_command ("linux", grub_cmd_linux, + 0, N_("Load Linux.")); + cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, +@@ -1150,9 +1147,6 @@ GRUB_MOD_INIT(linux) + + GRUB_MOD_FINI(linux) + { +- if (grub_efi_secure_boot()) +- return; +- + grub_unregister_command (cmd_linux); + grub_unregister_command (cmd_initrd); + } diff -Nru grub2-2.02~beta2/debian/patches/linuxefi_require_shim.patch grub2-2.02~beta2/debian/patches/linuxefi_require_shim.patch --- grub2-2.02~beta2/debian/patches/linuxefi_require_shim.patch 2016-03-15 18:08:17.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/linuxefi_require_shim.patch 2017-06-08 17:16:17.000000000 +0000 @@ -1,4 +1,4 @@ -From f393f2edf39bc9fc12cd6e6dab6cd1e40b149ac2 Mon Sep 17 00:00:00 2001 +From 4224acc6c0fb2fdd86018b736fda19a7a21f3952 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 13 Jan 2014 12:13:19 +0000 Subject: Make linuxefi refuse to boot without shim @@ -14,7 +14,7 @@ 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c -index 2bf38fa..f764f49 100644 +index 1995a50..ff29316 100644 --- a/grub-core/loader/i386/efi/linux.c +++ b/grub-core/loader/i386/efi/linux.c @@ -63,7 +63,7 @@ grub_linuxefi_secure_validate (void *data, grub_uint32_t size) diff -Nru grub2-2.02~beta2/debian/patches/linuxefi_rework_non-sb_cases.patch grub2-2.02~beta2/debian/patches/linuxefi_rework_non-sb_cases.patch --- grub2-2.02~beta2/debian/patches/linuxefi_rework_non-sb_cases.patch 1970-01-01 00:00:00.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/linuxefi_rework_non-sb_cases.patch 2017-06-08 17:16:17.000000000 +0000 @@ -0,0 +1,378 @@ +From a741a53e352513787aadb6c933bf1e3bc1dbe83c Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 10 Jun 2016 14:06:15 -0400 +Subject: [PATCH] Rework even more of efi chainload so non-sb cases work right. + +This ensures that if shim protocol is not loaded, or is loaded but shim +is disabled, we will fall back to a correct load method for the efi +chain loader. + +Here's what I tested with this version: + +results expected actual +------------------------------------------------------------ +sb + enabled + shim + fedora success success +sb + enabled + shim + win success success +sb + enabled + grub + fedora fail fail +sb + enabled + grub + win fail fail + +sb + mokdisabled + shim + fedora success success +sb + mokdisabled + shim + win success success +sb + mokdisabled + grub + fedora fail fail +sb + mokdisabled + grub + win fail fail + +sb disabled + shim + fedora success success* +sb disabled + shim + win success success* +sb disabled + grub + fedora success success +sb disabled + grub + win success success + +nosb + shim + fedora success success* +nosb + shim + win success success* +nosb + grub + fedora success success +nosb + grub + win success success + +* for some reason shim protocol is being installed in these cases, and I + can't see why, but I think it may be this firmware build returning an + erroneous value. But this effectively falls back to the mokdisabled + behavior, which works correctly, and the presence of the "grub" (i.e. + no shim) tests effectively tests the desired behavior here. + +Resolves: rhbz#1344512 + +Signed-off-by: Peter Jones +--- + grub-core/kern/efi/sb.c | 14 +++- + grub-core/loader/arm64/linux.c | 4 - + grub-core/loader/efi/chainloader.c | 117 ++++++++++++++++++++++--------------- + grub-core/loader/efi/linux.c | 13 ++-- + grub-core/loader/i386/efi/linux.c | 7 +- + include/grub/efi/linux.h | 2 + 6 files changed, 98 insertions(+), 59 deletions(-) + +Index: b/grub-core/kern/efi/sb.c +=================================================================== +--- a/grub-core/kern/efi/sb.c ++++ b/grub-core/kern/efi/sb.c +@@ -36,14 +36,20 @@ grub_efi_secure_boot (void) + grub_efi_boolean_t ret = 0; + + secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize); +- + if (datasize != 1 || !secure_boot) +- goto out; ++ { ++ grub_dprintf ("secureboot", "No SecureBoot variable\n"); ++ goto out; ++ } ++ grub_dprintf ("secureboot", "SecureBoot: %d\n", *secure_boot); + + setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize); +- + if (datasize != 1 || !setup_mode) +- goto out; ++ { ++ grub_dprintf ("secureboot", "No SetupMode variable\n"); ++ goto out; ++ } ++ grub_dprintf ("secureboot", "SetupMode: %d\n", *setup_mode); + + if (*secure_boot && !*setup_mode) + ret = 1; +Index: b/grub-core/loader/arm64/linux.c +=================================================================== +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -253,6 +253,7 @@ grub_cmd_linux (grub_command_t cmd __att + grub_file_t file = 0; + struct grub_arm64_linux_kernel_header lh; + struct grub_arm64_linux_pe_header *pe; ++ int rc; + + grub_dl_ref (my_mod); + +@@ -297,7 +298,8 @@ grub_cmd_linux (grub_command_t cmd __att + + grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); + +- if (!grub_linuxefi_secure_validate (kernel_addr, kernel_size)) ++ rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size); ++ if (rc < 0) + { + grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); + goto fail; +Index: b/grub-core/loader/efi/chainloader.c +=================================================================== +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -178,7 +178,6 @@ make_file_path (grub_efi_device_path_t * + /* Fill the file path for the directory. */ + d = (grub_efi_device_path_t *) ((char *) file_path + + ((char *) d - (char *) dp)); +- grub_efi_print_device_path (d); + copy_file_path ((grub_efi_file_path_device_path_t *) d, + dir_start, dir_end - dir_start); + +@@ -248,10 +247,9 @@ read_header (void *data, grub_efi_uint32 + grub_efi_status_t status; + + shim_lock = grub_efi_locate_protocol (&guid, NULL); +- + if (!shim_lock) + { +- grub_error (GRUB_ERR_BAD_ARGUMENT, "no shim lock protocol"); ++ grub_dprintf ("chain", "no shim lock protocol"); + return 0; + } + +@@ -276,7 +274,7 @@ read_header (void *data, grub_efi_uint32 + break; + } + +- return 0; ++ return -1; + } + + static void* +@@ -510,17 +508,24 @@ handle_image (void *data, grub_efi_uint3 + grub_uint32_t section_alignment; + grub_uint32_t buffer_size; + int found_entry_point = 0; ++ int rc; + + b = grub_efi_system_table->boot_services; + +- if (read_header (data, datasize, &context)) ++ rc = read_header (data, datasize, &context); ++ if (rc < 0) + { +- grub_dprintf ("chain", "Succeed to read header\n"); ++ grub_dprintf ("chain", "Failed to read header\n"); ++ goto error_exit; ++ } ++ else if (rc == 0) ++ { ++ grub_dprintf ("chain", "Secure Boot is not enabled\n"); ++ return 0; + } + else + { +- grub_dprintf ("chain", "Failed to read header\n"); +- goto error_exit; ++ grub_dprintf ("chain", "Header read without error\n"); + } + + /* +@@ -793,9 +798,55 @@ grub_secureboot_chainloader_unload (void + } + + static grub_err_t ++grub_load_and_start_image(void *boot_image) ++{ ++ grub_efi_boot_services_t *b; ++ grub_efi_status_t status; ++ grub_efi_loaded_image_t *loaded_image; ++ ++ b = grub_efi_system_table->boot_services; ++ ++ status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path, ++ boot_image, fsize, &image_handle); ++ if (status != GRUB_EFI_SUCCESS) ++ { ++ if (status == GRUB_EFI_OUT_OF_RESOURCES) ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources"); ++ else ++ grub_error (GRUB_ERR_BAD_OS, "cannot load image"); ++ return -1; ++ } ++ ++ /* LoadImage does not set a device handler when the image is ++ loaded from memory, so it is necessary to set it explicitly here. ++ This is a mess. */ ++ loaded_image = grub_efi_get_loaded_image (image_handle); ++ if (! loaded_image) ++ { ++ grub_error (GRUB_ERR_BAD_OS, "no loaded image available"); ++ return -1; ++ } ++ loaded_image->device_handle = dev_handle; ++ ++ if (cmdline) ++ { ++ loaded_image->load_options = cmdline; ++ loaded_image->load_options_size = cmdline_len; ++ } ++ ++ return 0; ++} ++ ++static grub_err_t + grub_secureboot_chainloader_boot (void) + { +- handle_image ((void *)address, fsize); ++ int rc; ++ rc = handle_image ((void *)address, fsize); ++ if (rc == 0) ++ { ++ grub_load_and_start_image((void *)address); ++ } ++ + grub_loader_unset (); + return grub_errno; + } +@@ -809,9 +860,9 @@ grub_cmd_chainloader (grub_command_t cmd + grub_efi_boot_services_t *b; + grub_device_t dev = 0; + grub_efi_device_path_t *dp = 0; +- grub_efi_loaded_image_t *loaded_image; + char *filename; + void *boot_image = 0; ++ int rc; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +@@ -898,9 +949,6 @@ grub_cmd_chainloader (grub_command_t cmd + if (! file_path) + goto fail; + +- grub_printf ("file path: "); +- grub_efi_print_device_path (file_path); +- + fsize = grub_file_size (file); + if (!fsize) + { +@@ -975,50 +1023,27 @@ grub_cmd_chainloader (grub_command_t cmd + } + #endif + +- if (grub_linuxefi_secure_validate((void *)address, fsize)) ++ rc = grub_linuxefi_secure_validate((void *)(grub_addr_t)address, fsize); ++ grub_dprintf ("chain", "linuxefi_secure_validate: %d\n", rc); ++ if (rc > 0) + { + grub_file_close (file); + grub_loader_set (grub_secureboot_chainloader_boot, + grub_secureboot_chainloader_unload, 0); + return 0; + } +- +- status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path, +- boot_image, fsize, &image_handle); +- if (status != GRUB_EFI_SUCCESS) ++ else if (rc == 0) + { +- if (status == GRUB_EFI_OUT_OF_RESOURCES) +- grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources"); +- else +- grub_error (GRUB_ERR_BAD_OS, "cannot load image"); +- +- goto fail; +- } +- +- /* LoadImage does not set a device handler when the image is +- loaded from memory, so it is necessary to set it explicitly here. +- This is a mess. */ +- loaded_image = grub_efi_get_loaded_image (image_handle); +- if (! loaded_image) +- { +- grub_error (GRUB_ERR_BAD_OS, "no loaded image available"); +- goto fail; ++ grub_load_and_start_image(boot_image); ++ grub_file_close (file); ++ grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); ++ return 0; + } +- loaded_image->device_handle = dev_handle; + + grub_file_close (file); ++ grub_device_close (dev); + +- if (cmdline) +- { +- loaded_image->load_options = cmdline; +- loaded_image->load_options_size = cmdline_len; +- } +- +- grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); +- return 0; +- +- fail: +- ++fail: + if (dev) + grub_device_close (dev); + +Index: b/grub-core/loader/efi/linux.c +=================================================================== +--- a/grub-core/loader/efi/linux.c ++++ b/grub-core/loader/efi/linux.c +@@ -33,21 +33,24 @@ struct grub_efi_shim_lock + }; + typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; + +-grub_efi_boolean_t ++int + grub_linuxefi_secure_validate (void *data, grub_uint32_t size) + { + grub_efi_guid_t guid = SHIM_LOCK_GUID; + grub_efi_shim_lock_t *shim_lock; ++ grub_efi_status_t status; + + shim_lock = grub_efi_locate_protocol(&guid, NULL); +- ++ grub_dprintf ("secureboot", "shim_lock: %p\n", shim_lock); + if (!shim_lock) +- return 1; ++ return 0; + +- if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS) ++ status = shim_lock->verify(data, size); ++ grub_dprintf ("secureboot", "shim_lock->verify(): %ld\n", status); ++ if (status == GRUB_EFI_SUCCESS) + return 1; + +- return 0; ++ return -1; + } + + typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *); +Index: b/grub-core/loader/i386/efi/linux.c +=================================================================== +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -155,6 +155,7 @@ grub_cmd_linux (grub_command_t cmd __att + struct linux_kernel_header lh; + grub_ssize_t len, start, filelen; + void *kernel = NULL; ++ int rc; + + grub_dl_ref (my_mod); + +@@ -180,11 +181,13 @@ grub_cmd_linux (grub_command_t cmd __att + + if (grub_file_read (file, kernel, filelen) != filelen) + { +- grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]); ++ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), ++ argv[0]); + goto fail; + } + +- if (! grub_linuxefi_secure_validate (kernel, filelen)) ++ rc = grub_linuxefi_secure_validate (kernel, filelen); ++ if (rc < 0) + { + grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); + goto fail; +Index: b/include/grub/efi/linux.h +=================================================================== +--- a/include/grub/efi/linux.h ++++ b/include/grub/efi/linux.h +@@ -22,7 +22,7 @@ + #include + #include + +-grub_efi_boolean_t ++int + EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size); + grub_err_t + EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset, diff -Nru grub2-2.02~beta2/debian/patches/series grub2-2.02~beta2/debian/patches/series --- grub2-2.02~beta2/debian/patches/series 2016-11-08 19:42:24.000000000 +0000 +++ grub2-2.02~beta2/debian/patches/series 2017-06-08 17:16:17.000000000 +0000 @@ -21,8 +21,16 @@ uefi_firmware_setup.patch mkconfig_ubuntu_distributor.patch linuxefi.patch +linuxefi_backport_arm64.patch +linuxefi_arm_sb_support.patch +linuxefi_fix_validation_race.patch +linuxefi_chainloader_path.patch +linuxefi_chainloader_sb.patch +linuxefi_loaders_enforce_sb.patch +linuxefi_re-enable_linux_cmd.patch +linuxefi_chainloader_pe_fixes.patch +linuxefi_rework_non-sb_cases.patch linuxefi_debug.patch -linuxefi_require_shim.patch linuxefi_non_sb_fallback.patch mkconfig_signed_kernel.patch install_signed.patch @@ -72,7 +80,6 @@ fix_diskfilter_lv_name_dblfree.patch fix_disk-module_option_handling.patch ppc64el-avoid_unnecessary_optimizations.patch -arm64-set-correct-length-of-device-path-end-entry.patch progress_avoid_null_deref.patch arm64-setjmp-Add-missing-license-macro.patch xfs-fix-directory-iteration.patch