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:
Frediano Ziglio authored and Andrew Cooper committed 2024-10-03 14:40:55 +01:00
1 parent 444cb9350f
commit eb21ce14d7
6 files changed
+119 -124

No files matched your search

+30 -114
View File
@@ -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
+1
View File
@@ -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
+4 -3
View File
@@ -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;
+63
View File
@@ -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;
}
+3 -7
View File
@@ -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";
+18
View File
@@ -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 */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.