diff --git a/grub/grub-efi/debian/deb_patches/0001-Make-series-null.patch b/grub/grub-efi/debian/deb_patches/0001-Make-series-null.patch new file mode 100644 index 000000000..45a581fd2 --- /dev/null +++ b/grub/grub-efi/debian/deb_patches/0001-Make-series-null.patch @@ -0,0 +1,81 @@ +From 8f26fc39497decab3f9a087d18803447a9b9295f Mon Sep 17 00:00:00 2001 +From: Li Zhou
+
+Signed-off-by: Jiang Lu
+
+Rebase for grub 2.06
+Signed-off-by: Yi Zhao
+---
+ docs/grub.texi | 11 +++++++
+ grub-core/kern/efi/init.c | 68 +++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 79 insertions(+)
+
+diff --git a/docs/grub.texi b/docs/grub.texi
+index f8b4b3b..95e8367 100644
+--- a/docs/grub.texi
++++ b/docs/grub.texi
+@@ -3991,6 +3991,7 @@ you forget a command, you can run the command @command{help}
+ * distrust:: Remove a pubkey from trusted keys
+ * drivemap:: Map a drive to another
+ * echo:: Display a line of text
++* efi-watchdog:: Manipulate EFI watchdog
+ * eval:: Evaluate agruments as GRUB commands
+ * export:: Export an environment variable
+ * false:: Do nothing, unsuccessfully
+@@ -4442,6 +4443,16 @@ When interpreting backslash escapes, backslash followed by any other
+ character will print that character.
+ @end deffn
+
++@node efi-watchdog
++@subsection efi-watchdog
++
++@deffn Command efi-watchdog enable|disable
++Enable or disable the system's watchdog timer. Only available in EFI targeted
++GRUB.
++The is logged upon watchdog timeout event. The UEFI BIOS reserves codes
++0x0000 to 0xFFFF.
++The represents number of seconds to set the watchdog timeout to.
++@end deffn
+
+ @node eval
+ @subsection eval
+diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
+index 7facacf..4a88397 100644
+--- a/grub-core/kern/efi/init.c
++++ b/grub-core/kern/efi/init.c
+@@ -28,6 +28,8 @@
+ #include
+ #include
+ #include
++#include
++#include
+
+ #ifdef GRUB_STACK_PROTECTOR
+
+@@ -82,6 +84,68 @@ stack_protector_init (void)
+
+ grub_addr_t grub_modbase;
+
++static grub_command_t cmd_list;
++
++static grub_err_t
++grub_cmd_efi_watchdog (grub_command_t cmd __attribute__ ((unused)),
++ int argc, char **args)
++{
++ long input;
++ grub_efi_status_t status;
++ grub_efi_uintn_t timeout;
++ grub_efi_uint64_t code;
++
++ if (argc < 1)
++ return grub_error (GRUB_ERR_BAD_ARGUMENT,
++ N_("usage: efi-watchdog (enable|disable) "));
++
++ if (grub_strcasecmp (args[0], "enable") == 0) {
++
++ if (argc != 3)
++ return grub_error (GRUB_ERR_BAD_ARGUMENT,
++ N_("usage: efi-watchdog enable "));
++
++ input = grub_strtol (args[1], 0, 0);
++
++ if (input >= 0) {
++ code = input;
++ } else {
++ return grub_error (GRUB_ERR_BAD_ARGUMENT,
++ N_(" must be non-negative"));
++ }
++
++ input = grub_strtol (args[2], 0, 0);
++
++ if (input >= 0) {
++ timeout = (grub_efi_uintn_t) input;
++ } else {
++ return grub_error (GRUB_ERR_BAD_ARGUMENT,
++ N_(" must be non-negative"));
++ }
++
++ } else if (grub_strcasecmp (args[0], "disable") == 0) {
++
++ if (argc != 1)
++ return grub_error (GRUB_ERR_BAD_ARGUMENT,
++ N_("usage: efi-watchdog disable"));
++ timeout = 0;
++ code = 0;
++
++ } else {
++ return grub_error (GRUB_ERR_BAD_ARGUMENT,
++ N_("usage: efi-watchdog (enable|disable) "));
++ }
++
++ status = efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer,
++ timeout, code, sizeof(L"GRUB"), L"GRUB");
++
++ if (status != GRUB_EFI_SUCCESS)
++ return grub_error (GRUB_ERR_BUG,
++ N_("Unexpected UEFI SetWatchdogTimer() error"));
++ else
++ return GRUB_ERR_NONE;
++}
++
+ void
+ grub_efi_init (void)
+ {
+@@ -109,6 +173,9 @@ grub_efi_init (void)
+ 0, 0, 0, NULL);
+
+ grub_efidisk_init ();
++
++ cmd_list = grub_register_command ("efi-watchdog", grub_cmd_efi_watchdog, 0,
++ N_("Enable/Disable system's watchdog timer."));
+ }
+
+ void (*grub_efi_net_config) (grub_efi_handle_t hnd,
+@@ -146,4 +213,5 @@ grub_efi_fini (void)
+ {
+ grub_efidisk_fini ();
+ grub_console_fini ();
++ grub_unregister_command (cmd_list);
+ }
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0004-correct-grub_errno.patch b/grub/grub-efi/debian/patches/0004-correct-grub_errno.patch
new file mode 100644
index 000000000..cd37b2511
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0004-correct-grub_errno.patch
@@ -0,0 +1,45 @@
+From fcab9daa2e62bcf2f6165fca4378d0e8a919a276 Mon Sep 17 00:00:00 2001
+From: Hongxu Jia
+Date: Sat, 19 Mar 2022 20:01:58 +0800
+Subject: [PATCH] correct grub_errno
+
+Correct grub_errno if allocate memory at preferred address success.
+
+Usually allocate memory at preferred address will fail and then
+allocate to another address. During second time allocate, it reset
+grub_errno = GRUB_ERR_NONE.
+
+While grub efi working on a server with huge memory, allocate memory at
+preferred address will succeed, no need to allocate again, and no change
+to correct grub_errno. It caused load kernel image fail in this
+situation.
+
+Set grub_errno = GRUB_ERR_NONE if first allocate success
+
+Upstream-Status: Inappropriate [oe specific]
+
+Signed-off-by: Hongxu Jia
+[lz: Adapt the git shortlog.]
+Signed-off-by: Li Zhou
+---
+ grub-core/loader/i386/linux.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
+index 9f74a96..747cfe0 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -179,6 +179,10 @@ allocate_pages (grub_size_t prot_size, grub_size_t *align,
+ prot_size, 1,
+ GRUB_RELOCATOR_PREFERENCE_LOW,
+ 1);
++
++ if (!err)
++ grub_errno = GRUB_ERR_NONE;
++
+ for (; err && *align + 1 > min_align; (*align)--)
+ {
+ grub_errno = GRUB_ERR_NONE;
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0005-grub-verify-Add-skip_check_cfg-variable.patch b/grub/grub-efi/debian/patches/0005-grub-verify-Add-skip_check_cfg-variable.patch
new file mode 100644
index 000000000..ee27329fc
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0005-grub-verify-Add-skip_check_cfg-variable.patch
@@ -0,0 +1,98 @@
+From 01120b5ec61ae7bbe550b1e2fe0f75c2d2073b1f Mon Sep 17 00:00:00 2001
+From: Hongxu Jia
+Date: Fri, 6 May 2022 15:44:14 +0800
+Subject: [PATCH] grub verify: Add skip_check_cfg variable
+
+While check_signatures enabled, with skip_check_cfg set to 1
+- Do not verify the signature on the file that has suffix `.cfg'
+- Do not authenticate user and password if cfg is changed
+
+Implement function grub_strendswith to find cfg file
+
+Upstream-Status: Pending
+
+Signed-off-by: Hongxu Jia
+---
+ grub-core/commands/pgp.c | 12 ++++++++++++
+ grub-core/kern/misc.c | 12 ++++++++++++
+ grub-core/normal/auth.c | 5 +++++
+ include/grub/misc.h | 1 +
+ 4 files changed, 30 insertions(+)
+
+diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c
+index 5daa1e9..e60a29a 100644
+--- a/grub-core/commands/pgp.c
++++ b/grub-core/commands/pgp.c
+@@ -873,6 +873,18 @@ grub_pubkey_init (grub_file_t io, enum grub_file_type type __attribute__ ((unuse
+ char *fsuf, *ptr;
+ grub_err_t err;
+ struct grub_pubkey_context *ctxt;
++ const char *val;
++
++ /* SKip to check the signature of cfg */
++ val = grub_env_get ("skip_check_cfg");
++ if (val && (val[0] == '1'))
++ {
++ if (grub_strendswith (io->name, ".cfg"))
++ {
++ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
++ return GRUB_ERR_NONE;
++ }
++ }
+
+ if (!sec)
+ {
+diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
+index 3af336e..8bf1d90 100644
+--- a/grub-core/kern/misc.c
++++ b/grub-core/kern/misc.c
+@@ -280,6 +280,18 @@ grub_strncmp (const char *s1, const char *s2, grub_size_t n)
+ return (int) (grub_uint8_t) *s1 - (int) (grub_uint8_t) *s2;
+ }
+
++int
++grub_strendswith (const char *str, const char *suffix)
++{
++ if (!str || !suffix)
++ return 0;
++ grub_size_t lenstr = grub_strlen(str);
++ grub_size_t lensuffix = grub_strlen(suffix);
++ if (lensuffix > lenstr)
++ return 0;
++ return grub_strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
++}
++
+ char *
+ grub_strchr (const char *s, int c)
+ {
+diff --git a/grub-core/normal/auth.c b/grub-core/normal/auth.c
+index 6be678c..57a1a42 100644
+--- a/grub-core/normal/auth.c
++++ b/grub-core/normal/auth.c
+@@ -136,6 +136,11 @@ is_authenticated (const char *userlist)
+ const char *superusers;
+ struct grub_auth_user *user;
+
++ /* SKip to authenticate grub cfg */
++ const char *val = grub_env_get ("skip_check_cfg");
++ if (val && (val[0] == '1'))
++ return 1;
++
+ superusers = grub_env_get ("superusers");
+
+ if (!superusers)
+diff --git a/include/grub/misc.h b/include/grub/misc.h
+index 7d2b551..cce29d7 100644
+--- a/include/grub/misc.h
++++ b/include/grub/misc.h
+@@ -82,6 +82,7 @@ grub_memcpy (void *dest, const void *src, grub_size_t n)
+ int EXPORT_FUNC(grub_memcmp) (const void *s1, const void *s2, grub_size_t n);
+ int EXPORT_FUNC(grub_strcmp) (const char *s1, const char *s2);
+ int EXPORT_FUNC(grub_strncmp) (const char *s1, const char *s2, grub_size_t n);
++int EXPORT_FUNC(grub_strendswith) (const char *str, const char *suffix);
+
+ char *EXPORT_FUNC(grub_strchr) (const char *s, int c);
+ char *EXPORT_FUNC(grub_strrchr) (const char *s, int c);
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0006-pe32.h-add-header-structures-for-TE-and-DOS-executab.patch b/grub/grub-efi/debian/patches/0006-pe32.h-add-header-structures-for-TE-and-DOS-executab.patch
new file mode 100644
index 000000000..01828473c
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0006-pe32.h-add-header-structures-for-TE-and-DOS-executab.patch
@@ -0,0 +1,82 @@
+From 3d9946f69f5ec17da747aa683ff7b5ccf9c31252 Mon Sep 17 00:00:00 2001
+From: Ricardo Neri
+Date: Fri, 27 Mar 2015 08:01:41 -0700
+Subject: [PATCH] pe32.h: add header structures for TE and DOS executables
+
+Upstream-Status: Inappropriate [embedded specific]
+
+Add header structures to describe the Terse Executable format and
+the DOS header format for executable images.
+
+These definitions are needed in subsequent commits to parse and
+verify the identity of the executable image when utilizing a shim
+to boot LUV.
+
+Signed-off-by: Ricardo Neri
+
+Add definitions of macros IMAGE_FILE_MACHINE_* which is involved by
+0004-efi-chainloader-port-shim-to-grub.patch.
+
+Signed-off-by: Kai Kang
+---
+ include/grub/efi/pe32.h | 46 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 46 insertions(+)
+
+diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
+index 0ed8781..de3a720 100644
+--- a/include/grub/efi/pe32.h
++++ b/include/grub/efi/pe32.h
+@@ -331,4 +331,50 @@ struct grub_pe32_reloc
+ #define GRUB_PE32_REL_I386_DIR32 0x6
+ #define GRUB_PE32_REL_I386_REL32 0x14
+
++//
++// PE32+ Machine type for EFI images
++//
++#define IMAGE_FILE_MACHINE_I386 0x014c
++#define IMAGE_FILE_MACHINE_IA64 0x0200
++#define IMAGE_FILE_MACHINE_EBC 0x0EBC
++#define IMAGE_FILE_MACHINE_X64 0x8664
++#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x01c2
++#define IMAGE_FILE_MACHINE_ARM64 0xaa64
++
++struct grub_te_header
++{
++ grub_uint16_t signature;
++ grub_uint16_t machine;
++ grub_uint8_t num_sections;
++ grub_uint8_t subsystem;
++ grub_uint16_t stripped_size;
++ grub_uint32_t entry_point;
++ grub_uint32_t code_base;
++ grub_uint64_t image_base;
++ struct grub_pe32_data_directory data_directory[2];
++};
++
++struct grub_dos_header
++{
++ grub_uint16_t magic;
++ grub_uint16_t cblp;
++ grub_uint16_t cp;
++ grub_uint16_t crlc;
++ grub_uint16_t cparhdr;
++ grub_uint16_t minalloc;
++ grub_uint16_t maxalloc;
++ grub_uint16_t ss;
++ grub_uint16_t sp;
++ grub_uint16_t csum;
++ grub_uint16_t ip;
++ grub_uint16_t cs;
++ grub_uint16_t lfarlc;
++ grub_uint16_t ovno;
++ grub_uint16_t res[4];
++ grub_uint16_t oemid;
++ grub_uint16_t oeminfo;
++ grub_uint16_t res2[10];
++ grub_uint32_t lfanew;
++};
++
+ #endif /* ! GRUB_EFI_PE32_HEADER */
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0007-shim-add-needed-data-structures.patch b/grub/grub-efi/debian/patches/0007-shim-add-needed-data-structures.patch
new file mode 100644
index 000000000..da3a09a28
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0007-shim-add-needed-data-structures.patch
@@ -0,0 +1,161 @@
+From 1b807419bd99382cfeb9584ab7e8c10a0e416c5d Mon Sep 17 00:00:00 2001
+From: Ricardo Neri
+Date: Fri, 27 Mar 2015 08:09:58 -0700
+Subject: [PATCH] shim: add needed data structures
+
+Upstream-Status: Inappropriate [embedded specific]
+
+Add the needed data structures for shim to load, parse, relocate and
+execute a binary. This includes file-parsing structures, an identifier for
+the UEFI protocol for image verification under secure boot provided by shim.
+
+Shim is thin loader developed by Matthew Garret
+(https://github.com/rhinstaller/shim). This code was ported from such project.
+
+Signed-off-by: Ricardo Neri
+---
+ include/grub/efi/shim.h | 132 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 132 insertions(+)
+ create mode 100644 include/grub/efi/shim.h
+
+diff --git a/include/grub/efi/shim.h b/include/grub/efi/shim.h
+new file mode 100644
+index 0000000..4b92a00
+--- /dev/null
++++ b/include/grub/efi/shim.h
+@@ -0,0 +1,132 @@
++/*
++ * shim.h - interface to shim: UEFI first-stage bootloader
++ *
++ * Copyright 2015 Intel Corporation.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the
++ * distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * Significant portions of this code are derived from Red Hat shim: UEFI
++ * first-stage bootloader.
++ * (https://github.com/rhinstaller/shim) and are Copyright 2012 Red Hat, Inc
++ */
++
++#ifndef GRUB_SHIM_HEADER
++#define GRUB_SHIM_HEADER 1
++
++#include
++
++struct grub_nt_headers32
++{
++ grub_efi_uint32_t signature;
++ struct grub_pe32_coff_header file_hdr;
++ struct grub_pe32_optional_header opt_hdr;
++};
++
++struct grub_nt_headers64
++{
++ grub_efi_uint32_t signature;
++ struct grub_pe32_coff_header file_hdr;
++ struct grub_pe64_optional_header opt_hdr;
++};
++
++struct grub_image_base_relocation
++{
++ grub_efi_uint32_t virtual_address;
++ grub_efi_uint32_t block_size;
++};
++
++struct grub_shim_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 header_size;
++ grub_efi_uint16_t image_type;
++ grub_efi_uint16_t num_sections;
++ 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;
++ union grub_shim_optional_header_union *pe_hdr;
++};
++
++struct grub_shim_lock
++{
++ grub_efi_status_t
++ (*verify) (void *buffer,
++ grub_uint32_t size);
++
++ grub_efi_status_t
++ (*hash) (grub_int8_t *data,
++ grub_int32_t datasize,
++ struct grub_shim_pe_coff_loader_image_context *context,
++ grub_uint8_t sha256hash,
++ grub_uint8_t sha1hash);
++
++ grub_efi_status_t
++ (*context) (void *data,
++ grub_uint32_t datasize,
++ struct grub_shim_pe_coff_loader_image_context *context);
++};
++
++union grub_shim_optional_header_union
++{
++ struct grub_nt_headers32 pe32;
++ struct grub_nt_headers64 pe32plus;
++ struct grub_te_header te;
++};
++
++#define GRUB_EFI_SHIM_PROTOCOL_GUID \
++ { 0x605dab50, 0xe046, 0x4300, \
++ { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } \
++ }
++
++#define SIGNATURE_16(A, B) ((A) | (B << 8))
++#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16))
++
++#define EFI_IMAGE_DOS_SIGNATURE SIGNATURE_16('M', 'Z')
++#define EFI_IMAGE_NT_SIGNATURE SIGNATURE_32('P', 'E', '\0', '\0')
++
++#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5
++
++#define ALIGN_VALUE(Value, Alignment) ((Value) + (((Alignment) - (Value)) & ((Alignment) - 1)))
++#define ALIGN_POINTER(Pointer, Alignment) ((void *) (ALIGN_VALUE ((grub_efi_uintn_t)(Pointer), (Alignment))))
++
++/* Based relocation types. */
++
++#define EFI_IMAGE_REL_BASED_ABSOLUTE 0
++#define EFI_IMAGE_REL_BASED_HIGH 1
++#define EFI_IMAGE_REL_BASED_LOW 2
++#define EFI_IMAGE_REL_BASED_HIGHLOW 3
++#define EFI_IMAGE_REL_BASED_HIGHADJ 4
++#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5
++#define EFI_IMAGE_REL_BASED_ARM_MOV32A 5
++#define EFI_IMAGE_REL_BASED_ARM_MOV32T 7
++#define EFI_IMAGE_REL_BASED_IA64_IMM64 9
++#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR16 9
++#define EFI_IMAGE_REL_BASED_DIR64 10
++
++
++#endif /* ! GRUB_SHIM_HEADER */
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0008-efi-chainloader-implement-an-UEFI-Exit-service.patch b/grub/grub-efi/debian/patches/0008-efi-chainloader-implement-an-UEFI-Exit-service.patch
new file mode 100644
index 000000000..7ba21008c
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0008-efi-chainloader-implement-an-UEFI-Exit-service.patch
@@ -0,0 +1,83 @@
+From a210b02b15d68bfe38651295f35edb1a21cef475 Mon Sep 17 00:00:00 2001
+From: Matt Fleming
+Date: Fri, 27 Mar 2015 08:11:19 -0700
+Subject: [PATCH] efi: chainloader: implement an UEFI Exit service
+
+Upstream-Status: Inappropriate [embedded specific]
+
+Implement an UEFI Exit service for shim in grub.
+When exiting, grub will call the UEFI boot-time service Exit. The
+effect of this is that UEFI will jump to the entry point of the
+UEFI started image. If we execute an image using shim within grub,
+shim takes care of loading/parsing/relocating/executing the image.
+Under this scenario, we also need to take care of the Exit call. Thus,
+we need to reimplement the function to make sure we perform a jump
+to the instruction after which shim executed the image.
+
+Once we have taken care of the exit of the shim-executed image
+the system Exit call is restored.
+
+Signed-off-by: Ricardo Neri
+[lz: Adapt git shortlog.]
+Signed-off-by: Li Zhou
+---
+ grub-core/kern/x86_64/efi/callwrap.S | 23 +++++++++++++++++++++++
+ include/grub/efi/api.h | 4 ++++
+ 2 files changed, 27 insertions(+)
+
+diff --git a/grub-core/kern/x86_64/efi/callwrap.S b/grub-core/kern/x86_64/efi/callwrap.S
+index 1337fd9..b849c2c 100644
+--- a/grub-core/kern/x86_64/efi/callwrap.S
++++ b/grub-core/kern/x86_64/efi/callwrap.S
+@@ -48,6 +48,26 @@ FUNCTION(efi_wrap_1)
+ addq $40, %rsp
+ ret
+
++FUNCTION(efi_call_foo)
++ pushq %rbp
++ pushq %r12
++ pushq %r13
++ pushq %r14
++ pushq %r15
++ movq %rsp, saved_sp(%rip)
++ subq $48, %rsp
++ mov %rsi, %rcx
++ call *%rdi
++
++FUNCTION(efi_shim_exit)
++ movq saved_sp(%rip), %rsp
++ popq %r15
++ popq %r14
++ popq %r13
++ popq %r12
++ popq %rbp
++ ret
++
+ FUNCTION(efi_wrap_2)
+ subq $40, %rsp
+ mov %rsi, %rcx
+@@ -127,3 +147,6 @@ FUNCTION(efi_wrap_10)
+ call *%rdi
+ addq $88, %rsp
+ ret
++
++ .data
++saved_sp: .quad 0
+diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
+index f1a5221..de3bbbd 100644
+--- a/include/grub/efi/api.h
++++ b/include/grub/efi/api.h
+@@ -1776,6 +1776,10 @@ typedef struct grub_efi_rng_protocol grub_efi_rng_protocol_t;
+
+ grub_uint64_t EXPORT_FUNC(efi_wrap_0) (void *func);
+ grub_uint64_t EXPORT_FUNC(efi_wrap_1) (void *func, grub_uint64_t arg1);
++grub_efi_status_t EXPORT_FUNC(efi_shim_exit) (grub_efi_handle_t handle, grub_efi_status_t exit_status,
++ grub_efi_uintn_t exit_data_size, grub_efi_char16_t *exit_data) __attribute__((noreturn));
++grub_uint64_t EXPORT_FUNC(efi_call_foo) (void *func, grub_uint64_t arg1,
++ grub_uint64_t arg2);
+ grub_uint64_t EXPORT_FUNC(efi_wrap_2) (void *func, grub_uint64_t arg1,
+ grub_uint64_t arg2);
+ grub_uint64_t EXPORT_FUNC(efi_wrap_3) (void *func, grub_uint64_t arg1,
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0009-efi-chainloader-port-shim-to-grub.patch b/grub/grub-efi/debian/patches/0009-efi-chainloader-port-shim-to-grub.patch
new file mode 100644
index 000000000..23f8f1b5c
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0009-efi-chainloader-port-shim-to-grub.patch
@@ -0,0 +1,582 @@
+From cb88b18b2648c89bccedb7bda25e398618110cbc Mon Sep 17 00:00:00 2001
+From: Ricardo Neri
+Date: Fri, 27 Mar 2015 08:19:21 -0700
+Subject: [PATCH] efi: chainloader: port shim to grub
+
+Upstream-Status: Inappropriate [embedded specific]
+
+Shim is a thin loader to execute signed binaries under the
+chain of trust of UEFI secure boot. Before executing the image,
+shim verifies that such image is signed with any of the Machine
+Owner Keys (MOKs). If the verification is successful, shim will
+load, parse, relocate and execute the image.
+
+Shim is useful in case the user does not want to modify the UEFI
+database of valid certificates (DB).
+
+This commit ports Matthew Garret's code from shim to grub in order
+to provide to grub the capability of load and execute trusted
+binaries. This is useful in case we need to chainload two bootloaders.
+
+Shim can be found here: https://github.com/rhinstaller/shim
+
+Signed-off-by: Ricardo Neri
+---
+ grub-core/loader/efi/chainloader.c | 534 +++++++++++++++++++++++++++++
+ 1 file changed, 534 insertions(+)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 2bd80f4..d192e2d 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -32,6 +32,7 @@
+ #include
+ #include
+ #include
++#include
+ #include
+ #include
+ #include
+@@ -49,6 +50,539 @@ static grub_efi_uintn_t pages;
+ static grub_efi_device_path_t *file_path;
+ static grub_efi_handle_t image_handle;
+ static grub_efi_char16_t *cmdline;
++static grub_int32_t shim_used;
++static grub_efi_physical_address_t shim_buffer;
++static grub_efi_uintn_t shim_pages;
++static grub_efi_loaded_image_t shim_li_bak;
++static grub_efi_status_t (*shim_entry_point) (grub_efi_handle_t image_handle,
++ grub_efi_system_table_t *systab);
++
++static const grub_uint16_t
++grub_shim_machine_type =
++#if defined(__x86_64__)
++ GRUB_PE32_MACHINE_X86_64;
++#elif defined(__aarch64__)
++ IMAGE_FILE_MACHINE_ARM64;
++#elif defined(__arm__)
++ IMAGE_FILE_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 shim chainloader
++#endif
++
++static grub_efi_guid_t grub_shim_protocol_guid = GRUB_EFI_SHIM_PROTOCOL_GUID;
++
++static grub_int32_t
++grub_shim_allow_64_bit (void)
++{
++/* TODO: what is the definition for aarch64? */
++#if defined(__x86_64__)
++ return 1;
++#elif defined(__i386__) || defined(__i686__)
++/* TODO: find out what to do with in_protocol */
++ return 0;
++#else /* assuming everything else is 32-bit... */
++ return 0;
++#endif
++}
++
++static grub_int32_t
++grub_shim_allow_32_bit (void)
++{
++/* TODO: what is the definition for aarch64? */
++#if defined(__x86_64__)
++/* TODO: find out what to do with in_protocol */
++ return 0;
++#elif defined(__i386__) || defined(__i686__)
++ return 1;
++#else /* assuming everything else is 32-bit... */
++ return 1;
++#endif
++}
++
++static grub_int32_t
++grub_shim_image_is_64_bit (union grub_shim_optional_header_union *pe_hdr)
++{
++ /* .Magic is the same offset in all cases */
++ if (pe_hdr->pe32plus.opt_hdr.magic == GRUB_PE32_PE64_MAGIC)
++ return 1;
++ return 0;
++}
++
++static grub_int32_t
++grub_shim_image_is_loadable (union grub_shim_optional_header_union *pe_hdr)
++{
++ /* If the machine type doesn't match the binary, bail, unless
++ * we're in an allowed 64-on-32 scenario
++ */
++ if (pe_hdr->pe32.file_hdr.machine != grub_shim_machine_type)
++ {
++ if (!(grub_shim_machine_type == GRUB_PE32_MACHINE_I386
++ && pe_hdr->pe32.file_hdr.machine == GRUB_PE32_MACHINE_X86_64
++ && grub_shim_allow_64_bit ()))
++ return 0;
++ }
++
++ /* If it's not a header type we recognize at all, bail */
++ switch (pe_hdr->pe32plus.opt_hdr.magic)
++ {
++ case GRUB_PE32_PE64_MAGIC:
++ case GRUB_PE32_PE32_MAGIC:
++ break;
++ default:
++ return 0;
++ }
++
++ /* and now just check for general 64-vs-32 compatibility */
++ if (grub_shim_image_is_64_bit(pe_hdr))
++ {
++ if (grub_shim_allow_64_bit ())
++ return 1;
++ }
++ else
++ {
++ if (grub_shim_allow_32_bit ())
++ return 1;
++ }
++ return 0;
++}
++
++/*
++ * Perform basic bounds checking of the intra-image pointers
++ */
++static grub_efi_uint64_t
++grub_shim_image_address (grub_addr_t image, grub_uint32_t size, grub_uint32_t addr)
++{
++ if (addr > size)
++ return 0;
++ return image + addr;
++}
++
++/*
++ * Perform the actual relocation
++ */
++static grub_err_t
++grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
++ void *orig, void *data)
++{
++ struct grub_image_base_relocation *reloc_base, *reloc_base_end;
++ grub_efi_uint64_t adjust;
++ grub_efi_uint16_t *reloc, *reloc_end;
++ grub_uint8_t *fixup, *fixup_base, *fixup_data = NULL;
++ grub_efi_uint16_t *fixup16;
++ grub_efi_uint32_t *fixup32;
++ grub_efi_uint64_t *fixup64;
++ grub_int32_t size = context->image_size;
++ void *image_end = (char *)orig + size;
++
++ if (grub_shim_image_is_64_bit(context->pe_hdr))
++ context->pe_hdr->pe32plus.opt_hdr.image_base = (grub_efi_uint64_t)(unsigned long)data;
++ else
++ context->pe_hdr->pe32.opt_hdr.image_base = (grub_efi_uint32_t)(unsigned long)data;
++
++ reloc_base = (struct grub_image_base_relocation *)
++ grub_shim_image_address ((grub_efi_uint64_t)orig, size,
++ context->reloc_dir->rva);
++ reloc_base_end = (struct grub_image_base_relocation *)
++ grub_shim_image_address ((grub_efi_uint64_t)orig, size,
++ context->reloc_dir->rva
++ + context->reloc_dir->size - 1);
++
++ if (!reloc_base || !reloc_base_end)
++ {
++ grub_printf("Reloc table overflows binary\n");
++ return GRUB_ERR_BAD_FILE_TYPE;
++ }
++
++ adjust = (grub_efi_uintn_t)data - context->image_address;
++
++ if (adjust == 0)
++ return GRUB_EFI_SUCCESS;
++
++ while (reloc_base < reloc_base_end)
++ {
++ reloc = (grub_efi_uint16_t *) ((grub_int8_t *) reloc_base
++ + sizeof (struct grub_image_base_relocation));
++
++ if ((reloc_base->block_size == 0)
++ || (reloc_base->block_size > context->reloc_dir->size))
++ {
++ grub_printf("Reloc block size %d is invalid\n", reloc_base->block_size);
++ return GRUB_ERR_FILE_READ_ERROR;
++ }
++
++ reloc_end = (grub_efi_uint16_t *)
++ ((grub_uint8_t *) reloc_base + reloc_base->block_size);
++ if ((void *)reloc_end < orig || (void *)reloc_end > image_end)
++ {
++ grub_printf("Reloc entry overflows binary\n");
++ return GRUB_ERR_FILE_READ_ERROR;
++ }
++
++ fixup_base = (grub_uint8_t *)
++ grub_shim_image_address ((grub_efi_uint64_t)data,
++ size,
++ reloc_base->virtual_address);
++ if (!fixup_base)
++ {
++ grub_printf("Invalid fixup_base\n");
++ return GRUB_ERR_FILE_READ_ERROR;
++ }
++
++ while (reloc < reloc_end)
++ {
++ fixup = fixup_base + (*reloc & 0xFFF);
++ switch ((*reloc) >> 12)
++ {
++ case EFI_IMAGE_REL_BASED_ABSOLUTE:
++ break;
++
++ case EFI_IMAGE_REL_BASED_HIGH:
++ fixup16 = (grub_efi_uint16_t *) fixup;
++ *fixup16 = (grub_efi_uint16_t)
++ (*fixup16
++ + ((grub_efi_uint16_t) ((grub_efi_uint32_t) adjust >> 16)));
++ if (fixup_data != NULL)
++ {
++ *(grub_efi_uint16_t *) fixup_data = *fixup16;
++ fixup_data = fixup_data + sizeof (grub_efi_uint16_t);
++ }
++ break;
++
++ case EFI_IMAGE_REL_BASED_LOW:
++ fixup16 = (grub_efi_uint16_t *) fixup;
++ *fixup16 = (grub_efi_uint16_t)
++ (*fixup16 + (grub_efi_uint16_t) adjust);
++ if (fixup_data != NULL)
++ {
++ *(grub_efi_uint16_t *) fixup_data = *fixup16;
++ fixup_data = fixup_data + sizeof (grub_efi_uint16_t);
++ }
++ break;
++
++ case EFI_IMAGE_REL_BASED_HIGHLOW:
++ fixup32 = (grub_efi_uint32_t *) fixup;
++ *fixup32 = *fixup32 + (grub_efi_uint32_t) adjust;
++ if (fixup_data != NULL)
++ {
++ fixup_data = ALIGN_POINTER (fixup_data, sizeof (grub_efi_uint32_t));
++ *(grub_efi_uint32_t *)fixup_data = *fixup32;
++ fixup_data = fixup_data + sizeof (grub_efi_uint32_t);
++ }
++ break;
++
++ case EFI_IMAGE_REL_BASED_DIR64:
++ fixup64 = (grub_efi_uint64_t *) fixup;
++ *fixup64 = *fixup64 + (grub_efi_uint64_t) adjust;
++ if (fixup_data != NULL)
++ {
++ fixup_data = ALIGN_POINTER (fixup_data, sizeof(grub_efi_uint64_t));
++ *(grub_efi_uint64_t *)(fixup_data) = *fixup64;
++ fixup_data = fixup_data + sizeof(grub_efi_uint64_t);
++ }
++ break;
++
++ default:
++ grub_printf("Unknown relocation\n");
++ return GRUB_ERR_FILE_READ_ERROR;
++ }
++ reloc += 1;
++ }
++ reloc_base = (struct grub_image_base_relocation *) reloc_end;
++ }
++
++ return GRUB_EFI_SUCCESS;
++}
++
++/*
++ * Read the binary header and grab appropriate information from it
++ */
++static grub_err_t
++grub_shim_read_header(grub_efi_physical_address_t data, grub_uint32_t datasize,
++ struct grub_shim_pe_coff_loader_image_context *context)
++{
++ struct grub_dos_header *dos_hdr = (struct grub_dos_header *)data;
++ union grub_shim_optional_header_union *pe_hdr = (union grub_shim_optional_header_union *)data;
++ grub_uint64_t header_without_data_dir, section_header_offset, opt_hdr_size;
++
++ if (datasize < sizeof (pe_hdr->pe32))
++ {
++ grub_printf("Invalid image\n");
++ return GRUB_ERR_BAD_FILE_TYPE;
++ }
++
++ if (dos_hdr->magic == EFI_IMAGE_DOS_SIGNATURE)
++ pe_hdr = (union grub_shim_optional_header_union *)((grub_uint8_t *)data
++ + dos_hdr->lfanew);
++
++ if (!grub_shim_image_is_loadable(pe_hdr))
++ {
++ grub_printf("Platform does not support this image\n");
++ return GRUB_ERR_BAD_FILE_TYPE;
++ }
++
++ if (grub_shim_image_is_64_bit(pe_hdr))
++ {
++ context->number_of_rva_and_sizes = pe_hdr->pe32plus.opt_hdr.num_data_directories;
++ context->header_size = pe_hdr->pe32plus.opt_hdr.header_size;
++ context->image_size = pe_hdr->pe32plus.opt_hdr.image_size;
++ opt_hdr_size = sizeof(struct grub_pe64_optional_header);
++ } else
++ {
++ context->number_of_rva_and_sizes = pe_hdr->pe32.opt_hdr.num_data_directories;
++ context->header_size = pe_hdr->pe32.opt_hdr.header_size;
++ context->image_size = (grub_efi_uint64_t)pe_hdr->pe32.opt_hdr.header_size;
++ opt_hdr_size = sizeof(struct grub_pe32_optional_header);
++ }
++
++ context->num_sections = pe_hdr->pe32.file_hdr.num_sections;
++
++ if (GRUB_PE32_NUM_DATA_DIRECTORIES < context->number_of_rva_and_sizes)
++ {
++ grub_printf("Image header too small\n");
++ return GRUB_ERR_FILE_READ_ERROR;
++ }
++
++ header_without_data_dir = opt_hdr_size
++ - sizeof (struct grub_pe32_data_directory)
++ * GRUB_PE32_NUM_DATA_DIRECTORIES;
++ if (((grub_efi_uint32_t)pe_hdr->pe32.file_hdr.optional_header_size
++ - header_without_data_dir) !=
++ context->number_of_rva_and_sizes * sizeof (struct grub_pe32_data_directory))
++ {
++ grub_printf("Image header overflows data directory\n");
++ return GRUB_ERR_FILE_READ_ERROR;
++ }
++
++ section_header_offset = dos_hdr->lfanew
++ + sizeof (grub_efi_uint32_t)
++ + sizeof (struct grub_pe32_coff_header)
++ + pe_hdr->pe32.file_hdr.optional_header_size;
++ if (((grub_efi_uint32_t)context->image_size - section_header_offset)
++ / sizeof (struct grub_pe32_section_table)
++ <= context->num_sections)
++ {
++ grub_printf("Image sections overflow image size\n");
++ return GRUB_ERR_FILE_READ_ERROR;
++ }
++
++ if ((context->header_size - section_header_offset)
++ / sizeof (struct grub_pe32_section_table)
++ < (grub_efi_uint32_t)context->num_sections)
++ {
++ grub_printf("Image sections overflow section headers\n");
++ return GRUB_ERR_FILE_READ_ERROR;
++ }
++
++ if ((((grub_efi_uint8_t *)pe_hdr
++ - (grub_efi_uint8_t *)data)
++ + sizeof(union grub_shim_optional_header_union )) > datasize)
++ {
++ grub_printf("Invalid image\n");
++ return GRUB_ERR_BAD_FILE_TYPE;
++ }
++
++ if (pe_hdr->te.signature != EFI_IMAGE_NT_SIGNATURE)
++ {
++ grub_printf("Unsupported image type\n");
++ return GRUB_ERR_BAD_FILE_TYPE;
++ }
++
++ if (pe_hdr->pe32.file_hdr.characteristics & GRUB_PE32_RELOCS_STRIPPED)
++ {
++ grub_printf("Unsupported image - Relocations have been stripped\n");
++ return GRUB_ERR_BAD_FILE_TYPE;
++ }
++
++ context->pe_hdr = pe_hdr;
++
++ if (grub_shim_image_is_64_bit(pe_hdr))
++ {
++ context->image_address = pe_hdr->pe32plus.opt_hdr.image_base;
++ context->entry_point = pe_hdr->pe32plus.opt_hdr.entry_addr;
++ context->reloc_dir = &pe_hdr->pe32plus.opt_hdr.base_relocation_table;
++ context->sec_dir = &pe_hdr->pe32plus.opt_hdr.certificate_table;
++ } else
++ {
++ context->image_address = pe_hdr->pe32.opt_hdr.image_base;
++ context->entry_point = pe_hdr->pe32.opt_hdr.entry_addr;
++ context->reloc_dir = &pe_hdr->pe32.opt_hdr.base_relocation_table;
++ context->sec_dir = &pe_hdr->pe32.opt_hdr.certificate_table;
++ }
++
++ context->first_section = (struct grub_pe32_section_table *)
++ ((char *)pe_hdr
++ + pe_hdr->pe32.file_hdr.optional_header_size
++ + sizeof(grub_efi_uint32_t)
++ + sizeof(struct grub_pe32_coff_header));
++
++ if (context->image_size < context->header_size)
++ {
++ grub_printf("Invalid image\n");
++ return GRUB_ERR_BAD_FILE_TYPE;
++ }
++
++ if ((unsigned long)((grub_efi_uint8_t *)context->sec_dir - (grub_efi_uint8_t *)data) >
++ (datasize - sizeof(struct grub_pe32_data_directory)))
++ {
++ grub_printf("Invalid image\n");
++ return GRUB_ERR_BAD_FILE_TYPE;
++ }
++
++ if (context->sec_dir->rva >= datasize)
++ {
++ grub_printf("Malformed security header\n");
++ return GRUB_ERR_BAD_FILE_TYPE;
++ }
++ return GRUB_ERR_NONE;
++}
++
++static grub_efi_status_t
++grub_shim_verify (grub_addr_t addr, grub_ssize_t size)
++{
++ struct grub_shim_lock *shim_lock;
++ shim_lock = grub_efi_locate_protocol (&grub_shim_protocol_guid, 0);
++ if (!shim_lock)
++ {
++ grub_error (GRUB_ERR_BAD_OS, "could not load shim protocol");
++ return GRUB_EFI_UNSUPPORTED;
++ }
++
++ return shim_lock->verify((void *) addr, size);
++}
++
++static grub_err_t
++grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
++ struct grub_shim_pe_coff_loader_image_context *context)
++{
++ grub_err_t status;
++ grub_efi_status_t efi_status;
++ grub_uint32_t sect_size;
++ /* TODO: can they be unsigned? */
++ grub_int8_t *base, *end;
++ grub_int32_t i;
++ struct grub_pe32_section_table *section;
++ grub_efi_boot_services_t *b;
++
++ shim_used = 0;
++ shim_buffer = 0;
++
++ status = grub_shim_verify (addr, size);
++ if (status != GRUB_ERR_NONE)
++ {
++ grub_error (GRUB_ERR_BAD_OS, "shim verification failed");
++ return GRUB_ERR_BAD_OS;
++ }
++
++ grub_memset(context, 0, sizeof(*context));
++ status = grub_shim_read_header (addr, size, context);
++ if (status != GRUB_ERR_NONE)
++ {
++ grub_error (GRUB_ERR_BAD_OS, "read header failed");
++ return GRUB_ERR_BAD_OS;
++ }
++
++ /* TODO: do we need to do this with efi_allocate? */
++ shim_pages = (((grub_efi_uintn_t) context->image_size + ((1 << 12) - 1)) >> 12);
++
++ b = grub_efi_system_table->boot_services;
++ efi_status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES,
++ GRUB_EFI_LOADER_CODE, shim_pages, &shim_buffer);
++ if (efi_status != GRUB_EFI_SUCCESS)
++ {
++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory for shim buffer"));
++ return GRUB_ERR_OUT_OF_MEMORY;
++ }
++
++ /* TODO: do we need the double cast? */
++ grub_memcpy ((void *) ((grub_efi_physical_address_t) shim_buffer),
++ (void *) ((grub_addr_t) addr), context->header_size);
++ /*
++ * Copy the executable's sections to their desired offsets
++ */
++ section = context->first_section;
++ for (i = 0; i < context->num_sections; i++, section++)
++ {
++ if (section->characteristics & 0x02000000)
++ /* section has EFI_IMAGE_SCN_MEM_DISCARDABLE attr set */
++ continue;
++
++ sect_size = section->virtual_size;
++
++ if (sect_size > section->raw_data_size)
++ sect_size = section->raw_data_size;
++
++ base = (grub_int8_t *)
++ grub_shim_image_address (shim_buffer, context->image_size,
++ section->virtual_address);
++ end = (grub_int8_t *)
++ grub_shim_image_address (shim_buffer, context->image_size,
++ section->virtual_address
++ + sect_size - 1);
++ if (!base || !end)
++ {
++ grub_printf("Invalid section base\n");
++ status = GRUB_ERR_BAD_FILE_TYPE;
++ goto fail;
++ }
++
++ if (section->virtual_address < context->header_size
++ || section->raw_data_offset < context->header_size)
++ {
++ grub_printf("Section is inside image headers\n");
++ status = GRUB_ERR_BAD_FILE_TYPE;
++ goto fail;
++ }
++
++ if (section->raw_data_size > 0)
++ /* TODO: do we need the double cast? */
++ grub_memcpy ((void *)base,
++ (void *) (((grub_addr_t) addr)
++ + section->raw_data_offset), sect_size);
++
++ if (sect_size < section->virtual_size)
++ grub_memset ((void *)(base + sect_size), 0,
++ section->virtual_size - sect_size);
++ }
++
++ if (context->number_of_rva_and_sizes <= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC)
++ {
++ grub_printf("Image has no relocation entry\n");
++ status = GRUB_ERR_BAD_FILE_TYPE;
++ goto fail;
++ }
++
++ if (context->reloc_dir->size)
++ {
++ status = grub_shim_relocate_coff (context, (void *) addr,
++ (void *) shim_buffer);
++ if (status != GRUB_ERR_NONE)
++ {
++ grub_printf("Relocation failed: [%u]\n", status);
++ status = GRUB_ERR_BAD_FILE_TYPE;
++ goto fail;
++ }
++ }
++ shim_entry_point = (void *)grub_shim_image_address (shim_buffer,
++ context->image_size,
++ context->entry_point);
++ if (!shim_entry_point)
++ {
++ grub_printf("Invalid entry point\n");
++ status = GRUB_ERR_BAD_FILE_TYPE;
++ goto fail;
++ }
++
++ shim_used = 1;
++ return GRUB_ERR_NONE;
++fail:
++ efi_call_2 (b->free_pages, shim_buffer, shim_pages);
++ shim_buffer = 0;
++ return status;
++}
+
+ static grub_err_t
+ grub_chainloader_unload (void)
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0010-efi-chainloader-use-shim-to-load-and-verify-an-image.patch b/grub/grub-efi/debian/patches/0010-efi-chainloader-use-shim-to-load-and-verify-an-image.patch
new file mode 100644
index 000000000..560a6d91a
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0010-efi-chainloader-use-shim-to-load-and-verify-an-image.patch
@@ -0,0 +1,98 @@
+From 5d5f5231b008fa5e6299a76f9ae92a6da035c4f0 Mon Sep 17 00:00:00 2001
+From: Ricardo Neri
+Date: Fri, 27 Mar 2015 08:26:08 -0700
+Subject: [PATCH] efi: chainloader: use shim to load and verify an image
+
+Upstream-Status: Inappropriate [embedded specific]
+
+The grub chainloader module uses the UEFI LoadImage service
+to load a chainloaded binary. However, if such binary is not
+signed by the UEFI certification authority, LoadImage will fail.
+Under shim, we can use Machine-Owned Keys (MOKs) to verify an
+image. Thus, in case LoadImage fails due to a security violation
+we rely on the shim verification service. If successful, the
+image is parsed and loaded.
+
+Signed-off-by: Ricardo Neri
+---
+ grub-core/loader/efi/chainloader.c | 49 ++++++++++++++++++++++++------
+ 1 file changed, 40 insertions(+), 9 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index d192e2d..121af25 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -761,6 +761,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ char *filename;
+ void *boot_image = 0;
+ grub_efi_handle_t dev_handle = 0;
++ struct grub_shim_pe_coff_loader_image_context context;
+
+ if (argc == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+@@ -892,23 +893,53 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ if (status != GRUB_EFI_SUCCESS)
+ {
+ if (status == GRUB_EFI_OUT_OF_RESOURCES)
+- grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
++ {
++ grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
++ goto fail;
++ }
++ /* try with shim */
++ else if (status == GRUB_EFI_SECURITY_VIOLATION)
++ {
++ status = grub_shim_load_image (address, size, &context);
++ if (status != GRUB_EFI_SUCCESS)
++ {
++ grub_error (GRUB_ERR_BAD_OS, "shim cannot load image");
++ goto fail;
++ }
++ }
+ else
+- grub_error (GRUB_ERR_BAD_OS, "cannot load image");
+-
+- goto fail;
++ {
++ 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 we use shim, the UEFI load_image failed, thus, we borrow
++ * grub_efi_image_handle and restore it later
++ */
++ if (shim_used)
++ /* if we use shim, the UEFI load_image failed, thus, we borrow
++ grub_efi_image_handle and restore it later */
++ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
++ else
++ /* 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;
+ }
+- loaded_image->device_handle = dev_handle;
++ if (shim_used)
++ {
++ grub_memcpy(&shim_li_bak, loaded_image, sizeof(shim_li_bak));
++ loaded_image->image_base = (void *)shim_buffer;
++ loaded_image->image_size = context.image_size;
++ }
++ else
++ loaded_image->device_handle = dev_handle;
+
+ if (argc > 1)
+ {
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0011-efi-chainloader-boot-the-image-using-shim.patch b/grub/grub-efi/debian/patches/0011-efi-chainloader-boot-the-image-using-shim.patch
new file mode 100644
index 000000000..ded75151c
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0011-efi-chainloader-boot-the-image-using-shim.patch
@@ -0,0 +1,63 @@
+From 9645bb29a0ffb93c854cbeed175c62775ba38bb7 Mon Sep 17 00:00:00 2001
+From: Ricardo Neri
+Date: Fri, 27 Mar 2015 08:29:13 -0700
+Subject: [PATCH] efi: chainloader: boot the image using shim
+
+Upstream-Status: Inappropriate [embedded specific]
+
+If the image was loaded using shim, boot the image. Given that
+shim loaded the image, the UEFI firmware will not know where to
+jump after the execution completes. Thus, replace the UEFI boot
+service Exit with our own implementation to make sure we jump
+to the instruction after the call to the entry point.
+
+Replace the system Exit service when done.
+
+Signed-off-by: Ricardo Neri
+---
+ grub-core/loader/efi/chainloader.c | 27 ++++++++++++++++++++++++++-
+ 1 file changed, 26 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 121af25..adaf3c9 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -609,9 +609,34 @@ grub_chainloader_boot (void)
+ grub_efi_status_t status;
+ grub_efi_uintn_t exit_data_size;
+ grub_efi_char16_t *exit_data = NULL;
++ grub_efi_loaded_image_t *loaded_image = NULL;
++ grub_efi_status_t
++ (*saved_exit) (grub_efi_handle_t image_handle,
++ grub_efi_status_t exit_status,
++ grub_efi_uintn_t exit_data_size,
++ grub_efi_char16_t *exit_data) __attribute__((noreturn));
+
+ b = grub_efi_system_table->boot_services;
+- status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data);
++
++ if (!shim_used)
++ status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data);
++ else
++ {
++ saved_exit = grub_efi_system_table->boot_services->exit;
++ grub_efi_system_table->boot_services->exit = efi_shim_exit;
++ status = efi_call_foo(shim_entry_point,
++ (grub_efi_uint64_t)grub_efi_image_handle,
++ (grub_efi_uint64_t)grub_efi_system_table);
++ grub_efi_system_table->boot_services->exit = saved_exit;
++
++ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
++ if (!loaded_image)
++ /* TODO: this is serious, what to do? */
++ grub_error (GRUB_ERR_BAD_OS, "GRUB loaded image not found");
++ else
++ /* restore loaded image */
++ grub_memcpy(loaded_image, &shim_li_bak, sizeof(shim_li_bak));
++ }
+ if (status != GRUB_EFI_SUCCESS)
+ {
+ if (exit_data)
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0012-efi-chainloader-take-care-of-unload-undershim.patch b/grub/grub-efi/debian/patches/0012-efi-chainloader-take-care-of-unload-undershim.patch
new file mode 100644
index 000000000..6eec11a64
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0012-efi-chainloader-take-care-of-unload-undershim.patch
@@ -0,0 +1,43 @@
+From 416eaf86565248e11bfb4ef56b6d5a5e21a4541f Mon Sep 17 00:00:00 2001
+From: Ricardo Neri
+Date: Fri, 27 Mar 2015 08:31:27 -0700
+Subject: [PATCH] efi: chainloader: take care of unload undershim
+
+Upstream-Status: Inappropriate [embedded specific]
+
+Under shim, we use a custom buffer to put the relocated image, make
+sure we free that memory when unloading.
+
+Signed-off-by: Ricardo Neri
+---
+ grub-core/loader/efi/chainloader.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index adaf3c9..285271d 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -590,8 +590,18 @@ grub_chainloader_unload (void)
+ grub_efi_boot_services_t *b;
+
+ b = grub_efi_system_table->boot_services;
+- efi_call_1 (b->unload_image, image_handle);
+- efi_call_2 (b->free_pages, address, pages);
++ if (!shim_used)
++ {
++ efi_call_1 (b->unload_image, image_handle);
++ efi_call_2 (b->free_pages, address, pages);
++ }
++ else
++ {
++ if (shim_buffer)
++ {
++ efi_call_2 (b->free_pages, shim_buffer, shim_pages);
++ }
++ }
+
+ grub_free (file_path);
+ grub_free (cmdline);
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0013-chainloader-handle-the-unauthenticated-image-by-shim.patch b/grub/grub-efi/debian/patches/0013-chainloader-handle-the-unauthenticated-image-by-shim.patch
new file mode 100644
index 000000000..d837aeae4
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0013-chainloader-handle-the-unauthenticated-image-by-shim.patch
@@ -0,0 +1,32 @@
+From d06de03facd9a330a2085450abeecb1b7e637f9c Mon Sep 17 00:00:00 2001
+From: Lans Zhang
+Date: Sun, 24 Apr 2016 12:58:10 +0800
+Subject: [PATCH] chainloader: handle the unauthenticated image by shim
+
+Upstream-Status: Pending
+
+EFI_ACCESS_DENIED is another case whenever an unauthenticated image is loaded
+by UEFI LoadImage() boot service. Shim verification protocol should handle
+this case as EFI_SECURITY_VIOLATION.
+
+Signed-off-by: Lans Zhang
+---
+ grub-core/loader/efi/chainloader.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 285271d..9ff4faf 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -933,7 +933,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
+ goto fail;
+ }
+ /* try with shim */
+- else if (status == GRUB_EFI_SECURITY_VIOLATION)
++ else if ((status == GRUB_EFI_ACCESS_DENIED) || (status == GRUB_EFI_SECURITY_VIOLATION))
+ {
+ status = grub_shim_load_image (address, size, &context);
+ if (status != GRUB_EFI_SUCCESS)
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0014-chainloader-Don-t-check-empty-section-in-file-like-..patch b/grub/grub-efi/debian/patches/0014-chainloader-Don-t-check-empty-section-in-file-like-..patch
new file mode 100644
index 000000000..59ee1690f
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0014-chainloader-Don-t-check-empty-section-in-file-like-..patch
@@ -0,0 +1,32 @@
+From 5b7c30a1d5f6a30b60cbed7cedc516a27dba36d9 Mon Sep 17 00:00:00 2001
+From: Lans Zhang
+Date: Sun, 24 Apr 2016 15:56:38 +0800
+Subject: [PATCH] chainloader: Don't check empty section in file like .bss
+
+Upstream-Status: Pending
+
+Because this kind of section always has a zeroed PointerToRawData denoting
+the offset to file and a valid VirtualSize denoting the real size in the
+memory.
+
+Signed-off-by: Lans Zhang
+---
+ grub-core/loader/efi/chainloader.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index 9ff4faf..f736bee 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -530,7 +530,7 @@ grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
+ }
+
+ if (section->virtual_address < context->header_size
+- || section->raw_data_offset < context->header_size)
++ || (section->raw_data_offset && section->raw_data_offset < context->header_size))
+ {
+ grub_printf("Section is inside image headers\n");
+ status = GRUB_ERR_BAD_FILE_TYPE;
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0015-chainloader-find-the-relocations-correctly.patch b/grub/grub-efi/debian/patches/0015-chainloader-find-the-relocations-correctly.patch
new file mode 100644
index 000000000..97905c8e6
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0015-chainloader-find-the-relocations-correctly.patch
@@ -0,0 +1,223 @@
+From 3df0895087be6affb95db4f42239bc0160c16bfa Mon Sep 17 00:00:00 2001
+From: Lans Zhang
+Date: Sun, 24 Apr 2016 19:02:28 +0800
+Subject: [PATCH] chainloader: find the relocations correctly
+
+Upstream-Status: Pending
+
+Refer to a846aedd0e9dfe26ca6afaf6a1db8a54c20363c1 in shim.
+
+Actually find the relocations correctly and process them that way
+in chainloader.
+
+Find the relocations based on the *file* address in the old binary,
+because it's only the same as the virtual address some of the time.
+
+Also perform some extra validation before processing it, and don't bail
+out in /error/ if both reloc_base and reloc_base_end are null - that
+condition is fine.
+
+Signed-off-by: Lans Zhang
+[lz: Adapt git log and do some whitespaces cleanups.]
+Signed-off-by: Li Zhou
+---
+ grub-core/loader/efi/chainloader.c | 97 +++++++++++++++++++++++++-----
+ 1 file changed, 81 insertions(+), 16 deletions(-)
+
+diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
+index f736bee..0979dc0 100644
+--- a/grub-core/loader/efi/chainloader.c
++++ b/grub-core/loader/efi/chainloader.c
+@@ -166,6 +166,7 @@ grub_shim_image_address (grub_addr_t image, grub_uint32_t size, grub_uint32_t ad
+ */
+ static grub_err_t
+ grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
++ struct grub_pe32_section_table *section,
+ void *orig, void *data)
+ {
+ struct grub_image_base_relocation *reloc_base, *reloc_base_end;
+@@ -177,19 +178,53 @@ grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
+ grub_efi_uint64_t *fixup64;
+ grub_int32_t size = context->image_size;
+ void *image_end = (char *)orig + size;
++ int n = 0;
+
+ if (grub_shim_image_is_64_bit(context->pe_hdr))
+ context->pe_hdr->pe32plus.opt_hdr.image_base = (grub_efi_uint64_t)(unsigned long)data;
+ else
+ context->pe_hdr->pe32.opt_hdr.image_base = (grub_efi_uint32_t)(unsigned long)data;
+
++
++ /* Alright, so here's how this works:
++ *
++ * context->RelocDir gives us two things:
++ * - the VA the table of base relocation blocks are (maybe) to be
++ * mapped at (RelocDir->VirtualAddress)
++ * - the virtual size (RelocDir->Size)
++ *
++ * The .reloc section (Section here) gives us some other things:
++ * - the name! kind of. (Section->Name)
++ * - the virtual size (Section->VirtualSize), which should be the same
++ * as RelocDir->Size
++ * - the virtual address (Section->VirtualAddress)
++ * - the file section size (Section->SizeOfRawData), which is
++ * a multiple of OptHdr->FileAlignment. Only useful for image
++ * validation, not really useful for iteration bounds.
++ * - the file address (Section->PointerToRawData)
++ * - 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 EFI_IMAGE_BASE_RELOCATION structs with some values packed behind
++ * them. The SizeOfBlock 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 = (struct grub_image_base_relocation *)
+ grub_shim_image_address ((grub_efi_uint64_t)orig, size,
+- context->reloc_dir->rva);
++ section->raw_data_offset);
++ /* reloc_base_end is the address of the first entry /past/ the
++ * table. */
+ reloc_base_end = (struct grub_image_base_relocation *)
+ grub_shim_image_address ((grub_efi_uint64_t)orig, size,
+- context->reloc_dir->rva
+- + context->reloc_dir->size - 1);
++ section->raw_data_offset
++ + section->virtual_size - 1);
++
++ if (!reloc_base && !reloc_base_end)
++ {
++ return GRUB_EFI_SUCCESS;
++ }
+
+ if (!reloc_base || !reloc_base_end)
+ {
+@@ -210,7 +245,7 @@ grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
+ if ((reloc_base->block_size == 0)
+ || (reloc_base->block_size > context->reloc_dir->size))
+ {
+- grub_printf("Reloc block size %d is invalid\n", reloc_base->block_size);
++ grub_printf("Reloc %d block size %d is invalid\n", n, reloc_base->block_size);
+ return GRUB_ERR_FILE_READ_ERROR;
+ }
+
+@@ -218,7 +253,7 @@ grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
+ ((grub_uint8_t *) reloc_base + reloc_base->block_size);
+ if ((void *)reloc_end < orig || (void *)reloc_end > image_end)
+ {
+- grub_printf("Reloc entry overflows binary\n");
++ grub_printf("Reloc %d entry overflows binary\n", n);
+ return GRUB_ERR_FILE_READ_ERROR;
+ }
+
+@@ -228,7 +263,7 @@ grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
+ reloc_base->virtual_address);
+ if (!fixup_base)
+ {
+- grub_printf("Invalid fixup_base\n");
++ grub_printf("Reloc %d invalid fixup_base\n", n);
+ return GRUB_ERR_FILE_READ_ERROR;
+ }
+
+@@ -286,12 +321,13 @@ grub_shim_relocate_coff (struct grub_shim_pe_coff_loader_image_context *context,
+ break;
+
+ default:
+- grub_printf("Unknown relocation\n");
++ grub_printf("Reloc %d unknown relocation\n", n);
+ return GRUB_ERR_FILE_READ_ERROR;
+ }
+ reloc += 1;
+ }
+ reloc_base = (struct grub_image_base_relocation *) reloc_end;
++ n++;
+ }
+
+ return GRUB_EFI_SUCCESS;
+@@ -462,9 +498,9 @@ grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
+ grub_efi_status_t efi_status;
+ grub_uint32_t sect_size;
+ /* TODO: can they be unsigned? */
+- grub_int8_t *base, *end;
++ grub_int8_t *base, *end, *reloc_base, *reloc_base_end;
+ grub_int32_t i;
+- struct grub_pe32_section_table *section;
++ struct grub_pe32_section_table *section, *reloc_section;
+ grub_efi_boot_services_t *b;
+
+ shim_used = 0;
+@@ -500,16 +536,21 @@ grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
+ /* TODO: do we need the double cast? */
+ grub_memcpy ((void *) ((grub_efi_physical_address_t) shim_buffer),
+ (void *) ((grub_addr_t) addr), context->header_size);
++
++ reloc_base = (grub_int8_t *) grub_shim_image_address (shim_buffer, size,
++ context->reloc_dir->rva);
++ /* reloc_base_end here is the address of the last byte of the table */
++ reloc_base_end = (grub_int8_t *) grub_shim_image_address (shim_buffer, size,
++ context->reloc_dir->rva +
++ context->reloc_dir->size - 1);
++ reloc_section = NULL;
++
+ /*
+ * Copy the executable's sections to their desired offsets
+ */
+ section = context->first_section;
+ for (i = 0; i < context->num_sections; i++, section++)
+ {
+- if (section->characteristics & 0x02000000)
+- /* section has EFI_IMAGE_SCN_MEM_DISCARDABLE attr set */
+- continue;
+-
+ sect_size = section->virtual_size;
+
+ if (sect_size > section->raw_data_size)
+@@ -522,6 +563,30 @@ grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
+ grub_shim_image_address (shim_buffer, context->image_size,
+ section->virtual_address
+ + sect_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_printf("Image has multiple relocation sections\n");
++ status = GRUB_ERR_BAD_FILE_TYPE;
++ goto fail;
++ }
++ /* 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 & 0x02000000)
++ /* section has EFI_IMAGE_SCN_MEM_DISCARDABLE attr set */
++ continue;
++
+ if (!base || !end)
+ {
+ grub_printf("Invalid section base\n");
+@@ -555,10 +620,10 @@ grub_shim_load_image(grub_addr_t addr, grub_ssize_t size,
+ goto fail;
+ }
+
+- if (context->reloc_dir->size)
++ if (context->reloc_dir->size && reloc_section)
+ {
+- status = grub_shim_relocate_coff (context, (void *) addr,
+- (void *) shim_buffer);
++ status = grub_shim_relocate_coff (context, reloc_section,
++ (void *) addr, (void *) shim_buffer);
+ if (status != GRUB_ERR_NONE)
+ {
+ grub_printf("Relocation failed: [%u]\n", status);
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0016-Add-a-module-for-reading-EFI-global-variables.patch b/grub/grub-efi/debian/patches/0016-Add-a-module-for-reading-EFI-global-variables.patch
new file mode 100644
index 000000000..5ddb1d58e
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0016-Add-a-module-for-reading-EFI-global-variables.patch
@@ -0,0 +1,282 @@
+From a9bccd374d23f67d2c3604f7c069be40ec996f9f Mon Sep 17 00:00:00 2001
+From: Lans Zhang
+Date: Thu, 22 Jun 2017 15:22:01 +0800
+Subject: [PATCH] Add a module for reading EFI global variables
+
+Add functions to read EFI global variables.
+
+Signed-off-by: Lans Zhang
+[lz: Add git log.]
+Signed-off-by: Li Zhou
+---
+ grub-core/Makefile.core.def | 8 ++
+ grub-core/commands/efi/efivar.c | 238 ++++++++++++++++++++++++++++++++
+ 2 files changed, 246 insertions(+)
+ create mode 100644 grub-core/commands/efi/efivar.c
+
+diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
+index 8022e1c..f8fad6e 100644
+--- a/grub-core/Makefile.core.def
++++ b/grub-core/Makefile.core.def
+@@ -761,6 +761,14 @@ module = {
+ enable = i386_multiboot;
+ };
+
++module = {
++ name = efivar;
++
++ common = commands/efi/efivar.c;
++
++ enable = efi;
++};
++
+ module = {
+ name = lsacpi;
+
+diff --git a/grub-core/commands/efi/efivar.c b/grub-core/commands/efi/efivar.c
+new file mode 100644
+index 0000000..bb9aed3
+--- /dev/null
++++ b/grub-core/commands/efi/efivar.c
+@@ -0,0 +1,238 @@
++/* efivar.c - Read EFI global variables. */
++/*
++ * GRUB -- GRand Unified Bootloader
++ * Copyright (C) 2015 Free Software Foundation, Inc.
++ * Copyright (C) 2015 CloudFlare, 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
++
++GRUB_MOD_LICENSE ("GPLv3+");
++
++static const struct grub_arg_option options[] = {
++ {"format", 'f', GRUB_ARG_OPTION_OPTIONAL, N_("Parse EFI_VAR in specific format (hex, uint8, ascii, dump). Default: hex."), N_("FORMAT"), ARG_TYPE_STRING},
++ {"set", 's', GRUB_ARG_OPTION_OPTIONAL, N_("Save parsed result to environment variable (does not work with dump)."), N_("ENV_VAR"), ARG_TYPE_STRING},
++ {0, 0, 0, 0, 0, 0}
++};
++
++enum efi_var_type
++ {
++ EFI_VAR_ASCII = 0,
++ EFI_VAR_UINT8,
++ EFI_VAR_HEX,
++ EFI_VAR_DUMP,
++ EFI_VAR_INVALID = -1
++ };
++
++static enum efi_var_type
++parse_efi_var_type (const char *type)
++{
++ if (!grub_strncmp (type, "ascii", sizeof("ascii")))
++ return EFI_VAR_ASCII;
++
++ if (!grub_strncmp (type, "uint8", sizeof("uint8")))
++ return EFI_VAR_UINT8;
++
++ if (!grub_strncmp (type, "hex", sizeof("hex")))
++ return EFI_VAR_HEX;
++
++ if (!grub_strncmp (type, "dump", sizeof("dump")))
++ return EFI_VAR_DUMP;
++
++ return EFI_VAR_INVALID;
++}
++
++static int
++grub_print_ascii (char *str, char c)
++{
++ if (grub_iscntrl (c))
++ {
++ switch (c)
++ {
++ case '\0':
++ str[0] = '\\';
++ str[1] = '0';
++ return 2;
++
++ case '\a':
++ str[0] = '\\';
++ str[1] = 'a';
++ return 2;
++
++ case '\b':
++ str[0] = '\\';
++ str[1] = 'b';
++ return 2;
++
++ case '\f':
++ str[0] = '\\';
++ str[1] = 'f';
++ return 2;
++
++ case '\n':
++ str[0] = '\\';
++ str[1] = 'n';
++ return 2;
++
++ case '\r':
++ str[0] = '\\';
++ str[1] = 'r';
++ return 2;
++
++ case '\t':
++ str[0] = '\\';
++ str[1] = 't';
++ return 2;
++
++ case '\v':
++ str[0] = '\\';
++ str[1] = 'v';
++ return 2;
++
++ default:
++ str[0] = '.'; /* as in hexdump -C */
++ return 1;
++ }
++ }
++
++ str[0] = c;
++ return 1;
++}
++
++static grub_err_t
++grub_cmd_get_efi_var (struct grub_extcmd_context *ctxt,
++ int argc, char **args)
++{
++ struct grub_arg_list *state = ctxt->state;
++ grub_err_t status;
++ void *efi_var = NULL;
++ grub_size_t efi_var_size = 0;
++ enum efi_var_type efi_type = EFI_VAR_HEX;
++ grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID;
++ char *env_var = NULL;
++ grub_size_t i;
++ char *ptr;
++
++ if (1 != argc)
++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
++
++ if (state[0].set)
++ efi_type = parse_efi_var_type (state[0].arg);
++
++ if (EFI_VAR_INVALID == efi_type)
++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid format specifier"));
++
++ grub_efi_get_variable (args[0], &global, &efi_var_size, &efi_var);
++ if (!efi_var || !efi_var_size)
++ {
++ status = grub_error (GRUB_ERR_READ_ERROR, N_("cannot read variable"));
++ goto err;
++ }
++
++ switch (efi_type)
++ {
++ case EFI_VAR_ASCII:
++ env_var = grub_malloc (efi_var_size * 2 + 1);
++ if (!env_var)
++ {
++ status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++ break;
++ }
++
++ ptr = env_var;
++
++ for (i = 0; i < efi_var_size; i++)
++ ptr += grub_print_ascii (ptr, ((const char *)efi_var)[i]);
++ *ptr = '\0';
++ break;
++
++ case EFI_VAR_UINT8:
++ env_var = grub_malloc (4);
++ if (!env_var)
++ {
++ status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++ break;
++ }
++ grub_snprintf (env_var, 4, "%u", *((grub_uint8_t *)efi_var));
++ break;
++
++ case EFI_VAR_HEX:
++ env_var = grub_malloc (efi_var_size * 2 + 1);
++ if (!env_var)
++ {
++ status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++ break;
++ }
++ for (i = 0; i < efi_var_size; i++)
++ grub_snprintf (env_var + (i * 2), 3, "%02x", ((grub_uint8_t *)efi_var)[i]);
++ break;
++
++ case EFI_VAR_DUMP:
++ if (state[1].set)
++ status = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("cannot set variable with dump format specifier"));
++ else
++ {
++ hexdump (0, (char *)efi_var, efi_var_size);
++ status = GRUB_ERR_NONE;
++ }
++ break;
++
++ default:
++ status = grub_error (GRUB_ERR_BUG, N_("should not happen (bug in module?)"));
++ }
++
++ if (efi_type != EFI_VAR_DUMP)
++ {
++ if (state[1].set)
++ status = grub_env_set (state[1].arg, env_var);
++ else
++ {
++ grub_printf ("%s\n", (const char *)env_var);
++ status = GRUB_ERR_NONE;
++ }
++ }
++
++err:
++
++ if (env_var)
++ grub_free (env_var);
++
++ if (efi_var)
++ grub_free (efi_var);
++
++ return status;
++}
++
++static grub_extcmd_t cmd = NULL;
++
++GRUB_MOD_INIT (efivar)
++{
++ cmd = grub_register_extcmd ("get_efivar", grub_cmd_get_efi_var, 0, N_("[-f FORMAT] [-s ENV_VAR] EFI_VAR"),
++ N_("Read EFI variable and print it or save its contents to environment variable."), options);
++}
++
++GRUB_MOD_FINI (efivar)
++{
++ if (cmd)
++ grub_unregister_extcmd (cmd);
++}
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0017-grub-shim-verify-Report-that-the-loaded-object-is-ve.patch b/grub/grub-efi/debian/patches/0017-grub-shim-verify-Report-that-the-loaded-object-is-ve.patch
new file mode 100644
index 000000000..7f0e6d9eb
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0017-grub-shim-verify-Report-that-the-loaded-object-is-ve.patch
@@ -0,0 +1,69 @@
+From 038c21e7a7609340734d044482f24fee7f9f7a8f Mon Sep 17 00:00:00 2001
+From: Jason Wessel
+Date: Thu, 17 Oct 2019 12:35:01 -0700
+Subject: [PATCH] grub shim verify: Report that the loaded object is verified
+
+When check_signatures is set to enforcing, the signatures of the
+loaded files have been checked, so the shim service should be informed
+that it is ok to execute the loaded file.
+
+Upstream-Status: Inappropriate
+
+Signed-off-by: Jason Wessel
+---
+ grub-core/loader/i386/linux.c | 25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
+index 747cfe0..87469e7 100644
+--- a/grub-core/loader/i386/linux.c
++++ b/grub-core/loader/i386/linux.c
+@@ -21,6 +21,10 @@
+ #include
+ #include
+ #include
++#include
++#include
++#include
++#include
+ #include
+ #include
+ #include
+@@ -647,6 +651,23 @@ grub_linux_unload (void)
+ return GRUB_ERR_NONE;
+ }
+
++static grub_efi_guid_t grub_shim_protocol_guid = GRUB_EFI_SHIM_PROTOCOL_GUID;
++
++static grub_efi_status_t
++grub_shim_verify (grub_addr_t addr, grub_ssize_t size)
++{
++ struct grub_shim_lock *shim_lock;
++ shim_lock = grub_efi_locate_protocol (&grub_shim_protocol_guid, 0);
++ if (!shim_lock)
++ {
++ grub_error (GRUB_ERR_BAD_OS, "could not load shim protocol");
++ return GRUB_EFI_UNSUPPORTED;
++ }
++
++ shim_lock->verify((void *) addr, size);
++ return GRUB_ERR_NONE;
++}
++
+ static grub_err_t
+ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+@@ -680,6 +701,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ argv[0]);
+ goto fail;
+ }
++ const char *ge_val = grub_env_get ("check_signatures");
++ if (ge_val && (ge_val[0] == '1' || ge_val[0] == 'e'))
++ /* Verify was handled by .sig files, inform shim */
++ grub_shim_verify((grub_addr_t)&lh, sizeof(lh));
+
+ if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
+ {
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0018-grub-verify-Add-strict_security-variable.patch b/grub/grub-efi/debian/patches/0018-grub-verify-Add-strict_security-variable.patch
new file mode 100644
index 000000000..8db193125
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0018-grub-verify-Add-strict_security-variable.patch
@@ -0,0 +1,111 @@
+From aacf59cc01555c645e5594c0cdaa0e6735921e80 Mon Sep 17 00:00:00 2001
+From: Jason Wessel
+Date: Thu, 17 Oct 2019 12:35:01 -0700
+Subject: [PATCH] grub verify: Add strict_security variable
+
+With strict_security set to 1, it is impossible to change the value of
+check_signatures. It will also cause grub to reboot instead of
+allowing a rescue or grub shell, which could allow an end user to
+alter boot arguments or load some other binary.
+
+Upstream-Status: Pending
+
+Signed-off-by: Jason Wessel
+---
+ grub-core/commands/pgp.c | 16 +++++++++++++++-
+ grub-core/kern/main.c | 9 +++++++++
+ grub-core/normal/main.c | 7 +++++--
+ 3 files changed, 29 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c
+index e60a29a..578ad18 100644
+--- a/grub-core/commands/pgp.c
++++ b/grub-core/commands/pgp.c
+@@ -864,6 +864,7 @@ grub_cmd_verify_signature (grub_extcmd_context_t ctxt,
+ }
+
+ static int sec = 0;
++static int strict_sec = 0;
+
+ static grub_err_t
+ grub_pubkey_init (grub_file_t io, enum grub_file_type type __attribute__ ((unused)),
+@@ -930,10 +931,21 @@ static char *
+ grub_env_write_sec (struct grub_env_var *var __attribute__ ((unused)),
+ const char *val)
+ {
+- sec = (*val == '1') || (*val == 'e');
++ if (!strict_sec)
++ sec = (*val == '1') || (*val == 'e');
+ return grub_strdup (sec ? "enforce" : "no");
+ }
+
++static char *
++grub_env_write_strict_sec (struct grub_env_var *var __attribute__ ((unused)),
++ const char *val)
++{
++ /* once it is set, it is a one way transition */
++ if (!strict_sec)
++ strict_sec = (*val == '1') || (*val == 'e');
++ return grub_strdup (strict_sec ? "enforce" : "no");
++}
++
+ static grub_ssize_t
+ pseudo_read (struct grub_file *file, char *buf, grub_size_t len)
+ {
+@@ -973,7 +985,9 @@ GRUB_MOD_INIT(pgp)
+ sec = 0;
+
+ grub_register_variable_hook ("check_signatures", 0, grub_env_write_sec);
++ grub_register_variable_hook ("strict_security", 0, grub_env_write_strict_sec);
+ grub_env_export ("check_signatures");
++ grub_env_export ("strict_security");
+
+ grub_pk_trusted = 0;
+ FOR_MODULES (header)
+diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
+index 73967e2..86e7f35 100644
+--- a/grub-core/kern/main.c
++++ b/grub-core/kern/main.c
+@@ -30,6 +30,7 @@
+ #include
+ #include
+ #include
++#include
+
+ #ifdef GRUB_MACHINE_PCBIOS
+ #include
+@@ -312,5 +313,13 @@ grub_main (void)
+ grub_boot_time ("After execution of embedded config. Attempt to go to normal mode");
+
+ grub_load_normal_mode ();
++ const char *val = grub_env_get ("strict_security");
++ if (val && (val[0] == '1' || val[0] == 'e'))
++ while (1) {
++ grub_printf("Boot configuration error - Attempting reboot\n");
++ grub_sleep(3);
++ grub_dl_load ("reboot");
++ grub_command_execute ("reboot", 0, 0);
++ }
+ grub_rescue_run ();
+ }
+diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
+index c4ebe9e..2c3f4f8 100644
+--- a/grub-core/normal/main.c
++++ b/grub-core/normal/main.c
+@@ -302,8 +302,11 @@ grub_enter_normal_mode (const char *config)
+ grub_boot_time ("Entering normal mode");
+ nested_level++;
+ grub_normal_execute (config, 0, 0);
+- grub_boot_time ("Entering shell");
+- grub_cmdline_run (0, 1);
++ const char *val = grub_env_get ("strict_security");
++ if (!(val && (val[0] == '1' || val[0] == 'e'))) {
++ grub_boot_time ("Entering shell");
++ grub_cmdline_run (0, 1);
++ }
+ nested_level--;
+ if (grub_normal_exit_level)
+ grub_normal_exit_level--;
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/0019-Disable-inside-lockdown-and-shim_lock-verifiers.patch b/grub/grub-efi/debian/patches/0019-Disable-inside-lockdown-and-shim_lock-verifiers.patch
new file mode 100644
index 000000000..e7ad48e16
--- /dev/null
+++ b/grub/grub-efi/debian/patches/0019-Disable-inside-lockdown-and-shim_lock-verifiers.patch
@@ -0,0 +1,48 @@
+From 7ed6b7cbdc5f0721a7f6e89e601ad1b8c2cff267 Mon Sep 17 00:00:00 2001
+From: Yi Zhao
+Date: Wed, 7 Apr 2021 11:00:37 +0800
+Subject: [PATCH] Disable inside lockdown and shim_lock verifiers
+
+The lockdown support[1] and secure boot detection[2] have been added to
+grub 2.06. These verifiers are registered when UEFI Secure Boot is
+enabled. Unfortunately, they conflict with the current MOK2 Verify
+mechanism. So disable them when enable SELoader.
+
+Fixes grub error:
+error: failed to verify kernel /bzImage
+
+[1] http://git.savannah.gnu.org/cgit/grub.git/commit/?id=578c95298bcc46e0296f4c786db64c2ff26ce2cc
+[2] http://git.savannah.gnu.org/cgit/grub.git/commit/?id=d7e54b2e5feee95d2f83058ed30d883c450d1473
+
+Upstream-Status: Inappropriate [embedded specific]
+
+Signed-off-by: Yi Zhao
+[lz: Adapt git log.]
+Signed-off-by: Li Zhou
+---
+ grub-core/kern/efi/init.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
+index 4a88397..e512a8e 100644
+--- a/grub-core/kern/efi/init.c
++++ b/grub-core/kern/efi/init.c
+@@ -159,6 +159,7 @@ grub_efi_init (void)
+ /* Initialize the memory management system. */
+ grub_efi_mm_init ();
+
++#if 0
+ /*
+ * Lockdown the GRUB and register the shim_lock verifier
+ * if the UEFI Secure Boot is enabled.
+@@ -168,6 +169,7 @@ grub_efi_init (void)
+ grub_lockdown ();
+ grub_shim_lock_verifier_setup ();
+ }
++#endif
+
+ efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer,
+ 0, 0, 0, NULL);
+--
+2.17.1
+
diff --git a/grub/grub-efi/debian/patches/series b/grub/grub-efi/debian/patches/series
new file mode 100644
index 000000000..221816f6c
--- /dev/null
+++ b/grub/grub-efi/debian/patches/series
@@ -0,0 +1,19 @@
+0001-grub2-add-tboot.patch
+0002-grub2-checking-if-loop-devices-are-available.patch
+0003-Make-UEFI-watchdog-behaviour-configurable.patch
+0004-correct-grub_errno.patch
+0005-grub-verify-Add-skip_check_cfg-variable.patch
+0006-pe32.h-add-header-structures-for-TE-and-DOS-executab.patch
+0007-shim-add-needed-data-structures.patch
+0008-efi-chainloader-implement-an-UEFI-Exit-service.patch
+0009-efi-chainloader-port-shim-to-grub.patch
+0010-efi-chainloader-use-shim-to-load-and-verify-an-image.patch
+0011-efi-chainloader-boot-the-image-using-shim.patch
+0012-efi-chainloader-take-care-of-unload-undershim.patch
+0013-chainloader-handle-the-unauthenticated-image-by-shim.patch
+0014-chainloader-Don-t-check-empty-section-in-file-like-..patch
+0015-chainloader-find-the-relocations-correctly.patch
+0016-Add-a-module-for-reading-EFI-global-variables.patch
+0017-grub-shim-verify-Report-that-the-loaded-object-is-ve.patch
+0018-grub-verify-Add-strict_security-variable.patch
+0019-Disable-inside-lockdown-and-shim_lock-verifiers.patch