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:
parent
1d36e193e6
commit
ad4aff0c12
935
0157-Add-support-for-Linux-EFI-stub-loading.patch
Normal file
935
0157-Add-support-for-Linux-EFI-stub-loading.patch
Normal 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
|
@ -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:
|
||||
|
@ -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:
|
||||
|
1390
0160-Add-secureboot-support-on-efi-chainloader.patch
Normal file
1390
0160-Add-secureboot-support-on-efi-chainloader.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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));
|
@ -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 = {
|
@ -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
|
@ -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
|
@ -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);
|
@ -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;
|
||||
};
|
||||
|
68
0185-Add-devicetree-loading.patch
Normal file
68
0185-Add-devicetree-loading.patch
Normal 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
|
@ -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
|
@ -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}
|
@ -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@"
|
@ -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
|
@ -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
|
@ -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@"
|
@ -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
|
@ -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
|
@ -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@"
|
@ -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 */
|
@ -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
|
@ -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
|
@ -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;
|
@ -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
|
||||
|
@ -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 = {
|
@ -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);
|
@ -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;
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user