Module Name:    src
Committed By:   manu
Date:           Fri Oct 18 01:38:28 UTC 2019

Modified Files:
        src/sys/arch/i386/conf: files.i386
        src/sys/arch/i386/i386: locore.S machdep.c multiboot.c
        src/sys/arch/i386/include: multiboot.h
Added Files:
        src/sys/arch/x86/x86: multiboot2.c

Log Message:
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


To generate a diff of this commit:
cvs rdiff -u -r1.400 -r1.401 src/sys/arch/i386/conf/files.i386
cvs rdiff -u -r1.172 -r1.173 src/sys/arch/i386/i386/locore.S
cvs rdiff -u -r1.822 -r1.823 src/sys/arch/i386/i386/machdep.c
cvs rdiff -u -r1.25 -r1.26 src/sys/arch/i386/i386/multiboot.c
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/i386/include/multiboot.h
cvs rdiff -u -r0 -r1.1 src/sys/arch/x86/x86/multiboot2.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/i386/conf/files.i386
diff -u src/sys/arch/i386/conf/files.i386:1.400 src/sys/arch/i386/conf/files.i386:1.401
--- src/sys/arch/i386/conf/files.i386:1.400	Fri Feb 15 08:54:01 2019
+++ src/sys/arch/i386/conf/files.i386	Fri Oct 18 01:38:28 2019
@@ -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
 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

Index: src/sys/arch/i386/i386/locore.S
diff -u src/sys/arch/i386/i386/locore.S:1.172 src/sys/arch/i386/i386/locore.S:1.173
--- src/sys/arch/i386/i386/locore.S:1.172	Sat Oct 12 06:31:03 2019
+++ src/sys/arch/i386/i386/locore.S	Fri Oct 18 01:38:28 2019
@@ -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 */

Index: src/sys/arch/i386/i386/machdep.c
diff -u src/sys/arch/i386/i386/machdep.c:1.822 src/sys/arch/i386/i386/machdep.c:1.823
--- src/sys/arch/i386/i386/machdep.c:1.822	Fri Oct 18 01:00:24 2019
+++ src/sys/arch/i386/i386/machdep.c	Fri Oct 18 01:38:28 2019
@@ -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
 

Index: src/sys/arch/i386/i386/multiboot.c
diff -u src/sys/arch/i386/i386/multiboot.c:1.25 src/sys/arch/i386/i386/multiboot.c:1.26
--- src/sys/arch/i386/i386/multiboot.c:1.25	Fri Oct 18 01:19:00 2019
+++ src/sys/arch/i386/i386/multiboot.c	Fri Oct 18 01:38:28 2019
@@ -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 multiboo
  *        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_inf
  * 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,
  * 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;
 

Index: src/sys/arch/i386/include/multiboot.h
diff -u src/sys/arch/i386/include/multiboot.h:1.10 src/sys/arch/i386/include/multiboot.h:1.11
--- src/sys/arch/i386/include/multiboot.h:1.10	Tue Nov 13 11:01:54 2018
+++ src/sys/arch/i386/include/multiboot.h	Fri Oct 18 01:38:28 2019
@@ -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) */
 
 /* --------------------------------------------------------------------- */

Added files:

Index: src/sys/arch/x86/x86/multiboot2.c
diff -u /dev/null src/sys/arch/x86/x86/multiboot2.c:1.1
--- /dev/null	Fri Oct 18 01:38:28 2019
+++ src/sys/arch/x86/x86/multiboot2.c	Fri Oct 18 01:38:28 2019
@@ -0,0 +1,1009 @@
+/*	$NetBSD: multiboot2.c,v 1.1 2019/10/18 01:38:28 manu Exp $	*/
+
+/*-
+ * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Julio M. Merino Vidal.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: multiboot2.c,v 1.1 2019/10/18 01:38:28 manu Exp $");
+
+#include "opt_multiboot.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/cdefs_elf.h>
+#include <sys/boot_flag.h>
+#include <sys/exec.h>
+#include <sys/exec_elf.h>
+#include <sys/optstr.h>
+#include <sys/ksyms.h>
+#include <sys/common_ansi.h>
+#include <sys/intr.h>
+
+#include <x86/efi.h>
+
+#include <machine/bootinfo.h>
+#include <machine/multiboot2.h>
+
+#if !defined(MULTIBOOT)
+#  error "MULTIBOOT not defined; this cannot happen."
+#endif
+
+/*
+ * This is an attempt to get an early debug output. It
+ * requires EFI Boot Services, and it does not work anyway:
+ * it causes EFI to try to handle interrupts while the kernel
+ * already took that over, hence we get a reboot.
+ */
+#define BS_PRINT(efisystbl, wstring) 					\
+	efi_systbl->st_coutif->ei_outputstring(efi_systbl->st_coutif,	\
+	    (efi_char *)__UNCONST(wstring))
+
+struct multiboot_symbols {
+	void *	s_symstart;
+	size_t	s_symsize;
+	void *	s_strstart;
+	size_t	s_strsize;
+};	
+
+/*
+ * Because of clashes between multiboot.h and multiboot2.h we
+ * cannot include both, and we need to redefine here:
+ */
+void            multiboot2_pre_reloc(char *);
+void            multiboot2_post_reloc(void);
+void            multiboot2_print_info(void);
+bool            multiboot2_ksyms_addsyms_elf(void); 
+
+extern int              biosbasemem;
+extern int              biosextmem;
+extern int              biosmem_implicit;
+extern int              boothowto;
+extern struct bootinfo  bootinfo;
+extern int              end;
+extern int *            esym;
+
+/* 
+ * There is no way to perform dynamic allocation
+ * at this time, hence we need to waste memory, 
+ * with the hope data will fit.
+ */
+static char multiboot_info[16384] = "\0\0\0\0";
+static bool multiboot2_enabled = false;
+static bool has_syms = false;
+static struct multiboot_symbols Multiboot_Symbols;
+
+
+#define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE))
+
+static void
+efi_exit_bs(struct efi_systbl *efi_systbl, void *efi_ih)
+{
+	struct efi_bs *efi_bs;
+	struct efi_md *desc;
+	uintn bufsize, key, size;
+	uint32_t vers;
+
+	if (efi_systbl == NULL)
+		panic("EFI system table is NULL");
+
+	if (efi_systbl->st_hdr.th_sig != EFI_SYSTBL_SIG)
+		panic("EFI system table signature is wrong");
+
+	efi_bs = efi_systbl->st_bs;
+
+	if (efi_bs == NULL)
+		panic("EFI BS is NULL");
+
+	if (efi_bs->bs_hdr.th_sig != EFI_BS_SIG)
+		panic("EFI BS signature is wrong");
+
+	if (efi_ih == NULL)
+		panic("EFI IH is NULL");
+
+	bufsize = 16384;
+
+	if (efi_bs->bs_allocatepool(EFI_MD_TYPE_DATA,
+	    bufsize, (void **)&desc) != 0)
+		panic("EFI AllocatePool failed");
+
+	if (efi_bs->bs_getmemorymap(&bufsize, desc, &key, &size, &vers) == 0)
+		goto exit_bs;
+
+	(void)efi_bs->bs_freepool((void *)desc);
+
+	if (efi_bs->bs_allocatepool(EFI_MD_TYPE_DATA,
+	    bufsize, (void **)&desc) != 0)
+		panic("EFI AllocatePool failed");
+
+	if (efi_bs->bs_getmemorymap(&bufsize, desc, &key, &size, &vers) != 0)
+		panic("EFI GetMemoryMap failed");
+
+exit_bs:
+	if (efi_bs->bs_exitbootservices(efi_ih, key) != 0)
+		panic("EFI ExitBootServices failed");
+
+	return;
+}
+
+static void
+copy_syms(struct multiboot_tag_elf_sections *mbt_elf)
+{
+	int i;
+	struct multiboot_symbols *ms;
+	Elf32_Shdr *symtabp, *strtabp;
+	Elf32_Word symsize, strsize;
+	Elf32_Addr symaddr, straddr;
+	Elf32_Addr symstart, strstart;
+
+	ms = RELOC(struct multiboot_symbols *, &Multiboot_Symbols);
+
+	/*
+	 * Locate a symbol table and its matching string table in the
+	 * section headers passed in by the boot loader.  Set 'symtabp'
+	 * and 'strtabp' with pointers to the matching entries.
+	 */
+	symtabp = strtabp = NULL;
+	for (i = 0; i < mbt_elf->num && symtabp == NULL &&
+	    strtabp == NULL; i++) {
+		Elf32_Shdr *shdrp;
+
+		shdrp = &((Elf32_Shdr *)mbt_elf->sections)[i];
+
+		if ((shdrp->sh_type == SHT_SYMTAB) &&
+		    shdrp->sh_link != SHN_UNDEF) {
+			Elf32_Shdr *shdrp2;
+
+			shdrp2 = &((Elf32_Shdr *)mbt_elf->sections)
+			    [shdrp->sh_link];
+
+			if (shdrp2->sh_type == SHT_STRTAB) {
+				symtabp = shdrp;
+				strtabp = shdrp2;
+			}
+		}
+	}
+	if (symtabp == NULL || strtabp == NULL)
+		return;
+
+	symaddr = symtabp->sh_addr;
+	straddr = strtabp->sh_addr;
+	symsize = symtabp->sh_size;
+	strsize = strtabp->sh_size;
+
+	/*
+	 * Copy the symbol and string tables just after the kernel's
+	 * end address, in this order.  Only the contents of these ELF
+	 * sections are copied; headers are discarded.  esym is later
+	 * updated to point to the lowest "free" address after the tables
+	 * so that they are mapped appropriately when enabling paging.
+	 *
+	 * We need to be careful to not overwrite valid data doing the
+	 * copies, hence all the different cases below.  We can assume
+	 * that if the tables start before the kernel's end address,
+	 * they will not grow over this address.
+	 */
+        if ((void *)symtabp < RELOC(void *, &end) &&
+	    (void *)strtabp < RELOC(void *, &end)) {
+		symstart = RELOC(Elf32_Addr, &end);
+		strstart = symstart + symsize;
+		memcpy((void *)symstart, (void *)symaddr, symsize);
+		memcpy((void *)strstart, (void *)straddr, strsize);
+        } else if ((void *)symtabp > RELOC(void *, &end) &&
+	           (void *)strtabp < RELOC(void *, &end)) {
+		symstart = RELOC(Elf32_Addr, &end);
+		strstart = symstart + symsize;
+		memcpy((void *)symstart, (void *)symaddr, symsize);
+		memcpy((void *)strstart, (void *)straddr, strsize);
+        } else if ((void *)symtabp < RELOC(void *, &end) &&
+	           (void *)strtabp > RELOC(void *, &end)) {
+		strstart = RELOC(Elf32_Addr, &end);
+		symstart = strstart + strsize;
+		memcpy((void *)strstart, (void *)straddr, strsize);
+		memcpy((void *)symstart, (void *)symaddr, symsize);
+	} else {
+		/* symtabp and strtabp are both over end */
+		if (symtabp < strtabp) {
+			symstart = RELOC(Elf32_Addr, &end);
+			strstart = symstart + symsize;
+			memcpy((void *)symstart, (void *)symaddr, symsize);
+			memcpy((void *)strstart, (void *)straddr, strsize);
+		} else {
+			strstart = RELOC(Elf32_Addr, &end);
+			symstart = strstart + strsize;
+			memcpy((void *)strstart, (void *)straddr, strsize);
+			memcpy((void *)symstart, (void *)symaddr, symsize);
+		}
+	}
+
+	*RELOC(bool *, &has_syms) = true;
+	*RELOC(int *, &esym) =
+	    (int)(symstart + symsize + strsize + KERNBASE);
+
+	ms->s_symstart = (void *)(symstart + KERNBASE);
+	ms->s_symsize  = symsize;
+	ms->s_strstart = (void *)(strstart + KERNBASE);
+	ms->s_strsize  = strsize;
+}
+
+void
+multiboot2_pre_reloc(char *mbi)
+{
+	uint32_t mbi_size;
+	void *mbidest = RELOC(void *, multiboot_info);
+	char *cp;
+	struct multiboot_tag_module *mbt;
+	struct multiboot_tag_elf_sections *mbt_elf = NULL;
+	struct efi_systbl *efi_systbl = NULL;
+	void *efi_ih = NULL;
+	bool has_bs = false;
+
+	mbi_size = *(uint32_t *)mbi;
+	if (mbi_size < sizeof(multiboot_info))
+		memcpy(mbidest, mbi, mbi_size);
+	else
+		panic("multiboot_info too big"); /* will not show up */
+
+	*RELOC(bool *, &multiboot2_enabled) = true;
+
+	for (cp = mbi + (2 * sizeof(uint32_t));
+	     cp - mbi < mbi_size;
+	     cp += roundup(mbt->size, MULTIBOOT_INFO_ALIGN)) {
+		mbt = (struct multiboot_tag_module *)cp;
+		switch (mbt->type) {
+		case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
+			mbt_elf = (struct multiboot_tag_elf_sections *)mbt;
+			break;
+#ifdef __LP64__
+		case MULTIBOOT_TAG_TYPE_EFI64:
+			efi_systbl = (struct efi_systbl *)
+				((struct multiboot_tag_efi64 *)mbt)->pointer;
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI64_IH:
+			efi_ih = (void *)
+			    ((struct multiboot_tag_efi64_ih *)mbt)->pointer;
+			break;
+#else
+		case MULTIBOOT_TAG_TYPE_EFI32:
+			efi_systbl = (struct efi_systbl *)
+				((struct multiboot_tag_efi32 *)mbt)->pointer;
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI32_IH:
+			efi_ih = (void *)
+			    ((struct multiboot_tag_efi32_ih *)mbt)->pointer;
+			break;
+#endif
+		case MULTIBOOT_TAG_TYPE_EFI_BS:
+#if notyet
+			has_bs = true;
+#endif
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* Broken */
+	if (has_bs)
+		efi_exit_bs(efi_systbl, efi_ih);	
+
+	if (mbt_elf)
+		copy_syms(mbt_elf);
+
+	return;
+}
+
+static void
+bootinfo_add(struct btinfo_common *item, int type, int len)    
+{
+	int i;  
+	struct bootinfo *bip = (struct bootinfo *)&bootinfo;
+	vaddr_t data;
+
+	item->type = type;
+	item->len = len;
+
+	data = (vaddr_t)&bip->bi_data;
+	for (i = 0; i < bip->bi_nentries; i++) {
+		struct btinfo_common *tmp;
+
+		tmp = (struct btinfo_common *)data;
+		data += tmp->len;
+	}
+	if (data + len < (vaddr_t)&bip->bi_data + sizeof(bip->bi_data)) {
+		memcpy((void *)data, item, len);
+		bip->bi_nentries++;
+	}
+}
+
+static void
+mbi_cmdline(struct multiboot_tag_string *mbt)
+{
+	char *cmdline = mbt->string;
+	struct btinfo_console bic;
+	struct btinfo_rootdevice bir;
+	char *cl;
+
+	if (optstr_get(cmdline, "console", bic.devname, sizeof(bic.devname))) {
+                if (strncmp(bic.devname, "com", sizeof(bic.devname)) == 0) {
+                        char opt[10];
+                
+                        if (optstr_get(cmdline, "console_speed",
+                        	       opt, sizeof(opt))) 
+                                bic.speed = strtoul(opt, NULL, 10);
+                        else
+                                bic.speed = 0; /* Use default speed. */
+
+                        if (optstr_get(cmdline, "console_addr",
+                        	       opt, sizeof(opt))) {
+                                if (opt[0] == '0' && opt[1] == 'x')
+                                        bic.addr = strtoul(opt + 2, NULL, 16);
+                                else
+                                        bic.addr = strtoul(opt, NULL, 10);
+                        } else {
+                                bic.addr = 0; /* Use default address. */
+			}
+
+                        bootinfo_add((struct btinfo_common *)&bic,
+                        	     BTINFO_CONSOLE, sizeof(bic));
+
+                }
+
+		if (strncmp(bic.devname, "pc", sizeof(bic.devname)) == 0)
+                        bootinfo_add((struct btinfo_common *)&bic,
+                        	     BTINFO_CONSOLE, sizeof(bic));
+        }
+
+	if (optstr_get(cmdline, "root", bir.devname, sizeof(bir.devname)))
+                bootinfo_add((struct btinfo_common *)&bir, BTINFO_ROOTDEVICE,
+                    sizeof(bir));
+
+	/*
+	 * Parse boot flags (-s and friends)
+	 */
+	cl = cmdline;
+
+	/* Skip kernel file name. */
+	while (*cl != '\0' && *cl != ' ')
+		cl++;
+	while (*cl == ' ')
+		cl++;
+
+	/* Check if there are flags and set 'howto' accordingly. */
+	if (*cl == '-') {
+		int howto = 0;
+
+		cl++;
+		while (*cl != '\0' && *cl != ' ') {
+			BOOT_FLAG(*cl, howto);
+			cl++;
+		}
+		if (*cl == ' ')
+			cl++;
+
+		boothowto = howto;
+	}
+
+	return;
+}
+
+static void
+mbi_modules(char *mbi, uint32_t mbi_size, int module_count)
+{
+	char *cp;
+	struct multiboot_tag_module *mbt;
+	size_t bim_len;
+	struct bi_modulelist_entry *bie;
+	struct btinfo_modulelist *bim;
+	char bimbuf[16384];
+
+	bim_len = sizeof(*bim) + (module_count * sizeof(*bie));
+	if (bim_len > sizeof(bimbuf))
+		return;
+
+	bim = (struct btinfo_modulelist *)bimbuf;
+
+	bim->num = module_count;
+	bim->endpa = end;
+
+	bie = (struct bi_modulelist_entry *)(bim + 1);
+
+	for (cp = mbi + (2 * sizeof(uint32_t));
+	     cp - mbi < mbi_size;
+	     cp += roundup(mbt->size, MULTIBOOT_INFO_ALIGN)) {
+		mbt = (struct multiboot_tag_module *)cp;
+		if (mbt->type != MULTIBOOT_TAG_TYPE_MODULE)
+			continue;
+
+		strncpy(bie->path, mbt->cmdline, sizeof(bie->path));
+		bie->type = BI_MODULE_ELF;
+		bie->len = mbt->mod_end - mbt->mod_start;
+		bie->base = mbt->mod_start;
+
+		bie++;
+	}
+
+	bootinfo_add((struct btinfo_common *)&bim,
+           BTINFO_MODULELIST, bim_len);
+
+	return;
+}
+
+static void
+mbi_basic_meminfo(struct multiboot_tag_basic_meminfo *mbt)
+{
+        /* Make sure we don't override user-set variables. */
+        if (biosbasemem == 0) {
+                biosbasemem = mbt->mem_lower;
+                biosmem_implicit = 1;
+        }
+        if (biosextmem == 0) {
+                biosextmem = mbt->mem_upper;
+                biosmem_implicit = 1;
+        }
+
+	return;
+}
+
+static void
+mbi_bootdev(struct multiboot_tag_bootdev *mbt)
+{
+	struct btinfo_bootdisk bid;
+
+	bid.labelsector = -1;
+	bid.biosdev = mbt->biosdev;
+	bid.partition = mbt->slice;
+	
+	bootinfo_add((struct btinfo_common *)&bid,
+           BTINFO_BOOTDISK, sizeof(bid));
+}
+
+static void
+mbi_mmap(struct multiboot_tag_mmap *mbt)
+{
+	char bimbuf[16384];
+	struct btinfo_memmap *bim;
+	char *cp;
+
+	if (mbt->entry_version != 0)
+		return;
+
+	bim = (struct btinfo_memmap *)bimbuf;
+	bim->num = 0;
+
+	for (cp = (char *)(mbt + 1);
+	     cp - (char *)mbt < mbt->size;
+	     cp += mbt->entry_size) {
+		struct multiboot_mmap_entry *mbe;
+		struct bi_memmap_entry *bie;
+
+		mbe = (struct multiboot_mmap_entry *)cp;
+		bie = &bim->entry[bim->num];
+
+		bie->addr = mbe->addr;
+		bie->size = mbe->len;
+		switch (mbe->type) {
+		case MULTIBOOT_MEMORY_AVAILABLE:
+			bie->type = BIM_Memory;
+			break;
+		case MULTIBOOT_MEMORY_RESERVED:
+			bie->type = BIM_Reserved;
+			break;
+		case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE:
+			bie->type = BIM_ACPI;
+			break;
+		case MULTIBOOT_MEMORY_NVS:
+			bie->type = BIM_NVS;
+			break;
+		case MULTIBOOT_MEMORY_BADRAM:
+		default:
+			bie->type = BIM_Unusable;
+			break;
+		}
+
+		bim->num++;
+
+		if ((char*)&bim->entry[bim->num] - (char *)bim > sizeof(bimbuf))
+			break;
+	}
+
+	bootinfo_add((struct btinfo_common *)bim, BTINFO_MEMMAP,
+	    sizeof(bimbuf));
+
+	return;
+}
+
+static void
+mbi_vbe(struct multiboot_tag_vbe *mbt, struct btinfo_framebuffer *bif)
+{
+	bif->vbemode = mbt->vbe_mode;
+	return;
+}
+
+static void
+mbi_framebuffer(struct multiboot_tag_framebuffer *mbt,
+     struct btinfo_framebuffer *bif)
+{
+	bif->physaddr = mbt->common.framebuffer_addr;
+	bif->width = mbt->common.framebuffer_width;	
+	bif->height = mbt->common.framebuffer_height;	
+	bif->depth = mbt->common.framebuffer_bpp;	
+	bif->stride = mbt->common.framebuffer_pitch;
+
+	return;
+}
+
+static void
+mbi_efi32(struct multiboot_tag_efi32 *mbt)
+{
+	struct btinfo_efi bie;
+
+	bie.systblpa = mbt->pointer;
+	bie.flags = BI_EFI_32BIT;
+	
+	bootinfo_add((struct btinfo_common *)&bie,
+           BTINFO_EFI, sizeof(bie));
+}
+
+static void
+mbi_efi64(struct multiboot_tag_efi64 *mbt)
+{
+	struct btinfo_efi bie;
+
+	bie.systblpa = mbt->pointer;
+	
+	bootinfo_add((struct btinfo_common *)&bie,
+           BTINFO_EFI, sizeof(bie));
+}
+
+static void
+mbi_efi_mmap(struct multiboot_tag_efi_mmap *mbt)
+{
+	char biebuf[16384];
+	struct btinfo_efimemmap *bie = (struct btinfo_efimemmap *)biebuf;
+	size_t bie_len;
+
+	if (mbt->descr_vers != 0)
+		goto out;
+
+	bie_len = sizeof(*bie) + mbt->size - sizeof(*mbt);
+	if (bie_len > sizeof(biebuf))
+		goto out;
+
+	bie->num = (mbt->size - sizeof(*mbt)) / mbt->descr_size;
+	bie->version = mbt->descr_vers;
+	bie->size = mbt->descr_size;
+	memcpy(bie->memmap, mbt + 1, mbt->size - sizeof(*mbt));
+
+	bootinfo_add((struct btinfo_common *)bie,
+           BTINFO_EFIMEMMAP, bie_len);
+
+out:
+	return;
+}
+
+void
+multiboot2_post_reloc(void)
+{
+	uint32_t mbi_size;
+	struct multiboot_tag *mbt;
+	char *mbi = multiboot_info;
+	char *cp;
+	int module_count = 0;
+	struct btinfo_framebuffer fbinfo;
+	bool has_fbinfo = false;
+
+	if (multiboot2_enabled == false)
+		goto out;
+
+	mbi_size = *(uint32_t *)multiboot_info;
+	if (mbi_size < 2 * sizeof(uint32_t))
+		goto out;
+
+	bootinfo.bi_nentries = 0;
+
+	memset(&fbinfo, 0, sizeof(fbinfo));
+
+	for (cp = mbi + (2 * sizeof(uint32_t));
+	     cp - mbi < mbi_size;
+	     cp += roundup(mbt->size, MULTIBOOT_INFO_ALIGN)) {
+		mbt = (struct multiboot_tag *)cp;
+		switch(mbt->type) {
+		case MULTIBOOT_TAG_TYPE_CMDLINE:
+			mbi_cmdline((void *)mbt);
+			break;
+		case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
+			break;
+		case MULTIBOOT_TAG_TYPE_MMAP:
+			mbi_mmap((void *)mbt);
+			break;
+		case MULTIBOOT_TAG_TYPE_MODULE:
+			module_count++;
+			break;
+		case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
+			mbi_basic_meminfo((void *)mbt);
+			break;
+		case MULTIBOOT_TAG_TYPE_BOOTDEV:
+			mbi_bootdev((void *)mbt);
+			break;
+		case MULTIBOOT_TAG_TYPE_VBE:
+			mbi_vbe((void *)mbt, &fbinfo);
+			break;
+		case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
+			mbi_framebuffer((void *)mbt, &fbinfo);
+			has_fbinfo = true;
+			break;
+		case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
+		case MULTIBOOT_TAG_TYPE_APM:
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI32:
+			mbi_efi32((void *)mbt);
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI64:
+			mbi_efi64((void *)mbt);
+			break;
+		case MULTIBOOT_TAG_TYPE_SMBIOS:
+		case MULTIBOOT_TAG_TYPE_ACPI_OLD:
+		case MULTIBOOT_TAG_TYPE_ACPI_NEW:
+		case MULTIBOOT_TAG_TYPE_NETWORK:
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI_MMAP:
+			mbi_efi_mmap((void *)mbt);
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI_BS:
+		case MULTIBOOT_TAG_TYPE_EFI32_IH:
+		case MULTIBOOT_TAG_TYPE_EFI64_IH:
+		case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
+		case MULTIBOOT_TAG_TYPE_END:
+		default:
+			break;
+		}
+	}
+
+	if (has_fbinfo)
+		bootinfo_add((struct btinfo_common *)&fbinfo,
+       		    BTINFO_FRAMEBUFFER, sizeof(fbinfo));
+
+	if (module_count > 0)
+		mbi_modules(mbi, mbi_size, module_count);
+
+out:
+	return;
+}
+
+
+#ifdef DEBUG
+static void
+mbi_hexdump(char *addr, size_t len)
+{
+	int i,j;
+
+	for (i = 0; i < len; i += 16) {
+		printf("  %p ", addr + i);
+		for (j = 0; j < 16 && i + j < len; j++) {
+			char *cp = addr + i + j;
+			printf("%s%s%x", 
+			       (i+j) % 4 ? "" : " ",
+			       (unsigned char)*cp < 0x10 ? "0" : "",
+			       (unsigned char)*cp);
+		}
+		printf("\n");
+	}
+
+	return;
+}
+#endif
+
+static const char *
+mbi_tag_name(uint32_t type)
+{
+	const char *tag_name;
+
+	switch (type) {
+	case MULTIBOOT_TAG_TYPE_END:
+		tag_name = "";
+		break;
+	case MULTIBOOT_TAG_TYPE_CMDLINE:
+		tag_name = "command line"; break;
+	case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
+		tag_name = "boot loader name"; break;
+	case MULTIBOOT_TAG_TYPE_MODULE:
+		tag_name = "module"; break;
+	case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
+		tag_name = "basic meminfo"; break;
+	case MULTIBOOT_TAG_TYPE_BOOTDEV:
+		tag_name = "boot device"; break;
+	case MULTIBOOT_TAG_TYPE_MMAP:
+		tag_name = "memory map"; break;
+	case MULTIBOOT_TAG_TYPE_VBE:
+		tag_name = "VESA BIOS Extensions"; break;
+	case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
+		tag_name = "framebuffer"; break;
+	case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
+		tag_name = "ELF sections"; break;
+	case MULTIBOOT_TAG_TYPE_APM:
+		tag_name = "APM"; break;
+	case MULTIBOOT_TAG_TYPE_EFI32:
+		tag_name = "EFI system table"; break;
+	case MULTIBOOT_TAG_TYPE_EFI64:
+		tag_name = "EFI system table"; break;
+	case MULTIBOOT_TAG_TYPE_SMBIOS:
+		tag_name = "SMBIOS"; break;
+	case MULTIBOOT_TAG_TYPE_ACPI_OLD:
+		tag_name = "ACPI 2"; break;
+	case MULTIBOOT_TAG_TYPE_ACPI_NEW:
+		tag_name = "ACPI 3"; break;
+	case MULTIBOOT_TAG_TYPE_NETWORK:
+		tag_name = "network"; break;
+	case MULTIBOOT_TAG_TYPE_EFI_MMAP:
+		tag_name = "EFI memory map"; break;
+	case MULTIBOOT_TAG_TYPE_EFI_BS:
+		tag_name = "EFI boot services available"; break;
+	case MULTIBOOT_TAG_TYPE_EFI32_IH:
+		tag_name = "EFI ImageHandle"; break;
+	case MULTIBOOT_TAG_TYPE_EFI64_IH:
+		tag_name = "EFI ImaheHandle"; break;
+	case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
+		tag_name = "load base"; break;
+	default:
+		tag_name = ""; break;
+	}
+
+	return tag_name;
+}
+
+void
+multiboot2_print_info(void)
+{
+	struct multiboot_tag *mbt;
+	char *cp;
+	uint32_t total_size;
+	uint32_t reserved;
+
+	if (multiboot2_enabled == false)
+		goto out;
+
+	total_size = *(uint32_t *)multiboot_info;
+	reserved = *(uint32_t *)multiboot_info + 1;
+	mbt = (struct multiboot_tag *)(uint32_t *)multiboot_info + 2;
+
+	for (cp = multiboot_info + sizeof(total_size) + sizeof(reserved);
+	     cp - multiboot_info < total_size;
+	     cp = cp + roundup(mbt->size, MULTIBOOT_TAG_ALIGN)) {
+		const char *tag_name;
+
+		mbt = (struct multiboot_tag *)cp;
+		tag_name = mbi_tag_name(mbt->type);
+
+#ifdef DEBUG
+		printf("multiboot2: tag[%d].type = %d(%s), .size = %d ",
+		    i++, mbt->type, tag_name, mbt->size);
+#else
+		if (*tag_name == '\0')
+			break;
+
+		printf("multiboot2: %s ", mbi_tag_name(mbt->type));
+#endif
+
+		switch (mbt->type) {
+		case MULTIBOOT_TAG_TYPE_CMDLINE:
+			printf("%s\n",
+			    ((struct multiboot_tag_string *)mbt)->string);
+			break;
+		case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
+			printf("%s\n",
+			    ((struct multiboot_tag_string *)mbt)->string);
+			break;
+		case MULTIBOOT_TAG_TYPE_MODULE:
+			printf("0x%08x - 0x%08x %s\n",
+			    ((struct multiboot_tag_module *)mbt)->mod_start,
+			    ((struct multiboot_tag_module *)mbt)->mod_end,
+			    ((struct multiboot_tag_module *)mbt)->cmdline);
+			break;
+		case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: {
+			struct multiboot_tag_basic_meminfo *meminfo;
+
+			meminfo = (struct multiboot_tag_basic_meminfo *)mbt;
+			printf("ower = %uKB, upper = %uKB\n",
+			    meminfo->mem_lower, meminfo->mem_upper);
+			break;
+		}
+		case MULTIBOOT_TAG_TYPE_BOOTDEV:
+			printf ("biosdev = 0x%x, slice = %d, part = %d\n",
+			    ((struct multiboot_tag_bootdev *)mbt)->biosdev,
+			    ((struct multiboot_tag_bootdev *)mbt)->slice,
+			    ((struct multiboot_tag_bootdev *)mbt)->part);
+			break;
+		case MULTIBOOT_TAG_TYPE_MMAP: {
+			struct multiboot_tag_mmap *memmap;
+			multiboot_memory_map_t *mmap;
+			uint32_t entry_size;
+			uint32_t entry_version;
+
+			memmap = (struct multiboot_tag_mmap *)mbt;
+			entry_size = memmap->entry_size;
+			entry_version = memmap->entry_version;
+			printf ("entry version = %d\n", entry_version);
+
+			if (entry_version != 0)
+				break;
+			
+			for (mmap = ((struct multiboot_tag_mmap *)mbt)->entries;
+		 	    (char *)mmap - (char *)mbt < mbt->size;
+		 	    mmap = (void *)((char *)mmap + entry_size))
+				printf("  0x%016"PRIx64" @ 0x%016"PRIx64" "
+				    "type 0x%x\n",
+				    (uint64_t)mmap->len, (uint64_t)mmap->addr,
+				    mmap->type);
+			break;
+		}
+		case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: {
+			struct multiboot_tag_framebuffer *fb = (void *)mbt;
+
+			printf ("%dx%dx%d @ 0x%"PRIx64"\n",
+			    fb->common.framebuffer_width,
+			    fb->common.framebuffer_height,
+			    fb->common.framebuffer_bpp,
+			    (uint64_t)fb->common.framebuffer_addr);
+#ifdef DEBUG
+			mbi_hexdump((char *)mbt, mbt->size);
+#endif
+			break;
+		}
+		case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
+			printf("num = %d, entsize = %d, shndx = %d\n",
+			    ((struct multiboot_tag_elf_sections *)mbt)->num,
+			    ((struct multiboot_tag_elf_sections *)mbt)->entsize,
+			    ((struct multiboot_tag_elf_sections *)mbt)->shndx);
+#ifdef DEBUG
+			mbi_hexdump((char *)mbt, mbt->size);
+#endif
+			break;
+		case MULTIBOOT_TAG_TYPE_APM:
+			printf("version = %d, cseg = 0x%x, offset = 0x%x, "
+			    "cseg_16 = 0x%x, dseg = 0x%x, flags = 0x%x, "
+			    "cseg_len = %d, cseg_16_len = %d, "
+			    "dseg_len = %d\n",
+			    ((struct multiboot_tag_apm *)mbt)->version,
+			    ((struct multiboot_tag_apm *)mbt)->cseg,
+			    ((struct multiboot_tag_apm *)mbt)->offset,
+			    ((struct multiboot_tag_apm *)mbt)->cseg_16,
+			    ((struct multiboot_tag_apm *)mbt)->dseg,
+			    ((struct multiboot_tag_apm *)mbt)->flags,
+			    ((struct multiboot_tag_apm *)mbt)->cseg_len,
+			    ((struct multiboot_tag_apm *)mbt)->cseg_16_len,
+			    ((struct multiboot_tag_apm *)mbt)->dseg_len);
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI32:
+			printf("0x%x\n",
+			    ((struct multiboot_tag_efi32 *)mbt)->pointer);
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI64:
+			printf("0x%"PRIx64"\n", (uint64_t)
+			    ((struct multiboot_tag_efi64 *)mbt)->pointer);
+			break;
+		case MULTIBOOT_TAG_TYPE_SMBIOS:
+			printf("major = %d, minor = %d\n",
+			    ((struct multiboot_tag_smbios *)mbt)->major,
+		 	    ((struct multiboot_tag_smbios *)mbt)->minor);
+#ifdef DEBUG
+			mbi_hexdump((char *)mbt, mbt->size);
+#endif
+			break;
+		case MULTIBOOT_TAG_TYPE_ACPI_OLD:
+			printf("\n");
+#ifdef DEBUG
+			mbi_hexdump((char *)mbt, mbt->size);
+#endif
+			break;
+		case MULTIBOOT_TAG_TYPE_ACPI_NEW:
+			printf("\n");
+#ifdef DEBUG
+			mbi_hexdump((char *)mbt, mbt->size);
+#endif
+			break;
+		case MULTIBOOT_TAG_TYPE_NETWORK:
+			printf("\n");
+#ifdef DEBUG
+			mbi_hexdump((char *)mbt, mbt->size);
+#endif
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI_MMAP:
+			printf("\n");
+#ifdef DEBUG
+			mbi_hexdump((char *)mbt, mbt->size);
+#endif
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI_BS:
+			printf("\n");
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI32_IH:
+			printf("0x%"PRIx32"\n", 
+			    ((struct multiboot_tag_efi32_ih *)mbt)->pointer);
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI64_IH:
+			printf("0x%"PRIx64"\n", (uint64_t)
+			    ((struct multiboot_tag_efi64_ih *)mbt)->pointer);
+			break;
+		case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: {
+			struct multiboot_tag_load_base_addr *ld = (void *)mbt;
+			printf("0x%x\n", ld->load_base_addr);
+			break;
+		}
+		case MULTIBOOT_TAG_TYPE_END:
+			printf("\n");
+			break;
+		default:
+			printf("\n");
+#ifdef DEBUG
+			mbi_hexdump((char *)mbt, mbt->size);
+#endif
+			break;
+		}
+	}
+
+out:
+	return;
+}
+
+
+
+
+/*
+ * Sets up the initial kernel symbol table.  Returns true if this was
+ * passed in by Multiboot; false otherwise.
+ */
+bool
+multiboot2_ksyms_addsyms_elf(void)
+{
+	struct multiboot_symbols *ms = &Multiboot_Symbols;
+
+	if (!multiboot2_enabled)
+		return false;
+
+	if (has_syms) {
+		Elf32_Ehdr ehdr;
+
+		KASSERT(esym != 0);
+
+		memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
+		ehdr.e_ident[EI_CLASS] = ELFCLASS32;
+		ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+		ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+		ehdr.e_type = ET_EXEC;
+		ehdr.e_machine = EM_386;
+		ehdr.e_version = 1;
+		ehdr.e_ehsize = sizeof(ehdr);
+
+		ksyms_addsyms_explicit((void *)&ehdr,
+		    ms->s_symstart, ms->s_symsize,
+		    ms->s_strstart, ms->s_strsize);
+	}
+
+	return has_syms;
+}

Reply via email to