From bbee35754c088eca0ffada3ed7457a2fe674de69 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 13 Jan 2014 12:13:20 +0000 Subject: If running under UEFI secure boot, attempt to use linuxefi loader Author: Steve Langasek Forwarded: no Last-Update: 2013-12-20 Patch-Name: linuxefi_non_sb_fallback.patch --- grub-core/loader/i386/efi/linux.c | 2 +- grub-core/loader/i386/linux.c | 43 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c index f764f49..88e2d34 100644 --- a/grub-core/loader/i386/efi/linux.c +++ b/grub-core/loader/i386/efi/linux.c @@ -234,7 +234,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (! grub_linuxefi_secure_validate (kernel, filelen)) { - grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); + grub_error (GRUB_ERR_ACCESS_DENIED, N_("%s has invalid signature"), argv[0]); grub_free (kernel); goto fail; } diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index 31fb91e..2380642 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -76,6 +76,8 @@ static grub_size_t maximal_cmdline_size; static struct linux_kernel_params linux_params; static char *linux_cmdline; #ifdef GRUB_MACHINE_EFI +static int using_linuxefi; +static grub_command_t initrdefi_cmd; static grub_efi_uintn_t efi_mmap_size; #else static const grub_size_t efi_mmap_size = 0; @@ -690,6 +692,41 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), grub_dl_ref (my_mod); +#ifdef GRUB_MACHINE_EFI + using_linuxefi = 0; + if (grub_efi_secure_boot ()) + { + /* Try linuxefi first, which will require a successful signature check + and then hand over to the kernel without calling ExitBootServices. + If that fails, however, fall back to calling ExitBootServices + ourselves and then booting an unsigned kernel. */ + grub_dl_t mod; + grub_command_t linuxefi_cmd; + + grub_dprintf ("linux", "Secure Boot enabled: trying linuxefi\n"); + + mod = grub_dl_load ("linuxefi"); + if (mod) + { + grub_dl_ref (mod); + linuxefi_cmd = grub_command_find ("linuxefi"); + initrdefi_cmd = grub_command_find ("initrdefi"); + if (linuxefi_cmd && initrdefi_cmd) + { + (linuxefi_cmd->func) (linuxefi_cmd, argc, argv); + if (grub_errno == GRUB_ERR_NONE) + { + grub_dprintf ("linux", "Handing off to linuxefi\n"); + using_linuxefi = 1; + return GRUB_ERR_NONE; + } + grub_dprintf ("linux", "linuxefi failed (%d)\n", grub_errno); + grub_errno = GRUB_ERR_NONE; + } + } + } +#endif + if (argc == 0) { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); @@ -1052,6 +1089,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), grub_err_t err; struct grub_linux_initrd_context initrd_ctx; +#ifdef GRUB_MACHINE_EFI + /* If we're using linuxefi, just forward to initrdefi. */ + if (using_linuxefi && initrdefi_cmd) + return (initrdefi_cmd->func) (initrdefi_cmd, argc, argv); +#endif + if (argc == 0) { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));