mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
x86/boot: Rewrite EFI/MBI2 code partly in C
No need to have it coded in assembly. Declare efi_multiboot2 in a new header to reuse between implementations and caller. Signed-off-by: Frediano Ziglio <frediano.ziglio@cloud.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Daniel P. Smith <dpsmith@apertussolutions.com> Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
This commit is contained in:
1 parent
444cb9350f
commit
eb21ce14d7
6 files changed
+119
-124
No files matched your search
+30
-114
@@ -130,8 +130,6 @@ multiboot2_header:
|
||||
.Lbad_cpu_msg: .asciz "ERR: Not a 64-bit CPU!"
|
||||
.Lbad_ldr_msg: .asciz "ERR: Not a Multiboot bootloader!"
|
||||
.Lbad_ldr_nbs: .asciz "ERR: Bootloader shutdown EFI x64 boot services!"
|
||||
.Lbad_ldr_nst: .asciz "ERR: EFI SystemTable is not provided by bootloader!"
|
||||
.Lbad_ldr_nih: .asciz "ERR: EFI ImageHandle is not provided by bootloader!"
|
||||
.Lbad_efi_msg: .asciz "ERR: EFI IA-32 platforms are not supported!"
|
||||
.Lbag_alg_msg: .asciz "ERR: Xen must be loaded at a 2Mb boundary!"
|
||||
.Lno_nx_msg: .asciz "ERR: Not an NX-capable CPU!"
|
||||
@@ -170,17 +168,6 @@ early_error: /* Here to improve the disassembly. */
|
||||
mov $sym_offs(.Lno_nx_msg), %ecx
|
||||
jmp .Lget_vtb
|
||||
#endif
|
||||
.Lmb2_no_st:
|
||||
/*
|
||||
* Here we are on EFI platform. vga_text_buffer was zapped earlier
|
||||
* because there is pretty good chance that VGA is unavailable.
|
||||
*/
|
||||
mov $sym_offs(.Lbad_ldr_nst), %ecx
|
||||
jmp .Lget_vtb
|
||||
.Lmb2_no_ih:
|
||||
/* Ditto. */
|
||||
mov $sym_offs(.Lbad_ldr_nih), %ecx
|
||||
jmp .Lget_vtb
|
||||
.Lmb2_no_bs:
|
||||
/*
|
||||
* Ditto. Additionally, here there is a chance that Xen was started
|
||||
@@ -198,6 +185,10 @@ early_error: /* Here to improve the disassembly. */
|
||||
mov $sym_offs(.Lbad_efi_msg), %ecx
|
||||
xor %edi,%edi # No VGA text buffer
|
||||
jmp .Lprint_err
|
||||
.Ldirect_error:
|
||||
mov sym_esi(vga_text_buffer), %edi
|
||||
mov %eax, %esi
|
||||
jmp 1f
|
||||
.Lget_vtb:
|
||||
mov sym_esi(vga_text_buffer), %edi
|
||||
.Lprint_err:
|
||||
@@ -244,53 +235,49 @@ __efi64_mb2_start:
|
||||
|
||||
/*
|
||||
* Align the stack as UEFI spec requires. Keep it aligned
|
||||
* before efi_multiboot2() call by pushing/popping even
|
||||
* before efi_multiboot2_prelude() call by pushing/popping even
|
||||
* numbers of items on it.
|
||||
*/
|
||||
and $~15, %rsp
|
||||
|
||||
/* Save magic number, we need it later but we need to use %eax. */
|
||||
mov %eax, %edx
|
||||
|
||||
/*
|
||||
* Initialize BSS (no nasty surprises!).
|
||||
* It must be done earlier than in BIOS case
|
||||
* because efi_multiboot2() touches it.
|
||||
* because efi_multiboot2_prelude() touches it.
|
||||
*/
|
||||
mov %eax, %edx
|
||||
lea __bss_start(%rip), %edi
|
||||
lea __bss_end(%rip), %ecx
|
||||
sub %edi, %ecx
|
||||
shr $3, %ecx
|
||||
xor %eax, %eax
|
||||
rep stosq
|
||||
mov %edx, %eax
|
||||
|
||||
/* Check for Multiboot2 bootloader. */
|
||||
cmp $MULTIBOOT2_BOOTLOADER_MAGIC,%eax
|
||||
je .Lefi_multiboot2_proto
|
||||
/*
|
||||
* Spill MB2 magic.
|
||||
* Spill the pointer too, to keep the stack aligned.
|
||||
*/
|
||||
push %rdx
|
||||
push %rbx
|
||||
|
||||
/* Jump to .Lnot_multiboot after switching CPU to x86_32 mode. */
|
||||
lea .Lnot_multiboot(%rip), %r15
|
||||
jmp x86_32_switch
|
||||
/*
|
||||
* efi_multiboot2_prelude() is called according to System V AMD64 ABI:
|
||||
* - IN: %edi - Multiboot2 magic,
|
||||
* %rsi - Multiboot2 pointer.
|
||||
* - OUT: %rax - error string.
|
||||
*/
|
||||
mov %edx, %edi
|
||||
mov %rbx, %rsi
|
||||
call efi_multiboot2_prelude
|
||||
lea .Ldirect_error(%rip), %r15
|
||||
test %rax, %rax
|
||||
jnz x86_32_switch
|
||||
|
||||
.Lefi_multiboot2_proto:
|
||||
/* Zero EFI SystemTable, EFI ImageHandle addresses and cmdline. */
|
||||
xor %esi,%esi
|
||||
xor %edi,%edi
|
||||
xor %edx,%edx
|
||||
|
||||
/* Skip Multiboot2 information fixed part. */
|
||||
lea (MB2_fixed_sizeof+MULTIBOOT2_TAG_ALIGN-1)(%rbx),%ecx
|
||||
and $~(MULTIBOOT2_TAG_ALIGN-1),%ecx
|
||||
|
||||
.Lefi_mb2_tsize:
|
||||
/* Check Multiboot2 information total size. */
|
||||
mov %ecx,%r8d
|
||||
sub %ebx,%r8d
|
||||
cmp %r8d,MB2_fixed_total_size(%rbx)
|
||||
jbe .Lrun_bs
|
||||
|
||||
/* Are EFI boot services available? */
|
||||
cmpl $MULTIBOOT2_TAG_TYPE_EFI_BS,MB2_tag_type(%rcx)
|
||||
jne .Lefi_mb2_st
|
||||
/* Restore Multiboot2 pointer and magic. */
|
||||
pop %rbx
|
||||
pop %rax
|
||||
|
||||
/* We are on EFI platform and EFI boot services are available. */
|
||||
incb efi_platform(%rip)
|
||||
@@ -300,77 +287,6 @@ __efi64_mb2_start:
|
||||
* be run on EFI platforms.
|
||||
*/
|
||||
incb skip_realmode(%rip)
|
||||
jmp .Lefi_mb2_next_tag
|
||||
|
||||
.Lefi_mb2_st:
|
||||
/* Get EFI SystemTable address from Multiboot2 information. */
|
||||
cmpl $MULTIBOOT2_TAG_TYPE_EFI64,MB2_tag_type(%rcx)
|
||||
cmove MB2_efi64_st(%rcx),%rsi
|
||||
je .Lefi_mb2_next_tag
|
||||
|
||||
/* Get EFI ImageHandle address from Multiboot2 information. */
|
||||
cmpl $MULTIBOOT2_TAG_TYPE_EFI64_IH,MB2_tag_type(%rcx)
|
||||
cmove MB2_efi64_ih(%rcx),%rdi
|
||||
je .Lefi_mb2_next_tag
|
||||
|
||||
/* Get command line from Multiboot2 information. */
|
||||
cmpl $MULTIBOOT2_TAG_TYPE_CMDLINE, MB2_tag_type(%rcx)
|
||||
jne .Lno_cmdline
|
||||
lea MB2_tag_string(%rcx), %rdx
|
||||
jmp .Lefi_mb2_next_tag
|
||||
.Lno_cmdline:
|
||||
|
||||
/* Is it the end of Multiboot2 information? */
|
||||
cmpl $MULTIBOOT2_TAG_TYPE_END,MB2_tag_type(%rcx)
|
||||
je .Lrun_bs
|
||||
|
||||
.Lefi_mb2_next_tag:
|
||||
/* Go to next Multiboot2 information tag. */
|
||||
add MB2_tag_size(%rcx),%ecx
|
||||
add $(MULTIBOOT2_TAG_ALIGN-1),%ecx
|
||||
and $~(MULTIBOOT2_TAG_ALIGN-1),%ecx
|
||||
jmp .Lefi_mb2_tsize
|
||||
|
||||
.Lrun_bs:
|
||||
/* Are EFI boot services available? */
|
||||
cmpb $0,efi_platform(%rip)
|
||||
|
||||
/* Jump to .Lmb2_no_bs after switching CPU to x86_32 mode. */
|
||||
lea .Lmb2_no_bs(%rip),%r15
|
||||
jz x86_32_switch
|
||||
|
||||
/* Is EFI SystemTable address provided by boot loader? */
|
||||
test %rsi,%rsi
|
||||
|
||||
/* Jump to .Lmb2_no_st after switching CPU to x86_32 mode. */
|
||||
lea .Lmb2_no_st(%rip),%r15
|
||||
jz x86_32_switch
|
||||
|
||||
/* Is EFI ImageHandle address provided by boot loader? */
|
||||
test %rdi,%rdi
|
||||
|
||||
/* Jump to .Lmb2_no_ih after switching CPU to x86_32 mode. */
|
||||
lea .Lmb2_no_ih(%rip),%r15
|
||||
jz x86_32_switch
|
||||
|
||||
/* Save Multiboot2 magic on the stack. */
|
||||
push %rax
|
||||
|
||||
/* Save EFI ImageHandle on the stack. */
|
||||
push %rdi
|
||||
|
||||
/*
|
||||
* efi_multiboot2() is called according to System V AMD64 ABI:
|
||||
* - IN: %rdi - EFI ImageHandle, %rsi - EFI SystemTable,
|
||||
* %rdx - MB2 cmdline
|
||||
*/
|
||||
call efi_multiboot2
|
||||
|
||||
/* Just pop an item from the stack. */
|
||||
pop %rax
|
||||
|
||||
/* Restore Multiboot2 magic. */
|
||||
pop %rax
|
||||
|
||||
/* Jump to trampoline_setup after switching CPU to x86_32 mode. */
|
||||
lea trampoline_setup(%rip),%r15
|
||||
|
||||
@@ -14,5 +14,6 @@ $(addprefix $(obj)/,$(EFIOBJ-y)): CFLAGS_stack_boundary := $(cflags-stack-bounda
|
||||
obj-y := common-stub.o stub.o
|
||||
obj-$(XEN_BUILD_EFI) := $(filter-out %.init.o,$(EFIOBJ-y))
|
||||
obj-bin-$(XEN_BUILD_EFI) := $(filter %.init.o,$(EFIOBJ-y))
|
||||
obj-bin-y += mbi2.o
|
||||
extra-$(XEN_BUILD_EFI) += buildid.o relocs-dummy.o
|
||||
nocov-$(XEN_BUILD_EFI) += stub.o
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <asm/msr.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/trampoline.h>
|
||||
#include <asm/efi.h>
|
||||
|
||||
static struct file __initdata ucode;
|
||||
static multiboot_info_t __initdata mbi = {
|
||||
@@ -816,9 +817,9 @@ static const char *__init get_option(const char *cmd, const char *opt)
|
||||
return o;
|
||||
}
|
||||
|
||||
void asmlinkage __init efi_multiboot2(EFI_HANDLE ImageHandle,
|
||||
EFI_SYSTEM_TABLE *SystemTable,
|
||||
const char *cmdline)
|
||||
void __init efi_multiboot2(EFI_HANDLE ImageHandle,
|
||||
EFI_SYSTEM_TABLE *SystemTable,
|
||||
const char *cmdline)
|
||||
{
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
|
||||
EFI_HANDLE gop_handle;
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <xen/efi.h>
|
||||
#include <xen/init.h>
|
||||
#include <xen/multiboot2.h>
|
||||
#include <asm/asm_defns.h>
|
||||
#include <asm/efi.h>
|
||||
|
||||
const char * asmlinkage __init
|
||||
efi_multiboot2_prelude(uint32_t magic, const multiboot2_fixed_t *mbi)
|
||||
{
|
||||
const multiboot2_tag_t *tag;
|
||||
EFI_HANDLE ImageHandle = NULL;
|
||||
EFI_SYSTEM_TABLE *SystemTable = NULL;
|
||||
const char *cmdline = NULL;
|
||||
bool have_bs = false;
|
||||
|
||||
if ( magic != MULTIBOOT2_BOOTLOADER_MAGIC )
|
||||
return "ERR: Not a Multiboot2 bootloader!";
|
||||
|
||||
/* Skip Multiboot2 information fixed part. */
|
||||
tag = _p(ROUNDUP((unsigned long)(mbi + 1), MULTIBOOT2_TAG_ALIGN));
|
||||
|
||||
for ( ; (const void *)tag - (const void *)mbi < mbi->total_size &&
|
||||
tag->type != MULTIBOOT2_TAG_TYPE_END;
|
||||
tag = _p(ROUNDUP((unsigned long)tag + tag->size,
|
||||
MULTIBOOT2_TAG_ALIGN)) )
|
||||
{
|
||||
switch ( tag->type )
|
||||
{
|
||||
case MULTIBOOT2_TAG_TYPE_EFI_BS:
|
||||
have_bs = true;
|
||||
break;
|
||||
|
||||
case MULTIBOOT2_TAG_TYPE_EFI64:
|
||||
SystemTable = _p(((const multiboot2_tag_efi64_t *)tag)->pointer);
|
||||
break;
|
||||
|
||||
case MULTIBOOT2_TAG_TYPE_EFI64_IH:
|
||||
ImageHandle = _p(((const multiboot2_tag_efi64_ih_t *)tag)->pointer);
|
||||
break;
|
||||
|
||||
case MULTIBOOT2_TAG_TYPE_CMDLINE:
|
||||
cmdline = ((const multiboot2_tag_string_t *)tag)->string;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Satisfy MISRA requirement. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !have_bs )
|
||||
return "ERR: Bootloader shutdown EFI x64 boot services!";
|
||||
if ( !SystemTable )
|
||||
return "ERR: EFI SystemTable is not provided by bootloader!";
|
||||
if ( !ImageHandle )
|
||||
return "ERR: EFI ImageHandle is not provided by bootloader!";
|
||||
|
||||
efi_multiboot2(ImageHandle, SystemTable, cmdline);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,13 +1,8 @@
|
||||
#include <xen/efi.h>
|
||||
#include <xen/init.h>
|
||||
#include <asm/asm_defns.h>
|
||||
#include <asm/efibind.h>
|
||||
#include <asm/efi.h>
|
||||
#include <asm/page.h>
|
||||
#include <efi/efidef.h>
|
||||
#include <efi/eficapsule.h>
|
||||
#include <efi/eficon.h>
|
||||
#include <efi/efidevp.h>
|
||||
#include <efi/efiapi.h>
|
||||
|
||||
/*
|
||||
* Here we are in EFI stub. EFI calls are not supported due to lack
|
||||
@@ -17,7 +12,8 @@
|
||||
*/
|
||||
|
||||
void __init noreturn efi_multiboot2(EFI_HANDLE ImageHandle,
|
||||
EFI_SYSTEM_TABLE *SystemTable)
|
||||
EFI_SYSTEM_TABLE *SystemTable,
|
||||
const char *cmdline)
|
||||
{
|
||||
static const CHAR16 __initconst err[] =
|
||||
L"Xen does not have EFI code build in!\r\nSystem halted!\r\n";
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef X86_ASM_EFI_H
|
||||
#define X86_ASM_EFI_H
|
||||
|
||||
#include <xen/types.h>
|
||||
#include <asm/x86_64/efibind.h>
|
||||
#include <efi/efidef.h>
|
||||
#include <efi/eficapsule.h>
|
||||
#include <efi/eficon.h>
|
||||
#include <efi/efidevp.h>
|
||||
#include <efi/efiapi.h>
|
||||
|
||||
void efi_multiboot2(EFI_HANDLE ImageHandle,
|
||||
EFI_SYSTEM_TABLE *SystemTable,
|
||||
const char *cmdline);
|
||||
|
||||
#endif /* X86_ASM_EFI_H */
|
||||