[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <34a1c2bd-53f2-4f4f-9f5a-272f677eb9a3@amd.com>
Date: Wed, 9 Apr 2025 17:24:26 +0530
From: "Aithal, Srikanth" <sraithal@....com>
To: Ard Biesheuvel <ardb@...nel.org>
Cc: linux-kernel@...r.kernel.org, Ingo Molnar <mingo@...nel.org>,
David Woodhouse <dwmw@...zon.co.uk>, "H. Peter Anvin" <hpa@...or.com>,
Kees Cook <keescook@...omium.org>, x86@...nel.org
Subject: Re: [tip: x86/boot] x86/boot: Move the EFI mixed mode startup code
back under arch/x86, into startup/
On 4/7/2025 3:11 PM, Aithal, Srikanth wrote:
> On 4/7/2025 2:00 PM, Ard Biesheuvel wrote:
>> On Mon, 7 Apr 2025 at 10:38, Aithal, Srikanth <sraithal@....com> wrote:
>>>
>>> Hello,
>>>
>>> This commit breaks the build of next-20250407. The kernel config is
>>> attached here.
>>>
>>> Build error:
>>>
>>> arch/x86/boot/startup/efi-mixed.o: warning: objtool:
>>> efi32_stub_entry+0x0: unannotated intra-function call
>>> make[3]: *** [scripts/Makefile.build:335:
>>> arch/x86/boot/startup/efi-mixed.o] Error 255
>>> make[3]: *** Deleting file 'arch/x86/boot/startup/efi-mixed.o'
>>> make[3]: *** Waiting for unfinished jobs....
>>> make[2]: *** [scripts/Makefile.build:461: arch/x86/boot/startup] Error 2
>>> make[2]: *** Waiting for unfinished jobs....
>>> make[1]: *** [/home/VT_BUILD/linux/Makefile:2006: .] Error 2
>>> make: *** [Makefile:248: __sub-make] Error 2
>>>
>>>
>>
>> Apologies for the breakage.
>>
>> Does it help to add the following to arch/x86/boot/startup/Makefile:
>>
>> OBJECT_FILES_NON_STANDARD := y
>>
>> ?
If the above is the solution, could you please let me know how soon it
might be included in the linux-next build?
>
> yes, this fixes the issue.
>
> Reported-by: Srikanth Aithal <sraithal@....com>
> Tested-by: Srikanth Aithal <sraithal@....com>
>
>>
>>>
>>> Thanks,
>>> Srikanth Aithal <sraithal@....com>
>>>
>>>
>>> On 4/7/2025 12:03 AM, tip-bot2 for Ard Biesheuvel wrote:
>>>> The following commit has been merged into the x86/boot branch of tip:
>>>>
>>>> Commit-ID: 4f2d1bbc2c92a32fd612e6c3b51832d5c1c3678e
>>>> Gitweb: https://git.kernel.org/
>>>> tip/4f2d1bbc2c92a32fd612e6c3b51832d5c1c3678e
>>>> Author: Ard Biesheuvel <ardb@...nel.org>
>>>> AuthorDate: Tue, 01 Apr 2025 15:34:20 +02:00
>>>> Committer: Ingo Molnar <mingo@...nel.org>
>>>> CommitterDate: Sun, 06 Apr 2025 20:15:14 +02:00
>>>>
>>>> x86/boot: Move the EFI mixed mode startup code back under arch/x86,
>>>> into startup/
>>>>
>>>> Linus expressed a strong preference for arch-specific asm code (i.e.,
>>>> virtually all of it) to reside under arch/ rather than anywhere else.
>>>>
>>>> So move the EFI mixed mode startup code back, and put it under
>>>> arch/x86/boot/startup/ where all shared x86 startup code is going to
>>>> live.
>>>>
>>>> Suggested-by: Linus Torvalds <torvalds@...ux-foundation.org>
>>>> Signed-off-by: Ard Biesheuvel <ardb@...nel.org>
>>>> Signed-off-by: Ingo Molnar <mingo@...nel.org>
>>>> Cc: David Woodhouse <dwmw@...zon.co.uk>
>>>> Cc: H. Peter Anvin <hpa@...or.com>
>>>> Cc: Kees Cook <keescook@...omium.org>
>>>> Link: https://lore.kernel.org/r/20250401133416.1436741-11-
>>>> ardb+git@...gle.com
>>>> ---
>>>> arch/x86/boot/startup/Makefile | 3 +-
>>>> arch/x86/boot/startup/efi-mixed.S | 253 ++++++++++++++++++
>>>> ++++-
>>>> drivers/firmware/efi/libstub/Makefile | 1 +-
>>>> drivers/firmware/efi/libstub/x86-mixed.S | 253
>>>> +----------------------
>>>> 4 files changed, 256 insertions(+), 254 deletions(-)
>>>> create mode 100644 arch/x86/boot/startup/efi-mixed.S
>>>> delete mode 100644 drivers/firmware/efi/libstub/x86-mixed.S
>>>>
>>>> diff --git a/arch/x86/boot/startup/Makefile b/arch/x86/boot/startup/
>>>> Makefile
>>>> index 03519ef..73946a3 100644
>>>> --- a/arch/x86/boot/startup/Makefile
>>>> +++ b/arch/x86/boot/startup/Makefile
>>>> @@ -1,3 +1,6 @@
>>>> # SPDX-License-Identifier: GPL-2.0
>>>>
>>>> +KBUILD_AFLAGS += -D__DISABLE_EXPORTS
>>>> +
>>>> lib-$(CONFIG_X86_64) += la57toggle.o
>>>> +lib-$(CONFIG_EFI_MIXED) += efi-mixed.o
>>>> diff --git a/arch/x86/boot/startup/efi-mixed.S b/arch/x86/boot/
>>>> startup/efi-mixed.S
>>>> new file mode 100644
>>>> index 0000000..e04ed99
>>>> --- /dev/null
>>>> +++ b/arch/x86/boot/startup/efi-mixed.S
>>>> @@ -0,0 +1,253 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>>> +/*
>>>> + * Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming
>>>> + *
>>>> + * Early support for invoking 32-bit EFI services from a 64-bit
>>>> kernel.
>>>> + *
>>>> + * Because this thunking occurs before ExitBootServices() we have to
>>>> + * restore the firmware's 32-bit GDT and IDT before we make EFI
>>>> service
>>>> + * calls.
>>>> + *
>>>> + * On the plus side, we don't have to worry about mangling 64-bit
>>>> + * addresses into 32-bits because we're executing with an identity
>>>> + * mapped pagetable and haven't transitioned to 64-bit virtual
>>>> addresses
>>>> + * yet.
>>>> + */
>>>> +
>>>> +#include <linux/linkage.h>
>>>> +#include <asm/desc_defs.h>
>>>> +#include <asm/msr.h>
>>>> +#include <asm/page_types.h>
>>>> +#include <asm/pgtable_types.h>
>>>> +#include <asm/processor-flags.h>
>>>> +#include <asm/segment.h>
>>>> +
>>>> + .text
>>>> + .code32
>>>> +#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
>>>> +SYM_FUNC_START(efi32_stub_entry)
>>>> + call 1f
>>>> +1: popl %ecx
>>>> +
>>>> + /* Clear BSS */
>>>> + xorl %eax, %eax
>>>> + leal (_bss - 1b)(%ecx), %edi
>>>> + leal (_ebss - 1b)(%ecx), %ecx
>>>> + subl %edi, %ecx
>>>> + shrl $2, %ecx
>>>> + cld
>>>> + rep stosl
>>>> +
>>>> + add $0x4, %esp /* Discard return address */
>>>> + movl 8(%esp), %ebx /* struct boot_params pointer */
>>>> + jmp efi32_startup
>>>> +SYM_FUNC_END(efi32_stub_entry)
>>>> +#endif
>>>> +
>>>> +/*
>>>> + * Called using a far call from __efi64_thunk() below, using the
>>>> x86_64 SysV
>>>> + * ABI (except for R8/R9 which are inaccessible to 32-bit code -
>>>> EAX/EBX are
>>>> + * used instead). EBP+16 points to the arguments passed via the
>>>> stack.
>>>> + *
>>>> + * The first argument (EDI) is a pointer to the boot service or
>>>> protocol, to
>>>> + * which the remaining arguments are passed, each truncated to 32
>>>> bits.
>>>> + */
>>>> +SYM_FUNC_START_LOCAL(efi_enter32)
>>>> + /*
>>>> + * Convert x86-64 SysV ABI params to i386 ABI
>>>> + */
>>>> + pushl 32(%ebp) /* Up to 3 args passed via the stack */
>>>> + pushl 24(%ebp)
>>>> + pushl 16(%ebp)
>>>> + pushl %ebx /* R9 */
>>>> + pushl %eax /* R8 */
>>>> + pushl %ecx
>>>> + pushl %edx
>>>> + pushl %esi
>>>> +
>>>> + /* Disable paging */
>>>> + movl %cr0, %eax
>>>> + btrl $X86_CR0_PG_BIT, %eax
>>>> + movl %eax, %cr0
>>>> +
>>>> + /* Disable long mode via EFER */
>>>> + movl $MSR_EFER, %ecx
>>>> + rdmsr
>>>> + btrl $_EFER_LME, %eax
>>>> + wrmsr
>>>> +
>>>> + call *%edi
>>>> +
>>>> + /* We must preserve return value */
>>>> + movl %eax, %edi
>>>> +
>>>> + call efi32_enable_long_mode
>>>> +
>>>> + addl $32, %esp
>>>> + movl %edi, %eax
>>>> + lret
>>>> +SYM_FUNC_END(efi_enter32)
>>>> +
>>>> + .code64
>>>> +SYM_FUNC_START(__efi64_thunk)
>>>> + push %rbp
>>>> + movl %esp, %ebp
>>>> + push %rbx
>>>> +
>>>> + /* Move args #5 and #6 into 32-bit accessible registers */
>>>> + movl %r8d, %eax
>>>> + movl %r9d, %ebx
>>>> +
>>>> + lcalll *efi32_call(%rip)
>>>> +
>>>> + pop %rbx
>>>> + pop %rbp
>>>> + RET
>>>> +SYM_FUNC_END(__efi64_thunk)
>>>> +
>>>> + .code32
>>>> +SYM_FUNC_START_LOCAL(efi32_enable_long_mode)
>>>> + movl %cr4, %eax
>>>> + btsl $(X86_CR4_PAE_BIT), %eax
>>>> + movl %eax, %cr4
>>>> +
>>>> + movl $MSR_EFER, %ecx
>>>> + rdmsr
>>>> + btsl $_EFER_LME, %eax
>>>> + wrmsr
>>>> +
>>>> + /* Disable interrupts - the firmware's IDT does not work in
>>>> long mode */
>>>> + cli
>>>> +
>>>> + /* Enable paging */
>>>> + movl %cr0, %eax
>>>> + btsl $X86_CR0_PG_BIT, %eax
>>>> + movl %eax, %cr0
>>>> + ret
>>>> +SYM_FUNC_END(efi32_enable_long_mode)
>>>> +
>>>> +/*
>>>> + * This is the common EFI stub entry point for mixed mode. It sets
>>>> up the GDT
>>>> + * and page tables needed for 64-bit execution, after which it
>>>> calls the
>>>> + * common 64-bit EFI entrypoint efi_stub_entry().
>>>> + *
>>>> + * Arguments: 0(%esp) image handle
>>>> + * 4(%esp) EFI system table pointer
>>>> + * %ebx struct boot_params pointer (or NULL)
>>>> + *
>>>> + * Since this is the point of no return for ordinary execution, no
>>>> registers
>>>> + * are considered live except for the function parameters. [Note
>>>> that the EFI
>>>> + * stub may still exit and return to the firmware using the Exit()
>>>> EFI boot
>>>> + * service.]
>>>> + */
>>>> +SYM_FUNC_START_LOCAL(efi32_startup)
>>>> + movl %esp, %ebp
>>>> +
>>>> + subl $8, %esp
>>>> + sgdtl (%esp) /* Save GDT descriptor to the
>>>> stack */
>>>> + movl 2(%esp), %esi /* Existing GDT pointer */
>>>> + movzwl (%esp), %ecx /* Existing GDT limit */
>>>> + inc %ecx /* Existing GDT size */
>>>> + andl $~7, %ecx /* Ensure size is multiple of
>>>> 8 */
>>>> +
>>>> + subl %ecx, %esp /* Allocate new GDT */
>>>> + andl $~15, %esp /* Realign the stack */
>>>> + movl %esp, %edi /* New GDT address */
>>>> + leal 7(%ecx), %eax /* New GDT limit */
>>>> + pushw %cx /* Push 64-bit CS (for LJMP
>>>> below) */
>>>> + pushl %edi /* Push new GDT address */
>>>> + pushw %ax /* Push new GDT limit */
>>>> +
>>>> + /* Copy GDT to the stack and add a 64-bit code segment at the
>>>> end */
>>>> + movl $GDT_ENTRY(DESC_CODE64, 0, 0xfffff) & 0xffffffff,
>>>> (%edi,%ecx)
>>>> + movl $GDT_ENTRY(DESC_CODE64, 0, 0xfffff) >> 32, 4(%edi,%ecx)
>>>> + shrl $2, %ecx
>>>> + cld
>>>> + rep movsl /* Copy the firmware GDT */
>>>> + lgdtl (%esp) /* Switch to the new GDT */
>>>> +
>>>> + call 1f
>>>> +1: pop %edi
>>>> +
>>>> + /* Record mixed mode entry */
>>>> + movb $0x0, (efi_is64 - 1b)(%edi)
>>>> +
>>>> + /* Set up indirect far call to re-enter 32-bit mode */
>>>> + leal (efi32_call - 1b)(%edi), %eax
>>>> + addl %eax, (%eax)
>>>> + movw %cs, 4(%eax)
>>>> +
>>>> + /* Disable paging */
>>>> + movl %cr0, %eax
>>>> + btrl $X86_CR0_PG_BIT, %eax
>>>> + movl %eax, %cr0
>>>> +
>>>> + /* Set up 1:1 mapping */
>>>> + leal (pte - 1b)(%edi), %eax
>>>> + movl $_PAGE_PRESENT | _PAGE_RW | _PAGE_PSE, %ecx
>>>> + leal (_PAGE_PRESENT | _PAGE_RW)(%eax), %edx
>>>> +2: movl %ecx, (%eax)
>>>> + addl $8, %eax
>>>> + addl $PMD_SIZE, %ecx
>>>> + jnc 2b
>>>> +
>>>> + movl $PAGE_SIZE, %ecx
>>>> + .irpc l, 0123
>>>> + movl %edx, \l * 8(%eax)
>>>> + addl %ecx, %edx
>>>> + .endr
>>>> + addl %ecx, %eax
>>>> + movl %edx, (%eax)
>>>> + movl %eax, %cr3
>>>> +
>>>> + call efi32_enable_long_mode
>>>> +
>>>> + /* Set up far jump to 64-bit mode (CS is already on the stack) */
>>>> + leal (efi_stub_entry - 1b)(%edi), %eax
>>>> + movl %eax, 2(%esp)
>>>> +
>>>> + movl 0(%ebp), %edi
>>>> + movl 4(%ebp), %esi
>>>> + movl %ebx, %edx
>>>> + ljmpl *2(%esp)
>>>> +SYM_FUNC_END(efi32_startup)
>>>> +
>>>> +/*
>>>> + * efi_status_t efi32_pe_entry(efi_handle_t image_handle,
>>>> + * efi_system_table_32_t *sys_table)
>>>> + */
>>>> +SYM_FUNC_START(efi32_pe_entry)
>>>> + pushl %ebx // save callee-save
>>>> registers
>>>> +
>>>> + /* Check whether the CPU supports long mode */
>>>> + movl $0x80000001, %eax // assume extended
>>>> info support
>>>> + cpuid
>>>> + btl $29, %edx // check long mode bit
>>>> + jnc 1f
>>>> + leal 8(%esp), %esp // preserve stack
>>>> alignment
>>>> + xor %ebx, %ebx // no struct
>>>> boot_params pointer
>>>> + jmp efi32_startup // only ESP and EBX
>>>> remain live
>>>> +1: movl $0x80000003, %eax // EFI_UNSUPPORTED
>>>> + popl %ebx
>>>> + RET
>>>> +SYM_FUNC_END(efi32_pe_entry)
>>>> +
>>>> +#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
>>>> + .org efi32_stub_entry + 0x200
>>>> + .code64
>>>> +SYM_FUNC_START_NOALIGN(efi64_stub_entry)
>>>> + jmp efi_handover_entry
>>>> +SYM_FUNC_END(efi64_stub_entry)
>>>> +#endif
>>>> +
>>>> + .data
>>>> + .balign 8
>>>> +SYM_DATA_START_LOCAL(efi32_call)
>>>> + .long efi_enter32 - .
>>>> + .word 0x0
>>>> +SYM_DATA_END(efi32_call)
>>>> +SYM_DATA(efi_is64, .byte 1)
>>>> +
>>>> + .bss
>>>> + .balign PAGE_SIZE
>>>> +SYM_DATA_LOCAL(pte, .fill 6 * PAGE_SIZE, 1, 0)
>>>> diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/
>>>> firmware/efi/libstub/Makefile
>>>> index d23a1b9..2f17339 100644
>>>> --- a/drivers/firmware/efi/libstub/Makefile
>>>> +++ b/drivers/firmware/efi/libstub/Makefile
>>>> @@ -85,7 +85,6 @@ lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o
>>>> string.o intrinsics.o systable.o \
>>>> lib-$(CONFIG_ARM) += arm32-stub.o
>>>> lib-$(CONFIG_ARM64) += kaslr.o arm64.o arm64-stub.o smbios.o
>>>> lib-$(CONFIG_X86) += x86-stub.o smbios.o
>>>> -lib-$(CONFIG_EFI_MIXED) += x86-mixed.o
>>>> lib-$(CONFIG_X86_64) += x86-5lvl.o
>>>> lib-$(CONFIG_RISCV) += kaslr.o riscv.o riscv-stub.o
>>>> lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o
>>>> diff --git a/drivers/firmware/efi/libstub/x86-mixed.S b/drivers/
>>>> firmware/efi/libstub/x86-mixed.S
>>>> deleted file mode 100644
>>>> index e04ed99..0000000
>>>> --- a/drivers/firmware/efi/libstub/x86-mixed.S
>>>> +++ /dev/null
>>>> @@ -1,253 +0,0 @@
>>>> -/* SPDX-License-Identifier: GPL-2.0 */
>>>> -/*
>>>> - * Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming
>>>> - *
>>>> - * Early support for invoking 32-bit EFI services from a 64-bit
>>>> kernel.
>>>> - *
>>>> - * Because this thunking occurs before ExitBootServices() we have to
>>>> - * restore the firmware's 32-bit GDT and IDT before we make EFI
>>>> service
>>>> - * calls.
>>>> - *
>>>> - * On the plus side, we don't have to worry about mangling 64-bit
>>>> - * addresses into 32-bits because we're executing with an identity
>>>> - * mapped pagetable and haven't transitioned to 64-bit virtual
>>>> addresses
>>>> - * yet.
>>>> - */
>>>> -
>>>> -#include <linux/linkage.h>
>>>> -#include <asm/desc_defs.h>
>>>> -#include <asm/msr.h>
>>>> -#include <asm/page_types.h>
>>>> -#include <asm/pgtable_types.h>
>>>> -#include <asm/processor-flags.h>
>>>> -#include <asm/segment.h>
>>>> -
>>>> - .text
>>>> - .code32
>>>> -#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
>>>> -SYM_FUNC_START(efi32_stub_entry)
>>>> - call 1f
>>>> -1: popl %ecx
>>>> -
>>>> - /* Clear BSS */
>>>> - xorl %eax, %eax
>>>> - leal (_bss - 1b)(%ecx), %edi
>>>> - leal (_ebss - 1b)(%ecx), %ecx
>>>> - subl %edi, %ecx
>>>> - shrl $2, %ecx
>>>> - cld
>>>> - rep stosl
>>>> -
>>>> - add $0x4, %esp /* Discard return address */
>>>> - movl 8(%esp), %ebx /* struct boot_params pointer */
>>>> - jmp efi32_startup
>>>> -SYM_FUNC_END(efi32_stub_entry)
>>>> -#endif
>>>> -
>>>> -/*
>>>> - * Called using a far call from __efi64_thunk() below, using the
>>>> x86_64 SysV
>>>> - * ABI (except for R8/R9 which are inaccessible to 32-bit code -
>>>> EAX/EBX are
>>>> - * used instead). EBP+16 points to the arguments passed via the
>>>> stack.
>>>> - *
>>>> - * The first argument (EDI) is a pointer to the boot service or
>>>> protocol, to
>>>> - * which the remaining arguments are passed, each truncated to 32
>>>> bits.
>>>> - */
>>>> -SYM_FUNC_START_LOCAL(efi_enter32)
>>>> - /*
>>>> - * Convert x86-64 SysV ABI params to i386 ABI
>>>> - */
>>>> - pushl 32(%ebp) /* Up to 3 args passed via the stack */
>>>> - pushl 24(%ebp)
>>>> - pushl 16(%ebp)
>>>> - pushl %ebx /* R9 */
>>>> - pushl %eax /* R8 */
>>>> - pushl %ecx
>>>> - pushl %edx
>>>> - pushl %esi
>>>> -
>>>> - /* Disable paging */
>>>> - movl %cr0, %eax
>>>> - btrl $X86_CR0_PG_BIT, %eax
>>>> - movl %eax, %cr0
>>>> -
>>>> - /* Disable long mode via EFER */
>>>> - movl $MSR_EFER, %ecx
>>>> - rdmsr
>>>> - btrl $_EFER_LME, %eax
>>>> - wrmsr
>>>> -
>>>> - call *%edi
>>>> -
>>>> - /* We must preserve return value */
>>>> - movl %eax, %edi
>>>> -
>>>> - call efi32_enable_long_mode
>>>> -
>>>> - addl $32, %esp
>>>> - movl %edi, %eax
>>>> - lret
>>>> -SYM_FUNC_END(efi_enter32)
>>>> -
>>>> - .code64
>>>> -SYM_FUNC_START(__efi64_thunk)
>>>> - push %rbp
>>>> - movl %esp, %ebp
>>>> - push %rbx
>>>> -
>>>> - /* Move args #5 and #6 into 32-bit accessible registers */
>>>> - movl %r8d, %eax
>>>> - movl %r9d, %ebx
>>>> -
>>>> - lcalll *efi32_call(%rip)
>>>> -
>>>> - pop %rbx
>>>> - pop %rbp
>>>> - RET
>>>> -SYM_FUNC_END(__efi64_thunk)
>>>> -
>>>> - .code32
>>>> -SYM_FUNC_START_LOCAL(efi32_enable_long_mode)
>>>> - movl %cr4, %eax
>>>> - btsl $(X86_CR4_PAE_BIT), %eax
>>>> - movl %eax, %cr4
>>>> -
>>>> - movl $MSR_EFER, %ecx
>>>> - rdmsr
>>>> - btsl $_EFER_LME, %eax
>>>> - wrmsr
>>>> -
>>>> - /* Disable interrupts - the firmware's IDT does not work in
>>>> long mode */
>>>> - cli
>>>> -
>>>> - /* Enable paging */
>>>> - movl %cr0, %eax
>>>> - btsl $X86_CR0_PG_BIT, %eax
>>>> - movl %eax, %cr0
>>>> - ret
>>>> -SYM_FUNC_END(efi32_enable_long_mode)
>>>> -
>>>> -/*
>>>> - * This is the common EFI stub entry point for mixed mode. It sets
>>>> up the GDT
>>>> - * and page tables needed for 64-bit execution, after which it
>>>> calls the
>>>> - * common 64-bit EFI entrypoint efi_stub_entry().
>>>> - *
>>>> - * Arguments: 0(%esp) image handle
>>>> - * 4(%esp) EFI system table pointer
>>>> - * %ebx struct boot_params pointer (or NULL)
>>>> - *
>>>> - * Since this is the point of no return for ordinary execution, no
>>>> registers
>>>> - * are considered live except for the function parameters. [Note
>>>> that the EFI
>>>> - * stub may still exit and return to the firmware using the Exit()
>>>> EFI boot
>>>> - * service.]
>>>> - */
>>>> -SYM_FUNC_START_LOCAL(efi32_startup)
>>>> - movl %esp, %ebp
>>>> -
>>>> - subl $8, %esp
>>>> - sgdtl (%esp) /* Save GDT descriptor to the
>>>> stack */
>>>> - movl 2(%esp), %esi /* Existing GDT pointer */
>>>> - movzwl (%esp), %ecx /* Existing GDT limit */
>>>> - inc %ecx /* Existing GDT size */
>>>> - andl $~7, %ecx /* Ensure size is multiple of
>>>> 8 */
>>>> -
>>>> - subl %ecx, %esp /* Allocate new GDT */
>>>> - andl $~15, %esp /* Realign the stack */
>>>> - movl %esp, %edi /* New GDT address */
>>>> - leal 7(%ecx), %eax /* New GDT limit */
>>>> - pushw %cx /* Push 64-bit CS (for LJMP
>>>> below) */
>>>> - pushl %edi /* Push new GDT address */
>>>> - pushw %ax /* Push new GDT limit */
>>>> -
>>>> - /* Copy GDT to the stack and add a 64-bit code segment at the
>>>> end */
>>>> - movl $GDT_ENTRY(DESC_CODE64, 0, 0xfffff) & 0xffffffff,
>>>> (%edi,%ecx)
>>>> - movl $GDT_ENTRY(DESC_CODE64, 0, 0xfffff) >> 32, 4(%edi,%ecx)
>>>> - shrl $2, %ecx
>>>> - cld
>>>> - rep movsl /* Copy the firmware GDT */
>>>> - lgdtl (%esp) /* Switch to the new GDT */
>>>> -
>>>> - call 1f
>>>> -1: pop %edi
>>>> -
>>>> - /* Record mixed mode entry */
>>>> - movb $0x0, (efi_is64 - 1b)(%edi)
>>>> -
>>>> - /* Set up indirect far call to re-enter 32-bit mode */
>>>> - leal (efi32_call - 1b)(%edi), %eax
>>>> - addl %eax, (%eax)
>>>> - movw %cs, 4(%eax)
>>>> -
>>>> - /* Disable paging */
>>>> - movl %cr0, %eax
>>>> - btrl $X86_CR0_PG_BIT, %eax
>>>> - movl %eax, %cr0
>>>> -
>>>> - /* Set up 1:1 mapping */
>>>> - leal (pte - 1b)(%edi), %eax
>>>> - movl $_PAGE_PRESENT | _PAGE_RW | _PAGE_PSE, %ecx
>>>> - leal (_PAGE_PRESENT | _PAGE_RW)(%eax), %edx
>>>> -2: movl %ecx, (%eax)
>>>> - addl $8, %eax
>>>> - addl $PMD_SIZE, %ecx
>>>> - jnc 2b
>>>> -
>>>> - movl $PAGE_SIZE, %ecx
>>>> - .irpc l, 0123
>>>> - movl %edx, \l * 8(%eax)
>>>> - addl %ecx, %edx
>>>> - .endr
>>>> - addl %ecx, %eax
>>>> - movl %edx, (%eax)
>>>> - movl %eax, %cr3
>>>> -
>>>> - call efi32_enable_long_mode
>>>> -
>>>> - /* Set up far jump to 64-bit mode (CS is already on the stack) */
>>>> - leal (efi_stub_entry - 1b)(%edi), %eax
>>>> - movl %eax, 2(%esp)
>>>> -
>>>> - movl 0(%ebp), %edi
>>>> - movl 4(%ebp), %esi
>>>> - movl %ebx, %edx
>>>> - ljmpl *2(%esp)
>>>> -SYM_FUNC_END(efi32_startup)
>>>> -
>>>> -/*
>>>> - * efi_status_t efi32_pe_entry(efi_handle_t image_handle,
>>>> - * efi_system_table_32_t *sys_table)
>>>> - */
>>>> -SYM_FUNC_START(efi32_pe_entry)
>>>> - pushl %ebx // save callee-save
>>>> registers
>>>> -
>>>> - /* Check whether the CPU supports long mode */
>>>> - movl $0x80000001, %eax // assume extended
>>>> info support
>>>> - cpuid
>>>> - btl $29, %edx // check long mode bit
>>>> - jnc 1f
>>>> - leal 8(%esp), %esp // preserve stack
>>>> alignment
>>>> - xor %ebx, %ebx // no struct
>>>> boot_params pointer
>>>> - jmp efi32_startup // only ESP and EBX
>>>> remain live
>>>> -1: movl $0x80000003, %eax // EFI_UNSUPPORTED
>>>> - popl %ebx
>>>> - RET
>>>> -SYM_FUNC_END(efi32_pe_entry)
>>>> -
>>>> -#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
>>>> - .org efi32_stub_entry + 0x200
>>>> - .code64
>>>> -SYM_FUNC_START_NOALIGN(efi64_stub_entry)
>>>> - jmp efi_handover_entry
>>>> -SYM_FUNC_END(efi64_stub_entry)
>>>> -#endif
>>>> -
>>>> - .data
>>>> - .balign 8
>>>> -SYM_DATA_START_LOCAL(efi32_call)
>>>> - .long efi_enter32 - .
>>>> - .word 0x0
>>>> -SYM_DATA_END(efi32_call)
>>>> -SYM_DATA(efi_is64, .byte 1)
>>>> -
>>>> - .bss
>>>> - .balign PAGE_SIZE
>>>> -SYM_DATA_LOCAL(pte, .fill 6 * PAGE_SIZE, 1, 0)
>
Powered by blists - more mailing lists