Linux-EFI Archive on lore.kernel.org
 help / color / Atom feed
From: Arvind Sankar <nivedita@alum.mit.edu>
To: Ard Biesheuvel <ardb@kernel.org>
Cc: linux-efi@vger.kernel.org, linux-arm-kernel@lists.infradead.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,
	mbrown@fensystems.co.uk, mingo@kernel.org
Subject: Re: [RFC PATCH 3/3] efi/x86: implement mixed mode boot without the handover protocol
Date: Thu, 13 Feb 2020 12:23:55 -0500
Message-ID: <20200213172355.GB1400002@rani.riverdale.lan> (raw)
In-Reply-To: <20200213145928.7047-4-ardb@kernel.org>

On Thu, Feb 13, 2020 at 03:59:28PM +0100, Ard Biesheuvel wrote:
> 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, allocate the setup block etc etc, all of
> which can be done by the stub using code we have already implemented.
> 
> 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 services 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 | 61 +++++++++++++++++++-
>  1 file changed, 59 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
> index a4f5561c1c0e..7baaf9c97f5a 100644
> --- a/arch/x86/boot/compressed/head_64.S
> +++ b/arch/x86/boot/compressed/head_64.S
> @@ -207,8 +207,8 @@ 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
>  1:
>  #endif
>  	pushl	%eax
> @@ -233,6 +233,8 @@ SYM_FUNC_START(efi32_stub_entry)
>  1:	pop	%ebp
>  	subl	$1b, %ebp
>  
> +	movl	%esi, efi32_boot_args+8(%ebp)
> +2:

I think it would be easier to read if this were turned into a proper
SYM_INNER_LABEL. You could then also just put efi32_pe_entry into the
.text section instead of moving it to the end of .head.text with
.subsection. Another option is to use a separate flag in .data to
indicate that we entered via efi32_pe_entry, then you could just jump
to efi32_stub_entry.

>  	movl	%ecx, efi32_boot_args(%ebp)
>  	movl	%edx, efi32_boot_args+4(%ebp)
>  	movb	$0, efi_is64(%ebp)
> @@ -249,6 +251,49 @@ SYM_FUNC_START(efi32_stub_entry)
>  
>  	jmp	startup_32
>  SYM_FUNC_END(efi32_stub_entry)
> +
> +#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)
> +
> +	.subsection 1
> +	.code32
> +SYM_FUNC_START(efi32_pe_entry)
> +	pushl	%ebp
> +
> +	call	3f
> +3:	pop	%ebp
> +	subl	$3b, %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	5f(%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	4f
> +
> +	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	2b
> +
> +4:	addl	$24, %esp
> +	popl	%ebp
> +	ret
> +SYM_FUNC_END(efi32_pe_entry)
> +
> +	/* EFI loaded image protocol GUID */
> +5:	.long	0x5B1B31A1
> +	.word	0x9562, 0x11d2
> +	.byte	0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B
> +	.previous

Any reason for this not to live in .data (or .rodata)?
>  #endif
>  
>  	.code64
> @@ -465,11 +510,23 @@ SYM_CODE_END(startup_64)
>  SYM_FUNC_START(efi64_stub_entry)
>  SYM_FUNC_START_ALIAS(efi_stub_entry)
>  	and	$~0xf, %rsp			/* realign the stack */
> +#ifdef CONFIG_EFI_MIXED
> +	cmpl	$0, %edx
> +	jz	0f
> +#endif
>  	call	efi_main
>  	movq	%rax,%rsi
>  	movl	BP_code32_start(%esi), %eax
>  	leaq	startup_64(%rax), %rax
>  	jmp	*%rax
> +
> +#ifdef CONFIG_EFI_MIXED
> +0:	movl	%edi, %ecx		// MS calling convention
> +	movl	%esi, %edx
> +	call	efi_pe_entry
> +1:	hlt
> +	jmp	1b
> +#endif
>  SYM_FUNC_END(efi64_stub_entry)
>  SYM_FUNC_END_ALIAS(efi_stub_entry)
>  #endif
> @@ -641,7 +698,7 @@ 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)
>  #endif
>  
> -- 
> 2.17.1
> 

  reply index

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-13 14:59 [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot Ard Biesheuvel
2020-02-13 14:59 ` [RFC PATCH 1/3] efi/x86: drop redundant .bss section Ard Biesheuvel
2020-02-13 14:59 ` [RFC PATCH 2/3] efi/x86: add true mixed mode entry point into .compat section Ard Biesheuvel
2020-02-13 16:59   ` Arvind Sankar
2020-02-13 17:13     ` Ard Biesheuvel
2020-02-13 14:59 ` [RFC PATCH 3/3] efi/x86: implement mixed mode boot without the handover protocol Ard Biesheuvel
2020-02-13 17:23   ` Arvind Sankar [this message]
2020-02-13 17:42     ` Ard Biesheuvel
2020-02-13 17:53 ` [RFC PATCH 0/3] efi/x86: add support for generic EFI mixed mode boot Arvind Sankar
2020-02-13 17:55   ` Ard Biesheuvel
2020-02-13 18:47     ` Arvind Sankar
2020-02-13 22:36       ` Ard Biesheuvel
2020-02-14  0:10         ` Arvind Sankar
2020-02-14  0:12           ` Arvind Sankar
2020-02-14  0:21             ` Ard Biesheuvel
2020-02-14  0:38               ` Arvind Sankar

Reply instructions:

You may reply publically 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=20200213172355.GB1400002@rani.riverdale.lan \
    --to=nivedita@alum.mit.edu \
    --cc=agraf@csgraf.de \
    --cc=ardb@kernel.org \
    --cc=daniel.kiper@oracle.com \
    --cc=hdegoede@redhat.com \
    --cc=leif@nuviainc.com \
    --cc=lersek@redhat.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-efi@vger.kernel.org \
    --cc=mbrown@fensystems.co.uk \
    --cc=mingo@kernel.org \
    --cc=mjg59@google.com \
    --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

Linux-EFI Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-efi/0 linux-efi/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-efi linux-efi/ https://lore.kernel.org/linux-efi \
		linux-efi@vger.kernel.org
	public-inbox-index linux-efi

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-efi


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git