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
This commit is contained in:
manu 2019-10-18 01:38:28 +00:00
parent 1281ec5b00
commit b2a4053feb
6 changed files with 1274 additions and 25 deletions

View File

@ -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 @@ defparam opt_beep.h BEEP_ONHALT_PERIOD=250
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

View File

@ -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 @@ _C_LABEL(Multiboot_Header):
.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 @@ _C_LABEL(Multiboot_Header):
*/
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 @@ begin:
/* 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 */

View File

@ -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 $ */
/*
* Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009, 2017
@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.822 2019/10/18 01:00:24 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.823 2019/10/18 01:38:28 manu Exp $");
#include "opt_beep.h"
#include "opt_compat_freebsd.h"
@ -420,7 +420,8 @@ cpu_startup(void)
initmsgbuf((void *)msgbuf_vaddr, sz);
#ifdef MULTIBOOT
multiboot_print_info();
multiboot1_print_info();
multiboot2_print_info();
#endif
#if NCARDBUS > 0
@ -1063,7 +1064,10 @@ init386_ksyms(void)
#endif
#if defined(MULTIBOOT)
if (multiboot_ksyms_addsyms_elf())
if (multiboot1_ksyms_addsyms_elf())
return;
if (multiboot2_ksyms_addsyms_elf())
return;
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: multiboot.c,v 1.25 2019/10/18 01:19:00 manu Exp $ */
/* $NetBSD: multiboot.c,v 1.26 2019/10/18 01:38:28 manu Exp $ */
/*-
* Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: multiboot.c,v 1.25 2019/10/18 01:19:00 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: multiboot.c,v 1.26 2019/10/18 01:38:28 manu Exp $");
#include "opt_multiboot.h"
@ -84,7 +84,7 @@ extern int * esym;
/*
* Copy of the Multiboot information structure passed to us by the boot
* loader. The Multiboot_Info structure has some pointers adjusted to the
* other variables -- see multiboot_pre_reloc() -- so you oughtn't access
* other variables -- see multiboot1_pre_reloc() -- so you oughtn't access
* them directly. In other words, always access them through the
* Multiboot_Info variable.
*/
@ -129,7 +129,7 @@ static void setup_memmap(struct multiboot_info *);
* can be obtained using the RELOC macro.
*/
void
multiboot_pre_reloc(struct multiboot_info *mi)
multiboot1_pre_reloc(struct multiboot_info *mi)
{
#define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE))
struct multiboot_info *midest =
@ -175,7 +175,7 @@ multiboot_pre_reloc(struct multiboot_info *mi)
* that no devices have been initialized yet (not even the console!).
*/
void
multiboot_post_reloc(void)
multiboot1_post_reloc(void)
{
struct multiboot_info *mi;
@ -202,7 +202,7 @@ multiboot_post_reloc(void)
* the console has to be available.
*/
void
multiboot_print_info(void)
multiboot1_print_info(void)
{
struct multiboot_info *mi = &Multiboot_Info;
struct multiboot_symbols *ms = &Multiboot_Symbols;
@ -269,7 +269,7 @@ bootinfo_add(struct btinfo_common *item, int type, int len)
* that this data is properly copied into upper memory during relocation.
*
* WARNING: This code runs before the kernel has relocated itself. See
* the note in multiboot_pre_reloc() for more information.
* the note in multiboot1_pre_reloc() for more information.
*/
static void
copy_syms(struct multiboot_info *mi)
@ -685,11 +685,14 @@ setup_memory(struct multiboot_info *mi)
* passed in by Multiboot; false otherwise.
*/
bool
multiboot_ksyms_addsyms_elf(void)
multiboot1_ksyms_addsyms_elf(void)
{
struct multiboot_info *mi = &Multiboot_Info;
struct multiboot_symbols *ms = &Multiboot_Symbols;
if (! Multiboot_Loader)
return false;
if (mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS) {
Elf32_Ehdr ehdr;

View File

@ -1,4 +1,4 @@
/* $NetBSD: multiboot.h,v 1.10 2018/11/13 11:01:54 mlelstv Exp $ */
/* $NetBSD: multiboot.h,v 1.11 2019/10/18 01:38:28 manu Exp $ */
/*-
* Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
@ -40,6 +40,12 @@
#define MULTIBOOT_HEADER_HAS_VBE 0x00000004
#define MULTIBOOT_HEADER_HAS_ADDR 0x00010000
#if defined(_LOCORE)
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
#define MULTIBOOT2_ARCHITECTURE_I386 0
#endif
#if !defined(_LOCORE)
struct multiboot_header {
uint32_t mh_magic;
@ -219,13 +225,18 @@ struct multiboot_module {
/* --------------------------------------------------------------------- */
/*
* Prototypes for public functions defined in multiboot.c.
* Prototypes for public functions defined in multiboot.c and multiboot2.c
*/
#if !defined(_LOCORE) && defined(_KERNEL)
void multiboot_pre_reloc(struct multiboot_info *);
void multiboot_post_reloc(void);
void multiboot_print_info(void);
bool multiboot_ksyms_addsyms_elf(void);
void multiboot1_pre_reloc(struct multiboot_info *);
void multiboot1_post_reloc(void);
void multiboot1_print_info(void);
bool multiboot1_ksyms_addsyms_elf(void);
void multiboot2_pre_reloc(struct multiboot_info *);
void multiboot2_post_reloc(void);
void multiboot2_print_info(void);
bool multiboot2_ksyms_addsyms_elf(void);
#endif /* !defined(_LOCORE) */
/* --------------------------------------------------------------------- */

File diff suppressed because it is too large Load Diff