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;
+}