From: Ard Biesheuvel <ardb@kernel.org>
To: linux-efi@vger.kernel.org
Cc: Ard Biesheuvel <ardb@kernel.org>,
lersek@redhat.com, leif@nuviainc.com, pjones@redhat.com,
mjg59@google.com, agraf@csgraf.de, daniel.kiper@oracle.com,
hdegoede@redhat.com, nivedita@alum.mit.edu, mingo@kernel.org
Subject: [PATCH v2 4/5] efi/x86: Implement mixed mode boot without the handover protocol
Date: Mon, 17 Feb 2020 15:48:21 +0100 [thread overview]
Message-ID: <20200217144822.24616-5-ardb@kernel.org> (raw)
In-Reply-To: <20200217144822.24616-1-ardb@kernel.org>
Add support for booting 64-bit x86 kernels from 32-bit firmware running
on 64-bit capable CPUs without requiring the bootloader to implement
the EFI handover protocol or allocate the setup block, etc etc, all of
which can be done by the stub itself, using code that already exists.
Instead, create an ordinary EFI application entrypoint but implemented
in 32-bit code [so that it can be invoked by 32-bit firmware], and stash
the address of this 32-bit entrypoint in the .compat section where the
bootloader can find it.
Note that we use the setup block embedded in the binary to go through
startup_32(), but it gets reallocated and copied in efi_pe_entry(),
using the same code that runs when the x86 kernel is booted in EFI
mode from native firmware. This requires the loaded image protocol to
be installed on the kernel image's EFI handle, and point to the kernel
image itself and not to its loader. This, in turn, requires the
bootloader to use the LoadImage() boot service to load the 64-bit
image from 32-bit firmware, which is in fact supported by firmware
based on EDK2. (Only StartImage() will fail, and instead, the newly
added entrypoint needs to be invoked)
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/x86/boot/compressed/head_64.S | 60 +++++++++++++++++++-
drivers/firmware/efi/libstub/x86-stub.c | 29 +++++-----
2 files changed, 74 insertions(+), 15 deletions(-)
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index a4f5561c1c0e..47a475146107 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -207,8 +207,11 @@ SYM_FUNC_START(startup_32)
cmp $0, %edi
jz 1f
leal efi64_stub_entry(%ebp), %eax
- movl %esi, %edx
movl efi32_boot_args+4(%ebp), %esi
+ movl efi32_boot_args+8(%ebp), %edx // saved bootparams pointer
+ cmpl $0, %edx
+ jnz 1f
+ leal efi32_pe_enter64(%ebp), %eax
1:
#endif
pushl %eax
@@ -233,6 +236,8 @@ SYM_FUNC_START(efi32_stub_entry)
1: pop %ebp
subl $1b, %ebp
+ movl %esi, efi32_boot_args+8(%ebp)
+SYM_INNER_LABEL(efi32_pe_stub_entry, SYM_L_LOCAL)
movl %ecx, efi32_boot_args(%ebp)
movl %edx, efi32_boot_args+4(%ebp)
movb $0, efi_is64(%ebp)
@@ -641,8 +646,59 @@ SYM_DATA_START_LOCAL(gdt)
SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end)
#ifdef CONFIG_EFI_MIXED
-SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0)
+SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0)
SYM_DATA(efi_is64, .byte 1)
+
+#define ST32_boottime 60 // offsetof(efi_system_table_32_t, boottime)
+#define BS32_handle_protocol 88 // offsetof(efi_boot_services_32_t, handle_protocol)
+#define LI32_image_base 32 // offsetof(efi_loaded_image_32_t, image_base)
+
+ .text
+ .code32
+SYM_FUNC_START(efi32_pe_entry)
+ pushl %ebp
+
+ call 1f
+1: pop %ebp
+ subl $1b, %ebp
+
+ /* Get the loaded image protocol pointer from the image handle */
+ subl $12, %esp // space for the loaded image pointer
+ pushl %esp // pass its address
+ leal 4f(%ebp), %eax
+ pushl %eax // pass the GUID address
+ pushl 28(%esp) // pass the image handle
+
+ movl 36(%esp), %eax // sys_table
+ movl ST32_boottime(%eax), %eax // sys_table->boottime
+ call *BS32_handle_protocol(%eax) // sys_table->boottime->handle_protocol
+ cmp $0, %eax
+ jnz 2f
+
+ movl 32(%esp), %ecx // image_handle
+ movl 36(%esp), %edx // sys_table
+ movl 12(%esp), %esi // loaded_image
+ movl LI32_image_base(%esi), %esi // loaded_image->image_base
+ jmp efi32_pe_stub_entry
+
+2: addl $24, %esp
+ popl %ebp
+ ret
+SYM_FUNC_END(efi32_pe_entry)
+
+ .code64
+SYM_CODE_START_LOCAL(efi32_pe_enter64)
+ movl %edi, %ecx // MS calling convention
+ movl %esi, %edx
+ call efi_pe_entry
+ /* not reached */
+SYM_CODE_END(efi32_pe_enter64)
+
+ .section ".rodata"
+ /* EFI loaded image protocol GUID */
+4: .long 0x5B1B31A1
+ .word 0x9562, 0x11d2
+ .byte 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B
#endif
/*
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index cec6baa14d5c..9db98839d7b4 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -424,21 +424,24 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
hdr->ramdisk_image = 0;
hdr->ramdisk_size = 0;
- status = efi_parse_options(cmdline_ptr);
- if (status != EFI_SUCCESS)
- goto fail2;
-
- if (!noinitrd()) {
- status = efi_load_initrd(image, &ramdisk_addr, &ramdisk_size,
- hdr->initrd_addr_max,
- above4g ? ULONG_MAX
- : hdr->initrd_addr_max);
+ if (efi_is_native()) {
+ status = efi_parse_options(cmdline_ptr);
if (status != EFI_SUCCESS)
goto fail2;
- hdr->ramdisk_image = ramdisk_addr & 0xffffffff;
- hdr->ramdisk_size = ramdisk_size & 0xffffffff;
- boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32;
- boot_params->ext_ramdisk_size = (u64)ramdisk_size >> 32;
+
+ if (!noinitrd()) {
+ status = efi_load_initrd(image, &ramdisk_addr,
+ &ramdisk_size,
+ hdr->initrd_addr_max,
+ above4g ? ULONG_MAX
+ : hdr->initrd_addr_max);
+ if (status != EFI_SUCCESS)
+ goto fail2;
+ hdr->ramdisk_image = ramdisk_addr & 0xffffffff;
+ hdr->ramdisk_size = ramdisk_size & 0xffffffff;
+ boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32;
+ boot_params->ext_ramdisk_size = (u64)ramdisk_size >> 32;
+ }
}
efi_stub_entry(handle, sys_table, boot_params);
--
2.17.1
next prev parent reply other threads:[~2020-02-17 14:48 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-17 14:48 [PATCH v2 0/5] efi/x86: add support for generic EFI mixed mode boot Ard Biesheuvel
2020-02-17 14:48 ` [PATCH v2 1/5] efi/x86: Drop redundant .bss section Ard Biesheuvel
2020-02-21 16:40 ` Arvind Sankar
2020-02-21 16:45 ` Ard Biesheuvel
2020-02-17 14:48 ` [PATCH v2 2/5] efi/libstub/x86: Make loaded_image protocol handling mixed mode safe Ard Biesheuvel
2020-02-17 14:48 ` [PATCH v2 3/5] efi/libstub/x86: Use Exit() boot service to exit the stub on errors Ard Biesheuvel
2020-02-17 14:48 ` Ard Biesheuvel [this message]
2020-02-21 16:39 ` [PATCH v2 4/5] efi/x86: Implement mixed mode boot without the handover protocol Arvind Sankar
2020-02-21 17:12 ` Ard Biesheuvel
2020-02-21 17:59 ` Arvind Sankar
2020-02-21 18:54 ` Ard Biesheuvel
2020-02-17 14:48 ` [PATCH v2 5/5] efi/x86: Add true mixed mode entry point into .compat section Ard Biesheuvel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200217144822.24616-5-ardb@kernel.org \
--to=ardb@kernel.org \
--cc=agraf@csgraf.de \
--cc=daniel.kiper@oracle.com \
--cc=hdegoede@redhat.com \
--cc=leif@nuviainc.com \
--cc=lersek@redhat.com \
--cc=linux-efi@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=mjg59@google.com \
--cc=nivedita@alum.mit.edu \
--cc=pjones@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).