Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch Multiboot2 kernel support for i386



details:   https://anonhg.NetBSD.org/src/rev/9ac54acdf02b
branches:  trunk
changeset: 966204:9ac54acdf02b
user:      manu <manu%NetBSD.org@localhost>
date:      Fri Oct 18 01:38:28 2019 +0000

description:
Multiboot2 kernel support for i386

That implementation works either with BIOS or UEFI bootstrap

This requires the following kernel changes:

Add UEFI boot services and I/O method protoypes
src/sys/arch/x86/include/efi.h 1.8 - 1.9

Fix EFI system table mapping in virtual space
src/sys/arch/x86/x86/efi.c 1.19 - 1.20

Make sure no bioscall is issued when booting off UEFI system
src/sys/arch/i386/i386/machdep.c 1.821 - 1.822
src/sys/arch/i386/pci/piixpcib.c 1.22 - 1.23

And the following bootstrap changes:

Add kernel symbols for multiboot1
src/sys/arch/i386/stand/lib/exec_multiboot1.c 1.2 - 1.3
src/sys/arch/i386/stand/lib/libi386.h 1.45 - 1.47

Fix kernel symbols for multiboot2
src/sys/arch/i386/stand/lib/exec_multiboot2.c 1.2 - 1.3

diffstat:

 sys/arch/i386/conf/files.i386     |     3 +-
 sys/arch/i386/i386/locore.S       |   233 ++++++++-
 sys/arch/i386/i386/machdep.c      |    12 +-
 sys/arch/i386/i386/multiboot.c    |    19 +-
 sys/arch/i386/include/multiboot.h |    23 +-
 sys/arch/x86/x86/multiboot2.c     |  1009 +++++++++++++++++++++++++++++++++++++
 6 files changed, 1274 insertions(+), 25 deletions(-)

diffs (truncated from 1471 to 300 lines):

diff -r 40050110bb6b -r 9ac54acdf02b sys/arch/i386/conf/files.i386
--- a/sys/arch/i386/conf/files.i386     Fri Oct 18 01:24:51 2019 +0000
+++ b/sys/arch/i386/conf/files.i386     Fri Oct 18 01:38:28 2019 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.i386,v 1.400 2019/02/15 08:54:01 nonaka Exp $
+#      $NetBSD: files.i386,v 1.401 2019/10/18 01:38:28 manu Exp $
 #
 # new style config file for i386 architecture
 #
@@ -51,6 +51,7 @@
 defflag        opt_multiboot.h         MULTIBOOT
 obsolete       defparam                MULTIBOOT_SYMTAB_SPACE
 file   arch/i386/i386/multiboot.c      multiboot
+file   arch/x86/x86/multiboot2.c       multiboot
 
 file   arch/i386/i386/autoconf.c
 file   arch/i386/i386/aout_machdep.c   exec_aout
diff -r 40050110bb6b -r 9ac54acdf02b sys/arch/i386/i386/locore.S
--- a/sys/arch/i386/i386/locore.S       Fri Oct 18 01:24:51 2019 +0000
+++ b/sys/arch/i386/i386/locore.S       Fri Oct 18 01:38:28 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: locore.S,v 1.172 2019/10/12 06:31:03 maxv Exp $        */
+/*     $NetBSD: locore.S,v 1.173 2019/10/18 01:38:28 manu Exp $        */
 
 /*
  * Copyright-o-rama!
@@ -128,7 +128,7 @@
  */
 
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.172 2019/10/12 06:31:03 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.173 2019/10/18 01:38:28 manu Exp $");
 
 #include "opt_copy_symtab.h"
 #include "opt_ddb.h"
@@ -346,12 +346,52 @@
        .long   MULTIBOOT_HEADER_FLAGS
        .long   -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
 
+       .align  8
+       .globl  Multiboot2_Header
+_C_LABEL(Multiboot2_Header):
+       .long   MULTIBOOT2_HEADER_MAGIC
+       .long   MULTIBOOT2_ARCHITECTURE_I386
+       .long   Multiboot2_Header_end - Multiboot2_Header
+       .long   -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT2_ARCHITECTURE_I386 \
+               + (Multiboot2_Header_end - Multiboot2_Header))
+
+       .long   1       /* MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST */
+       .long   12      /* sizeof(multiboot_header_tag_information_request) */
+                       /* + sizeof(uint32_t) * requests */
+       .long   4       /* MULTIBOOT_TAG_TYPE_BASIC_MEMINFO */
+       .long   0       /* pad for 8 bytes alignment */
+
+       .long   8       /* MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 */
+       .long   12      /* sizeof(struct multiboot_tag_efi32) */
+       .long   efi_multiboot2_loader - KERNBASE
+       .long   0       /* pad for 8 bytes alignment */
+
+#if notyet 
+       /* 
+        * Could be used to get an early console for debug,
+        * but this is broken.
+        */
+       .long   7       /* MULTIBOOT_HEADER_TAG_EFI_BS */
+       .long   8       /* sizeof(struct multiboot_tag) */
+#endif
+
+       .long   0       /* MULTIBOOT_HEADER_TAG_END */
+       .long   8       /* sizeof(struct multiboot_tag) */
+       .globl  Multiboot2_Header_end
+_C_LABEL(Multiboot2_Header_end):
+
 1:
        /* Check if we are being executed by a Multiboot-compliant boot
         * loader. */
        cmpl    $MULTIBOOT_INFO_MAGIC,%eax
-       jne     1f
+       je      multiboot1_loader
 
+       cmpl    $MULTIBOOT2_BOOTLOADER_MAGIC,%eax
+       je      multiboot2_loader
+
+       jmp     1f
+
+multiboot1_loader:
        /*
         * Indeed, a multiboot-compliant boot loader executed us. We switch
         * to the temporary stack, and copy the received Multiboot information
@@ -361,10 +401,187 @@
         */
        movl    $_RELOC(tmpstk),%esp
        pushl   %ebx            /* Address of Multiboot information */
-       call    _C_LABEL(multiboot_pre_reloc)
+       call    _C_LABEL(multiboot1_pre_reloc)
        addl    $4,%esp
        jmp     2f
+
+efi_multiboot2_loader:
+       /*
+        * EFI32 multiboot2 entry point. We are left here without
+        * stack and with no idea of where we were loaded in memory.
+        * The only inputs are 
+        * %eax MULTIBOOT2_BOOTLOADER_MAGIC
+        * %ebx pointer to multiboot_info
+        *
+        * Here we will copy the kernel to 0x100000 (KERNTEXTOFF - KERNBASE)
+        * as almost all the code in locore.S assume it is there. Once done, 
+        * we join the main start code .This is derived from
+        * src/sys/arch/i386/stand/efiboot/bootia32/startprog32.S
+        */
+
+       cli
+
+       /*
+        * Discover our load address and store it in %edx
+        */
+       movl    $_RELOC(tmpstk),%esp
+       call    next
+next:  popl    %edx
+       subl    $(next - efi_multiboot2_loader), %edx
+
+       /*
+        * Save multiboot_info for later. We cannot use
+        * temporary stack for that since we are going to
+        * overwrite it.
+        */
+       movl    %ebx, (multiboot2_info_ptr - efi_multiboot2_loader)(%edx)
+ 
+       /*
+        * Get relocated multiboot2_loader entry point in %ebx
+        */
+       movl    $(KERNTEXTOFF - KERNBASE), %ebx
+       addl    $(multiboot2_loader - start), %ebx
+
+        /* Copy kernel */
+        movl    $(KERNTEXTOFF - KERNBASE), %edi                /* dest */ 
+        movl    %edx, %esi
+       subl    $(efi_multiboot2_loader - start), %esi  /* src */
+       movl    $(__kernel_end - kernel_text), %ecx     /* size */
+#if defined(NO_OVERLAP)
+        movl    %ecx, %eax
+#else 
+        movl    %edi, %eax
+        subl    %esi, %eax
+        cmpl    %ecx, %eax      /* overlapping? */
+        movl    %ecx, %eax
+        jb      .Lbackwards
 #endif
+        /* nope, copy forwards. */
+        shrl    $2, %ecx        /* copy by words */
+        rep
+        movsl
+        and     $3, %eax        /* any bytes left? */
+        jnz     .Ltrailing
+        jmp     .Lcopy_done
+
+.Ltrailing:
+        cmp     $2, %eax
+        jb      11f
+        movw    (%esi), %ax
+        movw    %ax, (%edi)
+        je      .Lcopy_done
+        movb    2(%esi), %al
+        movb    %al, 2(%edi)
+        jmp     .Lcopy_done
+11:     movb    (%esi), %al
+        movb    %al, (%edi)
+        jmp     .Lcopy_done
+
+#if !defined(NO_OVERLAP)
+.Lbackwards:
+        addl    %ecx, %edi      /* copy backwards. */
+        addl    %ecx, %esi
+        and     $3, %eax        /* any fractional bytes? */
+        jnz     .Lback_align
+.Lback_aligned:
+        shrl    $2, %ecx
+        subl    $4, %esi
+        subl    $4, %edi
+        std
+        rep
+        movsl
+        cld
+        jmp     .Lcopy_done
+
+.Lback_align:
+        sub     %eax, %esi
+        sub     %eax, %edi
+        cmp     $2, %eax
+        jb      11f
+        je      12f
+        movb    2(%esi), %al
+        movb    %al, 2(%edi)
+12:     movw    (%esi), %ax
+        movw    %ax, (%edi)
+        jmp     .Lback_aligned
+11:     movb    (%esi), %al
+        movb    %al, (%edi)
+        jmp     .Lback_aligned
+#endif
+        /* End of copy kernel */
+.Lcopy_done:
+       cld                     /* LynxOS depends on it */
+
+       /* Prepare jump address */
+       lea     (efi_multiboot2_loader32a - efi_multiboot2_loader)(%edx), %eax
+       movl    %eax, (efi_multiboot2_loader32r - efi_multiboot2_loader)(%edx)
+
+       /* Setup GDT */
+       lea     (gdt - efi_multiboot2_loader)(%edx), %eax
+       movl    %eax, (gdtrr - efi_multiboot2_loader)(%edx)
+       lgdt    (gdtr - efi_multiboot2_loader)(%edx)
+
+       /* Jump to set %cs */
+       ljmp    *(efi_multiboot2_loader32r - efi_multiboot2_loader)(%edx)
+
+       .align  4
+efi_multiboot2_loader32a:
+       movl    $0x10, %eax     /* #define DATA_SEGMENT 0x10 */
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %fs
+       movw    %ax, %gs
+       movw    %ax, %ss
+
+       /* Already set new stack pointer */
+       movl    %esp, %ebp
+
+       /* Disable Paging in CR0 */
+       movl    %cr0, %eax
+       andl    $(~CR0_PG), %eax
+       movl    %eax, %cr0
+
+       /* Disable PAE in CR4 */
+       movl    %cr4, %eax
+       andl    $(~CR4_PAE), %eax
+       movl    %eax, %cr4
+
+       jmp     efi_multiboot2_loader32b
+
+       .align  4
+efi_multiboot2_loader32b:
+       xor     %eax, %eax
+       movl    %ebx, (efi_multiboot2_loader32r - efi_multiboot2_loader)(%edx)
+       /*
+        * Reload multiboot info from target location
+        */
+       movl    _RELOC(multiboot2_info_ptr), %ebx
+       ljmp    *(efi_multiboot2_loader32r - efi_multiboot2_loader)(%edx)
+
+       .align  16
+efi_multiboot2_loader32r:
+       .long   0
+       .long   0x08    /* #define      CODE_SEGMENT    0x08 */
+       .align  16
+gdt:
+       .long   0, 0
+       .byte   0xff, 0xff, 0x00, 0x00, 0x00, 0x9f, 0xcf, 0x00
+       .byte   0xff, 0xff, 0x00, 0x00, 0x00, 0x93, 0xcf, 0x00
+gdtr:
+       .word   gdtr - gdt
+gdtrr:
+       .quad   0
+multiboot2_info_ptr:
+       .long   0
+
+       .align 16
+multiboot2_loader:
+       movl    $_RELOC(tmpstk),%esp
+       pushl   %ebx            /* Address of Multiboot information */
+       call    _C_LABEL(multiboot2_pre_reloc)
+       addl    $4,%esp
+       jmp     2f
+#endif /* MULTIBOOT */
 
 1:
        /*
@@ -834,8 +1051,12 @@
        /* It is now safe to parse the Multiboot information structure
         * we saved before from C code.  Note that we cannot delay its
         * parsing any more because initgdt (called below) needs to make
-        * use of this information. */
-       call    _C_LABEL(multiboot_post_reloc)
+        * use of this information.
+        * We call both multiboot 1 and 2 flavors, they now if they 
+        * have something to do on their own.
+        */
+       call    _C_LABEL(multiboot1_post_reloc)
+       call    _C_LABEL(multiboot2_post_reloc)
 #endif
 
        subl    $NGDT*8, %esp           /* space for temporary gdt */
diff -r 40050110bb6b -r 9ac54acdf02b sys/arch/i386/i386/machdep.c
--- a/sys/arch/i386/i386/machdep.c      Fri Oct 18 01:24:51 2019 +0000
+++ b/sys/arch/i386/i386/machdep.c      Fri Oct 18 01:38:28 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: machdep.c,v 1.822 2019/10/18 01:00:24 manu Exp $       */
+/*     $NetBSD: machdep.c,v 1.823 2019/10/18 01:38:28 manu Exp $       */
 



Home | Main Index | Thread Index | Old Index