No need to have it coded in assembly.
Signed-off-by: Frediano Ziglio <frediano.ziglio@cloud.com>
---
Changes since v1:
- update some comments;
- explain why %ebx is saved before calling efi_parse_mbi2;
- move lea before test instruction;
- removed asmlinkage from efi_multiboot2 and add to efi_parse_mbi2;
- fix line length;
- update an error message specifying "Multiboot2" instead of "Multiboot";
- use obj-bin-X instead of obj-X in Makefile;
- avoid restoring %eax (MBI magic).
Changes since v3:
- rename new function to efi_multiboot2_prelude;
- declare efi_multiboot2 in a separate header.
Changes since v4:
- fix some style and space;
- fix MISRA requirement.
---
xen/arch/x86/boot/head.S | 142 +++++++--------------------------
xen/arch/x86/efi/Makefile | 1 +
xen/arch/x86/efi/efi-boot.h | 6 +-
xen/arch/x86/efi/parse-mbi2.c | 63 +++++++++++++++
xen/arch/x86/efi/stub.c | 3 +-
xen/arch/x86/include/asm/efi.h | 18 +++++
6 files changed, 115 insertions(+), 118 deletions(-)
create mode 100644 xen/arch/x86/efi/parse-mbi2.c
create mode 100644 xen/arch/x86/include/asm/efi.h
diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S
index e0901ee400..89b5e2af88 100644
--- a/xen/arch/x86/boot/head.S
+++ b/xen/arch/x86/boot/head.S
@@ -121,8 +121,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!"
@@ -161,17 +159,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
@@ -189,6 +176,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:
@@ -235,7 +226,7 @@ __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
@@ -243,7 +234,7 @@ __efi64_mb2_start:
/*
* 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
@@ -252,36 +243,30 @@ __efi64_mb2_start:
shr $3, %ecx
xor %eax, %eax
rep stosq
- mov %edx, %eax
-
- /* Check for Multiboot2 bootloader. */
- cmp $MULTIBOOT2_BOOTLOADER_MAGIC,%eax
- je .Lefi_multiboot2_proto
-
- /* Jump to .Lnot_multiboot after switching CPU to x86_32 mode. */
- lea .Lnot_multiboot(%rip), %r15
- jmp 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
+ /*
+ * Spill MB2 magic.
+ * Spill the pointer too, to keep the stack aligned.
+ */
+ push %rdx
+ push %rbx
- /* Are EFI boot services available? */
- cmpl $MULTIBOOT2_TAG_TYPE_EFI_BS,MB2_tag_type(%rcx)
- jne .Lefi_mb2_st
+ /*
+ * 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
+
+ /* Restore Multiboot2 pointer and magic. */
+ pop %rbx
+ pop %rax
/* We are on EFI platform and EFI boot services are available. */
incb efi_platform(%rip)
@@ -291,77 +276,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
diff --git a/xen/arch/x86/efi/Makefile b/xen/arch/x86/efi/Makefile
index 24dfecfad1..51140061fc 100644
--- a/xen/arch/x86/efi/Makefile
+++ b/xen/arch/x86/efi/Makefile
@@ -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 += parse-mbi2.o
extra-$(XEN_BUILD_EFI) += buildid.o relocs-dummy.o
nocov-$(XEN_BUILD_EFI) += stub.o
diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h
index 7aa55e7aaf..859c01c13f 100644
--- a/xen/arch/x86/efi/efi-boot.h
+++ b/xen/arch/x86/efi/efi-boot.h
@@ -816,9 +816,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;
diff --git a/xen/arch/x86/efi/parse-mbi2.c b/xen/arch/x86/efi/parse-mbi2.c
new file mode 100644
index 0000000000..55a1777483
--- /dev/null
+++ b/xen/arch/x86/efi/parse-mbi2.c
@@ -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;
+}
diff --git a/xen/arch/x86/efi/stub.c b/xen/arch/x86/efi/stub.c
index 2cd5c8d4dc..27d40964d5 100644
--- a/xen/arch/x86/efi/stub.c
+++ b/xen/arch/x86/efi/stub.c
@@ -17,7 +17,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";
diff --git a/xen/arch/x86/include/asm/efi.h b/xen/arch/x86/include/asm/efi.h
new file mode 100644
index 0000000000..575a33e302
--- /dev/null
+++ b/xen/arch/x86/include/asm/efi.h
@@ -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 */
--
2.34.1
On 26.09.2024 11:21, Frediano Ziglio wrote: > @@ -243,7 +234,7 @@ __efi64_mb2_start: > /* > * 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 I think this MOV wants to gain a comment, now that ... > lea __bss_start(%rip), %edi > @@ -252,36 +243,30 @@ __efi64_mb2_start: > shr $3, %ecx > xor %eax, %eax > rep stosq > - mov %edx, %eax ... this one's going away. > --- a/xen/arch/x86/efi/stub.c > +++ b/xen/arch/x86/efi/stub.c > @@ -17,7 +17,8 @@ > */ > > void __init noreturn efi_multiboot2(EFI_HANDLE ImageHandle, > - EFI_SYSTEM_TABLE *SystemTable) > + EFI_SYSTEM_TABLE *SystemTable, > + const char *cmdline) While with ... > --- /dev/null > +++ b/xen/arch/x86/include/asm/efi.h > @@ -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); ... the declaration now (supposedly) in scope the need for that earlier adjustment may be a little more obvious, you still ought to mention it in the description. If you did, you'd might have noticed that stub.c now also needs to include the new asm/efi.h, for the declaration to actually have its full intended effect. Jan
On Mon, Sep 30, 2024 at 4:51 PM Jan Beulich <jbeulich@suse.com> wrote: > > On 26.09.2024 11:21, Frediano Ziglio wrote: > > @@ -243,7 +234,7 @@ __efi64_mb2_start: > > /* > > * 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 > > I think this MOV wants to gain a comment, now that ... > > > lea __bss_start(%rip), %edi > > @@ -252,36 +243,30 @@ __efi64_mb2_start: > > shr $3, %ecx > > xor %eax, %eax > > rep stosq > > - mov %edx, %eax > > ... this one's going away. > What about diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index 89b5e2af88..6fa6ea93e5 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -231,12 +231,14 @@ __efi64_mb2_start: */ and $~15, %rsp + /* Move away 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_prelude() touches it. */ - mov %eax, %edx lea __bss_start(%rip), %edi lea __bss_end(%rip), %ecx sub %edi, %ecx ?? > > --- a/xen/arch/x86/efi/stub.c > > +++ b/xen/arch/x86/efi/stub.c > > @@ -17,7 +17,8 @@ > > */ > > > > void __init noreturn efi_multiboot2(EFI_HANDLE ImageHandle, > > - EFI_SYSTEM_TABLE *SystemTable) > > + EFI_SYSTEM_TABLE *SystemTable, > > + const char *cmdline) > > While with ... > > > --- /dev/null > > +++ b/xen/arch/x86/include/asm/efi.h > > @@ -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); > > ... the declaration now (supposedly) in scope the need for that earlier > adjustment may be a little more obvious, you still ought to mention it > in the description. If you did, you'd might have noticed that stub.c now > also needs to include the new asm/efi.h, for the declaration to actually > have its full intended effect. > > Jan Done, both stub and normal code. Frediano
On 01.10.2024 10:35, Frediano Ziglio wrote: > On Mon, Sep 30, 2024 at 4:51 PM Jan Beulich <jbeulich@suse.com> wrote: >> On 26.09.2024 11:21, Frediano Ziglio wrote: >>> @@ -243,7 +234,7 @@ __efi64_mb2_start: >>> /* >>> * 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 >> >> I think this MOV wants to gain a comment, now that ... >> >>> lea __bss_start(%rip), %edi >>> @@ -252,36 +243,30 @@ __efi64_mb2_start: >>> shr $3, %ecx >>> xor %eax, %eax >>> rep stosq >>> - mov %edx, %eax >> >> ... this one's going away. >> > > What about > > diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S > index 89b5e2af88..6fa6ea93e5 100644 > --- a/xen/arch/x86/boot/head.S > +++ b/xen/arch/x86/boot/head.S > @@ -231,12 +231,14 @@ __efi64_mb2_start: > */ > and $~15, %rsp > > + /* Move away 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_prelude() touches it. > */ > - mov %eax, %edx > lea __bss_start(%rip), %edi > lea __bss_end(%rip), %ecx > sub %edi, %ecx > > ?? Fine with me. Maybe s/Move away/Save"? Jan
On Tue, Oct 1, 2024 at 9:52 AM Jan Beulich <jbeulich@suse.com> wrote: > > On 01.10.2024 10:35, Frediano Ziglio wrote: > > On Mon, Sep 30, 2024 at 4:51 PM Jan Beulich <jbeulich@suse.com> wrote: > >> On 26.09.2024 11:21, Frediano Ziglio wrote: > >>> @@ -243,7 +234,7 @@ __efi64_mb2_start: > >>> /* > >>> * 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 > >> > >> I think this MOV wants to gain a comment, now that ... > >> > >>> lea __bss_start(%rip), %edi > >>> @@ -252,36 +243,30 @@ __efi64_mb2_start: > >>> shr $3, %ecx > >>> xor %eax, %eax > >>> rep stosq > >>> - mov %edx, %eax > >> > >> ... this one's going away. > >> > > > > What about > > > > diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S > > index 89b5e2af88..6fa6ea93e5 100644 > > --- a/xen/arch/x86/boot/head.S > > +++ b/xen/arch/x86/boot/head.S > > @@ -231,12 +231,14 @@ __efi64_mb2_start: > > */ > > and $~15, %rsp > > > > + /* Move away 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_prelude() touches it. > > */ > > - mov %eax, %edx > > lea __bss_start(%rip), %edi > > lea __bss_end(%rip), %ecx > > sub %edi, %ecx > > > > ?? > > Fine with me. Maybe s/Move away/Save"? > > Jan Done. One last though. Do you think I should now rename xen/arch/x86/efi/parse-mbi2.c file ? Frediano
On 01.10.2024 11:48, Frediano Ziglio wrote: > One last though. Do you think I should now rename > xen/arch/x86/efi/parse-mbi2.c file ? I wouldn't mind if it was named just mbi2.c, but the ultimate decision is with the EFI maintainers. Jan
© 2016 - 2024 Red Hat, Inc.