Module Name:    src
Committed By:   manu
Date:           Tue Dec 10 02:06:07 UTC 2019

Modified Files:
        src/sys/arch/amd64/amd64: locore.S machdep.c
        src/sys/arch/amd64/conf: GENERIC files.amd64 kern.ldscript
        src/sys/arch/x86/x86: efi.c multiboot2.c

Log Message:
Add multiboot 2 support to amd64 kernel


To generate a diff of this commit:
cvs rdiff -u -r1.192 -r1.193 src/sys/arch/amd64/amd64/locore.S
cvs rdiff -u -r1.342 -r1.343 src/sys/arch/amd64/amd64/machdep.c
cvs rdiff -u -r1.548 -r1.549 src/sys/arch/amd64/conf/GENERIC
cvs rdiff -u -r1.113 -r1.114 src/sys/arch/amd64/conf/files.amd64
cvs rdiff -u -r1.27 -r1.28 src/sys/arch/amd64/conf/kern.ldscript
cvs rdiff -u -r1.20 -r1.21 src/sys/arch/x86/x86/efi.c
cvs rdiff -u -r1.2 -r1.3 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/amd64/amd64/locore.S
diff -u src/sys/arch/amd64/amd64/locore.S:1.192 src/sys/arch/amd64/amd64/locore.S:1.193
--- src/sys/arch/amd64/amd64/locore.S:1.192	Fri Nov 22 23:36:25 2019
+++ src/sys/arch/amd64/amd64/locore.S	Tue Dec 10 02:06:07 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore.S,v 1.192 2019/11/22 23:36:25 ad Exp $	*/
+/*	$NetBSD: locore.S,v 1.193 2019/12/10 02:06:07 manu Exp $	*/
 
 /*
  * Copyright-o-rama!
@@ -158,6 +158,7 @@
 
 #include "opt_compat_netbsd.h"
 #include "opt_compat_netbsd32.h"
+#include "opt_multiboot.h"
 #include "opt_xen.h"
 #include "opt_svs.h"
 
@@ -177,6 +178,13 @@
 #include <machine/frameasm.h>
 #include <machine/cputypes.h>
 
+#ifndef XENPV
+#include <arch/i386/include/multiboot.h>
+#endif 
+
+#define CODE_SEGMENT	0x08
+#define DATA_SEGMENT	0x10
+
 #if NLAPIC > 0
 #include <machine/i82489reg.h>
 #endif
@@ -424,6 +432,50 @@ END(farjmp64)
 	.space	512
 tmpstk:
 
+.section multiboot,"ax",@progbits
+#if defined(MULTIBOOT)
+	.align	8
+	.globl	Multiboot2_Header
+_C_LABEL(Multiboot2_Header):
+	.int	MULTIBOOT2_HEADER_MAGIC
+	.int	MULTIBOOT2_ARCHITECTURE_I386
+	.int	Multiboot2_Header_end - Multiboot2_Header
+	.int	-(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT2_ARCHITECTURE_I386 \
+		+ (Multiboot2_Header_end - Multiboot2_Header))
+
+	.int	1	/* MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST */
+	.int	12	/* sizeof(multiboot_header_tag_information_request) */
+			/* + sizeof(uint32_t) * requests */
+	.int	4	/* MULTIBOOT_TAG_TYPE_BASIC_MEMINFO */
+	.align	8
+
+	.int	3	/* MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS */
+	.int	16	/* sizeof(struct multiboot_tag_efi64) */
+	.quad	(multiboot2_entry - KERNBASE)
+	.align	8
+
+	.int	9	/* MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 */
+	.int	16	/* sizeof(struct multiboot_tag_efi64) */
+	.quad	(multiboot2_entry - KERNBASE)
+	.align	8
+
+#if notyet
+	/*
+	 * Could be used to get an early console for debug,
+	 * but this is broken.
+	 */
+	.int	7	/* MULTIBOOT_HEADER_TAG_EFI_BS */
+	.int	8	/* sizeof(struct multiboot_tag) */
+	.align	8
+#endif
+
+	.int	0	/* MULTIBOOT_HEADER_TAG_END */
+	.int	8	/* sizeof(struct multiboot_tag) */
+	.align	8
+	.globl	Multiboot2_Header_end
+_C_LABEL(Multiboot2_Header_end):
+#endif	/* MULTIBOOT */
+
 /*
  * Some hackage to deal with 64bit symbols in 32 bit mode.
  * This may not be needed if things are cleaned up a little.
@@ -440,6 +492,700 @@ ENTRY(start)
 	/* Warm boot */
 	movw	$0x1234,0x472
 
+#if defined(MULTIBOOT)
+	jmp	.Lnative_loader
+
+
+multiboot2_entry:
+	.code64
+	/*
+	 * 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 0x200000 (KERNTEXTOFF - KERNBASE)
+	 *	as almost all the code in locore.S assume it is there. 
+	 *	This is derived from 
+	 *	src/sys/arch/i386/stand/efiboot/bootx64/startprog64.S
+	 * - copy multiboot_info, as done in multiboot_pre_reloc() from
+	 *	src/sys/arch/x86/x86/multiboot2.c
+	 *	Unfortunately we cannot call that function as there is 
+	 *	no simple way to build it as 32 bit code in a 64 bit kernel.
+	 * - Copy ELF symbols, also as in multiboot_pre_reloc()
+	 */
+
+	cli
+
+	/*
+	 * Discover our load address and use it to get start address
+	 */
+	mov	$_RELOC(tmpstk),%rsp
+	call	next
+next:	pop	%r8
+	sub	$(next - start), %r8
+
+	/*
+	 * Save multiboot_info for later. We cannot use	
+	 * temporary stack for that since we are going to
+	 * overwrite it.
+	 */
+	movl	%ebx, (multiboot2_info_ptr - start)(%r8)
+
+	/*
+	 * Get relocated multiboot2_loader entry point in %r9
+	 */
+	mov	$(KERNTEXTOFF - KERNBASE), %r9
+	add	$(multiboot2_loader - kernel_text), %r9
+
+	/* Copy kernel */
+	mov	$(KERNTEXTOFF - KERNBASE), %rdi			/* dest */
+	mov	%r8, %rsi		
+	sub	$(start - kernel_text), %rsi			/* src */
+	mov	$(__kernel_end - kernel_text), %rcx		/* size *.
+	mov	%rcx, %r12		
+	movq	%rdi, %r11		/* for misaligned check */
+
+#if !defined(NO_OVERLAP)
+	movq	%rdi, %r13
+	subq	%rsi, %r13
+#endif
+
+	shrq	$3, %rcx		/* count for copy by words */
+	jz	8f			/* j if less than 8 bytes */
+
+	lea	-8(%rdi, %r12), %r14	/* target address of last 8 */
+	mov	-8(%rsi, %r12), %r15	/* get last word */
+#if !defined(NO_OVERLAP)
+	cmpq	%r12, %r13		/* overlapping? */
+	jb	10f
+#endif
+
+/*
+ * Non-overlaping, copy forwards.
+ * Newer Intel cpus (Nehalem) will do 16byte read/write transfers
+ * if %ecx is more than 76.
+ * AMD might do something similar some day.
+ */
+	and	$7, %r11		/* destination misaligned ? */
+	jnz	12f
+	rep
+	movsq
+	mov	%r15, (%r14)		/* write last word */
+	jmp	.Lcopy_done
+
+/*
+ * Destination misaligned
+ * AMD say it is better to align the destination (not the source).
+ * This will also re-align copies if the source and dest are both
+ * misaligned by the same amount)
+ * (I think Nehalem will use its accelerated copy if the source
+ * and destination have the same alignment.)
+ */
+12:
+	lea	-9(%r11, %r12), %rcx	/* post re-alignment count */
+	neg	%r11			/* now -1 .. -7 */
+	mov	(%rsi), %r12		/* get first word */
+	mov	%rdi, %r13		/* target for first word */
+	lea	8(%rsi, %r11), %rsi
+	lea	8(%rdi, %r11), %rdi
+	shr	$3, %rcx
+	rep
+	movsq
+	mov	%r12, (%r13)		/* write first word */
+	mov	%r15, (%r14)		/* write last word */
+	jmp	.Lcopy_done
+
+#if !defined(NO_OVERLAP)
+/* Must copy backwards.
+ * Reverse copy is probably easy to code faster than 'rep movds'
+ * since that requires (IIRC) an extra clock every 3 iterations (AMD).
+ * However I don't suppose anything cares that much!
+ * The big cost is the std/cld pair - reputedly 50+ cycles on Netburst P4.
+ * The copy is aligned with the buffer start (more likely to
+ * be a multiple of 8 than the end).
+ */
+10:
+	lea	-8(%rsi, %rcx, 8), %rsi
+	lea	-8(%rdi, %rcx, 8), %rdi
+	std
+	rep
+	movsq
+	cld
+	mov	%r15, (%r14)	/* write last bytes */
+	jmp	.Lcopy_done
+#endif
+
+/* Less than 8 bytes to copy, copy by bytes */
+/* Intel Nehalem optimise 'rep movsb' for <= 7 bytes (9-15 clocks).
+ * For longer transfers it is 50+ !
+ */
+8:	mov	%r12, %rcx
+
+#if !defined(NO_OVERLAP)
+	cmpq	%r12, %r13	/* overlapping? */
+	jb	81f
+#endif
+
+	/* nope, copy forwards. */
+	rep
+	movsb
+	jmp	.Lcopy_done
+
+#if !defined(NO_OVERLAP)
+/* Must copy backwards */
+81:
+	lea	-1(%rsi, %rcx), %rsi
+	lea	-1(%rdi, %rcx), %rdi
+	std
+	rep
+	movsb
+	cld
+#endif
+	/* End of copy kernel */
+.Lcopy_done:
+
+	mov	%r8, %rdi	/* %rdi: loaded start address */
+	mov	%r9, %rsi	/* %rsi: kernel entry address */
+
+	/* Prepare jump address */
+	lea	(multiboot2_loader32a - start)(%rdi), %rax
+	movl	%eax, (multiboot2_loader32r - start)(%rdi)
+
+	/* Setup GDT */
+	lea	(gdt - start)(%rdi), %rax
+	mov	%rax, (gdtrr - start)(%rdi)
+	lgdt	(gdtr - start)(%rdi)
+
+	/* Jump to set %cs */
+	ljmp	*(multiboot2_loader32r - start)(%rdi)
+
+	.align	4
+	.code32
+multiboot2_loader32a:
+	movl	$DATA_SEGMENT, %eax
+	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	multiboot2_loader32b
+
+	.align	4
+multiboot2_loader32b:
+	xor	%eax, %eax
+
+	/* 
+	* Reload multiboot info from target location
+	*/	
+	movl	_RELOC(multiboot2_info_ptr), %ebx
+	call	*%esi
+
+	.align	16
+multiboot2_loader32r:
+	.long	0
+	.long	CODE_SEGMENT
+	.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:
+	/*
+	 * Here we would like to call multiboot2_pre_reloc() but
+	 * we do not yet run in long mode, which means we need
+	 * a 32 bit version of that function. Unfortunately, 
+	 * mixing 32-bit and 64-bit object file at link time
+	 * does not work. As a result, we need to do the job
+	 * of multiboot2_pre_reloc() here in assembly.
+	 */
+#if multiboot2_pre_reloc_would_be_built_as_ia32
+	movl	$_RELOC(tmpstk),%esp
+	mov	%ebx,%edi	/* Address of Multiboot information */
+	call	_C_LABEL(multiboot2_pre_reloc)
+#else
+	/*
+	 * Copy multiboot_info
+	 */
+	movl	$_RELOC(multiboot_info),%edi
+	movl	%ebx,%esi
+	movl	(%ebx),%ecx
+	shr	$2,%ecx
+	rep
+	movsl
+
+	/*
+	 * Set multiboot2_enabled
+	 */
+	movl	$1,%eax
+	movl	%eax,RELOC(multiboot2_enabled)
+
+	/*
+	 * Look for MULTIBOOT_TAG_TYPE_ELF_SECTIONS
+	 */
+	movl	$_RELOC(multiboot_info),%esi
+	movl	(%esi),%ecx	/* multiboot_info size */
+	movl	%esi,%edx
+	addl	%ecx,%edx	/* %edx: end of multiboot_info */
+	addl	$8,%esi		/* skip two words of multiboot_info header */
+mbt_loop:
+	movl	(%esi),%ebx	/* mbt->type */
+	cmpl	$9,%ebx		/* 9 for MULTIBOOT_TAG_TYPE_ELF_SECTIONS */
+	je	found_elf_sections
+
+	movl	4(%esi),%eax	/* mbt->size */
+	addl	%eax,%esi
+	addl	$7,%esi		/* roundup(%esi,8) */
+	andl	$~7,%esi
+
+	cmpl	%edx,%esi
+	jle	mbt_loop
+	jmp	elf_sections_done
+
+found_elf_sections:
+	movl	$0,%eax
+	movl	%esp,%ebp			/* %ebp is esymp */
+	push	%eax
+	push	$KERNBASE_LO			/* kernbase */
+	push	$_RELOC(end)			/* void *end */
+	push	%ebp				/* int **esymp */
+	push	$_RELOC(has_syms)		/* bool *has_symsp */
+	push	$_RELOC(Multiboot_Symbols)/* struct multiboot_symbol *ms */
+	push	%esi		/* struct multiboot_tag_elf_sections *mbt_elf */
+	call	multiboot2_copy_syms32
+
+	/* Asjust esym as a 64 bit pointer if esymp was set */
+	movl	(%ebp),%eax
+	testl	%eax,%eax		/* esymp = NULL? */
+	jz	elf_sections_done
+
+	movl	$RELOC(esym),%ebp
+	movl	%eax,(%ebp)
+	movl	$KERNBASE_HI,4(%ebp)
+
+	jmp	elf_sections_done
+
+	/*
+	 * This is multiboot2_copy_syms() from 
+	 * src/sys/arch/x86/x86/multiboot2.c
+	 * built with -m32 -mcmodel=32 -D_LOCORE_64
+	 */
+multiboot2_copy_syms32:
+	push	%ebp
+	mov	%esp,%ebp
+	push	%edi
+	push	%esi
+	push	%ebx
+	sub	$0x20,%esp
+	mov	0x8(%ebp),%esi
+	/* for (i = 0; i < mbt_elf->num && symtabp == NULL && */
+	mov	0x8(%esi),%ebx
+	test	%ebx,%ebx
+	je	copy_syms_4ce
+	add	$0x14,%esi
+	mov	%esi,%eax
+	xor	%edx,%edx
+	jmp	copy_syms_3a0
+copy_syms_395:
+	cmp	%edx,%ebx
+	jbe	copy_syms_4ce
+copy_syms_39d:
+	add	$0x40,%eax
+copy_syms_3a0:
+	add	$0x1,%edx
+	/* 	if ((shdrp->sh_type == SHT_SYMTAB) && */
+	cmpl	$0x2,0x4(%eax)
+	jne	copy_syms_395
+	/* 		shdrp->sh_link != SHN_UNDEF) { */
+	mov	0x28(%eax),%ecx
+	/* 	if ((shdrp->sh_type == SHT_SYMTAB) && */
+	test	%ecx,%ecx
+	je	copy_syms_395
+	/* 			[shdrp->sh_link]; */
+	shl	$0x6,%ecx
+	/* 		shdrp2 = &((locore_Elf_Shdr *)mbt_elf->sections) */
+	add	%esi,%ecx
+	/* 		if (shdrp2->sh_type == SHT_STRTAB) { */
+	cmpl	$0x3,0x4(%ecx)
+	jne	copy_syms_395
+	/* for (i = 0; i < mbt_elf->num && symtabp == NULL && */
+	cmp	%ebx,%edx
+	jae	copy_syms_6d1
+	test	%eax,%eax
+	je	copy_syms_608
+	/* if (symtabp == NULL || strtabp == NULL) */
+copy_syms_3cb:
+	test	%ecx,%ecx
+	lea	0x0(%esi),%esi
+	je	copy_syms_4ce
+	/* symaddr = symtabp->sh_addr; */
+	mov	0x10(%eax),%edi
+	mov	%edi,-0x10(%ebp)
+	mov	0x14(%eax),%ebx
+	mov	%ebx,-0x18(%ebp)
+	/* straddr = strtabp->sh_addr; */
+	mov	0x10(%ecx),%esi
+	mov	%esi,-0x14(%ebp)
+	mov	0x14(%ecx),%ebx
+	mov	%ebx,-0x20(%ebp)
+	/* symsize = symtabp->sh_size; */
+	mov	0x20(%eax),%ebx
+	/* strsize = strtabp->sh_size; */
+	mov	0x20(%ecx),%eax
+	mov	%eax,-0x1c(%ebp)
+	cmp	0x18(%ebp),%edi
+	jae	copy_syms_4d6
+	cmp	%esi,0x18(%ebp)
+	ja	copy_syms_4e0
+	jae	copy_syms_54d
+	/* cp2dst = (locore_Elf_Addr)(uintptr_t)endp + cp1size; */
+copy_syms_40f:
+	mov	-0x1c(%ebp),%ecx
+	mov	%ecx,%eax
+	xor	%edx,%edx
+	/* cp1dst = (locore_Elf_Addr)(uintptr_t)endp; */
+	mov	0x18(%ebp),%esi
+	xor	%edi,%edi
+	/* cp2dst = (locore_Elf_Addr)(uintptr_t)endp + cp1size; */
+	add	%esi,%eax
+	adc	%edi,%edx
+	mov	%eax,-0x2c(%ebp)
+	mov	%edx,-0x28(%ebp)
+	/* (void)memcpy((void *)(uintptr_t)cp1dst, */
+	mov	%ecx,%eax
+	mov	0x18(%ebp),%edi
+	mov	-0x14(%ebp),%esi
+	cmp	$0x4,%ecx
+	jae	copy_syms_5e8
+copy_syms_436:
+	test	$0x2,%al
+	je	copy_syms_43c
+	movsw	%ds:(%esi),%es:(%edi)
+copy_syms_43c:
+	test	$0x1,%al
+	je	copy_syms_441
+	movsb	%ds:(%esi),%es:(%edi)
+	/* (void)memcpy((void *)(uintptr_t)cp2dst, */
+copy_syms_441:
+	mov	%ebx,%eax
+	mov	0x18(%ebp),%edi
+	mov	-0x1c(%ebp),%esi
+	add	%esi,%edi
+	mov	-0x10(%ebp),%esi
+	cmp	$0x4,%ebx
+	jae	copy_syms_5c4
+copy_syms_457:
+	test	$0x2,%al
+	je	copy_syms_45d
+	movsw	%ds:(%esi),%es:(%edi)
+copy_syms_45d:
+	test	$0x1,%al
+	je	copy_syms_462
+	movsb	%ds:(%esi),%es:(%edi)
+	/* symstart = (cp1src == symaddr) ? cp1dst : cp2dst; */
+copy_syms_462:
+	mov	-0x18(%ebp),%edx
+	mov	-0x20(%ebp),%edi
+	xor	%edi,%edx
+	mov	-0x10(%ebp),%eax
+	mov	-0x14(%ebp),%ecx
+	xor	%ecx,%eax
+	or	%eax,%edx
+	je	copy_syms_6ba
+	mov	-0x2c(%ebp),%eax
+	mov	%eax,-0x24(%ebp)
+	mov	%ecx,-0x10(%ebp)
+	mov	%edi,-0x18(%ebp)
+	/* strstart = (cp1src == straddr) ? cp1dst : cp2dst; */
+copy_syms_486:
+	mov	-0x20(%ebp),%edx
+	xor	-0x18(%ebp),%edx
+	mov	-0x14(%ebp),%eax
+	xor	-0x10(%ebp),%eax
+	or	%eax,%edx
+	je	copy_syms_545
+copy_syms_49a:
+	mov	-0x2c(%ebp),%esi
+	/* ms->s_symstart = symstart + kernbase; */
+copy_syms_49d:
+	mov	-0x24(%ebp),%eax
+	add	0x1c(%ebp),%eax
+	mov	0xc(%ebp),%edi
+	mov	%eax,(%edi)
+	/* ms->s_symsize	= symsize; */
+	mov	%edi,%eax
+	mov	%ebx,0x4(%edi)
+	/* ms->s_strstart = strstart + kernbase; */
+	add	0x1c(%ebp),%esi
+	mov	%esi,0x8(%edi)
+	/* ms->s_strsize	= strsize; */
+	mov	-0x1c(%ebp),%edi
+	mov	%edi,0xc(%eax)
+	/* *has_symsp = true; */
+	mov	0x10(%ebp),%eax
+	movb	$0x1,(%eax)
+	/* *esymp = (int *)((uintptr_t)endp + symsize + strsize + kernbase); */
+	mov	0x18(%ebp),%eax
+	add	0x1c(%ebp),%eax
+	add	%eax,%ebx
+	add	%edi,%ebx
+	mov	0x14(%ebp),%eax
+	mov	%ebx,(%eax)
+copy_syms_4ce:
+	add	$0x20,%esp
+	pop	%ebx
+	pop	%esi
+	pop	%edi
+	pop	%ebp
+	ret	
+copy_syms_4d6:
+	jbe	copy_syms_54d
+	mov	-0x14(%ebp),%eax
+	cmp	%eax,0x18(%ebp)
+	jbe	copy_syms_54d
+	/* cp1dst = (locore_Elf_Addr)(uintptr_t)endp; */
+copy_syms_4e0:
+	mov	0x18(%ebp),%eax
+	mov	%eax,-0x24(%ebp)
+	/* cp2dst = (locore_Elf_Addr)(uintptr_t)endp + cp1size; */
+	mov	%ebx,%eax
+	xor	%edx,%edx
+	/* cp1dst = (locore_Elf_Addr)(uintptr_t)endp; */
+	mov	0x18(%ebp),%esi
+	xor	%edi,%edi
+	/* cp2dst = (locore_Elf_Addr)(uintptr_t)endp + cp1size; */
+	add	%esi,%eax
+	adc	%edi,%edx
+	mov	%eax,-0x2c(%ebp)
+	mov	%edx,-0x28(%ebp)
+	/* (void)memcpy((void *)(uintptr_t)cp1dst, */
+	mov	%ebx,%eax
+	mov	0x18(%ebp),%edi
+	mov	-0x10(%ebp),%esi
+	cmp	$0x4,%ebx
+	jae	copy_syms_5a8
+copy_syms_50a:
+	test	$0x2,%al
+	jne	copy_syms_57b
+	test	$0x1,%al
+	jne	copy_syms_578
+	/* (void)memcpy((void *)(uintptr_t)cp2dst, */
+copy_syms_512:
+	mov	-0x1c(%ebp),%ecx
+	mov	%ecx,%eax
+	mov	0x18(%ebp),%edi
+	add	%ebx,%edi
+	mov	-0x14(%ebp),%esi
+	cmp	$0x4,%ecx
+	jae	copy_syms_584
+copy_syms_524:
+	test	$0x2,%al
+	jne	copy_syms_56c
+	test	$0x1,%al
+	je	copy_syms_486
+copy_syms_530:
+	movsb	%ds:(%esi),%es:(%edi)
+	/* strstart = (cp1src == straddr) ? cp1dst : cp2dst; */
+	mov	-0x20(%ebp),%edx
+	xor	-0x18(%ebp),%edx
+	mov	-0x14(%ebp),%eax
+	xor	-0x10(%ebp),%eax
+	or	%eax,%edx
+	jne	copy_syms_49a
+copy_syms_545:
+	mov	0x18(%ebp),%esi
+	jmp	copy_syms_49d
+	/* 	if (symaddr < straddr) { */
+copy_syms_54d:
+	mov	-0x20(%ebp),%edi
+	cmp	%edi,-0x18(%ebp)
+	jb	copy_syms_4e0
+	ja	copy_syms_40f
+	mov	-0x14(%ebp),%edi
+	cmp	%edi,-0x10(%ebp)
+	jb	copy_syms_4e0
+	jmp	copy_syms_40f
+	/* (void)memcpy((void *)(uintptr_t)cp2dst, */
+copy_syms_56c:
+	movsw	%ds:(%esi),%es:(%edi)
+	test	$0x1,%al
+	je	copy_syms_486
+	jmp	copy_syms_530
+	/* (void)memcpy((void *)(uintptr_t)cp1dst, */
+copy_syms_578:
+	movsb	%ds:(%esi),%es:(%edi)
+	jmp	copy_syms_512
+copy_syms_57b:
+	movsw	%ds:(%esi),%es:(%edi)
+	test	$0x1,%al
+	nop
+	je	copy_syms_512
+	jmp	copy_syms_578
+	/* (void)memcpy((void *)(uintptr_t)cp2dst, */
+copy_syms_584:
+	test	$0x1,%edi
+	jne	copy_syms_650
+copy_syms_590:
+	test	$0x2,%edi
+	jne	copy_syms_63c
+copy_syms_59c:
+	mov	%eax,%ecx
+	shr	$0x2,%ecx
+	rep movsl %ds:(%esi),%es:(%edi)
+	jmp	copy_syms_524
+	/* (void)memcpy((void *)(uintptr_t)cp1dst, */
+copy_syms_5a8:
+	test	$0x1,%edi
+	jne	copy_syms_626
+copy_syms_5b0:
+	test	$0x2,%edi
+	jne	copy_syms_615
+copy_syms_5b8:
+	mov	%eax,%ecx
+	shr	$0x2,%ecx
+	rep movsl %ds:(%esi),%es:(%edi)
+	jmp	copy_syms_50a
+	/* (void)memcpy((void *)(uintptr_t)cp2dst, */
+copy_syms_5c4:
+	test	$0x1,%edi
+	jne	copy_syms_666
+copy_syms_5d0:
+	test	$0x2,%edi
+	jne	copy_syms_6a6
+copy_syms_5dc:
+	mov	%eax,%ecx
+	shr	$0x2,%ecx
+	rep movsl %ds:(%esi),%es:(%edi)
+	jmp	copy_syms_457
+	/* (void)memcpy((void *)(uintptr_t)cp1dst, */
+copy_syms_5e8:
+	test	$0x1,%edi
+	jne	copy_syms_68d
+copy_syms_5f4:
+	test	$0x2,%edi
+	jne	copy_syms_679
+copy_syms_5fc:
+	mov	%eax,%ecx
+	shr	$0x2,%ecx
+	rep movsl %ds:(%esi),%es:(%edi)
+	jmp	copy_syms_436
+	/* for (i = 0; i < mbt_elf->num && symtabp == NULL && */
+copy_syms_608:
+	test	%ecx,%ecx
+	jne	copy_syms_4ce
+	jmp	copy_syms_39d
+	/* (void)memcpy((void *)(uintptr_t)cp1dst, */
+copy_syms_615:
+	movzwl (%esi),%edx
+	mov	%dx,(%edi)
+	add	$0x2,%edi
+	add	$0x2,%esi
+	sub	$0x2,%eax
+	jmp	copy_syms_5b8
+copy_syms_626:
+	movzbl (%esi),%eax
+	mov	%al,(%edi)
+	mov	0x18(%ebp),%eax
+	lea	0x1(%eax),%edi
+	add	$0x1,%esi
+	lea	-0x1(%ebx),%eax
+	jmp	copy_syms_5b0
+	/* (void)memcpy((void *)(uintptr_t)cp2dst, */
+copy_syms_63c:
+	movzwl (%esi),%edx
+	mov	%dx,(%edi)
+	add	$0x2,%edi
+	add	$0x2,%esi
+	sub	$0x2,%eax
+	jmp	copy_syms_59c
+copy_syms_650:
+	movzbl (%esi),%eax
+	mov	%al,(%edi)
+	add	$0x1,%edi
+	add	$0x1,%esi
+	mov	-0x1c(%ebp),%eax
+	sub	$0x1,%eax
+	jmp	copy_syms_590
+copy_syms_666:
+	movzbl (%esi),%eax
+	mov	%al,(%edi)
+	add	$0x1,%edi
+	add	$0x1,%esi
+	lea	-0x1(%ebx),%eax
+	jmp	copy_syms_5d0
+	/* (void)memcpy((void *)(uintptr_t)cp1dst, */
+copy_syms_679:
+	movzwl (%esi),%edx
+	mov	%dx,(%edi)
+	add	$0x2,%edi
+	add	$0x2,%esi
+	sub	$0x2,%eax
+	jmp	copy_syms_5fc
+copy_syms_68d:
+	movzbl (%esi),%eax
+	mov	%al,(%edi)
+	mov	0x18(%ebp),%eax
+	lea	0x1(%eax),%edi
+	add	$0x1,%esi
+	mov	-0x1c(%ebp),%eax
+	sub	$0x1,%eax
+	jmp	copy_syms_5f4
+	/* (void)memcpy((void *)(uintptr_t)cp2dst, */
+copy_syms_6a6:
+	movzwl (%esi),%edx
+	mov	%dx,(%edi)
+	add	$0x2,%edi
+	add	$0x2,%esi
+	sub	$0x2,%eax
+	jmp	copy_syms_5dc
+copy_syms_6ba:
+	mov	-0x14(%ebp),%eax
+	mov	%eax,-0x10(%ebp)
+	mov	-0x20(%ebp),%eax
+	mov	%eax,-0x18(%ebp)
+	/* cp1dst = (locore_Elf_Addr)(uintptr_t)endp; */
+	mov	0x18(%ebp),%eax
+	mov	%eax,-0x24(%ebp)
+	jmp	copy_syms_486
+	/* if (symtabp == NULL || strtabp == NULL) */
+copy_syms_6d1:
+	test	%eax,%eax
+	jne	copy_syms_3cb
+	jmp	copy_syms_4ce
+elf_sections_done:
+#endif
+
+	jmp	.Lbegin
+
+
+#endif /* MULTIBOOT */
+
+.Lnative_loader:
 	/*
 	 * Load parameters from the stack (32 bits):
 	 *     boothowto, [bootdev], bootinfo, esym, biosextmem, biosbasemem
@@ -562,6 +1308,7 @@ ENTRY(start)
 	 * Done with the parameters!
 	 */
 
+.Lbegin:
 	/* First, reset the PSL. */
 	pushl	$PSL_MBO
 	popfl
@@ -877,6 +1624,16 @@ longmode_hi:
 	leaq	(USPACE-FRAMESIZE)(%rax),%rsp
 	xorq	%rbp,%rbp			/* mark end of frames */
 
+#if defined(MULTIBOOT)
+	/* 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.
+	 */
+	pushq	%rsi
+	call	_C_LABEL(multiboot2_post_reloc)
+	popq	%rsi
+#endif 
 	xorw	%ax,%ax
 	movw	%ax,%gs
 	movw	%ax,%fs

Index: src/sys/arch/amd64/amd64/machdep.c
diff -u src/sys/arch/amd64/amd64/machdep.c:1.342 src/sys/arch/amd64/amd64/machdep.c:1.343
--- src/sys/arch/amd64/amd64/machdep.c:1.342	Fri Dec  6 08:35:21 2019
+++ src/sys/arch/amd64/amd64/machdep.c	Tue Dec 10 02:06:07 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.342 2019/12/06 08:35:21 maxv Exp $	*/
+/*	$NetBSD: machdep.c,v 1.343 2019/12/10 02:06:07 manu Exp $	*/
 
 /*
  * Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011
@@ -110,9 +110,10 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.342 2019/12/06 08:35:21 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.343 2019/12/10 02:06:07 manu Exp $");
 
 #include "opt_modular.h"
+#include "opt_multiboot.h"
 #include "opt_user_ldt.h"
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -184,6 +185,8 @@ __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 
 #include <x86/cpuvar.h>
 #include <x86/machdep.h>
 
+#include <arch/i386/include/multiboot.h>
+
 #include <x86/x86/tsc.h>
 
 #include <dev/isa/isareg.h>
@@ -371,6 +374,10 @@ cpu_startup(void)
 
 	initmsgbuf((void *)msgbuf_vaddr, round_page(sz));
 
+#ifdef MULTIBOOT
+	multiboot2_print_info();
+#endif
+
 	minaddr = 0;
 
 	/*
@@ -1504,6 +1511,11 @@ init_x86_64_ksyms(void)
 	db_machine_init();
 #endif
 
+#if defined(MULTIBOOT)
+	if (multiboot2_ksyms_addsyms_elf())
+		return;
+#endif
+
 #ifndef XENPV
 	symtab = lookup_bootinfo(BTINFO_SYMTAB);
 	if (symtab) {

Index: src/sys/arch/amd64/conf/GENERIC
diff -u src/sys/arch/amd64/conf/GENERIC:1.548 src/sys/arch/amd64/conf/GENERIC:1.549
--- src/sys/arch/amd64/conf/GENERIC:1.548	Thu Dec  5 22:05:05 2019
+++ src/sys/arch/amd64/conf/GENERIC	Tue Dec 10 02:06:07 2019
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.548 2019/12/05 22:05:05 sevan Exp $
+# $NetBSD: GENERIC,v 1.549 2019/12/10 02:06:07 manu Exp $
 #
 # GENERIC machine description file
 #
@@ -22,10 +22,12 @@ include 	"arch/amd64/conf/std.amd64"
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident		"GENERIC-$Revision: 1.548 $"
+#ident		"GENERIC-$Revision: 1.549 $"
 
 maxusers	64		# estimated number of users
 
+options		MULTIBOOT	# Multiboot support (see multiboot(8)) 
+
 # delay between "rebooting ..." message and hardware reset, in milliseconds
 #options 	CPURESET_DELAY=2000
 

Index: src/sys/arch/amd64/conf/files.amd64
diff -u src/sys/arch/amd64/conf/files.amd64:1.113 src/sys/arch/amd64/conf/files.amd64:1.114
--- src/sys/arch/amd64/conf/files.amd64:1.113	Sat Sep  7 18:56:01 2019
+++ src/sys/arch/amd64/conf/files.amd64	Tue Dec 10 02:06:07 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: files.amd64,v 1.113 2019/09/07 18:56:01 maxv Exp $
+#	$NetBSD: files.amd64,v 1.114 2019/12/10 02:06:07 manu Exp $
 #
 # new style config file for amd64 architecture
 #
@@ -30,6 +30,10 @@ defflag opt_spectre.h	SPECTRE_V2_GCC_MIT
 defflag			USER_LDT
 defflag eisa.h		EISA
 
+# Multiboot support
+defflag	opt_multiboot.h	MULTIBOOT
+file	arch/x86/x86/multiboot2.c		multiboot
+
 # Start code
 file	arch/amd64/amd64/locore.S		machdep
 file	arch/amd64/amd64/vector.S		machdep

Index: src/sys/arch/amd64/conf/kern.ldscript
diff -u src/sys/arch/amd64/conf/kern.ldscript:1.27 src/sys/arch/amd64/conf/kern.ldscript:1.28
--- src/sys/arch/amd64/conf/kern.ldscript:1.27	Mon Aug 20 15:04:51 2018
+++ src/sys/arch/amd64/conf/kern.ldscript	Tue Dec 10 02:06:07 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern.ldscript,v 1.27 2018/08/20 15:04:51 maxv Exp $	*/
+/*	$NetBSD: kern.ldscript,v 1.28 2019/12/10 02:06:07 manu Exp $	*/
 
 #include "assym.h"
 
@@ -13,9 +13,13 @@ __LARGE_PAGE_SIZE = 0x200000 ;
 ENTRY(_start)
 SECTIONS
 {
+	multiboot 0x4000 :
+	{
+		KEEP(*(multiboot));
+	}
 	.text : AT (ADDR(.text) & 0x0fffffff)
 	{
-		. = ALIGN(__PAGE_SIZE);
+		. = ALIGN(__LARGE_PAGE_SIZE);
 		__text_user_start = . ;
 		*(.text.user)
 		. = ALIGN(__PAGE_SIZE);

Index: src/sys/arch/x86/x86/efi.c
diff -u src/sys/arch/x86/x86/efi.c:1.20 src/sys/arch/x86/x86/efi.c:1.21
--- src/sys/arch/x86/x86/efi.c:1.20	Fri Oct 18 00:56:25 2019
+++ src/sys/arch/x86/x86/efi.c	Tue Dec 10 02:06:07 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: efi.c,v 1.20 2019/10/18 00:56:25 manu Exp $	*/
+/*	$NetBSD: efi.c,v 1.21 2019/12/10 02:06:07 manu Exp $	*/
 
 /*-
  * Copyright (c) 2016 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: efi.c,v 1.20 2019/10/18 00:56:25 manu Exp $");
+__KERNEL_RCSID(0, "$NetBSD: efi.c,v 1.21 2019/12/10 02:06:07 manu Exp $");
 
 #include <sys/kmem.h>
 #include <sys/param.h>
@@ -77,11 +77,6 @@ efi_getva(paddr_t pa)
 	vaddr_t va;
 	int rv;
 
-#ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS
-	if (mm_md_direct_mapped_phys(pa, &va))
-		return va;
-#endif
-
 	rv = _x86_memio_map(x86_bus_space_mem, pa,     
 	    PAGE_SIZE, 0, (bus_space_handle_t *)&va);   
 	if (rv != 0) {
@@ -98,15 +93,6 @@ efi_getva(paddr_t pa)
 static void
 efi_relva(paddr_t pa, vaddr_t va)
 {
-
-#ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS
-	vaddr_t va0 __diagused;
-	if (mm_md_direct_mapped_phys(pa, &va0)) {
-		KASSERT(va0 == va);
-		return;
-	}
-#endif
-
 	(void)_x86_memio_unmap(x86_bus_space_mem, (bus_space_handle_t)va,
 	    PAGE_SIZE, NULL);
 }

Index: src/sys/arch/x86/x86/multiboot2.c
diff -u src/sys/arch/x86/x86/multiboot2.c:1.2 src/sys/arch/x86/x86/multiboot2.c:1.3
--- src/sys/arch/x86/x86/multiboot2.c:1.2	Fri Oct 18 14:59:22 2019
+++ src/sys/arch/x86/x86/multiboot2.c	Tue Dec 10 02:06:07 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: multiboot2.c,v 1.2 2019/10/18 14:59:22 hannken Exp $	*/
+/*	$NetBSD: multiboot2.c,v 1.3 2019/12/10 02:06:07 manu Exp $	*/
 
 /*-
  * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: multiboot2.c,v 1.2 2019/10/18 14:59:22 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: multiboot2.c,v 1.3 2019/12/10 02:06:07 manu Exp $");
 
 #include "opt_multiboot.h"
 
@@ -48,7 +48,19 @@ __KERNEL_RCSID(0, "$NetBSD: multiboot2.c
 #include <x86/efi.h>
 
 #include <machine/bootinfo.h>
-#include <machine/multiboot2.h>
+#include <arch/i386/include/multiboot2.h>
+
+#ifdef _LOCORE64
+typedef uint64_t   locore_vaddr_t;
+typedef Elf64_Shdr locore_Elf_Shdr;
+typedef Elf64_Word locore_Elf_Word;
+typedef Elf64_Addr locore_Elf_Addr;
+#else
+typedef vaddr_t   locore_vaddr_t;
+typedef Elf_Shdr locore_Elf_Shdr;
+typedef Elf_Word locore_Elf_Word;
+typedef Elf_Addr locore_Elf_Addr;
+#endif
 
 #if !defined(MULTIBOOT)
 #  error "MULTIBOOT not defined; this cannot happen."
@@ -65,12 +77,15 @@ __KERNEL_RCSID(0, "$NetBSD: multiboot2.c
 	    (efi_char *)__UNCONST(wstring))
 
 struct multiboot_symbols {
-	void *	s_symstart;
-	size_t	s_symsize;
-	void *	s_strstart;
-	size_t	s_strsize;
+	uint32_t s_symstart;
+	uint32_t s_symsize;
+	uint32_t s_strstart;
+	uint32_t s_strsize;
 };	
 
+void multiboot2_copy_syms(struct multiboot_tag_elf_sections *,
+			  struct multiboot_symbols *,
+			  bool *, int **, void *, vaddr_t);
 /*
  * Because of clashes between multiboot.h and multiboot2.h we
  * cannot include both, and we need to redefine here:
@@ -82,21 +97,24 @@ bool            multiboot2_ksyms_addsyms
 
 extern int              biosbasemem;
 extern int              biosextmem;
+#ifdef __i386__
 extern int              biosmem_implicit;
+#endif
 extern int              boothowto;
 extern struct bootinfo  bootinfo;
 extern int              end;
 extern int *            esym;
+extern char             start;    
 
 /* 
  * 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;
+char multiboot_info[16384] = "\0\0\0\0";
+bool multiboot2_enabled = false;
+bool has_syms = false;
+struct multiboot_symbols Multiboot_Symbols;
 
 
 #define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE))
@@ -151,17 +169,21 @@ exit_bs:
 	return;
 }
 
-static void
-copy_syms(struct multiboot_tag_elf_sections *mbt_elf)
+void
+multiboot2_copy_syms(struct multiboot_tag_elf_sections *mbt_elf, 
+		     struct multiboot_symbols *ms,
+		     bool *has_symsp, int **esymp, void *endp,
+		     vaddr_t kernbase)
 {
 	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);
+	locore_Elf_Shdr *symtabp, *strtabp;
+	locore_Elf_Word symsize, strsize;
+	locore_Elf_Addr symaddr, straddr;
+	locore_Elf_Addr symstart, strstart;
+	locore_Elf_Addr cp1src, cp1dst;
+	locore_Elf_Word cp1size;
+	locore_Elf_Addr cp2src, cp2dst;
+	locore_Elf_Word cp2size;
 
 	/*
 	 * Locate a symbol table and its matching string table in the
@@ -171,20 +193,20 @@ copy_syms(struct multiboot_tag_elf_secti
 	symtabp = strtabp = NULL;
 	for (i = 0; i < mbt_elf->num && symtabp == NULL &&
 	    strtabp == NULL; i++) {
-		Elf32_Shdr *shdrp;
+		locore_Elf_Shdr *shdrp;
 
-		shdrp = &((Elf32_Shdr *)mbt_elf->sections)[i];
+		shdrp = &((locore_Elf_Shdr *)mbt_elf->sections)[i];
 
 		if ((shdrp->sh_type == SHT_SYMTAB) &&
 		    shdrp->sh_link != SHN_UNDEF) {
-			Elf32_Shdr *shdrp2;
+			locore_Elf_Shdr *shdrp2;
 
-			shdrp2 = &((Elf32_Shdr *)mbt_elf->sections)
+			shdrp2 = &((locore_Elf_Shdr *)mbt_elf->sections)
 			    [shdrp->sh_link];
 
 			if (shdrp2->sh_type == SHT_STRTAB) {
-				symtabp = shdrp;
-				strtabp = shdrp2;
+				symtabp = (locore_Elf_Shdr *)shdrp;
+				strtabp = (locore_Elf_Shdr *)shdrp2;
 			}
 		}
 	}
@@ -208,47 +230,48 @@ copy_syms(struct multiboot_tag_elf_secti
 	 * 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);
+        if ((void *)(uintptr_t)symaddr < endp &&
+	    (void *)(uintptr_t)straddr < endp) {
+		cp1src = symaddr; cp1size = symsize;
+		cp2src = straddr; cp2size = strsize;
+        } else if ((void *)(uintptr_t)symaddr > endp &&
+		   (void *)(uintptr_t)straddr < endp) {
+		cp1src = symaddr; cp1size = symsize;
+		cp2src = straddr; cp2size = strsize;
+        } else if ((void *)(uintptr_t)symaddr < endp &&
+		   (void *)(uintptr_t)straddr > endp) {
+		cp1src = straddr; cp1size = strsize;
+		cp2src = symaddr; cp2size = 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);
+		/* symaddr and straddr are both over end */
+		if (symaddr < straddr) {
+			cp1src = symaddr; cp1size = symsize;
+			cp2src = straddr; cp2size = strsize;
 		} else {
-			strstart = RELOC(Elf32_Addr, &end);
-			symstart = strstart + strsize;
-			memcpy((void *)strstart, (void *)straddr, strsize);
-			memcpy((void *)symstart, (void *)symaddr, symsize);
+			cp1src = straddr; cp1size = strsize;
+			cp2src = symaddr; cp2size = symsize;
 		}
 	}
 
-	*RELOC(bool *, &has_syms) = true;
-	*RELOC(int *, &esym) =
-	    (int)(symstart + symsize + strsize + KERNBASE);
+	cp1dst = (locore_Elf_Addr)(uintptr_t)endp;
+	cp2dst = (locore_Elf_Addr)(uintptr_t)endp + cp1size;
+
+	(void)memcpy((void *)(uintptr_t)cp1dst,
+		     (void *)(uintptr_t)cp1src, cp1size);
+	(void)memcpy((void *)(uintptr_t)cp2dst,
+		     (void *)(uintptr_t)cp2src, cp2size);
+
+	symstart = (cp1src == symaddr) ? cp1dst : cp2dst;
+	strstart = (cp1src == straddr) ? cp1dst : cp2dst;
 
-	ms->s_symstart = (void *)(symstart + KERNBASE);
+	ms->s_symstart = symstart + kernbase;
 	ms->s_symsize  = symsize;
-	ms->s_strstart = (void *)(strstart + KERNBASE);
+	ms->s_strstart = strstart + kernbase;
 	ms->s_strsize  = strsize;
+
+	*has_symsp = true;
+	*esymp = (int *)((uintptr_t)endp + symsize + strsize + kernbase);
+
 }
 
 void
@@ -313,7 +336,12 @@ multiboot2_pre_reloc(char *mbi)
 		efi_exit_bs(efi_systbl, efi_ih);	
 
 	if (mbt_elf)
-		copy_syms(mbt_elf);
+		multiboot2_copy_syms(mbt_elf,
+		    RELOC(struct multiboot_symbols *, &Multiboot_Symbols),
+		    RELOC(bool *, &has_syms),
+		    RELOC(int **, &esym),
+		    RELOC(void *, &end),
+		    KERNBASE);
 
 	return;
 }
@@ -460,11 +488,15 @@ mbi_basic_meminfo(struct multiboot_tag_b
         /* Make sure we don't override user-set variables. */
         if (biosbasemem == 0) {
                 biosbasemem = mbt->mem_lower;
+#ifdef __i386__
                 biosmem_implicit = 1;
+#endif
         }
         if (biosextmem == 0) {
                 biosextmem = mbt->mem_upper;
+#ifdef __i386__
                 biosmem_implicit = 1;
+#endif
         }
 
 	return;
@@ -985,28 +1017,45 @@ bool
 multiboot2_ksyms_addsyms_elf(void)
 {
 	struct multiboot_symbols *ms = &Multiboot_Symbols;
+	vaddr_t symstart = (vaddr_t)ms->s_symstart;
+	vaddr_t strstart = (vaddr_t)ms->s_strstart;
+	Elf_Ehdr ehdr;
 
-	if (!multiboot2_enabled)
+	if (!multiboot2_enabled || !has_syms)
 		return false;
 
-	if (has_syms) {
-		Elf32_Ehdr ehdr;
+	KASSERT(esym != 0);
 
-		KASSERT(esym != 0);
+#ifdef __LP64__
+	/* Adjust pointer as 64 bits */
+	symstart &= 0xffffffff;
+	symstart |= ((vaddr_t)KERNBASE_HI << 32);
+	strstart &= 0xffffffff;
+	strstart |= ((vaddr_t)KERNBASE_HI << 32);
+#endif
 
-		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);
-	}
+	memset(&ehdr, 0, sizeof(ehdr));
+	memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
+	ehdr.e_ident[EI_CLASS] = ELFCLASS;
+	ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+	ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+	ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV;
+	ehdr.e_ident[EI_ABIVERSION] = 0;
+	ehdr.e_type = ET_EXEC;
+#ifdef __amd64__
+	ehdr.e_machine = EM_X86_64;
+#elif __i386__
+	ehdr.e_machine = EM_386;
+#else
+	#error "Unknwo ELF machine type"
+#endif
+	ehdr.e_version = 1;
+	ehdr.e_entry = (Elf_Addr)&start;
+	ehdr.e_ehsize = sizeof(ehdr);
+
+	ksyms_addsyms_explicit((void *)&ehdr,
+	    (void *)symstart, ms->s_symsize,
+	    (void *)strstart, ms->s_strsize);
 
-	return has_syms;
+	return true;
 }

Reply via email to