Blame SOURCES/0004-Add-support-for-Linux-EFI-stub-loading.patch

5593c8
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
5593c8
From: Matthew Garrett <mjg@redhat.com>
5593c8
Date: Tue, 10 Jul 2012 11:58:52 -0400
5593c8
Subject: [PATCH] Add support for Linux EFI stub loading.
5593c8
5593c8
Also:
5593c8
5593c8
commit 71c843745f22f81e16d259e2e19c99bf3c1855c1
5593c8
Author: Colin Watson <cjwatson@ubuntu.com>
5593c8
Date:   Tue Oct 23 10:40:49 2012 -0400
5593c8
5593c8
Don't allow insmod when secure boot is enabled.
5593c8
5593c8
Hi,
5593c8
5593c8
Fedora's patch to forbid insmod in UEFI Secure Boot environments is fine
5593c8
as far as it goes.  However, the insmod command is not the only way that
5593c8
modules can be loaded.  In particular, the 'normal' command, which
5593c8
implements the usual GRUB menu and the fully-featured command prompt,
5593c8
will implicitly load commands not currently loaded into memory.  This
5593c8
permits trivial Secure Boot violations by writing commands implementing
5593c8
whatever you want to do and pointing $prefix at the malicious code.
5593c8
5593c8
I'm currently test-building this patch (replacing your current
5593c8
grub-2.00-no-insmod-on-sb.patch), but this should be more correct.  It
5593c8
moves the check into grub_dl_load_file.
5593c8
---
5593c8
 grub-core/Makefile.core.def       |  16 +-
5593c8
 grub-core/kern/dl.c               |  21 +++
5593c8
 grub-core/kern/efi/efi.c          |  28 ++++
5593c8
 grub-core/kern/efi/mm.c           |  32 ++++
5593c8
 grub-core/loader/arm64/linux.c    | 118 +++++++-------
5593c8
 grub-core/loader/arm64/xen_boot.c |   1 -
5593c8
 grub-core/loader/efi/linux.c      |  70 ++++++++
5593c8
 grub-core/loader/i386/efi/linux.c | 335 ++++++++++++++++++++++++++++++++++++++
5593c8
 grub-core/loader/i386/pc/linux.c  |  10 +-
5593c8
 include/grub/arm/linux.h          |   9 +
5593c8
 include/grub/arm64/linux.h        |   9 +
5593c8
 include/grub/efi/efi.h            |   7 +-
5593c8
 include/grub/efi/linux.h          |  31 ++++
5593c8
 13 files changed, 618 insertions(+), 69 deletions(-)
5593c8
 create mode 100644 grub-core/loader/efi/linux.c
5593c8
 create mode 100644 grub-core/loader/i386/efi/linux.c
5593c8
 create mode 100644 include/grub/efi/linux.h
5593c8
5593c8
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
5593c8
index 8022e1c0a79..45d3edaa4dc 100644
5593c8
--- a/grub-core/Makefile.core.def
5593c8
+++ b/grub-core/Makefile.core.def
5593c8
@@ -1734,13 +1734,6 @@ module = {
5593c8
   enable = i386_pc;
5593c8
 };
5593c8
 
5593c8
-
5593c8
-module = {
5593c8
-  name = linux16;
5593c8
-  common = loader/i386/pc/linux.c;
5593c8
-  enable = x86;
5593c8
-};
5593c8
-
5593c8
 module = {
5593c8
   name = ntldr;
5593c8
   i386_pc = loader/i386/pc/ntldr.c;
5593c8
@@ -1796,7 +1789,9 @@ module = {
5593c8
 
5593c8
 module = {
5593c8
   name = linux;
5593c8
-  x86 = loader/i386/linux.c;
5593c8
+  i386_pc = loader/i386/pc/linux.c;
5593c8
+  x86_64_efi = loader/i386/efi/linux.c;
5593c8
+  i386_efi = loader/i386/efi/linux.c;
5593c8
   i386_xen_pvh = loader/i386/linux.c;
5593c8
   xen = loader/i386/xen.c;
5593c8
   i386_pc = lib/i386/pc/vesa_modes_table.c;
5593c8
@@ -1811,9 +1806,14 @@ module = {
5593c8
   arm64 = loader/arm64/linux.c;
5593c8
   riscv32 = loader/riscv/linux.c;
5593c8
   riscv64 = loader/riscv/linux.c;
5593c8
+  emu = loader/emu/linux.c;
5593c8
+  fdt = lib/fdt.c;
5593c8
+
5593c8
   common = loader/linux.c;
5593c8
   common = lib/cmdline.c;
5593c8
   enable = noemu;
5593c8
+
5593c8
+  efi = loader/efi/linux.c;
5593c8
 };
5593c8
 
5593c8
 module = {
5593c8
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
5593c8
index 48f8a79073d..b7149370950 100644
5593c8
--- a/grub-core/kern/dl.c
5593c8
+++ b/grub-core/kern/dl.c
5593c8
@@ -38,6 +38,14 @@
5593c8
 #define GRUB_MODULES_MACHINE_READONLY
5593c8
 #endif
5593c8
 
5593c8
+#ifdef GRUB_MACHINE_EMU
5593c8
+#include <sys/mman.h>
5593c8
+#endif
5593c8
+
5593c8
+#ifdef GRUB_MACHINE_EFI
5593c8
+#include <grub/efi/efi.h>
5593c8
+#endif
5593c8
+
5593c8
 
5593c8
 
5593c8
 #pragma GCC diagnostic ignored "-Wcast-align"
5593c8
@@ -695,6 +703,19 @@ grub_dl_load_file (const char *filename)
5593c8
   void *core = 0;
5593c8
   grub_dl_t mod = 0;
5593c8
 
5593c8
+#ifdef GRUB_MACHINE_EFI
5593c8
+  if (grub_efi_secure_boot ())
5593c8
+    {
5593c8
+#if 0
5593c8
+      /* This is an error, but grub2-mkconfig still generates a pile of
5593c8
+       * insmod commands, so emitting it would be mostly just obnoxious. */
5593c8
+      grub_error (GRUB_ERR_ACCESS_DENIED,
5593c8
+		  "Secure Boot forbids loading module from %s", filename);
5593c8
+#endif
5593c8
+      return 0;
5593c8
+    }
5593c8
+#endif
5593c8
+
5593c8
   grub_boot_time ("Loading module %s", filename);
5593c8
 
5593c8
   file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE);
5593c8
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
5593c8
index 8cff7be0289..35b8f670602 100644
5593c8
--- a/grub-core/kern/efi/efi.c
5593c8
+++ b/grub-core/kern/efi/efi.c
5593c8
@@ -286,6 +286,34 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
5593c8
   return grub_efi_get_variable_with_attributes (var, guid, datasize_out, data_out, NULL);
5593c8
 }
5593c8
 
5593c8
+grub_efi_boolean_t
5593c8
+grub_efi_secure_boot (void)
5593c8
+{
5593c8
+  grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
5593c8
+  grub_size_t datasize;
5593c8
+  char *secure_boot = NULL;
5593c8
+  char *setup_mode = NULL;
5593c8
+  grub_efi_boolean_t ret = 0;
5593c8
+
5593c8
+  secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
5593c8
+
5593c8
+  if (datasize != 1 || !secure_boot)
5593c8
+    goto out;
5593c8
+
5593c8
+  setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
5593c8
+
5593c8
+  if (datasize != 1 || !setup_mode)
5593c8
+    goto out;
5593c8
+
5593c8
+  if (*secure_boot && !*setup_mode)
5593c8
+    ret = 1;
5593c8
+
5593c8
+ out:
5593c8
+  grub_free (secure_boot);
5593c8
+  grub_free (setup_mode);
5593c8
+  return ret;
5593c8
+}
5593c8
+
5593c8
 #pragma GCC diagnostic ignored "-Wcast-align"
5593c8
 
5593c8
 /* Search the mods section from the PE32/PE32+ image. This code uses
5593c8
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
5593c8
index 9838fb2f50d..f6aef0ef649 100644
5593c8
--- a/grub-core/kern/efi/mm.c
5593c8
+++ b/grub-core/kern/efi/mm.c
5593c8
@@ -113,6 +113,38 @@ grub_efi_drop_alloc (grub_efi_physical_address_t address,
5593c8
     }
5593c8
 }
5593c8
 
5593c8
+/* Allocate pages below a specified address */
5593c8
+void *
5593c8
+grub_efi_allocate_pages_max (grub_efi_physical_address_t max,
5593c8
+			     grub_efi_uintn_t pages)
5593c8
+{
5593c8
+  grub_efi_status_t status;
5593c8
+  grub_efi_boot_services_t *b;
5593c8
+  grub_efi_physical_address_t address = max;
5593c8
+
5593c8
+  if (max > 0xffffffff)
5593c8
+    return 0;
5593c8
+
5593c8
+  b = grub_efi_system_table->boot_services;
5593c8
+  status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address);
5593c8
+
5593c8
+  if (status != GRUB_EFI_SUCCESS)
5593c8
+    return 0;
5593c8
+
5593c8
+  if (address == 0)
5593c8
+    {
5593c8
+      /* Uggh, the address 0 was allocated... This is too annoying,
5593c8
+	 so reallocate another one.  */
5593c8
+      address = max;
5593c8
+      status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address);
5593c8
+      grub_efi_free_pages (0, pages);
5593c8
+      if (status != GRUB_EFI_SUCCESS)
5593c8
+	return 0;
5593c8
+    }
5593c8
+
5593c8
+  return (void *) ((grub_addr_t) address);
5593c8
+}
5593c8
+
5593c8
 /* Allocate pages. Return the pointer to the first of allocated pages.  */
5593c8
 void *
5593c8
 grub_efi_allocate_pages_real (grub_efi_physical_address_t address,
5593c8
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
5593c8
index ef3e9f9444c..a312c668685 100644
5593c8
--- a/grub-core/loader/arm64/linux.c
5593c8
+++ b/grub-core/loader/arm64/linux.c
5593c8
@@ -29,6 +29,7 @@
5593c8
 #include <grub/efi/efi.h>
5593c8
 #include <grub/efi/fdtload.h>
5593c8
 #include <grub/efi/memory.h>
5593c8
+#include <grub/efi/linux.h>
5593c8
 #include <grub/efi/pe32.h>
5593c8
 #include <grub/i18n.h>
5593c8
 #include <grub/lib/cmdline.h>
5593c8
@@ -41,6 +42,7 @@ static int loaded;
5593c8
 
5593c8
 static void *kernel_addr;
5593c8
 static grub_uint64_t kernel_size;
5593c8
+static grub_uint32_t handover_offset;
5593c8
 
5593c8
 static char *linux_args;
5593c8
 static grub_uint32_t cmdline_size;
5593c8
@@ -67,7 +69,8 @@ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
5593c8
 static grub_err_t
5593c8
 finalize_params_linux (void)
5593c8
 {
5593c8
-  int node, retval;
5593c8
+  grub_efi_loaded_image_t *loaded_image = NULL;
5593c8
+  int node, retval, len;
5593c8
 
5593c8
   void *fdt;
5593c8
 
5593c8
@@ -102,79 +105,70 @@ finalize_params_linux (void)
5593c8
   if (grub_fdt_install() != GRUB_ERR_NONE)
5593c8
     goto failure;
5593c8
 
5593c8
-  return GRUB_ERR_NONE;
5593c8
-
5593c8
-failure:
5593c8
-  grub_fdt_unload();
5593c8
-  return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
5593c8
-}
5593c8
-
5593c8
-grub_err_t
5593c8
-grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
5593c8
-{
5593c8
-  grub_efi_memory_mapped_device_path_t *mempath;
5593c8
-  grub_efi_handle_t image_handle;
5593c8
-  grub_efi_boot_services_t *b;
5593c8
-  grub_efi_status_t status;
5593c8
-  grub_efi_loaded_image_t *loaded_image;
5593c8
-  int len;
5593c8
-
5593c8
-  mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t));
5593c8
-  if (!mempath)
5593c8
-    return grub_errno;
5593c8
-
5593c8
-  mempath[0].header.type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE;
5593c8
-  mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE;
5593c8
-  mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath));
5593c8
-  mempath[0].memory_type = GRUB_EFI_LOADER_DATA;
5593c8
-  mempath[0].start_address = addr;
5593c8
-  mempath[0].end_address = addr + size;
5593c8
-
5593c8
-  mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE;
5593c8
-  mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
5593c8
-  mempath[1].header.length = sizeof (grub_efi_device_path_t);
5593c8
-
5593c8
-  b = grub_efi_system_table->boot_services;
5593c8
-  status = b->load_image (0, grub_efi_image_handle,
5593c8
-			  (grub_efi_device_path_t *) mempath,
5593c8
-			  (void *) addr, size, &image_handle);
5593c8
-  if (status != GRUB_EFI_SUCCESS)
5593c8
-    return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
5593c8
-
5593c8
-  grub_dprintf ("linux", "linux command line: '%s'\n", args);
5593c8
+  grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
5593c8
+                fdt);
5593c8
 
5593c8
   /* Convert command line to UCS-2 */
5593c8
-  loaded_image = grub_efi_get_loaded_image (image_handle);
5593c8
+  loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
5593c8
+  if (!loaded_image)
5593c8
+    goto failure;
5593c8
+
5593c8
   loaded_image->load_options_size = len =
5593c8
-    (grub_strlen (args) + 1) * sizeof (grub_efi_char16_t);
5593c8
+    (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t);
5593c8
   loaded_image->load_options =
5593c8
     grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
5593c8
   if (!loaded_image->load_options)
5593c8
-    return grub_errno;
5593c8
+    return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters");
5593c8
 
5593c8
   loaded_image->load_options_size =
5593c8
     2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
5593c8
-			    (grub_uint8_t *) args, len, NULL);
5593c8
+                           (grub_uint8_t *) linux_args, len, NULL);
5593c8
 
5593c8
-  grub_dprintf ("linux", "starting image %p\n", image_handle);
5593c8
-  status = b->start_image (image_handle, 0, NULL);
5593c8
+  return GRUB_ERR_NONE;
5593c8
 
5593c8
-  /* When successful, not reached */
5593c8
-  b->unload_image (image_handle);
5593c8
-  grub_efi_free_pages ((grub_addr_t) loaded_image->load_options,
5593c8
-		       GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
5593c8
+failure:
5593c8
+  grub_fdt_unload();
5593c8
+  return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
5593c8
+}
5593c8
 
5593c8
-  return grub_errno;
5593c8
+static void
5593c8
+free_params (void)
5593c8
+{
5593c8
+  grub_efi_loaded_image_t *loaded_image = NULL;
5593c8
+
5593c8
+  loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
5593c8
+  if (loaded_image)
5593c8
+    {
5593c8
+      if (loaded_image->load_options)
5593c8
+       grub_efi_free_pages ((grub_efi_physical_address_t)(grub_efi_uintn_t)loaded_image->load_options,
5593c8
+                            GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
5593c8
+      loaded_image->load_options = NULL;
5593c8
+      loaded_image->load_options_size = 0;
5593c8
+    }
5593c8
+}
5593c8
+
5593c8
+grub_err_t
5593c8
+grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args)
5593c8
+{
5593c8
+  grub_err_t retval;
5593c8
+
5593c8
+  retval = finalize_params_linux ();
5593c8
+  if (retval != GRUB_ERR_NONE)
5593c8
+    return grub_errno;
5593c8
+
5593c8
+  grub_dprintf ("linux", "linux command line: '%s'\n", args);
5593c8
+
5593c8
+  retval = grub_efi_linux_boot ((char *)addr, handover_offset, (void *)addr);
5593c8
+
5593c8
+  /* Never reached... */
5593c8
+  free_params();
5593c8
+  return retval;
5593c8
 }
5593c8
 
5593c8
 static grub_err_t
5593c8
 grub_linux_boot (void)
5593c8
 {
5593c8
-  if (finalize_params_linux () != GRUB_ERR_NONE)
5593c8
-    return grub_errno;
5593c8
-
5593c8
-  return (grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr,
5593c8
-                                          kernel_size, linux_args));
5593c8
+  return (grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr, linux_args));
5593c8
 }
5593c8
 
5593c8
 static grub_err_t
5593c8
@@ -288,6 +282,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
5593c8
 {
5593c8
   grub_file_t file = 0;
5593c8
   struct linux_arch_kernel_header lh;
5593c8
+  struct grub_armxx_linux_pe_header *pe;
5593c8
   grub_err_t err;
5593c8
 
5593c8
   grub_dl_ref (my_mod);
5593c8
@@ -333,6 +328,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
5593c8
 
5593c8
   grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
5593c8
 
5593c8
+  if (!grub_linuxefi_secure_validate (kernel_addr, kernel_size))
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
5593c8
+  handover_offset = pe->opt.entry_addr;
5593c8
+
5593c8
   cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
5593c8
   linux_args = grub_malloc (cmdline_size);
5593c8
   if (!linux_args)
5593c8
diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
5593c8
index 22cc25eccd9..d9b7a9ba400 100644
5593c8
--- a/grub-core/loader/arm64/xen_boot.c
5593c8
+++ b/grub-core/loader/arm64/xen_boot.c
5593c8
@@ -266,7 +266,6 @@ xen_boot (void)
5593c8
     return err;
5593c8
 
5593c8
   return grub_arch_efi_linux_boot_image (xen_hypervisor->start,
5593c8
-					  xen_hypervisor->size,
5593c8
 					  xen_hypervisor->cmdline);
5593c8
 }
5593c8
 
5593c8
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
5593c8
new file mode 100644
5593c8
index 00000000000..c24202a5dd1
5593c8
--- /dev/null
5593c8
+++ b/grub-core/loader/efi/linux.c
5593c8
@@ -0,0 +1,70 @@
5593c8
+/*
5593c8
+ *  GRUB  --  GRand Unified Bootloader
5593c8
+ *  Copyright (C) 2014 Free Software Foundation, Inc.
5593c8
+ *
5593c8
+ *  GRUB is free software: you can redistribute it and/or modify
5593c8
+ *  it under the terms of the GNU General Public License as published by
5593c8
+ *  the Free Software Foundation, either version 3 of the License, or
5593c8
+ *  (at your option) any later version.
5593c8
+ *
5593c8
+ *  GRUB is distributed in the hope that it will be useful,
5593c8
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
5593c8
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5593c8
+ *  GNU General Public License for more details.
5593c8
+ *
5593c8
+ *  You should have received a copy of the GNU General Public License
5593c8
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
5593c8
+ */
5593c8
+
5593c8
+#include <grub/err.h>
5593c8
+#include <grub/mm.h>
5593c8
+#include <grub/types.h>
5593c8
+#include <grub/cpu/linux.h>
5593c8
+#include <grub/efi/efi.h>
5593c8
+#include <grub/efi/pe32.h>
5593c8
+#include <grub/efi/linux.h>
5593c8
+
5593c8
+#define SHIM_LOCK_GUID \
5593c8
+ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
5593c8
+
5593c8
+struct grub_efi_shim_lock
5593c8
+{
5593c8
+  grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
5593c8
+};
5593c8
+typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
5593c8
+
5593c8
+grub_efi_boolean_t
5593c8
+grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
5593c8
+{
5593c8
+  grub_efi_guid_t guid = SHIM_LOCK_GUID;
5593c8
+  grub_efi_shim_lock_t *shim_lock;
5593c8
+
5593c8
+  shim_lock = grub_efi_locate_protocol(&guid, NULL);
5593c8
+
5593c8
+  if (!shim_lock)
5593c8
+    return 1;
5593c8
+
5593c8
+  if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS)
5593c8
+    return 1;
5593c8
+
5593c8
+  return 0;
5593c8
+}
5593c8
+
5593c8
+#pragma GCC diagnostic push
5593c8
+#pragma GCC diagnostic ignored "-Wcast-align"
5593c8
+
5593c8
+typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
5593c8
+
5593c8
+grub_err_t
5593c8
+grub_efi_linux_boot (void *kernel_addr, grub_off_t offset,
5593c8
+		     void *kernel_params)
5593c8
+{
5593c8
+  handover_func hf;
5593c8
+
5593c8
+  hf = (handover_func)((char *)kernel_addr + offset);
5593c8
+  hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
5593c8
+
5593c8
+  return GRUB_ERR_BUG;
5593c8
+}
5593c8
+
5593c8
+#pragma GCC diagnostic pop
5593c8
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
5593c8
new file mode 100644
5593c8
index 00000000000..bb2616a8092
5593c8
--- /dev/null
5593c8
+++ b/grub-core/loader/i386/efi/linux.c
5593c8
@@ -0,0 +1,335 @@
5593c8
+/*
5593c8
+ *  GRUB  --  GRand Unified Bootloader
5593c8
+ *  Copyright (C) 2012  Free Software Foundation, Inc.
5593c8
+ *
5593c8
+ *  GRUB is free software: you can redistribute it and/or modify
5593c8
+ *  it under the terms of the GNU General Public License as published by
5593c8
+ *  the Free Software Foundation, either version 3 of the License, or
5593c8
+ *  (at your option) any later version.
5593c8
+ *
5593c8
+ *  GRUB is distributed in the hope that it will be useful,
5593c8
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
5593c8
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5593c8
+ *  GNU General Public License for more details.
5593c8
+ *
5593c8
+ *  You should have received a copy of the GNU General Public License
5593c8
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
5593c8
+ */
5593c8
+
5593c8
+#include <grub/loader.h>
5593c8
+#include <grub/file.h>
5593c8
+#include <grub/err.h>
5593c8
+#include <grub/types.h>
5593c8
+#include <grub/mm.h>
5593c8
+#include <grub/cpu/linux.h>
5593c8
+#include <grub/command.h>
5593c8
+#include <grub/i18n.h>
5593c8
+#include <grub/lib/cmdline.h>
5593c8
+#include <grub/efi/efi.h>
5593c8
+#include <grub/efi/linux.h>
5593c8
+
5593c8
+GRUB_MOD_LICENSE ("GPLv3+");
5593c8
+
5593c8
+static grub_dl_t my_mod;
5593c8
+static int loaded;
5593c8
+static void *kernel_mem;
5593c8
+static grub_uint64_t kernel_size;
5593c8
+static grub_uint8_t *initrd_mem;
5593c8
+static grub_uint32_t handover_offset;
5593c8
+struct linux_kernel_params *params;
5593c8
+static char *linux_cmdline;
5593c8
+
5593c8
+#define BYTES_TO_PAGES(bytes)   (((bytes) + 0xfff) >> 12)
5593c8
+
5593c8
+static grub_err_t
5593c8
+grub_linuxefi_boot (void)
5593c8
+{
5593c8
+  int offset = 0;
5593c8
+
5593c8
+#ifdef __x86_64__
5593c8
+  offset = 512;
5593c8
+#endif
5593c8
+  asm volatile ("cli");
5593c8
+
5593c8
+  return grub_efi_linux_boot ((char *)kernel_mem, handover_offset + offset,
5593c8
+			      params);
5593c8
+}
5593c8
+
5593c8
+static grub_err_t
5593c8
+grub_linuxefi_unload (void)
5593c8
+{
5593c8
+  grub_dl_unref (my_mod);
5593c8
+  loaded = 0;
5593c8
+  if (initrd_mem)
5593c8
+    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem,
5593c8
+			 BYTES_TO_PAGES(params->ramdisk_size));
5593c8
+  if (linux_cmdline)
5593c8
+    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
5593c8
+			 linux_cmdline,
5593c8
+			 BYTES_TO_PAGES(params->cmdline_size + 1));
5593c8
+  if (kernel_mem)
5593c8
+    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem,
5593c8
+			 BYTES_TO_PAGES(kernel_size));
5593c8
+  if (params)
5593c8
+    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params,
5593c8
+			 BYTES_TO_PAGES(16384));
5593c8
+  return GRUB_ERR_NONE;
5593c8
+}
5593c8
+
5593c8
+static grub_err_t
5593c8
+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
5593c8
+                 int argc, char *argv[])
5593c8
+{
5593c8
+  grub_file_t *files = 0;
5593c8
+  int i, nfiles = 0;
5593c8
+  grub_size_t size = 0;
5593c8
+  grub_uint8_t *ptr;
5593c8
+
5593c8
+  if (argc == 0)
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  if (!loaded)
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  files = grub_zalloc (argc * sizeof (files[0]));
5593c8
+  if (!files)
5593c8
+    goto fail;
5593c8
+
5593c8
+  for (i = 0; i < argc; i++)
5593c8
+    {
5593c8
+      files[i] = grub_file_open (argv[i], GRUB_FILE_TYPE_LINUX_INITRD | GRUB_FILE_TYPE_NO_DECOMPRESS);
5593c8
+      if (! files[i])
5593c8
+        goto fail;
5593c8
+      nfiles++;
5593c8
+      size += ALIGN_UP (grub_file_size (files[i]), 4);
5593c8
+    }
5593c8
+
5593c8
+  initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
5593c8
+  if (!initrd_mem)
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  params->ramdisk_size = size;
5593c8
+  params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem;
5593c8
+
5593c8
+  ptr = initrd_mem;
5593c8
+
5593c8
+  for (i = 0; i < nfiles; i++)
5593c8
+    {
5593c8
+      grub_ssize_t cursize = grub_file_size (files[i]);
5593c8
+      if (grub_file_read (files[i], ptr, cursize) != cursize)
5593c8
+        {
5593c8
+          if (!grub_errno)
5593c8
+            grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
5593c8
+                        argv[i]);
5593c8
+          goto fail;
5593c8
+        }
5593c8
+      ptr += cursize;
5593c8
+      grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
5593c8
+      ptr += ALIGN_UP_OVERHEAD (cursize, 4);
5593c8
+    }
5593c8
+
5593c8
+  params->ramdisk_size = size;
5593c8
+
5593c8
+ fail:
5593c8
+  for (i = 0; i < nfiles; i++)
5593c8
+    grub_file_close (files[i]);
5593c8
+  grub_free (files);
5593c8
+
5593c8
+  if (initrd_mem && grub_errno)
5593c8
+    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem,
5593c8
+			 BYTES_TO_PAGES(size));
5593c8
+
5593c8
+  return grub_errno;
5593c8
+}
5593c8
+
5593c8
+static grub_err_t
5593c8
+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
5593c8
+		int argc, char *argv[])
5593c8
+{
5593c8
+  grub_file_t file = 0;
5593c8
+  struct linux_i386_kernel_header lh;
5593c8
+  grub_ssize_t len, start, filelen;
5593c8
+  void *kernel = NULL;
5593c8
+
5593c8
+  grub_dl_ref (my_mod);
5593c8
+
5593c8
+  if (argc == 0)
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
5593c8
+  if (! file)
5593c8
+    goto fail;
5593c8
+
5593c8
+  filelen = grub_file_size (file);
5593c8
+
5593c8
+  kernel = grub_malloc(filelen);
5593c8
+
5593c8
+  if (!kernel)
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  if (grub_file_read (file, kernel, filelen) != filelen)
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]);
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  if (! grub_linuxefi_secure_validate (kernel, filelen))
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"),
5593c8
+		  argv[0]);
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
5593c8
+
5593c8
+  if (! params)
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  grub_memset (params, 0, 16384);
5593c8
+
5593c8
+  grub_memcpy (&lh, kernel, sizeof (lh));
5593c8
+
5593c8
+  if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number"));
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  if (lh.version < grub_cpu_to_le16 (0x020b))
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  if (!lh.handover_offset)
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  grub_dprintf ("linux", "setting up cmdline\n");
5593c8
+  linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
5593c8
+					 BYTES_TO_PAGES(lh.cmdline_size + 1));
5593c8
+
5593c8
+  if (!linux_cmdline)
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
5593c8
+  grub_create_loader_cmdline (argc, argv,
5593c8
+                              linux_cmdline + sizeof (LINUX_IMAGE) - 1,
5593c8
+			      lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1),
5593c8
+			      GRUB_VERIFY_KERNEL_CMDLINE);
5593c8
+
5593c8
+  lh.cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
5593c8
+
5593c8
+  handover_offset = lh.handover_offset;
5593c8
+
5593c8
+  start = (lh.setup_sects + 1) * 512;
5593c8
+  len = grub_file_size(file) - start;
5593c8
+
5593c8
+  kernel_mem = grub_efi_allocate_pages_max(lh.pref_address,
5593c8
+					   BYTES_TO_PAGES(lh.init_size));
5593c8
+
5593c8
+  if (!kernel_mem)
5593c8
+    kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
5593c8
+					     BYTES_TO_PAGES(lh.init_size));
5593c8
+
5593c8
+  if (!kernel_mem)
5593c8
+    {
5593c8
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
5593c8
+      goto fail;
5593c8
+    }
5593c8
+
5593c8
+  grub_memcpy (kernel_mem, (char *)kernel + start, len);
5593c8
+  grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
5593c8
+  loaded=1;
5593c8
+
5593c8
+  lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
5593c8
+  grub_memcpy (params, &lh, 2 * 512);
5593c8
+
5593c8
+  params->type_of_loader = 0x21;
5593c8
+
5593c8
+ fail:
5593c8
+
5593c8
+  if (file)
5593c8
+    grub_file_close (file);
5593c8
+
5593c8
+  if (kernel)
5593c8
+    grub_free (kernel);
5593c8
+
5593c8
+  if (grub_errno != GRUB_ERR_NONE)
5593c8
+    {
5593c8
+      grub_dl_unref (my_mod);
5593c8
+      loaded = 0;
5593c8
+    }
5593c8
+
5593c8
+  if (linux_cmdline && !loaded)
5593c8
+    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
5593c8
+			 linux_cmdline,
5593c8
+			 BYTES_TO_PAGES(lh.cmdline_size + 1));
5593c8
+
5593c8
+  if (kernel_mem && !loaded)
5593c8
+    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem,
5593c8
+			 BYTES_TO_PAGES(kernel_size));
5593c8
+
5593c8
+  if (params && !loaded)
5593c8
+    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params,
5593c8
+			 BYTES_TO_PAGES(16384));
5593c8
+
5593c8
+  return grub_errno;
5593c8
+}
5593c8
+
5593c8
+static grub_command_t cmd_linux, cmd_initrd;
5593c8
+static grub_command_t cmd_linuxefi, cmd_initrdefi;
5593c8
+
5593c8
+GRUB_MOD_INIT(linux)
5593c8
+{
5593c8
+  cmd_linux =
5593c8
+    grub_register_command ("linux", grub_cmd_linux,
5593c8
+                           0, N_("Load Linux."));
5593c8
+  cmd_linuxefi =
5593c8
+    grub_register_command ("linuxefi", grub_cmd_linux,
5593c8
+                           0, N_("Load Linux."));
5593c8
+  cmd_initrd =
5593c8
+    grub_register_command ("initrd", grub_cmd_initrd,
5593c8
+                           0, N_("Load initrd."));
5593c8
+  cmd_initrdefi =
5593c8
+    grub_register_command ("initrdefi", grub_cmd_initrd,
5593c8
+                           0, N_("Load initrd."));
5593c8
+  my_mod = mod;
5593c8
+}
5593c8
+
5593c8
+GRUB_MOD_FINI(linux)
5593c8
+{
5593c8
+  grub_unregister_command (cmd_linux);
5593c8
+  grub_unregister_command (cmd_linuxefi);
5593c8
+  grub_unregister_command (cmd_initrd);
5593c8
+  grub_unregister_command (cmd_initrdefi);
5593c8
+}
5593c8
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
5593c8
index 2a299520160..8be4c3b3f48 100644
5593c8
--- a/grub-core/loader/i386/pc/linux.c
5593c8
+++ b/grub-core/loader/i386/pc/linux.c
5593c8
@@ -474,14 +474,20 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
5593c8
   return grub_errno;
5593c8
 }
5593c8
 
5593c8
-static grub_command_t cmd_linux, cmd_initrd;
5593c8
+static grub_command_t cmd_linux, cmd_linux16, cmd_initrd, cmd_initrd16;
5593c8
 
5593c8
 GRUB_MOD_INIT(linux16)
5593c8
 {
5593c8
   cmd_linux =
5593c8
+    grub_register_command ("linux", grub_cmd_linux,
5593c8
+			   0, N_("Load Linux."));
5593c8
+  cmd_linux16 =
5593c8
     grub_register_command ("linux16", grub_cmd_linux,
5593c8
 			   0, N_("Load Linux."));
5593c8
   cmd_initrd =
5593c8
+    grub_register_command ("initrd", grub_cmd_initrd,
5593c8
+			   0, N_("Load initrd."));
5593c8
+  cmd_initrd16 =
5593c8
     grub_register_command ("initrd16", grub_cmd_initrd,
5593c8
 			   0, N_("Load initrd."));
5593c8
   my_mod = mod;
5593c8
@@ -490,5 +496,7 @@ GRUB_MOD_INIT(linux16)
5593c8
 GRUB_MOD_FINI(linux16)
5593c8
 {
5593c8
   grub_unregister_command (cmd_linux);
5593c8
+  grub_unregister_command (cmd_linux16);
5593c8
   grub_unregister_command (cmd_initrd);
5593c8
+  grub_unregister_command (cmd_initrd16);
5593c8
 }
5593c8
diff --git a/include/grub/arm/linux.h b/include/grub/arm/linux.h
5593c8
index bcd5a7eb186..b582f67f661 100644
5593c8
--- a/include/grub/arm/linux.h
5593c8
+++ b/include/grub/arm/linux.h
5593c8
@@ -20,6 +20,7 @@
5593c8
 #ifndef GRUB_ARM_LINUX_HEADER
5593c8
 #define GRUB_ARM_LINUX_HEADER 1
5593c8
 
5593c8
+#include <grub/efi/pe32.h>
5593c8
 #include "system.h"
5593c8
 
5593c8
 #define GRUB_LINUX_ARM_MAGIC_SIGNATURE 0x016f2818
5593c8
@@ -34,9 +35,17 @@ struct linux_arm_kernel_header {
5593c8
   grub_uint32_t hdr_offset;
5593c8
 };
5593c8
 
5593c8
+struct grub_arm_linux_pe_header
5593c8
+{
5593c8
+  grub_uint32_t magic;
5593c8
+  struct grub_pe32_coff_header coff;
5593c8
+  struct grub_pe32_optional_header opt;
5593c8
+};
5593c8
+
5593c8
 #if defined(__arm__)
5593c8
 # define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM_MAGIC_SIGNATURE
5593c8
 # define linux_arch_kernel_header linux_arm_kernel_header
5593c8
+# define grub_armxx_linux_pe_header grub_arm_linux_pe_header
5593c8
 #endif
5593c8
 
5593c8
 #if defined GRUB_MACHINE_UBOOT
5593c8
diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h
5593c8
index 7e22b4ab699..ea030312df3 100644
5593c8
--- a/include/grub/arm64/linux.h
5593c8
+++ b/include/grub/arm64/linux.h
5593c8
@@ -19,6 +19,7 @@
5593c8
 #ifndef GRUB_ARM64_LINUX_HEADER
5593c8
 #define GRUB_ARM64_LINUX_HEADER 1
5593c8
 
5593c8
+#include <grub/efi/pe32.h>
5593c8
 #include <grub/types.h>
5593c8
 
5593c8
 #define GRUB_LINUX_ARM64_MAGIC_SIGNATURE 0x644d5241 /* 'ARM\x64' */
5593c8
@@ -38,9 +39,17 @@ struct linux_arm64_kernel_header
5593c8
   grub_uint32_t hdr_offset;	/* Offset of PE/COFF header */
5593c8
 };
5593c8
 
5593c8
+struct grub_arm64_linux_pe_header
5593c8
+{
5593c8
+  grub_uint32_t magic;
5593c8
+  struct grub_pe32_coff_header coff;
5593c8
+  struct grub_pe64_optional_header opt;
5593c8
+};
5593c8
+
5593c8
 #if defined(__aarch64__)
5593c8
 # define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM64_MAGIC_SIGNATURE
5593c8
 # define linux_arch_kernel_header linux_arm64_kernel_header
5593c8
+# define grub_armxx_linux_pe_header grub_arm64_linux_pe_header
5593c8
 #endif
5593c8
 
5593c8
 #endif /* ! GRUB_ARM64_LINUX_HEADER */
5593c8
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
5593c8
index 83d958f9945..6295df85f3f 100644
5593c8
--- a/include/grub/efi/efi.h
5593c8
+++ b/include/grub/efi/efi.h
5593c8
@@ -47,6 +47,9 @@ EXPORT_FUNC(grub_efi_allocate_fixed) (grub_efi_physical_address_t address,
5593c8
 				      grub_efi_uintn_t pages);
5593c8
 void *
5593c8
 EXPORT_FUNC(grub_efi_allocate_any_pages) (grub_efi_uintn_t pages);
5593c8
+void *
5593c8
+EXPORT_FUNC(grub_efi_allocate_pages_max) (grub_efi_physical_address_t max,
5593c8
+					  grub_efi_uintn_t pages);
5593c8
 void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address,
5593c8
 				       grub_efi_uintn_t pages);
5593c8
 grub_efi_uintn_t EXPORT_FUNC(grub_efi_find_mmap_size) (void);
5593c8
@@ -88,6 +91,7 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var,
5593c8
 				     const grub_efi_guid_t *guid,
5593c8
 				     void *data,
5593c8
 				     grub_size_t datasize);
5593c8
+grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void);
5593c8
 int
5593c8
 EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
5593c8
 					     const grub_efi_device_path_t *dp2);
5593c8
@@ -101,8 +105,7 @@ void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void);
5593c8
 grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *);
5593c8
 #include <grub/cpu/linux.h>
5593c8
 grub_err_t grub_arch_efi_linux_check_image(struct linux_arch_kernel_header *lh);
5593c8
-grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, grub_size_t size,
5593c8
-                                           char *args);
5593c8
+grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, char *args);
5593c8
 #endif
5593c8
 
5593c8
 grub_addr_t grub_efi_modules_addr (void);
5593c8
diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h
5593c8
new file mode 100644
5593c8
index 00000000000..d9ede36773b
5593c8
--- /dev/null
5593c8
+++ b/include/grub/efi/linux.h
5593c8
@@ -0,0 +1,31 @@
5593c8
+/*
5593c8
+ *  GRUB  --  GRand Unified Bootloader
5593c8
+ *  Copyright (C) 2014  Free Software Foundation, Inc.
5593c8
+ *
5593c8
+ *  GRUB is free software: you can redistribute it and/or modify
5593c8
+ *  it under the terms of the GNU General Public License as published by
5593c8
+ *  the Free Software Foundation, either version 3 of the License, or
5593c8
+ *  (at your option) any later version.
5593c8
+ *
5593c8
+ *  GRUB is distributed in the hope that it will be useful,
5593c8
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
5593c8
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5593c8
+ *  GNU General Public License for more details.
5593c8
+ *
5593c8
+ *  You should have received a copy of the GNU General Public License
5593c8
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
5593c8
+ */
5593c8
+#ifndef GRUB_EFI_LINUX_HEADER
5593c8
+#define GRUB_EFI_LINUX_HEADER	1
5593c8
+
5593c8
+#include <grub/efi/api.h>
5593c8
+#include <grub/err.h>
5593c8
+#include <grub/symbol.h>
5593c8
+
5593c8
+grub_efi_boolean_t
5593c8
+EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size);
5593c8
+grub_err_t
5593c8
+EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
5593c8
+				  void *kernel_param);
5593c8
+
5593c8
+#endif /* ! GRUB_EFI_LINUX_HEADER */