-From 72da0de7449b8eada6a23f9a5e4b48f07955a368 Mon Sep 17 00:00:00 2001
+From 3b2f0fe2c4f9d1f4734ad33d0b57a77e0036a68d Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg@redhat.com>
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: 2016-09-19
+Last-Update: 2019-05-26
Patch-Name: linuxefi.patch
---
- grub-core/Makefile.core.def | 8 +
+ grub-core/Makefile.core.def | 7 +
grub-core/kern/efi/mm.c | 32 +++
- grub-core/loader/i386/efi/linux.c | 371 ++++++++++++++++++++++++++++++
+ grub-core/loader/i386/efi/linux.c | 375 ++++++++++++++++++++++++++++++
include/grub/efi/efi.h | 3 +
- include/grub/i386/linux.h | 1 +
- 5 files changed, 415 insertions(+)
+ 4 files changed, 417 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 2dfa22a92..68e47a727 100644
+index 474a63e68..67a98abbb 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
-@@ -1733,6 +1733,14 @@ module = {
+@@ -1849,6 +1849,13 @@ module = {
enable = x86_64_efi;
};
+module = {
+ name = linuxefi;
+ efi = loader/i386/efi/linux.c;
-+ efi = lib/cmdline.c;
+ enable = i386_efi;
+ enable = x86_64_efi;
+};
name = chain;
efi = loader/efi/chainloader.c;
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
-index 20a47aaf5..efb15cc1b 100644
+index b02fab1b1..a9e37108c 100644
--- 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;
- static grub_efi_uint32_t finish_desc_version;
- int grub_efi_is_finished = 0;
+@@ -113,6 +113,38 @@ grub_efi_drop_alloc (grub_efi_physical_address_t address,
+ }
+ }
+/* Allocate pages below a specified address */
+void *
+
/* Allocate pages. Return the pointer to the first of allocated pages. */
void *
- grub_efi_allocate_pages (grub_efi_physical_address_t address,
+ grub_efi_allocate_pages_real (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 000000000..b622b3b71
+index 000000000..dd376ce03
--- /dev/null
+++ b/grub-core/loader/i386/efi/linux.c
-@@ -0,0 +1,371 @@
+@@ -0,0 +1,375 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2012 Free Software Foundation, Inc.
+#include <grub/loader.h>
+#include <grub/file.h>
+#include <grub/err.h>
++#include <grub/misc.h>
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/cpu/linux.h>
+#include <grub/command.h>
+#include <grub/i18n.h>
+#include <grub/lib/cmdline.h>
++#include <grub/linux.h>
+#include <grub/efi/efi.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+{
+ 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 0;
++ }
+
-+ 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;
+}
+
+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
-+ grub_file_t *files = 0;
-+ int i, nfiles = 0;
+ grub_size_t size = 0;
-+ grub_uint8_t *ptr;
++ struct grub_linux_initrd_context initrd_ctx;
+
+ if (argc == 0)
+ {
+ goto fail;
+ }
+
-+ files = grub_zalloc (argc * sizeof (files[0]));
-+ if (!files)
++ if (grub_initrd_init (argc, argv, &initrd_ctx))
+ goto fail;
+
-+ for (i = 0; i < argc; i++)
-+ {
-+ grub_file_filter_disable_compression ();
-+ files[i] = grub_file_open (argv[i]);
-+ if (! files[i])
-+ goto fail;
-+ nfiles++;
-+ size += ALIGN_UP (grub_file_size (files[i]), 4);
-+ }
++ size = grub_get_initrd_size (&initrd_ctx);
+
+ initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
+
+ goto fail;
+ }
+
++ grub_dprintf ("linuxefi", "initrd_mem = %lx\n", (unsigned long) initrd_mem);
++
+ params->ramdisk_size = size;
+ params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem;
+
-+ ptr = initrd_mem;
-+
-+ for (i = 0; i < nfiles; i++)
-+ {
-+ grub_ssize_t cursize = grub_file_size (files[i]);
-+ if (grub_file_read (files[i], ptr, cursize) != cursize)
-+ {
-+ if (!grub_errno)
-+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
-+ argv[i]);
-+ goto fail;
-+ }
-+ ptr += cursize;
-+ grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
-+ ptr += ALIGN_UP_OVERHEAD (cursize, 4);
-+ }
++ if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
++ goto fail;
+
+ params->ramdisk_size = size;
+
+ fail:
-+ for (i = 0; i < nfiles; i++)
-+ grub_file_close (files[i]);
-+ grub_free (files);
++ grub_initrd_close (&initrd_ctx);
+
+ if (initrd_mem && grub_errno)
+ grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, BYTES_TO_PAGES(size));
+ int argc, char *argv[])
+{
+ grub_file_t file = 0;
-+ struct linux_kernel_header lh;
++ struct linux_i386_kernel_header lh;
+ grub_ssize_t len, start, filelen;
+ void *kernel;
+
+ goto fail;
+ }
+
-+ file = grub_file_open (argv[0]);
++ file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
+ if (! file)
+ goto fail;
+
+ goto fail;
+ }
+
++ grub_dprintf ("linuxefi", "params = %lx\n", (unsigned long) params);
++
+ grub_memset (params, 0, 16384);
+
+ if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
+ goto fail;
+ }
+
++ grub_dprintf ("linuxefi", "linux_cmdline = %lx\n",
++ (unsigned long) linux_cmdline);
++
+ grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
-+ grub_create_loader_cmdline (argc, argv,
-+ linux_cmdline + sizeof (LINUX_IMAGE) - 1,
-+ lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1));
++ {
++ grub_err_t err;
++ err = grub_create_loader_cmdline (argc, argv,
++ linux_cmdline
++ + sizeof (LINUX_IMAGE) - 1,
++ lh.cmdline_size
++ - (sizeof (LINUX_IMAGE) - 1),
++ GRUB_VERIFY_KERNEL_CMDLINE);
++ if (err)
++ goto fail;
++ }
+
+ lh.cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
+
+ start = (lh.setup_sects + 1) * 512;
+ len = grub_file_size(file) - start;
+
-+ kernel_mem = grub_efi_allocate_pages(lh.pref_address,
++ kernel_mem = grub_efi_allocate_fixed(lh.pref_address,
+ BYTES_TO_PAGES(lh.init_size));
+
+ if (!kernel_mem)
+ goto fail;
+ }
+
++ grub_dprintf ("linuxefi", "kernel_mem = %lx\n", (unsigned long) kernel_mem);
++
+ if (grub_file_seek (file, start) == (grub_off_t) -1)
+ {
+ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+ grub_unregister_command (cmd_initrd);
+}
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
-index 5e87950fd..62a3d9726 100644
+index a237952b3..085ee0524 100644
--- 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);
- void *
- EXPORT_FUNC(grub_efi_allocate_pages) (grub_efi_physical_address_t address,
+@@ -47,6 +47,9 @@ EXPORT_FUNC(grub_efi_allocate_fixed) (grub_efi_physical_address_t address,
grub_efi_uintn_t pages);
+ void *
+ EXPORT_FUNC(grub_efi_allocate_any_pages) (grub_efi_uintn_t pages);
+void *
+EXPORT_FUNC(grub_efi_allocate_pages_max) (grub_efi_physical_address_t max,
+ grub_efi_uintn_t pages);
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 da0ca3b83..fc36bdaf3 100644
---- a/include/grub/i386/linux.h
-+++ b/include/grub/i386/linux.h
-@@ -139,6 +139,7 @@ struct linux_kernel_header
- grub_uint64_t setup_data;
- grub_uint64_t pref_address;
- grub_uint32_t init_size;
-+ grub_uint32_t handover_offset;
- } GRUB_PACKED;
-
- /* Boot parameters for Linux based on 2.6.12. This is used by the setup
+ grub_efi_uintn_t EXPORT_FUNC(grub_efi_find_mmap_size) (void);