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