Rework SB patches and 10_linux.in changes even harder.

Apparently working on two identical trees at once is not good for doing things
right.

Resolves: rhbz#1601578
Signed-off-by: Peter Jones <pjones@redhat.com>
This commit is contained in:
Peter Jones 2018-07-17 10:20:54 -04:00
parent 1d36e193e6
commit ad4aff0c12
242 changed files with 2904 additions and 4133 deletions

View File

@ -0,0 +1,935 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg@redhat.com>
Date: Tue, 10 Jul 2012 11:58:52 -0400
Subject: [PATCH] Add support for Linux EFI stub loading.
Also:
commit 71c843745f22f81e16d259e2e19c99bf3c1855c1
Author: Colin Watson <cjwatson@ubuntu.com>
Date: Tue Oct 23 10:40:49 2012 -0400
Don't allow insmod when secure boot is enabled.
Hi,
Fedora's patch to forbid insmod in UEFI Secure Boot environments is fine
as far as it goes. However, the insmod command is not the only way that
modules can be loaded. In particular, the 'normal' command, which
implements the usual GRUB menu and the fully-featured command prompt,
will implicitly load commands not currently loaded into memory. This
permits trivial Secure Boot violations by writing commands implementing
whatever you want to do and pointing $prefix at the malicious code.
I'm currently test-building this patch (replacing your current
grub-2.00-no-insmod-on-sb.patch), but this should be more correct. It
moves the check into grub_dl_load_file.
---
grub-core/Makefile.core.def | 17 +-
grub-core/kern/dl.c | 21 +++
grub-core/kern/efi/efi.c | 28 ++++
grub-core/kern/efi/mm.c | 32 ++++
grub-core/loader/arm64/linux.c | 121 +++++++-------
grub-core/loader/efi/linux.c | 65 ++++++++
grub-core/loader/i386/efi/linux.c | 335 ++++++++++++++++++++++++++++++++++++++
grub-core/loader/i386/pc/linux.c | 10 +-
include/grub/arm64/linux.h | 7 +
include/grub/efi/efi.h | 4 +
include/grub/efi/linux.h | 31 ++++
include/grub/i386/linux.h | 1 +
12 files changed, 606 insertions(+), 66 deletions(-)
create mode 100644 grub-core/loader/efi/linux.c
create mode 100644 grub-core/loader/i386/efi/linux.c
create mode 100644 include/grub/efi/linux.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index fc4767f1985..622381f5208 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1627,13 +1627,6 @@ module = {
enable = i386_pc;
};
-
-module = {
- name = linux16;
- common = loader/i386/pc/linux.c;
- enable = x86;
-};
-
module = {
name = ntldr;
i386_pc = loader/i386/pc/ntldr.c;
@@ -1686,7 +1679,9 @@ module = {
module = {
name = linux;
- x86 = loader/i386/linux.c;
+ i386_pc = loader/i386/pc/linux.c;
+ x86_64_efi = loader/i386/efi/linux.c;
+ i386_efi = loader/i386/efi/linux.c;
xen = loader/i386/xen.c;
i386_pc = lib/i386/pc/vesa_modes_table.c;
mips = loader/mips/linux.c;
@@ -1695,9 +1690,15 @@ module = {
ia64_efi = loader/ia64/efi/linux.c;
arm = loader/arm/linux.c;
arm64 = loader/arm64/linux.c;
+ arm64 = loader/efi/linux.c;
+ emu = loader/emu/linux.c;
+ fdt = lib/fdt.c;
+
common = loader/linux.c;
common = lib/cmdline.c;
enable = noemu;
+
+ efi = loader/efi/linux.c;
};
module = {
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index e394cd96f8c..04e804d1668 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -38,6 +38,14 @@
#define GRUB_MODULES_MACHINE_READONLY
#endif
+#ifdef GRUB_MACHINE_EMU
+#include <sys/mman.h>
+#endif
+
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/efi.h>
+#endif
+
#pragma GCC diagnostic ignored "-Wcast-align"
@@ -686,6 +694,19 @@ grub_dl_load_file (const char *filename)
void *core = 0;
grub_dl_t mod = 0;
+#ifdef GRUB_MACHINE_EFI
+ if (grub_efi_secure_boot ())
+ {
+#if 0
+ /* This is an error, but grub2-mkconfig still generates a pile of
+ * insmod commands, so emitting it would be mostly just obnoxious. */
+ grub_error (GRUB_ERR_ACCESS_DENIED,
+ "Secure Boot forbids loading module from %s", filename);
+#endif
+ return 0;
+ }
+#endif
+
grub_boot_time ("Loading module %s", filename);
file = grub_file_open (filename);
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 708581fcbde..c8a9d8307c0 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -273,6 +273,34 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
return NULL;
}
+grub_efi_boolean_t
+grub_efi_secure_boot (void)
+{
+ grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
+ grub_size_t datasize;
+ char *secure_boot = NULL;
+ char *setup_mode = NULL;
+ grub_efi_boolean_t ret = 0;
+
+ secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
+
+ if (datasize != 1 || !secure_boot)
+ goto out;
+
+ setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
+
+ if (datasize != 1 || !setup_mode)
+ goto out;
+
+ if (*secure_boot && !*setup_mode)
+ ret = 1;
+
+ out:
+ grub_free (secure_boot);
+ grub_free (setup_mode);
+ return ret;
+}
+
#pragma GCC diagnostic ignored "-Wcast-align"
/* Search the mods section from the PE32/PE32+ image. This code uses
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index c48e9b5c7c3..775daed16e6 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -113,6 +113,38 @@ grub_efi_drop_alloc (grub_efi_physical_address_t address,
}
}
+/* Allocate pages below a specified address */
+void *
+grub_efi_allocate_pages_max (grub_efi_physical_address_t max,
+ grub_efi_uintn_t pages)
+{
+ grub_efi_status_t status;
+ grub_efi_boot_services_t *b;
+ grub_efi_physical_address_t address = max;
+
+ if (max > 0xffffffff)
+ return 0;
+
+ b = grub_efi_system_table->boot_services;
+ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address);
+
+ if (status != GRUB_EFI_SUCCESS)
+ return 0;
+
+ if (address == 0)
+ {
+ /* Uggh, the address 0 was allocated... This is too annoying,
+ so reallocate another one. */
+ address = max;
+ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address);
+ grub_efi_free_pages (0, pages);
+ if (status != GRUB_EFI_SUCCESS)
+ return 0;
+ }
+
+ return (void *) ((grub_addr_t) address);
+}
+
/* Allocate pages. Return the pointer to the first of allocated pages. */
void *
grub_efi_allocate_pages_real (grub_efi_physical_address_t address,
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
index ebe1e730d63..ab0d27ee4df 100644
--- a/grub-core/loader/arm64/linux.c
+++ b/grub-core/loader/arm64/linux.c
@@ -29,6 +29,7 @@
#include <grub/efi/efi.h>
#include <grub/efi/fdtload.h>
#include <grub/efi/memory.h>
+#include <grub/efi/linux.h>
#include <grub/efi/pe32.h>
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
@@ -40,6 +41,7 @@ static int loaded;
static void *kernel_addr;
static grub_uint64_t kernel_size;
+static grub_uint32_t handover_offset;
static char *linux_args;
static grub_uint32_t cmdline_size;
@@ -66,7 +68,8 @@ grub_arm64_uefi_check_image (struct linux_arm64_kernel_header * lh)
static grub_err_t
finalize_params_linux (void)
{
- int node, retval;
+ grub_efi_loaded_image_t *loaded_image = NULL;
+ int node, retval, len;
void *fdt;
@@ -101,79 +104,73 @@ finalize_params_linux (void)
if (grub_fdt_install() != GRUB_ERR_NONE)
goto failure;
- return GRUB_ERR_NONE;
-
-failure:
- grub_fdt_unload();
- return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
-}
-
-grub_err_t
-grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
-{
- grub_efi_memory_mapped_device_path_t *mempath;
- grub_efi_handle_t image_handle;
- grub_efi_boot_services_t *b;
- grub_efi_status_t status;
- grub_efi_loaded_image_t *loaded_image;
- int len;
-
- mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t));
- if (!mempath)
- return grub_errno;
-
- mempath[0].header.type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE;
- mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE;
- mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath));
- mempath[0].memory_type = GRUB_EFI_LOADER_DATA;
- mempath[0].start_address = addr;
- mempath[0].end_address = addr + size;
-
- mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE;
- mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
- mempath[1].header.length = sizeof (grub_efi_device_path_t);
-
- b = grub_efi_system_table->boot_services;
- status = b->load_image (0, grub_efi_image_handle,
- (grub_efi_device_path_t *) mempath,
- (void *) addr, size, &image_handle);
- if (status != GRUB_EFI_SUCCESS)
- return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
-
- grub_dprintf ("linux", "linux command line: '%s'\n", args);
+ grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
+ fdt);
/* Convert command line to UCS-2 */
- loaded_image = grub_efi_get_loaded_image (image_handle);
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (!loaded_image)
+ goto failure;
+
loaded_image->load_options_size = len =
- (grub_strlen (args) + 1) * sizeof (grub_efi_char16_t);
+ (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t);
loaded_image->load_options =
grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
if (!loaded_image->load_options)
- return grub_errno;
+ return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters");
loaded_image->load_options_size =
2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
- (grub_uint8_t *) args, len, NULL);
+ (grub_uint8_t *) linux_args, len, NULL);
- grub_dprintf ("linux", "starting image %p\n", image_handle);
- status = b->start_image (image_handle, 0, NULL);
+ return GRUB_ERR_NONE;
- /* When successful, not reached */
- b->unload_image (image_handle);
- grub_efi_free_pages ((grub_addr_t) loaded_image->load_options,
- GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+failure:
+ grub_fdt_unload();
+ return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
+}
- return grub_errno;
+static void
+free_params (void)
+{
+ grub_efi_loaded_image_t *loaded_image = NULL;
+
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (loaded_image)
+ {
+ if (loaded_image->load_options)
+ grub_efi_free_pages ((grub_efi_physical_address_t)
+ loaded_image->load_options,
+ GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+ loaded_image->load_options = NULL;
+ loaded_image->load_options_size = 0;
+ }
+}
+
+grub_err_t
+grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
+{
+ grub_err_t retval;
+
+ retval = finalize_params_linux ();
+ if (retval != GRUB_ERR_NONE)
+ return grub_errno;
+
+ grub_dprintf ("linux", "linux command line: '%s'\n", args);
+
+ retval = grub_efi_linux_boot ((char *)kernel_addr, handover_offset,
+ kernel_addr);
+
+ /* Never reached... */
+ free_params();
+ return retval;
}
static grub_err_t
grub_linux_boot (void)
{
- if (finalize_params_linux () != GRUB_ERR_NONE)
- return grub_errno;
-
- return (grub_arm64_uefi_boot_image((grub_addr_t)kernel_addr,
- kernel_size, linux_args));
+ return grub_arm64_uefi_boot_image ((grub_addr_t)kernel_addr,
+ kernel_size, linux_args);
}
static grub_err_t
@@ -250,6 +247,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
{
grub_file_t file = 0;
struct linux_arm64_kernel_header lh;
+ struct grub_arm64_linux_pe_header *pe;
grub_dl_ref (my_mod);
@@ -294,6 +292,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
+ if (!grub_linuxefi_secure_validate (kernel_addr, kernel_size))
+ {
+ grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
+ goto fail;
+ }
+
+ pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
+ handover_offset = pe->opt.entry_addr;
+
cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
linux_args = grub_malloc (cmdline_size);
if (!linux_args)
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
new file mode 100644
index 00000000000..aea378adf5c
--- /dev/null
+++ b/grub-core/loader/efi/linux.c
@@ -0,0 +1,65 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2014 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/cpu/linux.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/pe32.h>
+#include <grub/efi/linux.h>
+
+#define SHIM_LOCK_GUID \
+ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
+
+struct grub_efi_shim_lock
+{
+ grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
+};
+typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
+
+grub_efi_boolean_t
+grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
+{
+ grub_efi_guid_t guid = SHIM_LOCK_GUID;
+ grub_efi_shim_lock_t *shim_lock;
+
+ shim_lock = grub_efi_locate_protocol(&guid, NULL);
+
+ if (!shim_lock)
+ return 1;
+
+ if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS)
+ return 1;
+
+ return 0;
+}
+
+typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
+
+grub_err_t
+grub_efi_linux_boot (void *kernel_addr, grub_off_t offset,
+ void *kernel_params)
+{
+ handover_func hf;
+
+ hf = (handover_func)((char *)kernel_addr + offset);
+ hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
+
+ return GRUB_ERR_BUG;
+}
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
new file mode 100644
index 00000000000..3db82e782df
--- /dev/null
+++ b/grub-core/loader/i386/efi/linux.c
@@ -0,0 +1,335 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/file.h>
+#include <grub/err.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/efi/efi.h>
+#include <grub/efi/linux.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_dl_t my_mod;
+static int loaded;
+static void *kernel_mem;
+static grub_uint64_t kernel_size;
+static grub_uint8_t *initrd_mem;
+static grub_uint32_t handover_offset;
+struct linux_kernel_params *params;
+static char *linux_cmdline;
+
+#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
+
+static grub_err_t
+grub_linuxefi_boot (void)
+{
+ int offset = 0;
+
+#ifdef __x86_64__
+ offset = 512;
+#endif
+ asm volatile ("cli");
+
+ return grub_efi_linux_boot ((char *)kernel_mem, handover_offset + offset,
+ params);
+}
+
+static grub_err_t
+grub_linuxefi_unload (void)
+{
+ grub_dl_unref (my_mod);
+ loaded = 0;
+ if (initrd_mem)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem,
+ BYTES_TO_PAGES(params->ramdisk_size));
+ if (linux_cmdline)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
+ linux_cmdline,
+ BYTES_TO_PAGES(params->cmdline_size + 1));
+ if (kernel_mem)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem,
+ BYTES_TO_PAGES(kernel_size));
+ if (params)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params,
+ BYTES_TO_PAGES(16384));
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+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;
+
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+ goto fail;
+ }
+
+ if (!loaded)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
+ goto fail;
+ }
+
+ files = grub_zalloc (argc * sizeof (files[0]));
+ if (!files)
+ 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);
+ }
+
+ initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
+ if (!initrd_mem)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
+ goto fail;
+ }
+
+ 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);
+ }
+
+ params->ramdisk_size = size;
+
+ fail:
+ for (i = 0; i < nfiles; i++)
+ grub_file_close (files[i]);
+ grub_free (files);
+
+ if (initrd_mem && grub_errno)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem,
+ BYTES_TO_PAGES(size));
+
+ return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_file_t file = 0;
+ struct linux_kernel_header lh;
+ grub_ssize_t len, start, filelen;
+ void *kernel = NULL;
+
+ grub_dl_ref (my_mod);
+
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+ goto fail;
+ }
+
+ file = grub_file_open (argv[0]);
+ if (! file)
+ goto fail;
+
+ filelen = grub_file_size (file);
+
+ kernel = grub_malloc(filelen);
+
+ if (!kernel)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
+ goto fail;
+ }
+
+ if (grub_file_read (file, kernel, filelen) != filelen)
+ {
+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]);
+ goto fail;
+ }
+
+ if (! grub_linuxefi_secure_validate (kernel, filelen))
+ {
+ grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"),
+ argv[0]);
+ goto fail;
+ }
+
+ params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
+
+ if (! params)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
+ goto fail;
+ }
+
+ grub_memset (params, 0, 16384);
+
+ grub_memcpy (&lh, kernel, sizeof (lh));
+
+ if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
+ {
+ grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number"));
+ goto fail;
+ }
+
+ if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
+ {
+ grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
+ goto fail;
+ }
+
+ if (lh.version < grub_cpu_to_le16 (0x020b))
+ {
+ grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
+ goto fail;
+ }
+
+ if (!lh.handover_offset)
+ {
+ grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
+ goto fail;
+ }
+
+ grub_dprintf ("linux", "setting up cmdline\n");
+ linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
+ BYTES_TO_PAGES(lh.cmdline_size + 1));
+
+ if (!linux_cmdline)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
+ goto fail;
+ }
+
+ 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));
+
+ lh.cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
+
+ handover_offset = lh.handover_offset;
+
+ start = (lh.setup_sects + 1) * 512;
+ len = grub_file_size(file) - start;
+
+ kernel_mem = grub_efi_allocate_pages_max(lh.pref_address,
+ BYTES_TO_PAGES(lh.init_size));
+
+ if (!kernel_mem)
+ kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
+ BYTES_TO_PAGES(lh.init_size));
+
+ if (!kernel_mem)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
+ goto fail;
+ }
+
+ grub_memcpy (kernel_mem, (char *)kernel + start, len);
+ grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
+ loaded=1;
+
+ lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
+ grub_memcpy (params, &lh, 2 * 512);
+
+ params->type_of_loader = 0x21;
+
+ fail:
+
+ if (file)
+ grub_file_close (file);
+
+ if (kernel)
+ grub_free (kernel);
+
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_dl_unref (my_mod);
+ loaded = 0;
+ }
+
+ if (linux_cmdline && !loaded)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
+ linux_cmdline,
+ BYTES_TO_PAGES(lh.cmdline_size + 1));
+
+ if (kernel_mem && !loaded)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)kernel_mem,
+ BYTES_TO_PAGES(kernel_size));
+
+ if (params && !loaded)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)params,
+ BYTES_TO_PAGES(16384));
+
+ return grub_errno;
+}
+
+static grub_command_t cmd_linux, cmd_initrd;
+static grub_command_t cmd_linuxefi, cmd_initrdefi;
+
+GRUB_MOD_INIT(linux)
+{
+ cmd_linux =
+ grub_register_command ("linux", grub_cmd_linux,
+ 0, N_("Load Linux."));
+ cmd_linuxefi =
+ grub_register_command ("linuxefi", grub_cmd_linux,
+ 0, N_("Load Linux."));
+ cmd_initrd =
+ grub_register_command ("initrd", grub_cmd_initrd,
+ 0, N_("Load initrd."));
+ cmd_initrdefi =
+ grub_register_command ("initrdefi", grub_cmd_initrd,
+ 0, N_("Load initrd."));
+ my_mod = mod;
+}
+
+GRUB_MOD_FINI(linux)
+{
+ grub_unregister_command (cmd_linux);
+ grub_unregister_command (cmd_linuxefi);
+ grub_unregister_command (cmd_initrd);
+ grub_unregister_command (cmd_initrdefi);
+}
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
index b69cb7a3a7f..a3c87cf2fc2 100644
--- a/grub-core/loader/i386/pc/linux.c
+++ b/grub-core/loader/i386/pc/linux.c
@@ -468,14 +468,20 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
return grub_errno;
}
-static grub_command_t cmd_linux, cmd_initrd;
+static grub_command_t cmd_linux, cmd_linux16, cmd_initrd, cmd_initrd16;
GRUB_MOD_INIT(linux16)
{
cmd_linux =
+ grub_register_command ("linux", grub_cmd_linux,
+ 0, N_("Load Linux."));
+ cmd_linux16 =
grub_register_command ("linux16", grub_cmd_linux,
0, N_("Load Linux."));
cmd_initrd =
+ grub_register_command ("initrd", grub_cmd_initrd,
+ 0, N_("Load initrd."));
+ cmd_initrd16 =
grub_register_command ("initrd16", grub_cmd_initrd,
0, N_("Load initrd."));
my_mod = mod;
@@ -484,5 +490,7 @@ GRUB_MOD_INIT(linux16)
GRUB_MOD_FINI(linux16)
{
grub_unregister_command (cmd_linux);
+ grub_unregister_command (cmd_linux16);
grub_unregister_command (cmd_initrd);
+ grub_unregister_command (cmd_initrd16);
}
diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h
index b0634762450..6ea38bd95ab 100644
--- a/include/grub/arm64/linux.h
+++ b/include/grub/arm64/linux.h
@@ -20,6 +20,7 @@
#define GRUB_ARM64_LINUX_HEADER 1
#include <grub/efi/efi.h>
+#include <grub/efi/pe32.h>
#define GRUB_LINUX_ARM64_MAGIC_SIGNATURE 0x644d5241 /* 'ARM\x64' */
@@ -41,5 +42,11 @@ struct linux_arm64_kernel_header
grub_err_t grub_arm64_uefi_check_image (struct linux_arm64_kernel_header *lh);
grub_err_t grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size,
char *args);
+struct grub_arm64_linux_pe_header
+{
+ grub_uint32_t magic;
+ struct grub_pe32_coff_header coff;
+ struct grub_pe64_optional_header opt;
+};
#endif /* ! GRUB_ARM64_LINUX_HEADER */
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index c996913e5bc..f68a19de442 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -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
@@ -81,6 +84,7 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var,
const grub_efi_guid_t *guid,
void *data,
grub_size_t datasize);
+grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void);
int
EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
const grub_efi_device_path_t *dp2);
diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h
new file mode 100644
index 00000000000..d9ede36773b
--- /dev/null
+++ b/include/grub/efi/linux.h
@@ -0,0 +1,31 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2014 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GRUB_EFI_LINUX_HEADER
+#define GRUB_EFI_LINUX_HEADER 1
+
+#include <grub/efi/api.h>
+#include <grub/err.h>
+#include <grub/symbol.h>
+
+grub_efi_boolean_t
+EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size);
+grub_err_t
+EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
+ void *kernel_param);
+
+#endif /* ! GRUB_EFI_LINUX_HEADER */
diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
index 0bd75881708..5d8282a7db6 100644
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -139,6 +139,7 @@ struct linux_i386_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

View File

@ -7,16 +7,18 @@ We want a single buffer that contains the entire kernel image in order to
perform a TPM measurement. Allocate one and copy the entire kernel into it
before pulling out the individual blocks later on.
---
grub-core/loader/i386/linux.c | 34 +++++++++++++++++++++-------------
1 file changed, 21 insertions(+), 13 deletions(-)
grub-core/loader/i386/linux.c | 37 ++++++++++++++++++++++++-------------
1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
index 930a90b1f32..626ec9fef0c 100644
index 44301e12659..388c40abb8b 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -681,12 +681,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -679,13 +679,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
{
grub_file_t file = 0;
struct linux_i386_kernel_header lh;
+ grub_uint8_t *linux_params_ptr;
grub_uint8_t setup_sects;
- grub_size_t real_size, prot_size, prot_file_size;
+ grub_size_t real_size, prot_size, prot_file_size, kernel_offset;
@ -29,7 +31,7 @@ index 930a90b1f32..626ec9fef0c 100644
grub_dl_ref (my_mod);
@@ -700,7 +701,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -699,7 +701,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (! file)
goto fail;
@ -46,7 +48,7 @@ index 930a90b1f32..626ec9fef0c 100644
{
if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
@@ -708,6 +717,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -707,6 +717,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
@ -56,7 +58,15 @@ index 930a90b1f32..626ec9fef0c 100644
if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
{
grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
@@ -807,13 +819,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -798,6 +811,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
preferred_address))
goto fail;
+
grub_memset (&linux_params, 0, sizeof (linux_params));
grub_memcpy (&linux_params.setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
@@ -806,13 +820,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
linux_params.ps_mouse = linux_params.padding10 = 0;
len = sizeof (linux_params) - sizeof (lh);
@ -68,12 +78,13 @@ index 930a90b1f32..626ec9fef0c 100644
- goto fail;
- }
+
+ grub_memcpy (&linux_params + sizeof (lh), kernel + kernel_offset, len);
+ linux_params_ptr = (void *)&linux_params;
+ grub_memcpy (linux_params_ptr + sizeof (lh), kernel + kernel_offset, len);
+ kernel_offset += len;
linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
@@ -872,7 +880,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -871,7 +882,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* The other parameters are filled when booting. */
@ -82,7 +93,7 @@ index 930a90b1f32..626ec9fef0c 100644
grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
(unsigned) real_size, (unsigned) prot_size);
@@ -1020,9 +1028,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -1019,9 +1030,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
- (sizeof (LINUX_IMAGE) - 1));
len = prot_file_size;
@ -93,7 +104,7 @@ index 930a90b1f32..626ec9fef0c 100644
if (grub_errno == GRUB_ERR_NONE)
{
@@ -1033,6 +1039,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -1032,6 +1041,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
fail:

View File

@ -11,10 +11,10 @@ before pulling out the individual blocks later on.
1 file changed, 21 insertions(+), 13 deletions(-)
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
index ebe7630210b..e2bb1a99a74 100644
index a3c87cf2fc2..caa76bee8af 100644
--- a/grub-core/loader/i386/pc/linux.c
+++ b/grub-core/loader/i386/pc/linux.c
@@ -124,13 +124,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -123,13 +123,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_file_t file = 0;
struct linux_i386_kernel_header lh;
grub_uint8_t setup_sects;
@ -30,7 +30,7 @@ index ebe7630210b..e2bb1a99a74 100644
grub_dl_ref (my_mod);
@@ -144,7 +145,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -143,7 +144,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (! file)
goto fail;
@ -47,7 +47,7 @@ index ebe7630210b..e2bb1a99a74 100644
{
if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
@@ -152,6 +161,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -151,6 +160,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
@ -57,7 +57,7 @@ index ebe7630210b..e2bb1a99a74 100644
if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
{
grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
@@ -315,13 +327,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -314,13 +326,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_memmove (grub_linux_real_chunk, &lh, sizeof (lh));
len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh);
@ -74,7 +74,7 @@ index ebe7630210b..e2bb1a99a74 100644
if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
|| grub_le_to_cpu16 (lh.version) < 0x0200)
@@ -356,10 +364,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -355,10 +363,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
len = grub_linux16_prot_size;
@ -87,7 +87,7 @@ index ebe7630210b..e2bb1a99a74 100644
if (grub_errno == GRUB_ERR_NONE)
{
@@ -369,6 +375,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -368,6 +374,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
fail:

File diff suppressed because it is too large Load Diff

View File

@ -12,8 +12,9 @@ Signed-off-by: Peter Jones <pjones@redhat.com>
grub-core/Makefile.core.def | 1 +
grub-core/commands/iorw.c | 7 +++++
grub-core/commands/memrw.c | 7 +++++
grub-core/kern/efi/efi.c | 28 ------------------
grub-core/kern/efi/sb.c | 58 ++++++++++++++++++++++++++++++++++++++
grub-core/kern/dl.c | 1 +
grub-core/kern/efi/efi.c | 34 --------------------
grub-core/kern/efi/sb.c | 64 ++++++++++++++++++++++++++++++++++++++
grub-core/loader/efi/appleloader.c | 7 +++++
grub-core/loader/efi/chainloader.c | 1 +
grub-core/loader/i386/bsd.c | 7 +++++
@ -22,13 +23,13 @@ Signed-off-by: Peter Jones <pjones@redhat.com>
grub-core/loader/multiboot.c | 7 +++++
grub-core/loader/xnu.c | 7 +++++
include/grub/efi/efi.h | 1 -
include/grub/efi/sb.h | 29 +++++++++++++++++++
include/grub/efi/sb.h | 29 +++++++++++++++++
include/grub/ia64/linux.h | 0
include/grub/mips/linux.h | 0
include/grub/powerpc/linux.h | 0
include/grub/sparc64/linux.h | 0
grub-core/Makefile.am | 1 +
19 files changed, 146 insertions(+), 29 deletions(-)
20 files changed, 153 insertions(+), 35 deletions(-)
create mode 100644 grub-core/kern/efi/sb.c
create mode 100644 include/grub/efi/sb.h
create mode 100644 include/grub/ia64/linux.h
@ -37,10 +38,10 @@ Signed-off-by: Peter Jones <pjones@redhat.com>
create mode 100644 include/grub/sparc64/linux.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 338244f6b47..423def037c2 100644
index 622381f5208..52911374be5 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -196,6 +196,7 @@ kernel = {
@@ -195,6 +195,7 @@ kernel = {
i386_multiboot = kern/i386/pc/acpi.c;
i386_coreboot = kern/acpi.c;
i386_multiboot = kern/acpi.c;
@ -112,11 +113,23 @@ index 98769eadb34..088cbe9e2bc 100644
grub_unregister_extcmd (cmd_read_byte);
grub_unregister_extcmd (cmd_read_word);
grub_unregister_extcmd (cmd_read_dword);
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index 04e804d1668..621070918d4 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -32,6 +32,7 @@
#include <grub/env.h>
#include <grub/cache.h>
#include <grub/i18n.h>
+#include <grub/efi/sb.h>
/* Platforms where modules are in a readonly area of memory. */
#if defined(GRUB_MACHINE_QEMU)
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 92e1583b37d..e339f264b3a 100644
index 91129e33566..708581fcbde 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -278,34 +278,6 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
@@ -273,40 +273,6 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
return NULL;
}
@ -130,14 +143,20 @@ index 92e1583b37d..e339f264b3a 100644
- grub_efi_boolean_t ret = 0;
-
- secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
-
- if (datasize != 1 || !secure_boot)
- goto out;
- {
- grub_dprintf ("secureboot", "No SecureBoot variable\n");
- goto out;
- }
- grub_dprintf ("secureboot", "SecureBoot: %d\n", *secure_boot);
-
- setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
-
- if (datasize != 1 || !setup_mode)
- goto out;
- {
- grub_dprintf ("secureboot", "No SetupMode variable\n");
- goto out;
- }
- grub_dprintf ("secureboot", "SetupMode: %d\n", *setup_mode);
-
- if (*secure_boot && !*setup_mode)
- ret = 1;
@ -153,10 +172,10 @@ index 92e1583b37d..e339f264b3a 100644
/* Search the mods section from the PE32/PE32+ image. This code uses
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
new file mode 100644
index 00000000000..a41b6c5b851
index 00000000000..d74778b0cac
--- /dev/null
+++ b/grub-core/kern/efi/sb.c
@@ -0,0 +1,58 @@
@@ -0,0 +1,64 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2014 Free Software Foundation, Inc.
@ -195,14 +214,20 @@ index 00000000000..a41b6c5b851
+ grub_efi_boolean_t ret = 0;
+
+ secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
+
+ if (datasize != 1 || !secure_boot)
+ goto out;
+ {
+ grub_dprintf ("secureboot", "No SecureBoot variable\n");
+ goto out;
+ }
+ grub_dprintf ("secureboot", "SecureBoot: %d\n", *secure_boot);
+
+ setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
+
+ if (datasize != 1 || !setup_mode)
+ goto out;
+ {
+ grub_dprintf ("secureboot", "No SetupMode variable\n");
+ goto out;
+ }
+ grub_dprintf ("secureboot", "SetupMode: %d\n", *setup_mode);
+
+ if (*secure_boot && !*setup_mode)
+ ret = 1;
@ -247,7 +272,7 @@ index 74888c463ba..69c2a10d351 100644
grub_unregister_command (cmd);
}
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index 87a91e16f17..aee8e6becf6 100644
index af2189619a3..5cd9b6e08a8 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -34,6 +34,7 @@
@ -291,7 +316,7 @@ index 7f96515da65..87709aa23e8 100644
grub_unregister_extcmd (cmd_openbsd);
grub_unregister_extcmd (cmd_netbsd);
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
index 44301e12659..930a90b1f32 100644
index 388c40abb8b..35055431247 100644
--- a/grub-core/loader/i386/linux.c
+++ b/grub-core/loader/i386/linux.c
@@ -35,6 +35,7 @@
@ -302,7 +327,7 @@ index 44301e12659..930a90b1f32 100644
GRUB_MOD_LICENSE ("GPLv3+");
@@ -1139,6 +1140,9 @@ static grub_command_t cmd_linux, cmd_initrd;
@@ -1150,6 +1151,9 @@ static grub_command_t cmd_linux, cmd_initrd;
GRUB_MOD_INIT(linux)
{
@ -312,7 +337,7 @@ index 44301e12659..930a90b1f32 100644
cmd_linux = grub_register_command ("linux", grub_cmd_linux,
0, N_("Load Linux."));
cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
@@ -1148,6 +1152,9 @@ GRUB_MOD_INIT(linux)
@@ -1159,6 +1163,9 @@ GRUB_MOD_INIT(linux)
GRUB_MOD_FINI(linux)
{
@ -323,7 +348,7 @@ index 44301e12659..930a90b1f32 100644
grub_unregister_command (cmd_initrd);
}
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
index b69cb7a3a7f..ebe7630210b 100644
index caa76bee8af..783a3cd93bc 100644
--- a/grub-core/loader/i386/pc/linux.c
+++ b/grub-core/loader/i386/pc/linux.c
@@ -35,6 +35,7 @@
@ -334,7 +359,7 @@ index b69cb7a3a7f..ebe7630210b 100644
GRUB_MOD_LICENSE ("GPLv3+");
@@ -472,6 +473,9 @@ static grub_command_t cmd_linux, cmd_initrd;
@@ -480,6 +481,9 @@ static grub_command_t cmd_linux, cmd_linux16, cmd_initrd, cmd_initrd16;
GRUB_MOD_INIT(linux16)
{
@ -342,9 +367,9 @@ index b69cb7a3a7f..ebe7630210b 100644
+ return;
+
cmd_linux =
grub_register_command ("linux16", grub_cmd_linux,
grub_register_command ("linux", grub_cmd_linux,
0, N_("Load Linux."));
@@ -483,6 +487,9 @@ GRUB_MOD_INIT(linux16)
@@ -497,6 +501,9 @@ GRUB_MOD_INIT(linux16)
GRUB_MOD_FINI(linux16)
{
@ -352,8 +377,8 @@ index b69cb7a3a7f..ebe7630210b 100644
+ return;
+
grub_unregister_command (cmd_linux);
grub_unregister_command (cmd_linux16);
grub_unregister_command (cmd_initrd);
}
diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
index 40c67e82489..26df46a4161 100644
--- a/grub-core/loader/multiboot.c

View File

@ -8,15 +8,15 @@ Allow booting 64-bit kernels on 32-bit EFI on x86.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/efi/linux.c | 9 +++-
grub-core/loader/i386/efi/linux.c | 110 +++++++++++++++++++++++++++-----------
grub-core/loader/i386/efi/linux.c | 109 ++++++++++++++++++++++++++------------
include/grub/i386/linux.h | 7 ++-
3 files changed, 93 insertions(+), 33 deletions(-)
3 files changed, 88 insertions(+), 37 deletions(-)
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
index 8890bdf059a..2a7024134da 100644
index dbf63e20ed8..7fe7201a388 100644
--- a/grub-core/loader/efi/linux.c
+++ b/grub-core/loader/efi/linux.c
@@ -56,12 +56,17 @@ grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
@@ -66,12 +66,17 @@ grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
grub_err_t
@ -37,7 +37,7 @@ index 8890bdf059a..2a7024134da 100644
return GRUB_ERR_BUG;
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index 8b5a817b9d1..bed5919cab3 100644
index 8db228c5bf5..1279f510a24 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -44,14 +44,10 @@ static char *linux_cmdline;
@ -57,16 +57,7 @@ index 8b5a817b9d1..bed5919cab3 100644
params);
}
@@ -119,6 +115,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
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;
@@ -153,14 +151,20 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
@@ -154,14 +150,20 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
return grub_errno;
}
@ -81,14 +72,15 @@ index 8b5a817b9d1..bed5919cab3 100644
{
grub_file_t file = 0;
- struct linux_kernel_header lh;
+ struct linux_kernel_header *lh;
grub_ssize_t len, start, filelen;
- grub_ssize_t len, start, filelen;
+ struct linux_i386_kernel_header *lh = NULL;
+ grub_ssize_t start, filelen;
void *kernel = NULL;
+ int setup_header_end_offset;
int rc;
grub_dl_ref (my_mod);
@@ -200,69 +204,107 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -201,48 +203,79 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
@ -102,24 +94,27 @@ index 8b5a817b9d1..bed5919cab3 100644
goto fail;
}
- grub_memset (params, 0, 16384);
+ grub_dprintf ("linuxefi", "params = %p\n", (unsigned long) params);
- grub_dprintf ("linux", "params = %lx\n", (unsigned long) params);
+ grub_dprintf ("linux", "params = %p\n", params);
- grub_memcpy (&lh, kernel, sizeof (lh));
- grub_memset (params, 0, 16384);
+ grub_memset (params, 0, sizeof(*params));
- grub_memcpy (&lh, kernel, sizeof (lh));
-
- if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
+ setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201);
+ grub_dprintf ("linuxefi", "copying %d bytes from %p to %p\n",
+ MIN(0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1,
+ grub_dprintf ("linux", "copying %zu bytes from %p to %p\n",
+ MIN((grub_size_t)0x202+setup_header_end_offset,
+ sizeof (*params)) - 0x1f1,
+ (grub_uint8_t *)kernel + 0x1f1,
+ (grub_uint8_t *)params + 0x1f1);
+ grub_memcpy ((grub_uint8_t *)params + 0x1f1,
+ (grub_uint8_t *)kernel + 0x1f1,
+ MIN(0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
+ lh = (struct linux_kernel_header *)params;
+ grub_dprintf ("linuxefi", "lh is at %p\n", lh);
+ grub_dprintf ("linuxefi", "checking lh->boot_flag\n");
+ MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
+ lh = (struct linux_i386_kernel_header *)params;
+ grub_dprintf ("linux", "lh is at %p\n", lh);
+ grub_dprintf ("linux", "checking lh->boot_flag\n");
+ if (lh->boot_flag != grub_cpu_to_le16 (0xaa55))
{
grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number"));
@ -127,7 +122,7 @@ index 8b5a817b9d1..bed5919cab3 100644
}
- if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
+ grub_dprintf ("linuxefi", "checking lh->setup_sects\n");
+ grub_dprintf ("linux", "checking lh->setup_sects\n");
+ if (lh->setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
{
grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
@ -135,7 +130,7 @@ index 8b5a817b9d1..bed5919cab3 100644
}
- if (lh.version < grub_cpu_to_le16 (0x020b))
+ grub_dprintf ("linuxefi", "checking lh->version\n");
+ grub_dprintf ("linux", "checking lh->version\n");
+ if (lh->version < grub_cpu_to_le16 (0x020b))
{
grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
@ -143,7 +138,7 @@ index 8b5a817b9d1..bed5919cab3 100644
}
- if (!lh.handover_offset)
+ grub_dprintf ("linuxefi", "checking lh->handover_offset\n");
+ grub_dprintf ("linux", "checking lh->handover_offset\n");
+ if (!lh->handover_offset)
{
grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
@ -151,7 +146,7 @@ index 8b5a817b9d1..bed5919cab3 100644
}
+#if defined(__x86_64__) || defined(__aarch64__)
+ grub_dprintf ("linuxefi", "checking lh->xloadflags\n");
+ grub_dprintf ("linux", "checking lh->xloadflags\n");
+ if (!(lh->xloadflags & LINUX_XLF_KERNEL_64))
+ {
+ grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support 64-bit CPUs"));
@ -169,7 +164,7 @@ index 8b5a817b9d1..bed5919cab3 100644
+ }
+#endif
+
+ grub_dprintf ("linuxefi", "setting up cmdline\n");
grub_dprintf ("linux", "setting up cmdline\n");
linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
- BYTES_TO_PAGES(lh.cmdline_size + 1));
-
@ -177,12 +172,7 @@ index 8b5a817b9d1..bed5919cab3 100644
if (!linux_cmdline)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
goto fail;
}
+ grub_dprintf ("linuxefi", "linux_cmdline = %lx\n",
+ (unsigned long)linux_cmdline);
+
@@ -255,21 +288,22 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv,
linux_cmdline + sizeof (LINUX_IMAGE) - 1,
@ -190,19 +180,19 @@ index 8b5a817b9d1..bed5919cab3 100644
+ lh->cmdline_size - (sizeof (LINUX_IMAGE) - 1));
- lh.cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
+ grub_dprintf ("linuxefi", "setting lh->cmd_line_ptr\n");
+ grub_dprintf ("linux", "setting lh->cmd_line_ptr\n");
+ lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
- handover_offset = lh.handover_offset;
+ grub_dprintf ("linuxefi", "computing handover offset\n");
+ grub_dprintf ("linux", "computing handover offset\n");
+ handover_offset = lh->handover_offset;
- start = (lh.setup_sects + 1) * 512;
- len = grub_file_size(file) - start;
+ start = (lh->setup_sects + 1) * 512;
len = grub_file_size(file) - start;
- kernel_mem = grub_efi_allocate_pages(lh.pref_address,
- BYTES_TO_PAGES(lh.init_size));
- kernel_mem = grub_efi_allocate_pages_max(lh.pref_address,
- BYTES_TO_PAGES(lh.init_size));
+ kernel_mem = grub_efi_allocate_pages_max(lh->pref_address,
+ BYTES_TO_PAGES(lh->init_size));
@ -213,16 +203,16 @@ index 8b5a817b9d1..bed5919cab3 100644
if (!kernel_mem)
{
@@ -270,17 +312,25 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
@@ -277,14 +311,21 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- grub_memcpy (kernel_mem, (char *)kernel + start, len);
+ grub_dprintf ("linuxefi", "kernel_mem = %lx\n", (unsigned long) kernel_mem);
+ grub_dprintf ("linux", "kernel_mem = %lx\n", (unsigned long) kernel_mem);
+
grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
loaded=1;
+ grub_dprintf ("linuxefi", "setting lh->code32_start to %p\n", kernel_mem);
+ grub_dprintf ("linux", "setting lh->code32_start to %p\n", kernel_mem);
+ lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
- lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
@ -230,22 +220,21 @@ index 8b5a817b9d1..bed5919cab3 100644
+ grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start);
- params->type_of_loader = 0x21;
+ grub_dprintf ("linuxefi", "setting lh->type_of_loader\n");
+ grub_dprintf ("linux", "setting lh->type_of_loader\n");
+ lh->type_of_loader = 0x6;
+
+ grub_dprintf ("linuxefi", "setting lh->ext_loader_{type,ver}\n");
+ grub_dprintf ("linux", "setting lh->ext_loader_{type,ver}\n");
+ params->ext_loader_type = 0;
+ params->ext_loader_ver = 2;
+ grub_dprintf("linuxefi", "kernel_mem: %p handover_offset: %08x\n",
+ kernel_mem, handover_offset);
grub_dprintf("linux", "kernel_mem: %p handover_offset: %08x\n",
kernel_mem, handover_offset);
fail:
-
if (file)
grub_file_close (file);
@@ -301,10 +342,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
loaded = 0;
}
@@ -296,7 +346,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (linux_cmdline && !loaded)
- if (linux_cmdline && !loaded)
+ if (linux_cmdline && lh && !loaded)
grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
linux_cmdline,
- BYTES_TO_PAGES(lh.cmdline_size + 1));

View File

@ -10,7 +10,7 @@ Signed-off-by: Peter Jones <pjones@redhat.com>
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index fc4767f1985..a6e257f946a 100644
index 52911374be5..6b652231ecc 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -191,6 +191,7 @@ kernel = {

View File

@ -1,479 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg@redhat.com>
Date: Tue, 10 Jul 2012 11:58:52 -0400
Subject: [PATCH] Add support for linuxefi
---
grub-core/Makefile.core.def | 8 +
grub-core/kern/efi/mm.c | 32 ++++
grub-core/loader/i386/efi/linux.c | 371 ++++++++++++++++++++++++++++++++++++++
include/grub/efi/efi.h | 3 +
include/grub/i386/linux.h | 1 +
5 files changed, 415 insertions(+)
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 a6e257f946a..aacad137b36 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1759,6 +1759,14 @@ 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;
+};
+
module = {
name = chain;
efi = loader/efi/chainloader.c;
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index c48e9b5c7c3..775daed16e6 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -113,6 +113,38 @@ grub_efi_drop_alloc (grub_efi_physical_address_t address,
}
}
+/* Allocate pages below a specified address */
+void *
+grub_efi_allocate_pages_max (grub_efi_physical_address_t max,
+ grub_efi_uintn_t pages)
+{
+ grub_efi_status_t status;
+ grub_efi_boot_services_t *b;
+ grub_efi_physical_address_t address = max;
+
+ if (max > 0xffffffff)
+ return 0;
+
+ b = grub_efi_system_table->boot_services;
+ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address);
+
+ if (status != GRUB_EFI_SUCCESS)
+ return 0;
+
+ if (address == 0)
+ {
+ /* Uggh, the address 0 was allocated... This is too annoying,
+ so reallocate another one. */
+ address = max;
+ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, GRUB_EFI_LOADER_DATA, pages, &address);
+ grub_efi_free_pages (0, pages);
+ if (status != GRUB_EFI_SUCCESS)
+ return 0;
+ }
+
+ return (void *) ((grub_addr_t) address);
+}
+
/* Allocate pages. Return the pointer to the first of allocated pages. */
void *
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 00000000000..b79e6320ba9
--- /dev/null
+++ b/grub-core/loader/i386/efi/linux.c
@@ -0,0 +1,371 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/file.h>
+#include <grub/err.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/efi/efi.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_dl_t my_mod;
+static int loaded;
+static void *kernel_mem;
+static grub_uint64_t kernel_size;
+static grub_uint8_t *initrd_mem;
+static grub_uint32_t handover_offset;
+struct linux_kernel_params *params;
+static char *linux_cmdline;
+
+#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
+
+#define SHIM_LOCK_GUID \
+ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
+
+struct grub_efi_shim_lock
+{
+ grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
+};
+typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
+
+static grub_efi_boolean_t
+grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
+{
+ grub_efi_guid_t guid = SHIM_LOCK_GUID;
+ grub_efi_shim_lock_t *shim_lock;
+
+ shim_lock = grub_efi_locate_protocol(&guid, NULL);
+
+ if (!shim_lock)
+ return 1;
+
+ if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS)
+ return 1;
+
+ return 0;
+}
+
+typedef void(*handover_func)(void *, grub_efi_system_table_t *, struct linux_kernel_params *);
+
+static grub_err_t
+grub_linuxefi_boot (void)
+{
+ handover_func hf;
+ int offset = 0;
+
+#ifdef __x86_64__
+ offset = 512;
+#endif
+
+ hf = (handover_func)((char *)kernel_mem + handover_offset + offset);
+
+ asm volatile ("cli");
+
+ hf (grub_efi_image_handle, grub_efi_system_table, params);
+
+ /* Not reached */
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_linuxefi_unload (void)
+{
+ grub_dl_unref (my_mod);
+ loaded = 0;
+ if (initrd_mem)
+ grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(params->ramdisk_size));
+ if (linux_cmdline)
+ grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(params->cmdline_size + 1));
+ if (kernel_mem)
+ grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
+ if (params)
+ grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384));
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+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;
+
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+ goto fail;
+ }
+
+ if (!loaded)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
+ goto fail;
+ }
+
+ files = grub_zalloc (argc * sizeof (files[0]));
+ if (!files)
+ 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);
+ }
+
+ initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
+
+ if (!initrd_mem)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
+ goto fail;
+ }
+
+ params->ramdisk_size = size;
+ params->ramdisk_image = (grub_uint32_t)(grub_uint64_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);
+ }
+
+ params->ramdisk_size = size;
+
+ fail:
+ for (i = 0; i < nfiles; i++)
+ grub_file_close (files[i]);
+ grub_free (files);
+
+ if (initrd_mem && grub_errno)
+ grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(size));
+
+ return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_file_t file = 0;
+ struct linux_kernel_header lh;
+ grub_ssize_t len, start, filelen;
+ void *kernel;
+
+ grub_dl_ref (my_mod);
+
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+ goto fail;
+ }
+
+ file = grub_file_open (argv[0]);
+ if (! file)
+ goto fail;
+
+ filelen = grub_file_size (file);
+
+ kernel = grub_malloc(filelen);
+
+ if (!kernel)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
+ goto fail;
+ }
+
+ if (grub_file_read (file, kernel, filelen) != filelen)
+ {
+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]);
+ goto fail;
+ }
+
+ if (! grub_linuxefi_secure_validate (kernel, filelen))
+ {
+ grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
+ grub_free (kernel);
+ goto fail;
+ }
+
+ grub_file_seek (file, 0);
+
+ grub_free(kernel);
+
+ params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
+
+ if (! params)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
+ goto fail;
+ }
+
+ memset (params, 0, 16384);
+
+ if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
+ {
+ if (!grub_errno)
+ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+ argv[0]);
+ goto fail;
+ }
+
+ if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
+ {
+ grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number"));
+ goto fail;
+ }
+
+ if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
+ {
+ grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
+ goto fail;
+ }
+
+ if (lh.version < grub_cpu_to_le16 (0x020b))
+ {
+ grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
+ goto fail;
+ }
+
+ if (!lh.handover_offset)
+ {
+ grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
+ goto fail;
+ }
+
+ linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
+ BYTES_TO_PAGES(lh.cmdline_size + 1));
+
+ if (!linux_cmdline)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
+ goto fail;
+ }
+
+ 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));
+
+ lh.cmd_line_ptr = (grub_uint32_t)(grub_uint64_t)linux_cmdline;
+
+ handover_offset = lh.handover_offset;
+
+ start = (lh.setup_sects + 1) * 512;
+ len = grub_file_size(file) - start;
+
+ kernel_mem = grub_efi_allocate_pages(lh.pref_address,
+ BYTES_TO_PAGES(lh.init_size));
+
+ if (!kernel_mem)
+ kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
+ BYTES_TO_PAGES(lh.init_size));
+
+ if (!kernel_mem)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
+ goto fail;
+ }
+
+ if (grub_file_seek (file, start) == (grub_off_t) -1)
+ {
+ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+ argv[0]);
+ goto fail;
+ }
+
+ if (grub_file_read (file, kernel_mem, len) != len && !grub_errno)
+ {
+ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
+ argv[0]);
+ }
+
+ if (grub_errno == GRUB_ERR_NONE)
+ {
+ grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
+ loaded = 1;
+ lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
+ }
+
+ memcpy(params, &lh, 2 * 512);
+
+ params->type_of_loader = 0x21;
+
+ fail:
+
+ if (file)
+ grub_file_close (file);
+
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_dl_unref (my_mod);
+ loaded = 0;
+ }
+
+ if (linux_cmdline && !loaded)
+ grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(lh.cmdline_size + 1));
+
+ if (kernel_mem && !loaded)
+ grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
+
+ if (params && !loaded)
+ grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384));
+
+ return grub_errno;
+}
+
+static grub_command_t cmd_linux, cmd_initrd;
+
+GRUB_MOD_INIT(linuxefi)
+{
+ cmd_linux =
+ grub_register_command ("linuxefi", grub_cmd_linux,
+ 0, N_("Load Linux."));
+ cmd_initrd =
+ grub_register_command ("initrdefi", grub_cmd_initrd,
+ 0, N_("Load initrd."));
+ my_mod = mod;
+}
+
+GRUB_MOD_FINI(linuxefi)
+{
+ grub_unregister_command (cmd_linux);
+ grub_unregister_command (cmd_initrd);
+}
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index c996913e5bc..3efbafbb418 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -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 0bd75881708..5d8282a7db6 100644
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -139,6 +139,7 @@ struct linux_i386_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

View File

@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 16 Jul 2012 18:57:11 -0400
Subject: [PATCH] Use "linuxefi" and "initrdefi" where appropriate.
---
util/grub.d/10_linux.in | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 87a7da34982..37d539fcf93 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -139,9 +139,16 @@ linux_entry ()
printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/"
fi
message="$(gettext_printf "Loading Linux %s ..." ${version})"
+ if [ -d /sys/firmware/efi ]; then
+ linuxcmd=linuxefi
+ initrdcmd=initrdefi
+ else
+ linuxcmd=linux
+ initrdcmd=initrd
+ fi
sed "s/^/$submenu_indentation/" << EOF
echo '$(echo "$message" | grub_quote)'
- linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
+ ${linuxcmd} ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
EOF
if test -n "${initrd}" ; then
# TRANSLATORS: ramdisk isn't identifier. Should be translated.
@@ -152,7 +159,7 @@ EOF
done
sed "s/^/$submenu_indentation/" << EOF
echo '$(echo "$message" | grub_quote)'
- initrd $(echo $initrd_path)
+ ${initrdcmd} $(echo $initrd_path)
EOF
fi
sed "s/^/$submenu_indentation/" << EOF

View File

@ -1,121 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Colin Watson <cjwatson@ubuntu.com>
Date: Tue, 23 Oct 2012 10:40:49 -0400
Subject: [PATCH] Don't allow insmod when secure boot is enabled.
Hi,
Fedora's patch to forbid insmod in UEFI Secure Boot environments is fine
as far as it goes. However, the insmod command is not the only way that
modules can be loaded. In particular, the 'normal' command, which
implements the usual GRUB menu and the fully-featured command prompt,
will implicitly load commands not currently loaded into memory. This
permits trivial Secure Boot violations by writing commands implementing
whatever you want to do and pointing $prefix at the malicious code.
I'm currently test-building this patch (replacing your current
grub-2.00-no-insmod-on-sb.patch), but this should be more correct. It
moves the check into grub_dl_load_file.
---
grub-core/kern/dl.c | 22 ++++++++++++++++++++++
grub-core/kern/efi/efi.c | 28 ++++++++++++++++++++++++++++
include/grub/efi/efi.h | 1 +
3 files changed, 51 insertions(+)
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index e394cd96f8c..621070918d4 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -32,12 +32,21 @@
#include <grub/env.h>
#include <grub/cache.h>
#include <grub/i18n.h>
+#include <grub/efi/sb.h>
/* Platforms where modules are in a readonly area of memory. */
#if defined(GRUB_MACHINE_QEMU)
#define GRUB_MODULES_MACHINE_READONLY
#endif
+#ifdef GRUB_MACHINE_EMU
+#include <sys/mman.h>
+#endif
+
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/efi.h>
+#endif
+
#pragma GCC diagnostic ignored "-Wcast-align"
@@ -686,6 +695,19 @@ grub_dl_load_file (const char *filename)
void *core = 0;
grub_dl_t mod = 0;
+#ifdef GRUB_MACHINE_EFI
+ if (grub_efi_secure_boot ())
+ {
+#if 0
+ /* This is an error, but grub2-mkconfig still generates a pile of
+ * insmod commands, so emitting it would be mostly just obnoxious. */
+ grub_error (GRUB_ERR_ACCESS_DENIED,
+ "Secure Boot forbids loading module from %s", filename);
+#endif
+ return 0;
+ }
+#endif
+
grub_boot_time ("Loading module %s", filename);
file = grub_file_open (filename);
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index e339f264b3a..92e1583b37d 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -278,6 +278,34 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
return NULL;
}
+grub_efi_boolean_t
+grub_efi_secure_boot (void)
+{
+ grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
+ grub_size_t datasize;
+ char *secure_boot = NULL;
+ char *setup_mode = NULL;
+ grub_efi_boolean_t ret = 0;
+
+ secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
+
+ if (datasize != 1 || !secure_boot)
+ goto out;
+
+ setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
+
+ if (datasize != 1 || !setup_mode)
+ goto out;
+
+ if (*secure_boot && !*setup_mode)
+ ret = 1;
+
+ out:
+ grub_free (secure_boot);
+ grub_free (setup_mode);
+ return ret;
+}
+
#pragma GCC diagnostic ignored "-Wcast-align"
/* Search the mods section from the PE32/PE32+ image. This code uses
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 3efbafbb418..f68a19de442 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -84,6 +84,7 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var,
const grub_efi_guid_t *guid,
void *data,
grub_size_t datasize);
+grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void);
int
EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
const grub_efi_device_path_t *dp2);

View File

@ -21,10 +21,10 @@ Signed-off-by: Peter Jones <grub2-owner@fedoraproject.org>
create mode 100644 grub-core/commands/blscfg.c
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index aacad137b36..3f42ce16fad 100644
index 6b652231ecc..7ed07b3e2fd 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -768,6 +768,14 @@ module = {
@@ -769,6 +769,14 @@ module = {
common = commands/blocklist.c;
};

View File

@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 14 Jan 2014 13:12:23 -0500
Subject: [PATCH] Add devicetree loading
Signed-off-by: Peter Jones <pjones@redhat.com>
Switch to use APM Mustang device tree, for hardware testing.
Signed-off-by: David A. Marlin <d.marlin@redhat.com>
Use the default device tree from the grub default file
instead of hardcoding a value.
Signed-off-by: David A. Marlin <dmarlin@redhat.com>
---
util/grub-mkconfig.in | 3 ++-
util/grub.d/10_linux.in | 15 +++++++++++++++
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index b0a8626dd1c..f68d4925ee6 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -254,7 +254,8 @@ export GRUB_DEFAULT \
GRUB_ENABLE_CRYPTODISK \
GRUB_BADRAM \
GRUB_OS_PROBER_SKIP_LIST \
- GRUB_DISABLE_SUBMENU
+ GRUB_DISABLE_SUBMENU \
+ GRUB_DEFAULT_DTB
if test "x${grub_cfg}" != "x"; then
rm -f "${grub_cfg}.new"
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 87a7da34982..233754ff296 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -153,6 +153,13 @@ EOF
sed "s/^/$submenu_indentation/" << EOF
echo '$(echo "$message" | grub_quote)'
initrd $(echo $initrd_path)
+EOF
+ fi
+ if test -n "${fdt}" ; then
+ message="$(gettext_printf "Loading fdt ...")"
+ sed "s/^/$submenu_indentation/" << EOF
+ echo '$(echo "$message" | grub_quote)'
+ devicetree ${rel_dirname}/${fdt}
EOF
fi
sed "s/^/$submenu_indentation/" << EOF
@@ -236,6 +243,14 @@ while [ "x$list" != "x" ] ; do
gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
fi
+ fdt=
+ for i in "dtb-${version}" "dtb-${alt_version}"; do
+ if test -f "${dirname}/${i}/${GRUB_DEFAULT_DTB}" ; then
+ fdt="${i}/${GRUB_DEFAULT_DTB}"
+ break
+ fi
+ done
+
config=
for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
if test -e "${i}" ; then

View File

@ -11,8 +11,8 @@ very appealing.
grub-core/kern/main.c | 5 -----
grub-core/boot/i386/pc/boot.S | 3 ---
grub-core/boot/i386/pc/diskboot.S | 5 -----
util/grub.d/10_linux.in | 3 ---
5 files changed, 5 insertions(+), 36 deletions(-)
util/grub.d/10_linux.in | 7 -------
5 files changed, 5 insertions(+), 40 deletions(-)
diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c
index 4880cefe3f8..b22e1bcc94b 100644
@ -143,30 +143,34 @@ index c1addc0df29..68d31de0c4c 100644
movw $LOCAL(firstlist), %di
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 37d539fcf93..3c290f65403 100644
index 233754ff296..3a5aa0f8dc9 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -138,7 +138,6 @@ linux_entry ()
@@ -138,27 +138,20 @@ linux_entry ()
fi
printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/"
fi
- message="$(gettext_printf "Loading Linux %s ..." ${version})"
if [ -d /sys/firmware/efi ]; then
linuxcmd=linuxefi
initrdcmd=initrdefi
@@ -147,7 +146,6 @@ linux_entry ()
initrdcmd=initrd
fi
sed "s/^/$submenu_indentation/" << EOF
- echo '$(echo "$message" | grub_quote)'
${linuxcmd} ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
EOF
if test -n "${initrd}" ; then
@@ -158,7 +156,6 @@ EOF
- # TRANSLATORS: ramdisk isn't identifier. Should be translated.
- message="$(gettext_printf "Loading initial ramdisk ...")"
initrd_path=
for i in ${initrd}; do
initrd_path="${initrd_path} ${rel_dirname}/${i}"
done
sed "s/^/$submenu_indentation/" << EOF
- echo '$(echo "$message" | grub_quote)'
${initrdcmd} $(echo $initrd_path)
initrd $(echo $initrd_path)
EOF
fi
if test -n "${fdt}" ; then
- message="$(gettext_printf "Loading fdt ...")"
sed "s/^/$submenu_indentation/" << EOF
- echo '$(echo "$message" | grub_quote)'
devicetree ${rel_dirname}/${fdt}
EOF
fi

View File

@ -1,42 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 28 Oct 2013 10:05:07 -0400
Subject: [PATCH] Use linux16 when appropriate (#880840)
The kernel group really would prefer that we use the 16 bit entry point
on x86 bios machines.
Resolves: rhbz#880840
Signed-off-by: Peter Jones <pjones@redhat.com>
---
util/grub.d/10_linux.in | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 3c290f65403..c8376a5189c 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -86,6 +86,11 @@ linux_entry ()
type="$3"
args="$4"
+ sixteenbit=""
+ case "$machine" in
+ i?86|x86_64) sixteenbit="16" ;;
+ esac
+
if [ -z "$boot_device_id" ]; then
boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
fi
@@ -142,8 +147,8 @@ linux_entry ()
linuxcmd=linuxefi
initrdcmd=initrdefi
else
- linuxcmd=linux
- initrdcmd=initrd
+ linuxcmd=linux${sixteenbit}
+ initrdcmd=initrd${sixteenbit}
fi
sed "s/^/$submenu_indentation/" << EOF
${linuxcmd} ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}

View File

@ -9,7 +9,7 @@ Subject: [PATCH] Don't say "GNU/Linux" in generated menus.
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index c8376a5189c..11f50d5730b 100644
index 3a5aa0f8dc9..6299836b5cd 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -29,9 +29,9 @@ export TEXTDOMAINDIR="@localedir@"

View File

@ -1,79 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 14 Jan 2014 13:12:23 -0500
Subject: [PATCH] Make 10_linux work with our changes for linux16 and linuxefi
on aarch64
Signed-off-by: Peter Jones <pjones@redhat.com>
---
util/grub.d/10_linux.in | 35 ++++++++++++++++++++++++++---------
1 file changed, 26 insertions(+), 9 deletions(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 11f50d5730b..c889b47db59 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -86,9 +86,18 @@ linux_entry ()
type="$3"
args="$4"
- sixteenbit=""
+ linuxcmd=linux
+ initrdcmd=initrd
case "$machine" in
- i?86|x86_64) sixteenbit="16" ;;
+ i?86|x86_64)
+ if [ -d /sys/firmware/efi ]; then
+ linuxcmd=linuxefi
+ initrdcmd=initrdefi
+ else
+ linuxcmd=linux16
+ initrdcmd=linux16
+ fi
+ ;;
esac
if [ -z "$boot_device_id" ]; then
@@ -143,13 +152,6 @@ linux_entry ()
fi
printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/"
fi
- if [ -d /sys/firmware/efi ]; then
- linuxcmd=linuxefi
- initrdcmd=initrdefi
- else
- linuxcmd=linux${sixteenbit}
- initrdcmd=initrd${sixteenbit}
- fi
sed "s/^/$submenu_indentation/" << EOF
${linuxcmd} ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
EOF
@@ -162,6 +164,13 @@ EOF
done
sed "s/^/$submenu_indentation/" << EOF
${initrdcmd} $(echo $initrd_path)
+EOF
+ fi
+ if test -n "${fdt}" ; then
+ message="$(gettext_printf "Loading fdt ...")"
+ sed "s/^/$submenu_indentation/" << EOF
+ echo '$(echo "$message" | grub_quote)'
+ devicetree ${rel_dirname}/${fdt}
EOF
fi
sed "s/^/$submenu_indentation/" << EOF
@@ -245,6 +254,14 @@ while [ "x$list" != "x" ] ; do
gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
fi
+ fdt=
+ for i in "dtb-${version}" "dtb-${alt_version}"; do
+ if test -e "${dirname}/${i}/foundation-v8.dtb" ; then
+ fdt="${i}/foundation-v8.dtb"
+ break
+ fi
+ done
+
config=
for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
if test -e "${i}" ; then

View File

@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 14 Jan 2014 16:15:46 -0500
Subject: [PATCH] Don't print during fdt loading method.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
util/grub.d/10_linux.in | 2 --
1 file changed, 2 deletions(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index c889b47db59..c0c822c7147 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -167,9 +167,7 @@ EOF
EOF
fi
if test -n "${fdt}" ; then
- message="$(gettext_printf "Loading fdt ...")"
sed "s/^/$submenu_indentation/" << EOF
- echo '$(echo "$message" | grub_quote)'
devicetree ${rel_dirname}/${fdt}
EOF
fi

View File

@ -14,7 +14,7 @@ Signed-off-by: Peter Jones <pjones@redhat.com>
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index c0c822c7147..2e533ffd8aa 100644
index 6299836b5cd..b744438e04a 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -26,7 +26,7 @@ datarootdir="@datarootdir@"

View File

@ -1,25 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Fedora Ninjas <grub2-owner@fedoraproject.org>
Date: Mon, 10 Feb 2014 16:13:10 -0500
Subject: [PATCH] Switch to use APM Mustang device tree, for hardware testing.
Signed-off-by: David A. Marlin <d.marlin@redhat.com>
---
util/grub.d/10_linux.in | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 2e533ffd8aa..4e9a6308b3c 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -254,8 +254,8 @@ while [ "x$list" != "x" ] ; do
fdt=
for i in "dtb-${version}" "dtb-${alt_version}"; do
- if test -e "${dirname}/${i}/foundation-v8.dtb" ; then
- fdt="${i}/foundation-v8.dtb"
+ if test -e "${dirname}/${i}/apm-mustang.dtb" ; then
+ fdt="${i}/apm-mustang.dtb"
break
fi
done

View File

@ -1,42 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Fedora Ninjas <grub2-owner@fedoraproject.org>
Date: Wed, 12 Feb 2014 14:54:04 -0500
Subject: [PATCH] Use the default device tree from the grub default file
instead of hardcoding a value.
Signed-off-by: David A. Marlin <dmarlin@redhat.com>
---
util/grub-mkconfig.in | 3 ++-
util/grub.d/10_linux.in | 4 ++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index b0a8626dd1c..f68d4925ee6 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -254,7 +254,8 @@ export GRUB_DEFAULT \
GRUB_ENABLE_CRYPTODISK \
GRUB_BADRAM \
GRUB_OS_PROBER_SKIP_LIST \
- GRUB_DISABLE_SUBMENU
+ GRUB_DISABLE_SUBMENU \
+ GRUB_DEFAULT_DTB
if test "x${grub_cfg}" != "x"; then
rm -f "${grub_cfg}.new"
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 4e9a6308b3c..c548d989b2e 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -254,8 +254,8 @@ while [ "x$list" != "x" ] ; do
fdt=
for i in "dtb-${version}" "dtb-${alt_version}"; do
- if test -e "${dirname}/${i}/apm-mustang.dtb" ; then
- fdt="${i}/apm-mustang.dtb"
+ if test -f "${dirname}/${i}/${GRUB_DEFAULT_DTB}" ; then
+ fdt="${i}/${GRUB_DEFAULT_DTB}"
break
fi
done

View File

@ -14,7 +14,7 @@ Signed-off-by: Peter Jones <pjones@redhat.com>
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index c548d989b2e..03ea8460bfd 100644
index b744438e04a..43d98476b88 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -29,7 +29,8 @@ export TEXTDOMAINDIR="@localedir@"

View File

@ -1,426 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 18 Sep 2014 11:26:14 -0400
Subject: [PATCH] Load arm with SB enabled.
Make sure we actually try to validate secure boot on this platform (even
though we're not shipping it enabled by default.)
This means giving the kernel grub's loaded image as the vehicle for the
kernel command line, because we can't call systab->bs->LoadImage() if SB
is enabled.
---
grub-core/Makefile.core.def | 3 +
grub-core/loader/arm64/linux.c | 121 ++++++++++++++++++++------------------
grub-core/loader/efi/linux.c | 65 ++++++++++++++++++++
grub-core/loader/i386/efi/linux.c | 39 +-----------
include/grub/arm64/linux.h | 7 +++
include/grub/efi/linux.h | 31 ++++++++++
6 files changed, 173 insertions(+), 93 deletions(-)
create mode 100644 grub-core/loader/efi/linux.c
create mode 100644 include/grub/efi/linux.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 3f42ce16fad..e675ab2da01 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1704,6 +1704,8 @@ module = {
ia64_efi = loader/ia64/efi/linux.c;
arm = loader/arm/linux.c;
arm64 = loader/arm64/linux.c;
+ arm64 = loader/efi/linux.c;
+ fdt = lib/fdt.c;
common = loader/linux.c;
common = lib/cmdline.c;
enable = noemu;
@@ -1771,6 +1773,7 @@ module = {
name = linuxefi;
efi = loader/i386/efi/linux.c;
efi = lib/cmdline.c;
+ efi = loader/efi/linux.c;
enable = i386_efi;
enable = x86_64_efi;
};
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
index ebe1e730d63..ab0d27ee4df 100644
--- a/grub-core/loader/arm64/linux.c
+++ b/grub-core/loader/arm64/linux.c
@@ -29,6 +29,7 @@
#include <grub/efi/efi.h>
#include <grub/efi/fdtload.h>
#include <grub/efi/memory.h>
+#include <grub/efi/linux.h>
#include <grub/efi/pe32.h>
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
@@ -40,6 +41,7 @@ static int loaded;
static void *kernel_addr;
static grub_uint64_t kernel_size;
+static grub_uint32_t handover_offset;
static char *linux_args;
static grub_uint32_t cmdline_size;
@@ -66,7 +68,8 @@ grub_arm64_uefi_check_image (struct linux_arm64_kernel_header * lh)
static grub_err_t
finalize_params_linux (void)
{
- int node, retval;
+ grub_efi_loaded_image_t *loaded_image = NULL;
+ int node, retval, len;
void *fdt;
@@ -101,79 +104,73 @@ finalize_params_linux (void)
if (grub_fdt_install() != GRUB_ERR_NONE)
goto failure;
- return GRUB_ERR_NONE;
-
-failure:
- grub_fdt_unload();
- return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
-}
-
-grub_err_t
-grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
-{
- grub_efi_memory_mapped_device_path_t *mempath;
- grub_efi_handle_t image_handle;
- grub_efi_boot_services_t *b;
- grub_efi_status_t status;
- grub_efi_loaded_image_t *loaded_image;
- int len;
-
- mempath = grub_malloc (2 * sizeof (grub_efi_memory_mapped_device_path_t));
- if (!mempath)
- return grub_errno;
-
- mempath[0].header.type = GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE;
- mempath[0].header.subtype = GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE;
- mempath[0].header.length = grub_cpu_to_le16_compile_time (sizeof (*mempath));
- mempath[0].memory_type = GRUB_EFI_LOADER_DATA;
- mempath[0].start_address = addr;
- mempath[0].end_address = addr + size;
-
- mempath[1].header.type = GRUB_EFI_END_DEVICE_PATH_TYPE;
- mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
- mempath[1].header.length = sizeof (grub_efi_device_path_t);
-
- b = grub_efi_system_table->boot_services;
- status = b->load_image (0, grub_efi_image_handle,
- (grub_efi_device_path_t *) mempath,
- (void *) addr, size, &image_handle);
- if (status != GRUB_EFI_SUCCESS)
- return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
-
- grub_dprintf ("linux", "linux command line: '%s'\n", args);
+ grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
+ fdt);
/* Convert command line to UCS-2 */
- loaded_image = grub_efi_get_loaded_image (image_handle);
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (!loaded_image)
+ goto failure;
+
loaded_image->load_options_size = len =
- (grub_strlen (args) + 1) * sizeof (grub_efi_char16_t);
+ (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t);
loaded_image->load_options =
grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
if (!loaded_image->load_options)
- return grub_errno;
+ return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters");
loaded_image->load_options_size =
2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
- (grub_uint8_t *) args, len, NULL);
+ (grub_uint8_t *) linux_args, len, NULL);
- grub_dprintf ("linux", "starting image %p\n", image_handle);
- status = b->start_image (image_handle, 0, NULL);
+ return GRUB_ERR_NONE;
- /* When successful, not reached */
- b->unload_image (image_handle);
- grub_efi_free_pages ((grub_addr_t) loaded_image->load_options,
- GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+failure:
+ grub_fdt_unload();
+ return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
+}
- return grub_errno;
+static void
+free_params (void)
+{
+ grub_efi_loaded_image_t *loaded_image = NULL;
+
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (loaded_image)
+ {
+ if (loaded_image->load_options)
+ grub_efi_free_pages ((grub_efi_physical_address_t)
+ loaded_image->load_options,
+ GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+ loaded_image->load_options = NULL;
+ loaded_image->load_options_size = 0;
+ }
+}
+
+grub_err_t
+grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
+{
+ grub_err_t retval;
+
+ retval = finalize_params_linux ();
+ if (retval != GRUB_ERR_NONE)
+ return grub_errno;
+
+ grub_dprintf ("linux", "linux command line: '%s'\n", args);
+
+ retval = grub_efi_linux_boot ((char *)kernel_addr, handover_offset,
+ kernel_addr);
+
+ /* Never reached... */
+ free_params();
+ return retval;
}
static grub_err_t
grub_linux_boot (void)
{
- if (finalize_params_linux () != GRUB_ERR_NONE)
- return grub_errno;
-
- return (grub_arm64_uefi_boot_image((grub_addr_t)kernel_addr,
- kernel_size, linux_args));
+ return grub_arm64_uefi_boot_image ((grub_addr_t)kernel_addr,
+ kernel_size, linux_args);
}
static grub_err_t
@@ -250,6 +247,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
{
grub_file_t file = 0;
struct linux_arm64_kernel_header lh;
+ struct grub_arm64_linux_pe_header *pe;
grub_dl_ref (my_mod);
@@ -294,6 +292,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
+ if (!grub_linuxefi_secure_validate (kernel_addr, kernel_size))
+ {
+ grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
+ goto fail;
+ }
+
+ pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
+ handover_offset = pe->opt.entry_addr;
+
cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
linux_args = grub_malloc (cmdline_size);
if (!linux_args)
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
new file mode 100644
index 00000000000..aea378adf5c
--- /dev/null
+++ b/grub-core/loader/efi/linux.c
@@ -0,0 +1,65 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2014 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/cpu/linux.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/pe32.h>
+#include <grub/efi/linux.h>
+
+#define SHIM_LOCK_GUID \
+ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
+
+struct grub_efi_shim_lock
+{
+ grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
+};
+typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
+
+grub_efi_boolean_t
+grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
+{
+ grub_efi_guid_t guid = SHIM_LOCK_GUID;
+ grub_efi_shim_lock_t *shim_lock;
+
+ shim_lock = grub_efi_locate_protocol(&guid, NULL);
+
+ if (!shim_lock)
+ return 1;
+
+ if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS)
+ return 1;
+
+ return 0;
+}
+
+typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
+
+grub_err_t
+grub_efi_linux_boot (void *kernel_addr, grub_off_t offset,
+ void *kernel_params)
+{
+ handover_func hf;
+
+ hf = (handover_func)((char *)kernel_addr + offset);
+ hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
+
+ return GRUB_ERR_BUG;
+}
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index b79e6320ba9..e5b778577f9 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -26,6 +26,7 @@
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
#include <grub/efi/efi.h>
+#include <grub/efi/linux.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -40,52 +41,18 @@ static char *linux_cmdline;
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
-#define SHIM_LOCK_GUID \
- { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
-
-struct grub_efi_shim_lock
-{
- grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
-};
-typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
-
-static grub_efi_boolean_t
-grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
-{
- grub_efi_guid_t guid = SHIM_LOCK_GUID;
- grub_efi_shim_lock_t *shim_lock;
-
- shim_lock = grub_efi_locate_protocol(&guid, NULL);
-
- if (!shim_lock)
- return 1;
-
- if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS)
- return 1;
-
- return 0;
-}
-
-typedef void(*handover_func)(void *, grub_efi_system_table_t *, struct linux_kernel_params *);
-
static grub_err_t
grub_linuxefi_boot (void)
{
- handover_func hf;
int offset = 0;
#ifdef __x86_64__
offset = 512;
#endif
-
- hf = (handover_func)((char *)kernel_mem + handover_offset + offset);
-
asm volatile ("cli");
- hf (grub_efi_image_handle, grub_efi_system_table, params);
-
- /* Not reached */
- return GRUB_ERR_NONE;
+ return grub_efi_linux_boot ((char *)kernel_mem, handover_offset + offset,
+ params);
}
static grub_err_t
diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h
index b0634762450..6ea38bd95ab 100644
--- a/include/grub/arm64/linux.h
+++ b/include/grub/arm64/linux.h
@@ -20,6 +20,7 @@
#define GRUB_ARM64_LINUX_HEADER 1
#include <grub/efi/efi.h>
+#include <grub/efi/pe32.h>
#define GRUB_LINUX_ARM64_MAGIC_SIGNATURE 0x644d5241 /* 'ARM\x64' */
@@ -41,5 +42,11 @@ struct linux_arm64_kernel_header
grub_err_t grub_arm64_uefi_check_image (struct linux_arm64_kernel_header *lh);
grub_err_t grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size,
char *args);
+struct grub_arm64_linux_pe_header
+{
+ grub_uint32_t magic;
+ struct grub_pe32_coff_header coff;
+ struct grub_pe64_optional_header opt;
+};
#endif /* ! GRUB_ARM64_LINUX_HEADER */
diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h
new file mode 100644
index 00000000000..d9ede36773b
--- /dev/null
+++ b/include/grub/efi/linux.h
@@ -0,0 +1,31 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2014 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GRUB_EFI_LINUX_HEADER
+#define GRUB_EFI_LINUX_HEADER 1
+
+#include <grub/efi/api.h>
+#include <grub/err.h>
+#include <grub/symbol.h>
+
+grub_efi_boolean_t
+EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size);
+grub_err_t
+EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
+ void *kernel_param);
+
+#endif /* ! GRUB_EFI_LINUX_HEADER */

View File

@ -12,7 +12,7 @@ Signed-off-by: Peter Jones <pjones@redhat.com>
1 file changed, 27 insertions(+), 7 deletions(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 03ea8460bfd..4ad98fbd767 100644
index 43d98476b88..a8a8e2cf325 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -78,6 +78,32 @@ case x"$GRUB_FS" in
@ -48,7 +48,7 @@ index 03ea8460bfd..4ad98fbd767 100644
title_correction_code=
linux_entry ()
@@ -105,17 +131,11 @@ linux_entry ()
@@ -91,17 +117,11 @@ linux_entry ()
boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
fi
if [ x$type != xsimple ] ; then

View File

@ -1,74 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 27 Oct 2014 09:22:55 -0400
Subject: [PATCH] Try to emit linux16/initrd16 and linuxefi/initrdefi in
30-os_prober.
Resolves: rhbz#1108296
Signed-off-by: Peter Jones <pjones@redhat.com>
---
util/grub.d/30_os-prober.in | 30 ++++++++++++++++++++++++++----
1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
index 9b8f5968e2d..dc98eace934 100644
--- a/util/grub.d/30_os-prober.in
+++ b/util/grub.d/30_os-prober.in
@@ -141,6 +141,28 @@ for OS in ${OSPROBED} ; do
# os-prober returns text string followed by optional counter
CLASS="--class $(echo "${LABEL}" | LC_ALL=C sed 's,[[:digit:]]*$,,' | cut -d' ' -f1 | tr 'A-Z' 'a-z' | LC_ALL=C sed 's,[^[:alnum:]_],_,g')"
+ sixteenbit=""
+ linuxefi="linux"
+ initrdefi="initrd"
+ case "$machine" in
+ i?86|x86_64)
+ sixteenbit="16"
+ linuxefi="linuxefi"
+ initrdefi="initrdefi"
+ ;;
+ aarch64)
+ linuxefi="linux"
+ initrdefi="initrd"
+ esac
+ linux="linux${sixteenbit}"
+ initrd="initrd${sixteenbit}"
+ # there's no way to tell that the /other/ os is booting through UEFI,
+ # but if we are it's an okay bet...
+ if [ -d /sys/firmware/efi ]; then
+ linux=$linuxefi
+ initrd=$initrdefi
+ fi
+
gettext_printf "Found %s on %s\n" "${LONGNAME}" "${DEVICE}" >&2
case ${BOOT} in
@@ -241,11 +263,11 @@ EOF
save_default_entry | grub_add_tab
printf '%s\n' "${prepare_boot_cache}"
cat << EOF
- linux ${LKERNEL} ${LPARAMS}
+ ${linux} ${LKERNEL} ${LPARAMS}
EOF
if [ -n "${LINITRD}" ] ; then
cat << EOF
- initrd ${LINITRD}
+ ${initrd} ${LINITRD}
EOF
fi
cat << EOF
@@ -261,11 +283,11 @@ EOF
save_default_entry | sed -e "s/^/$grub_tab$grub_tab/"
printf '%s\n' "${prepare_boot_cache}" | grub_add_tab
cat << EOF
- linux ${LKERNEL} ${LPARAMS}
+ ${linux} ${LKERNEL} ${LPARAMS}
EOF
if [ -n "${LINITRD}" ] ; then
cat << EOF
- initrd ${LINITRD}
+ ${initrd} ${LINITRD}
EOF
fi
cat << EOF

View File

@ -20,10 +20,10 @@ Signed-off-by: Peter Jones <pjones@redhat.com>
create mode 100644 include/grub/net/url.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index e675ab2da01..338244f6b47 100644
index 7ed07b3e2fd..8a0193fa5e3 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2194,6 +2194,7 @@ module = {
@@ -2185,6 +2185,7 @@ module = {
common = net/ethernet.c;
common = net/arp.c;
common = net/netbuff.c;

View File

@ -239,7 +239,7 @@ index bdb9982aefb..8218f3d477f 100644
if [ -z "$GRUB_DEVICE_UUID" ]; then
GRUB_DEVICE_UUID="$GRUB_DEVICE_UUID_GENERATED"
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 4ad98fbd767..24a10f95d2c 100644
index a8a8e2cf325..4e49ccdf742 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -111,7 +111,8 @@ linux_entry ()
@ -250,9 +250,9 @@ index 4ad98fbd767..24a10f95d2c 100644
+ isdebug="$4"
+ args="$5"
linuxcmd=linux
initrdcmd=initrd
@@ -137,6 +138,9 @@ linux_entry ()
if [ -z "$boot_device_id" ]; then
boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
@@ -123,6 +124,9 @@ linux_entry ()
quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"
title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
fi
@ -262,7 +262,7 @@ index 4ad98fbd767..24a10f95d2c 100644
echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
else
echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
@@ -311,11 +315,15 @@ while [ "x$list" != "x" ] ; do
@@ -295,11 +299,15 @@ while [ "x$list" != "x" ] ; do
fi
if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then
@ -280,7 +280,7 @@ index 4ad98fbd767..24a10f95d2c 100644
if [ -z "$boot_device_id" ]; then
boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
fi
@@ -324,10 +332,15 @@ while [ "x$list" != "x" ] ; do
@@ -308,10 +316,15 @@ while [ "x$list" != "x" ] ; do
is_top_level=false
fi

View File

@ -13,7 +13,7 @@ Subject: [PATCH] Make grub_fatal() also backtrace.
create mode 100644 grub-core/lib/arm64/backtrace.c
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 423def037c2..edf249f0002 100644
index 8a0193fa5e3..9983d5fa6ad 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -175,6 +175,9 @@ kernel = {

View File

@ -1,94 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg59@coreos.com>
Date: Tue, 14 Jul 2015 16:58:51 -0700
Subject: [PATCH] Fix race in EFI validation
---
grub-core/loader/i386/efi/linux.c | 44 ++++++++++-----------------------------
1 file changed, 11 insertions(+), 33 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index e5b778577f9..7ccf32d9d45 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -154,7 +154,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_file_t file = 0;
struct linux_kernel_header lh;
grub_ssize_t len, start, filelen;
- void *kernel;
+ void *kernel = NULL;
grub_dl_ref (my_mod);
@@ -191,10 +191,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- grub_file_seek (file, 0);
-
- grub_free(kernel);
-
params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
if (! params)
@@ -203,15 +199,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- memset (params, 0, 16384);
+ grub_memset (params, 0, 16384);
- if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
- {
- if (!grub_errno)
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
- argv[0]);
- goto fail;
- }
+ grub_memcpy (&lh, kernel, sizeof (lh));
if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
{
@@ -271,27 +261,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- if (grub_file_seek (file, start) == (grub_off_t) -1)
- {
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
- argv[0]);
- goto fail;
- }
+ grub_memcpy (kernel_mem, (char *)kernel + start, len);
+ grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
+ loaded=1;
- if (grub_file_read (file, kernel_mem, len) != len && !grub_errno)
- {
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
- argv[0]);
- }
-
- if (grub_errno == GRUB_ERR_NONE)
- {
- grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
- loaded = 1;
- lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
- }
-
- memcpy(params, &lh, 2 * 512);
+ lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
+ grub_memcpy (params, &lh, 2 * 512);
params->type_of_loader = 0x21;
@@ -300,6 +275,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (file)
grub_file_close (file);
+ if (kernel)
+ grub_free (kernel);
+
if (grub_errno != GRUB_ERR_NONE)
{
grub_dl_unref (my_mod);

View File

@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Raymund Will <rw@suse.com>
Date: Fri, 10 Apr 2015 01:45:02 -0400
Subject: [PATCH] Use device part of chainloader target, if present.
Otherwise chainloading is restricted to '$root', which might not even
be readable by EFI!
v1. use grub_file_get_device_name() to get device name
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/efi/chainloader.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index adc85636633..14ce6ddd7ad 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -223,8 +223,11 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
if (! file)
goto fail;
- /* Get the root device's device path. */
- dev = grub_device_open (0);
+ /* Get the device path from filename. */
+ char *devname = grub_file_get_device_name (filename);
+ dev = grub_device_open (devname);
+ if (devname)
+ grub_free (devname);
if (! dev)
goto fail;

View File

@ -1,797 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 6 Oct 2015 13:04:37 -0400
Subject: [PATCH] Add secureboot support on efi chainloader
Expand the chainloader to be able to verify the image by means of shim
lock protocol. The PE/COFF image is loaded and relocated by the
chainloader instead of calling LoadImage and StartImage UEFI boot
Service as they require positive verification result from keys enrolled
in KEK or DB. The shim will use MOK in addition to firmware enrolled
keys to verify the image.
The chainloader module could be used to load other UEFI bootloaders,
such as xen.efi, and could be signed by any of MOK, KEK or DB.
Based on https://build.opensuse.org/package/view_file/openSUSE:Factory/grub2/grub2-secureboot-chainloader.patch
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/efi/chainloader.c | 612 ++++++++++++++++++++++++++++++++++---
include/grub/efi/pe32.h | 20 +-
2 files changed, 595 insertions(+), 37 deletions(-)
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index 14ce6ddd7ad..87a91e16f17 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -32,6 +32,8 @@
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/efi/disk.h>
+#include <grub/efi/pe32.h>
+#include <grub/efi/linux.h>
#include <grub/command.h>
#include <grub/i18n.h>
#include <grub/net.h>
@@ -46,9 +48,14 @@ static grub_dl_t my_mod;
static grub_efi_physical_address_t address;
static grub_efi_uintn_t pages;
+static grub_ssize_t fsize;
static grub_efi_device_path_t *file_path;
static grub_efi_handle_t image_handle;
static grub_efi_char16_t *cmdline;
+static grub_ssize_t cmdline_len;
+static grub_efi_handle_t dev_handle;
+
+static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table);
static grub_err_t
grub_chainloader_unload (void)
@@ -63,6 +70,7 @@ grub_chainloader_unload (void)
grub_free (cmdline);
cmdline = 0;
file_path = 0;
+ dev_handle = 0;
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
@@ -191,12 +199,523 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
return file_path;
}
+#define SHIM_LOCK_GUID \
+ { 0x605dab50, 0xe046, 0x4300, { 0xab,0xb6,0x3d,0xd8,0x10,0xdd,0x8b,0x23 } }
+
+typedef union
+{
+ struct grub_pe32_header_32 pe32;
+ struct grub_pe32_header_64 pe32plus;
+} grub_pe_header_t;
+
+struct pe_coff_loader_image_context
+{
+ grub_efi_uint64_t image_address;
+ grub_efi_uint64_t image_size;
+ grub_efi_uint64_t entry_point;
+ grub_efi_uintn_t size_of_headers;
+ grub_efi_uint16_t image_type;
+ grub_efi_uint16_t number_of_sections;
+ grub_efi_uint32_t section_alignment;
+ struct grub_pe32_section_table *first_section;
+ struct grub_pe32_data_directory *reloc_dir;
+ struct grub_pe32_data_directory *sec_dir;
+ grub_efi_uint64_t number_of_rva_and_sizes;
+ grub_pe_header_t *pe_hdr;
+};
+
+typedef struct pe_coff_loader_image_context pe_coff_loader_image_context_t;
+
+struct grub_efi_shim_lock
+{
+ grub_efi_status_t (*verify)(void *buffer,
+ grub_efi_uint32_t size);
+ grub_efi_status_t (*hash)(void *data,
+ grub_efi_int32_t datasize,
+ pe_coff_loader_image_context_t *context,
+ grub_efi_uint8_t *sha256hash,
+ grub_efi_uint8_t *sha1hash);
+ grub_efi_status_t (*context)(void *data,
+ grub_efi_uint32_t size,
+ pe_coff_loader_image_context_t *context);
+};
+
+typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
+
+static grub_efi_boolean_t
+read_header (void *data, grub_efi_uint32_t size,
+ pe_coff_loader_image_context_t *context)
+{
+ grub_efi_guid_t guid = SHIM_LOCK_GUID;
+ grub_efi_shim_lock_t *shim_lock;
+ grub_efi_status_t status;
+
+ shim_lock = grub_efi_locate_protocol (&guid, NULL);
+
+ if (!shim_lock)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "no shim lock protocol");
+ return 0;
+ }
+
+ status = shim_lock->context (data, size, context);
+
+ if (status == GRUB_EFI_SUCCESS)
+ {
+ grub_dprintf ("chain", "context success\n");
+ return 1;
+ }
+
+ switch (status)
+ {
+ case GRUB_EFI_UNSUPPORTED:
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "context error unsupported");
+ break;
+ case GRUB_EFI_INVALID_PARAMETER:
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "context error invalid parameter");
+ break;
+ default:
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "context error code");
+ break;
+ }
+
+ return 0;
+}
+
+static void*
+image_address (void *image, grub_efi_uint64_t sz, grub_efi_uint64_t adr)
+{
+ if (adr > sz)
+ return NULL;
+
+ return ((grub_uint8_t*)image + adr);
+}
+
+static int
+image_is_64_bit (grub_pe_header_t *pe_hdr)
+{
+ /* .Magic is the same offset in all cases */
+ if (pe_hdr->pe32plus.optional_header.magic == GRUB_PE32_PE64_MAGIC)
+ return 1;
+ return 0;
+}
+
+static const grub_uint16_t machine_type =
+#if defined(__x86_64__)
+ GRUB_PE32_MACHINE_X86_64;
+#elif defined(__aarch64__)
+ GRUB_PE32_MACHINE_ARM64;
+#elif defined(__arm__)
+ GRUB_PE32_MACHINE_ARMTHUMB_MIXED;
+#elif defined(__i386__) || defined(__i486__) || defined(__i686__)
+ GRUB_PE32_MACHINE_I386;
+#elif defined(__ia64__)
+ GRUB_PE32_MACHINE_IA64;
+#else
+#error this architecture is not supported by grub2
+#endif
+
+static grub_efi_status_t
+relocate_coff (pe_coff_loader_image_context_t *context,
+ struct grub_pe32_section_table *section,
+ void *orig, void *data)
+{
+ struct grub_pe32_data_directory *reloc_base, *reloc_base_end;
+ grub_efi_uint64_t adjust;
+ struct grub_pe32_fixup_block *reloc, *reloc_end;
+ char *fixup, *fixup_base, *fixup_data = NULL;
+ grub_efi_uint16_t *fixup_16;
+ grub_efi_uint32_t *fixup_32;
+ grub_efi_uint64_t *fixup_64;
+ grub_efi_uint64_t size = context->image_size;
+ void *image_end = (char *)orig + size;
+ int n = 0;
+
+ if (image_is_64_bit (context->pe_hdr))
+ context->pe_hdr->pe32plus.optional_header.image_base =
+ (grub_uint64_t)(unsigned long)data;
+ else
+ context->pe_hdr->pe32.optional_header.image_base =
+ (grub_uint32_t)(unsigned long)data;
+
+ /* Alright, so here's how this works:
+ *
+ * context->reloc_dir gives us two things:
+ * - the VA the table of base relocation blocks are (maybe) to be
+ * mapped at (reloc_dir->rva)
+ * - the virtual size (reloc_dir->size)
+ *
+ * The .reloc section (section here) gives us some other things:
+ * - the name! kind of. (section->name)
+ * - the virtual size (section->virtual_size), which should be the same
+ * as RelocDir->Size
+ * - the virtual address (section->virtual_address)
+ * - the file section size (section->raw_data_size), which is
+ * a multiple of optional_header->file_alignment. Only useful for image
+ * validation, not really useful for iteration bounds.
+ * - the file address (section->raw_data_offset)
+ * - a bunch of stuff we don't use that's 0 in our binaries usually
+ * - Flags (section->characteristics)
+ *
+ * and then the thing that's actually at the file address is an array
+ * of struct grub_pe32_fixup_block structs with some values packed behind
+ * them. The block_size field of this structure includes the
+ * structure itself, and adding it to that structure's address will
+ * yield the next entry in the array.
+ */
+
+ reloc_base = image_address (orig, size, section->raw_data_offset);
+ reloc_base_end = image_address (orig, size, section->raw_data_offset
+ + section->virtual_size - 1);
+
+ grub_dprintf ("chain", "reloc_base %p reloc_base_end %p\n", reloc_base,
+ reloc_base_end);
+
+ if (!reloc_base && !reloc_base_end)
+ return GRUB_EFI_SUCCESS;
+
+ if (!reloc_base || !reloc_base_end)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc table overflows binary");
+ return GRUB_EFI_UNSUPPORTED;
+ }
+
+ adjust = (grub_uint64_t)data - context->image_address;
+ if (adjust == 0)
+ return GRUB_EFI_SUCCESS;
+
+ while (reloc_base < reloc_base_end)
+ {
+ grub_uint16_t *entry;
+ reloc = (struct grub_pe32_fixup_block *)((char*)reloc_base);
+
+ if ((reloc_base->size == 0) ||
+ (reloc_base->size > context->reloc_dir->size))
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "Reloc %d block size %d is invalid\n", n,
+ reloc_base->size);
+ return GRUB_EFI_UNSUPPORTED;
+ }
+
+ entry = &reloc->entries[0];
+ reloc_end = (struct grub_pe32_fixup_block *)
+ ((char *)reloc_base + reloc_base->size);
+
+ if ((void *)reloc_end < data || (void *)reloc_end > image_end)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc entry %d overflows binary",
+ n);
+ return GRUB_EFI_UNSUPPORTED;
+ }
+
+ fixup_base = image_address(data, size, reloc_base->rva);
+
+ if (!fixup_base)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc %d Invalid fixupbase", n);
+ return GRUB_EFI_UNSUPPORTED;
+ }
+
+ while ((void *)entry < (void *)reloc_end)
+ {
+ fixup = fixup_base + (*entry & 0xFFF);
+ switch ((*entry) >> 12)
+ {
+ case GRUB_PE32_REL_BASED_ABSOLUTE:
+ break;
+ case GRUB_PE32_REL_BASED_HIGH:
+ fixup_16 = (grub_uint16_t *)fixup;
+ *fixup_16 = (grub_uint16_t)
+ (*fixup_16 + ((grub_uint16_t)((grub_uint32_t)adjust >> 16)));
+ if (fixup_data != NULL)
+ {
+ *(grub_uint16_t *) fixup_data = *fixup_16;
+ fixup_data = fixup_data + sizeof (grub_uint16_t);
+ }
+ break;
+ case GRUB_PE32_REL_BASED_LOW:
+ fixup_16 = (grub_uint16_t *)fixup;
+ *fixup_16 = (grub_uint16_t) (*fixup_16 + (grub_uint16_t)adjust);
+ if (fixup_data != NULL)
+ {
+ *(grub_uint16_t *) fixup_data = *fixup_16;
+ fixup_data = fixup_data + sizeof (grub_uint16_t);
+ }
+ break;
+ case GRUB_PE32_REL_BASED_HIGHLOW:
+ fixup_32 = (grub_uint32_t *)fixup;
+ *fixup_32 = *fixup_32 + (grub_uint32_t)adjust;
+ if (fixup_data != NULL)
+ {
+ fixup_data = (char *)ALIGN_UP ((grub_addr_t)fixup_data, sizeof (grub_uint32_t));
+ *(grub_uint32_t *) fixup_data = *fixup_32;
+ fixup_data += sizeof (grub_uint32_t);
+ }
+ break;
+ case GRUB_PE32_REL_BASED_DIR64:
+ fixup_64 = (grub_uint64_t *)fixup;
+ *fixup_64 = *fixup_64 + (grub_uint64_t)adjust;
+ if (fixup_data != NULL)
+ {
+ fixup_data = (char *)ALIGN_UP ((grub_addr_t)fixup_data, sizeof (grub_uint64_t));
+ *(grub_uint64_t *) fixup_data = *fixup_64;
+ fixup_data += sizeof (grub_uint64_t);
+ }
+ break;
+ default:
+ grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "Reloc %d unknown relocation type %d",
+ n, (*entry) >> 12);
+ return GRUB_EFI_UNSUPPORTED;
+ }
+ entry += 1;
+ }
+ reloc_base = (struct grub_pe32_data_directory *)reloc_end;
+ n++;
+ }
+
+ return GRUB_EFI_SUCCESS;
+}
+
+static grub_efi_device_path_t *
+grub_efi_get_media_file_path (grub_efi_device_path_t *dp)
+{
+ while (1)
+ {
+ grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
+ grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
+
+ if (type == GRUB_EFI_END_DEVICE_PATH_TYPE)
+ break;
+ else if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
+ && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
+ return dp;
+
+ dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
+ }
+
+ return NULL;
+}
+
+static grub_efi_boolean_t
+handle_image (void *data, grub_efi_uint32_t datasize)
+{
+ grub_efi_boot_services_t *b;
+ grub_efi_loaded_image_t *li, li_bak;
+ grub_efi_status_t efi_status;
+ char *buffer = NULL;
+ char *buffer_aligned = NULL;
+ grub_efi_uint32_t i, size;
+ struct grub_pe32_section_table *section;
+ char *base, *end;
+ pe_coff_loader_image_context_t context;
+ grub_uint32_t section_alignment;
+ grub_uint32_t buffer_size;
+
+ b = grub_efi_system_table->boot_services;
+
+ if (read_header (data, datasize, &context))
+ {
+ grub_dprintf ("chain", "Succeed to read header\n");
+ }
+ else
+ {
+ grub_dprintf ("chain", "Failed to read header\n");
+ goto error_exit;
+ }
+
+ section_alignment = context.section_alignment;
+ buffer_size = context.image_size + section_alignment;
+
+ efi_status = efi_call_3 (b->allocate_pool, GRUB_EFI_LOADER_DATA,
+ buffer_size, &buffer);
+
+ if (efi_status != GRUB_EFI_SUCCESS)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+ goto error_exit;
+ }
+
+ buffer_aligned = (char *)ALIGN_UP ((grub_addr_t)buffer, section_alignment);
+
+ if (!buffer_aligned)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+ goto error_exit;
+ }
+
+ grub_memcpy (buffer_aligned, data, context.size_of_headers);
+
+ char *reloc_base, *reloc_base_end;
+ reloc_base = image_address (buffer_aligned, datasize,
+ context.reloc_dir->rva);
+ /* RelocBaseEnd here is the address of the last byte of the table */
+ reloc_base_end = image_address (buffer_aligned, datasize,
+ context.reloc_dir->rva
+ + context.reloc_dir->size - 1);
+ struct grub_pe32_section_table *reloc_section = NULL;
+
+ section = context.first_section;
+ for (i = 0; i < context.number_of_sections; i++, section++)
+ {
+ size = section->virtual_size;
+ if (size > section->raw_data_size)
+ size = section->raw_data_size;
+
+ base = image_address (buffer_aligned, context.image_size,
+ section->virtual_address);
+ end = image_address (buffer_aligned, context.image_size,
+ section->virtual_address + size - 1);
+
+
+ /* We do want to process .reloc, but it's often marked
+ * discardable, so we don't want to memcpy it. */
+ if (grub_memcmp (section->name, ".reloc\0\0", 8) == 0)
+ {
+ if (reloc_section)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "Image has multiple relocation sections");
+ goto error_exit;
+ }
+
+ /* If it has nonzero sizes, and our bounds check
+ * made sense, and the VA and size match RelocDir's
+ * versions, then we believe in this section table. */
+ if (section->raw_data_size && section->virtual_size &&
+ base && end && reloc_base == base && reloc_base_end == end)
+ {
+ reloc_section = section;
+ }
+ }
+
+ if (section->characteristics && GRUB_PE32_SCN_MEM_DISCARDABLE)
+ continue;
+
+ if (!base || !end)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid section size");
+ goto error_exit;
+ }
+
+ if (section->virtual_address < context.size_of_headers ||
+ section->raw_data_offset < context.size_of_headers)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "Section %d is inside image headers", i);
+ goto error_exit;
+ }
+
+ if (section->raw_data_size > 0)
+ grub_memcpy (base, (grub_efi_uint8_t*)data + section->raw_data_offset,
+ size);
+
+ if (size < section->virtual_size)
+ grub_memset (base + size, 0, section->virtual_size - size);
+
+ grub_dprintf ("chain", "copied section %s\n", section->name);
+ }
+
+ /* 5 == EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC */
+ if (context.number_of_rva_and_sizes <= 5)
+ {
+ grub_dprintf ("chain", "image has no relocation entry\n");
+ goto error_exit;
+ }
+
+ if (context.reloc_dir->size && reloc_section)
+ {
+ /* run the relocation fixups */
+ efi_status = relocate_coff (&context, reloc_section, data,
+ buffer_aligned);
+
+ if (efi_status != GRUB_EFI_SUCCESS)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "relocation failed");
+ goto error_exit;
+ }
+ }
+
+ entry_point = image_address (buffer_aligned, context.image_size,
+ context.entry_point);
+
+ if (!entry_point)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid entry point");
+ goto error_exit;
+ }
+
+ li = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (!li)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "no loaded image available");
+ goto error_exit;
+ }
+
+ grub_memcpy (&li_bak, li, sizeof (grub_efi_loaded_image_t));
+ li->image_base = buffer_aligned;
+ li->image_size = context.image_size;
+ li->load_options = cmdline;
+ li->load_options_size = cmdline_len;
+ li->file_path = grub_efi_get_media_file_path (file_path);
+ li->device_handle = dev_handle;
+ if (li->file_path)
+ {
+ grub_printf ("file path: ");
+ grub_efi_print_device_path (li->file_path);
+ }
+ else
+ {
+ grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found");
+ goto error_exit;
+ }
+
+ efi_status = efi_call_2 (entry_point, grub_efi_image_handle,
+ grub_efi_system_table);
+
+ grub_memcpy (li, &li_bak, sizeof (grub_efi_loaded_image_t));
+ efi_status = efi_call_1 (b->free_pool, buffer);
+
+ return 1;
+
+error_exit:
+ if (buffer)
+ efi_call_1 (b->free_pool, buffer);
+
+ return 0;
+}
+
+static grub_err_t
+grub_secureboot_chainloader_unload (void)
+{
+ grub_efi_boot_services_t *b;
+
+ b = grub_efi_system_table->boot_services;
+ efi_call_2 (b->free_pages, address, pages);
+ grub_free (file_path);
+ grub_free (cmdline);
+ cmdline = 0;
+ file_path = 0;
+ dev_handle = 0;
+
+ grub_dl_unref (my_mod);
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_secureboot_chainloader_boot (void)
+{
+ handle_image ((void *)address, fsize);
+ grub_loader_unset ();
+ return grub_errno;
+}
+
static grub_err_t
grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
- grub_ssize_t size;
grub_efi_status_t status;
grub_efi_boot_services_t *b;
grub_device_t dev = 0;
@@ -204,7 +723,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
grub_efi_loaded_image_t *loaded_image;
char *filename;
void *boot_image = 0;
- grub_efi_handle_t dev_handle = 0;
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
@@ -216,9 +734,36 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
address = 0;
image_handle = 0;
file_path = 0;
+ dev_handle = 0;
b = grub_efi_system_table->boot_services;
+ if (argc > 1)
+ {
+ int i;
+ grub_efi_char16_t *p16;
+
+ for (i = 1, cmdline_len = 0; i < argc; i++)
+ cmdline_len += grub_strlen (argv[i]) + 1;
+
+ cmdline_len *= sizeof (grub_efi_char16_t);
+ cmdline = p16 = grub_malloc (cmdline_len);
+ if (! cmdline)
+ goto fail;
+
+ for (i = 1; i < argc; i++)
+ {
+ char *p8;
+
+ p8 = argv[i];
+ while (*p8)
+ *(p16++) = *(p8++);
+
+ *(p16++) = ' ';
+ }
+ *(--p16) = 0;
+ }
+
file = grub_file_open (filename);
if (! file)
goto fail;
@@ -267,14 +812,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
grub_printf ("file path: ");
grub_efi_print_device_path (file_path);
- size = grub_file_size (file);
- if (!size)
+ fsize = grub_file_size (file);
+ if (!fsize)
{
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
filename);
goto fail;
}
- pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12);
+ pages = (((grub_efi_uintn_t) fsize + ((1 << 12) - 1)) >> 12);
status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES,
GRUB_EFI_LOADER_CODE,
@@ -288,7 +833,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
}
boot_image = (void *) ((grub_addr_t) address);
- if (grub_file_read (file, boot_image, size) != size)
+ if (grub_file_read (file, boot_image, fsize) != fsize)
{
if (grub_errno == GRUB_ERR_NONE)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
@@ -298,7 +843,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
}
#if defined (__i386__) || defined (__x86_64__)
- if (size >= (grub_ssize_t) sizeof (struct grub_macho_fat_header))
+ if (fsize >= (grub_ssize_t) sizeof (struct grub_macho_fat_header))
{
struct grub_macho_fat_header *head = boot_image;
if (head->magic
@@ -307,6 +852,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
grub_uint32_t i;
struct grub_macho_fat_arch *archs
= (struct grub_macho_fat_arch *) (head + 1);
+
+ if (grub_efi_secure_boot())
+ {
+ grub_error (GRUB_ERR_BAD_OS,
+ "MACHO binaries are forbidden with Secure Boot");
+ goto fail;
+ }
+
for (i = 0; i < grub_cpu_to_le32 (head->nfat_arch); i++)
{
if (GRUB_MACHO_CPUTYPE_IS_HOST_CURRENT (archs[i].cputype))
@@ -321,21 +874,28 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
> ~grub_cpu_to_le32 (archs[i].size)
|| grub_cpu_to_le32 (archs[i].offset)
+ grub_cpu_to_le32 (archs[i].size)
- > (grub_size_t) size)
+ > (grub_size_t) fsize)
{
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
filename);
goto fail;
}
boot_image = (char *) boot_image + grub_cpu_to_le32 (archs[i].offset);
- size = grub_cpu_to_le32 (archs[i].size);
+ fsize = grub_cpu_to_le32 (archs[i].size);
}
}
#endif
+ if (grub_linuxefi_secure_validate((void *)address, fsize))
+ {
+ grub_file_close (file);
+ grub_loader_set (grub_secureboot_chainloader_boot,
+ grub_secureboot_chainloader_unload, 0);
+ return 0;
+ }
+
status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
- boot_image, size,
- &image_handle);
+ boot_image, fsize, &image_handle);
if (status != GRUB_EFI_SUCCESS)
{
if (status == GRUB_EFI_OUT_OF_RESOURCES)
@@ -357,33 +917,10 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
}
loaded_image->device_handle = dev_handle;
- if (argc > 1)
+ if (cmdline)
{
- int i, len;
- grub_efi_char16_t *p16;
-
- for (i = 1, len = 0; i < argc; i++)
- len += grub_strlen (argv[i]) + 1;
-
- len *= sizeof (grub_efi_char16_t);
- cmdline = p16 = grub_malloc (len);
- if (! cmdline)
- goto fail;
-
- for (i = 1; i < argc; i++)
- {
- char *p8;
-
- p8 = argv[i];
- while (*p8)
- *(p16++) = *(p8++);
-
- *(p16++) = ' ';
- }
- *(--p16) = 0;
-
loaded_image->load_options = cmdline;
- loaded_image->load_options_size = len;
+ loaded_image->load_options_size = cmdline_len;
}
grub_file_close (file);
@@ -405,6 +942,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
if (address)
efi_call_2 (b->free_pages, address, pages);
+ if (cmdline)
+ grub_free (cmdline);
+
grub_dl_unref (my_mod);
return grub_errno;
diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
index 7d44732d2c3..6e24dae2cb6 100644
--- a/include/grub/efi/pe32.h
+++ b/include/grub/efi/pe32.h
@@ -214,7 +214,11 @@ struct grub_pe64_optional_header
struct grub_pe32_section_table
{
char name[8];
- grub_uint32_t virtual_size;
+ union
+ {
+ grub_uint32_t physical_address;
+ grub_uint32_t virtual_size;
+ };
grub_uint32_t virtual_address;
grub_uint32_t raw_data_size;
grub_uint32_t raw_data_offset;
@@ -265,6 +269,20 @@ struct grub_pe32_header
#endif
};
+struct grub_pe32_header_32
+{
+ char signature[GRUB_PE32_SIGNATURE_SIZE];
+ struct grub_pe32_coff_header coff_header;
+ struct grub_pe32_optional_header optional_header;
+};
+
+struct grub_pe32_header_64
+{
+ char signature[GRUB_PE32_SIGNATURE_SIZE];
+ struct grub_pe32_coff_header coff_header;
+ struct grub_pe64_optional_header optional_header;
+};
+
struct grub_pe32_fixup_block
{
grub_uint32_t page_rva;

Some files were not shown because too many files have changed in this diff Show More