Module Name:    src
Committed By:   martin
Date:           Tue Sep 17 19:32:01 UTC 2019

Modified Files:
        src/share/man/man8/man8.x86 [netbsd-9]: boot.8
        src/sys/arch/i386/include [netbsd-9]: Makefile
        src/sys/arch/i386/stand/boot [netbsd-9]: Makefile.boot
        src/sys/arch/i386/stand/dosboot [netbsd-9]: Makefile
        src/sys/arch/i386/stand/efiboot [netbsd-9]: Makefile.efiboot boot.c
            efiboot.c efiboot.h eficons.c efimemory.c
        src/sys/arch/i386/stand/efiboot/bootia32 [netbsd-9]: Makefile
            efibootia32.c
        src/sys/arch/i386/stand/efiboot/bootx64 [netbsd-9]: Makefile
            efibootx64.c
        src/sys/arch/i386/stand/lib [netbsd-9]: Makefile biosdisk.c biosdisk.h
            bootinfo_memmap.c exec.c libi386.h multiboot.S pread.c
        src/sys/arch/i386/stand/netboot [netbsd-9]: Makefile.netboot
        src/sys/arch/i386/stand/pxeboot [netbsd-9]: Makefile
Added Files:
        src/sys/arch/i386/include [netbsd-9]: multiboot2.h
        src/sys/arch/i386/stand/efiboot/bootia32 [netbsd-9]: multiboot32.S
        src/sys/arch/i386/stand/efiboot/bootx64 [netbsd-9]: multiboot64.S
        src/sys/arch/i386/stand/lib [netbsd-9]: exec_multiboot1.c
            exec_multiboot2.c

Log Message:
Pull up following revision(s) (requested by manu in ticket #203):

        sys/arch/i386/include/multiboot2.h: revision 1.1
        sys/arch/i386/stand/lib/exec.c: revision 1.74
        sys/arch/i386/stand/efiboot/efiboot.c: revision 1.11
        sys/arch/i386/stand/efiboot/bootia32/multiboot32.S: revision 1.1
        sys/arch/i386/stand/lib/biosdisk.c: revision 1.52
        sys/arch/i386/stand/efiboot/bootx64/efibootx64.c: revision 1.5
        sys/arch/i386/stand/efiboot/eficons.c: revision 1.7
        sys/arch/i386/stand/efiboot/bootia32/efibootia32.c: revision 1.5
        sys/arch/i386/stand/lib/libi386.h: revision 1.45
        sys/arch/i386/stand/lib/bootinfo_memmap.c: revision 1.6
        sys/arch/i386/stand/lib/pread.c: revision 1.8
        sys/arch/i386/stand/efiboot/efiboot.h: revision 1.10
        sys/arch/i386/stand/efiboot/bootia32/Makefile: revision 1.3
        sys/arch/i386/stand/lib/Makefile: revision 1.47
        sys/arch/i386/stand/efiboot/bootx64/Makefile: revision 1.2
        sys/arch/i386/stand/lib/multiboot.S: revision 1.3
        sys/arch/i386/stand/efiboot/bootx64/multiboot64.S: revision 1.1
        sys/arch/i386/stand/efiboot/efimemory.c: revision 1.9
        sys/arch/i386/stand/efiboot/boot.c: revision 1.16
        sys/arch/i386/include/Makefile: revision 1.50
        sys/arch/i386/stand/efiboot/Makefile.efiboot: revision 1.16
        share/man/man8/man8.x86/boot.8: revision 1.20
        sys/arch/i386/stand/boot/Makefile.boot: revision 1.73
        sys/arch/i386/stand/pxeboot/Makefile: revision 1.26
        sys/arch/i386/stand/lib/exec_multiboot1.c: revision 1.1
        sys/arch/i386/stand/netboot/Makefile.netboot: revision 1.11
        sys/arch/i386/stand/lib/exec_multiboot2.c: revision 1.1
        sys/arch/i386/stand/lib/biosdisk.h: revision 1.12
        sys/arch/i386/stand/lib/exec_multiboot2.c: revision 1.2
        sys/arch/i386/stand/dosboot/Makefile: revision 1.32

Add multiboot 2 support to x86 bootloaders

multiboot 2 is required to boot Xen on an EFI system.

This also require a kernel patch for properly discovering
the ACPI RSDP, which is available after 20190912, in
src/sys/arch/x86/acpi/acpi_machdep.c 1.26-1.28

There are a few missing bit in this multiboot 2 implementation
(which are unused by Xen):
- Header tags Address, Freambuffer, and Relocatable are ignored
- Tags APM and Network are not provided
- Tags ACPI old and ACP new are only provided for ACPI boot
- Tag boot device does not provides the subpart (BSD disklabel partition)
Notes:
- multiboot2 is disabled in dosboot, otherwise the binary
  gets too big and build fails.
- in src/sys/arch/i386/stand/efiboot, consinit() is renamed
  as efi_consinit() to avoid prototype conflicts in src/sys/sys/systm.h

Remove debug define.

It remained there unseen because it was misspelled!

Remove obsoeolete BUGS note that UEFI bootloader does not support multiboot


To generate a diff of this commit:
cvs rdiff -u -r1.15.2.1 -r1.15.2.2 src/share/man/man8/man8.x86/boot.8
cvs rdiff -u -r1.49 -r1.49.4.1 src/sys/arch/i386/include/Makefile
cvs rdiff -u -r0 -r1.1.2.2 src/sys/arch/i386/include/multiboot2.h
cvs rdiff -u -r1.72 -r1.72.4.1 src/sys/arch/i386/stand/boot/Makefile.boot
cvs rdiff -u -r1.31 -r1.31.6.1 src/sys/arch/i386/stand/dosboot/Makefile
cvs rdiff -u -r1.15 -r1.15.2.1 \
    src/sys/arch/i386/stand/efiboot/Makefile.efiboot
cvs rdiff -u -r1.13.2.1 -r1.13.2.2 src/sys/arch/i386/stand/efiboot/boot.c
cvs rdiff -u -r1.10 -r1.10.2.1 src/sys/arch/i386/stand/efiboot/efiboot.c
cvs rdiff -u -r1.9 -r1.9.2.1 src/sys/arch/i386/stand/efiboot/efiboot.h
cvs rdiff -u -r1.6 -r1.6.6.1 src/sys/arch/i386/stand/efiboot/eficons.c
cvs rdiff -u -r1.8 -r1.8.2.1 src/sys/arch/i386/stand/efiboot/efimemory.c
cvs rdiff -u -r1.2 -r1.2.24.1 \
    src/sys/arch/i386/stand/efiboot/bootia32/Makefile
cvs rdiff -u -r1.4 -r1.4.6.1 \
    src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c
cvs rdiff -u -r0 -r1.1.2.2 \
    src/sys/arch/i386/stand/efiboot/bootia32/multiboot32.S
cvs rdiff -u -r1.1 -r1.1.26.1 \
    src/sys/arch/i386/stand/efiboot/bootx64/Makefile
cvs rdiff -u -r1.4 -r1.4.6.1 \
    src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c
cvs rdiff -u -r0 -r1.1.2.2 \
    src/sys/arch/i386/stand/efiboot/bootx64/multiboot64.S
cvs rdiff -u -r1.45.8.1 -r1.45.8.2 src/sys/arch/i386/stand/lib/Makefile
cvs rdiff -u -r1.49.6.1 -r1.49.6.2 src/sys/arch/i386/stand/lib/biosdisk.c
cvs rdiff -u -r1.10.6.1 -r1.10.6.2 src/sys/arch/i386/stand/lib/biosdisk.h
cvs rdiff -u -r1.5 -r1.5.70.1 src/sys/arch/i386/stand/lib/bootinfo_memmap.c
cvs rdiff -u -r1.73 -r1.73.2.1 src/sys/arch/i386/stand/lib/exec.c
cvs rdiff -u -r0 -r1.1.2.2 src/sys/arch/i386/stand/lib/exec_multiboot1.c
cvs rdiff -u -r0 -r1.2.2.2 src/sys/arch/i386/stand/lib/exec_multiboot2.c
cvs rdiff -u -r1.44 -r1.44.2.1 src/sys/arch/i386/stand/lib/libi386.h
cvs rdiff -u -r1.2 -r1.2.20.1 src/sys/arch/i386/stand/lib/multiboot.S
cvs rdiff -u -r1.7 -r1.7.70.1 src/sys/arch/i386/stand/lib/pread.c
cvs rdiff -u -r1.10 -r1.10.34.1 \
    src/sys/arch/i386/stand/netboot/Makefile.netboot
cvs rdiff -u -r1.25 -r1.25.6.1 src/sys/arch/i386/stand/pxeboot/Makefile

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

Modified files:

Index: src/share/man/man8/man8.x86/boot.8
diff -u src/share/man/man8/man8.x86/boot.8:1.15.2.1 src/share/man/man8/man8.x86/boot.8:1.15.2.2
--- src/share/man/man8/man8.x86/boot.8:1.15.2.1	Fri Sep 13 07:00:14 2019
+++ src/share/man/man8/man8.x86/boot.8	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-.\"	$NetBSD: boot.8,v 1.15.2.1 2019/09/13 07:00:14 martin Exp $
+.\"	$NetBSD: boot.8,v 1.15.2.2 2019/09/17 19:32:00 martin Exp $
 .\"
 .\" Copyright (c) 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -821,11 +821,6 @@ field of the
 .Nx
 disklabel (if it is a hard disk).
 .Pp
-.Ic multiboot
-is not supported by
-.Tn UEFI
-bootstrap code.
-.Pp
 .Tn UEFI
 implementation are supposed to support either
 .Xr mbr 8

Index: src/sys/arch/i386/include/Makefile
diff -u src/sys/arch/i386/include/Makefile:1.49 src/sys/arch/i386/include/Makefile:1.49.4.1
--- src/sys/arch/i386/include/Makefile:1.49	Thu Jul 12 10:46:44 2018
+++ src/sys/arch/i386/include/Makefile	Tue Sep 17 19:31:59 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.49 2018/07/12 10:46:44 maxv Exp $
+#	$NetBSD: Makefile,v 1.49.4.1 2019/09/17 19:31:59 martin Exp $
 
 INCSDIR= /usr/include/i386
 
@@ -15,7 +15,7 @@ INCS=	ansi.h aout_machdep.h apmvar.h asm
 	joystick.h \
 	kcore.h \
 	limits.h lock.h \
-	math.h mcontext.h mutex.h mtrr.h multiboot.h \
+	math.h mcontext.h mutex.h mtrr.h multiboot.h multiboot2.h \
 	param.h pcb.h pio.h pmap.h proc.h profile.h psl.h \
 	pte.h ptrace.h \
 	reg.h rwlock.h \

Index: src/sys/arch/i386/stand/boot/Makefile.boot
diff -u src/sys/arch/i386/stand/boot/Makefile.boot:1.72 src/sys/arch/i386/stand/boot/Makefile.boot:1.72.4.1
--- src/sys/arch/i386/stand/boot/Makefile.boot:1.72	Wed Jul 25 23:45:32 2018
+++ src/sys/arch/i386/stand/boot/Makefile.boot	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.boot,v 1.72 2018/07/25 23:45:32 kamil Exp $
+# $NetBSD: Makefile.boot,v 1.72.4.1 2019/09/17 19:32:00 martin Exp $
 
 S=	${.CURDIR}/../../../../..
 
@@ -11,7 +11,8 @@ NEWVERSWHAT?= "BIOS Boot"
 
 AFLAGS.biosboot.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
 
-SOURCES?= biosboot.S boot2.c conf.c devopen.c exec.c
+SOURCES?= biosboot.S boot2.c conf.c devopen.c exec.c \
+	  exec_multiboot1.c exec_multiboot2.c
 SRCS= ${SOURCES}
 
 .include <bsd.init.mk>

Index: src/sys/arch/i386/stand/dosboot/Makefile
diff -u src/sys/arch/i386/stand/dosboot/Makefile:1.31 src/sys/arch/i386/stand/dosboot/Makefile:1.31.6.1
--- src/sys/arch/i386/stand/dosboot/Makefile:1.31	Sat Jun  2 14:30:07 2018
+++ src/sys/arch/i386/stand/dosboot/Makefile	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.31 2018/06/02 14:30:07 christos Exp $
+#	$NetBSD: Makefile,v 1.31.6.1 2019/09/17 19:32:00 martin Exp $
 
 S=	${.CURDIR}/../../../..
 
@@ -8,12 +8,13 @@ NEWVERSWHAT=	"DOS Boot"
 STARTFILE=	${DOSSTART}
 RELOC=		0x100
 
-SRCS= main.c devopen.c exec.c
+SRCS= main.c devopen.c exec.c exec_multiboot1.c exec_multiboot2.c
 
 CPPFLAGS+= -DSLOW	# for libz
 CPPFLAGS+= -DCOMPAT_386BSD_MBRPART
 CPPFLAGS+= -DXMS
 CPPFLAGS+= -DLIBSA_ENABLE_LS_OP
+CPPFLAGS+= -DNO_MULTIBOOT2 # keep the binary small
 #uncomment if there are problems with memory detection
 #CPPFLAGS+= -DCONSERVATIVE_MEMDETECT
 

Index: src/sys/arch/i386/stand/efiboot/Makefile.efiboot
diff -u src/sys/arch/i386/stand/efiboot/Makefile.efiboot:1.15 src/sys/arch/i386/stand/efiboot/Makefile.efiboot:1.15.2.1
--- src/sys/arch/i386/stand/efiboot/Makefile.efiboot:1.15	Fri Jul 26 11:30:31 2019
+++ src/sys/arch/i386/stand/efiboot/Makefile.efiboot	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.efiboot,v 1.15 2019/07/26 11:30:31 nonaka Exp $
+# $NetBSD: Makefile.efiboot,v 1.15.2.1 2019/09/17 19:32:00 martin Exp $
 
 S=		${.CURDIR}/../../../../..
 
@@ -18,6 +18,7 @@ SOURCES+= efidisk.c efidisk_ll.c efigets
 SOURCES+= efinet.c efipxe.c
 LIBI386SRCS= biosdisk.c bootinfo.c bootinfo_biosgeom.c bootmenu.c
 LIBI386SRCS+= diskbuf.c exec.c menuutils.c parseutils.c pread.c
+LIBI386SRCS+= exec_multiboot1.c exec_multiboot2.c
 # use our own nfs implementation
 LIBSASRCS+= nfs.c
 SRCS= ${SOURCES} ${EXTRA_SOURCES} ${LIBI386SRCS} ${LIBSASRCS}

Index: src/sys/arch/i386/stand/efiboot/boot.c
diff -u src/sys/arch/i386/stand/efiboot/boot.c:1.13.2.1 src/sys/arch/i386/stand/efiboot/boot.c:1.13.2.2
--- src/sys/arch/i386/stand/efiboot/boot.c:1.13.2.1	Fri Sep 13 07:00:13 2019
+++ src/sys/arch/i386/stand/efiboot/boot.c	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: boot.c,v 1.13.2.1 2019/09/13 07:00:13 martin Exp $	*/
+/*	$NetBSD: boot.c,v 1.13.2.2 2019/09/17 19:32:00 martin Exp $	*/
 
 /*-
  * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
@@ -558,7 +558,7 @@ command_consdev(char *arg)
 						goto error;
 				}
 			}
-			consinit(cdp->tag, ioport, speed);
+			efi_consinit(cdp->tag, ioport, speed);
 			print_banner();
 			return;
 		}

Index: src/sys/arch/i386/stand/efiboot/efiboot.c
diff -u src/sys/arch/i386/stand/efiboot/efiboot.c:1.10 src/sys/arch/i386/stand/efiboot/efiboot.c:1.10.2.1
--- src/sys/arch/i386/stand/efiboot/efiboot.c:1.10	Mon Jul 29 12:37:26 2019
+++ src/sys/arch/i386/stand/efiboot/efiboot.c	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: efiboot.c,v 1.10 2019/07/29 12:37:26 nonaka Exp $	*/
+/*	$NetBSD: efiboot.c,v 1.10.2.1 2019/09/17 19:32:00 martin Exp $	*/
 
 /*-
  * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
@@ -39,6 +39,7 @@ uintptr_t efi_main_sp;
 physaddr_t efi_loadaddr, efi_kernel_start;
 u_long efi_kernel_size;
 bool efi_cleanuped;
+struct btinfo_efimemmap *btinfo_efimemmap = NULL;
 
 static EFI_PHYSICAL_ADDRESS heap_start = EFI_ALLOCATE_MAX_ADDRESS;
 static UINTN heap_size = 1 * 1024 * 1024;			/* 1MB */
@@ -109,7 +110,6 @@ efi_cleanup(void)
 	EFI_MEMORY_DESCRIPTOR *desc;
 	UINTN NoEntries, MapKey, DescriptorSize;
 	UINT32 DescriptorVersion;
-	struct btinfo_efimemmap *bim;
 	size_t allocsz;
 
 	clearit();
@@ -138,12 +138,12 @@ efi_cleanup(void)
 	efi_memory_compact_map(desc, &NoEntries, DescriptorSize);
 	allocsz = sizeof(struct btinfo_efimemmap) - 1
 	    + NoEntries * DescriptorSize;
-	bim = alloc(allocsz);
-	bim->num = NoEntries;
-	bim->version = DescriptorVersion;
-	bim->size = DescriptorSize;
-	memcpy(bim->memmap, desc, NoEntries * DescriptorSize);
-	BI_ADD(bim, BTINFO_EFIMEMMAP, allocsz);
+	btinfo_efimemmap = alloc(allocsz);
+	btinfo_efimemmap->num = NoEntries;
+	btinfo_efimemmap->version = DescriptorVersion;
+	btinfo_efimemmap->size = DescriptorSize;
+	memcpy(btinfo_efimemmap->memmap, desc, NoEntries * DescriptorSize);
+	BI_ADD(btinfo_efimemmap, BTINFO_EFIMEMMAP, allocsz);
 }
 
 static void

Index: src/sys/arch/i386/stand/efiboot/efiboot.h
diff -u src/sys/arch/i386/stand/efiboot/efiboot.h:1.9 src/sys/arch/i386/stand/efiboot/efiboot.h:1.9.2.1
--- src/sys/arch/i386/stand/efiboot/efiboot.h:1.9	Mon Jul 29 11:28:51 2019
+++ src/sys/arch/i386/stand/efiboot/efiboot.h	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: efiboot.h,v 1.9 2019/07/29 11:28:51 nonaka Exp $	*/
+/*	$NetBSD: efiboot.h,v 1.9.2.1 2019/09/17 19:32:00 martin Exp $	*/
 
 /*-
  * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
@@ -65,7 +65,7 @@ int utf8_to_ucs2(const char *, CHAR16 **
 
 /* eficons.c */
 int cninit(void);
-void consinit(int, int, int);
+void efi_consinit(int, int, int);
 void efi_cons_show(void);
 void command_text(char *);
 void command_gop(char *);
@@ -80,11 +80,14 @@ void efi_disk_show(void);
 
 /* efimemory.c */
 void efi_memory_probe(void);
+void efi_memory_probe_reloc(EFI_PHYSICAL_ADDRESS, EFI_PHYSICAL_ADDRESS, bool);
 void efi_memory_show_map(bool, bool);
 EFI_MEMORY_DESCRIPTOR *efi_memory_get_map(UINTN *, UINTN *, UINTN *, UINT32 *,
     bool);
 EFI_MEMORY_DESCRIPTOR *efi_memory_compact_map(EFI_MEMORY_DESCRIPTOR *, UINTN *,
     UINTN);
+struct bi_memmap_entry;
+int efi_memory_get_memmap(struct bi_memmap_entry **memmap, size_t *num);
 
 /* efinet.c */
 void efi_net_probe(void);

Index: src/sys/arch/i386/stand/efiboot/eficons.c
diff -u src/sys/arch/i386/stand/efiboot/eficons.c:1.6 src/sys/arch/i386/stand/efiboot/eficons.c:1.6.6.1
--- src/sys/arch/i386/stand/efiboot/eficons.c:1.6	Wed May 16 19:53:54 2018
+++ src/sys/arch/i386/stand/efiboot/eficons.c	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: eficons.c,v 1.6 2018/05/16 19:53:54 jakllsch Exp $	*/
+/*	$NetBSD: eficons.c,v 1.6.6.1 2019/09/17 19:32:00 martin Exp $	*/
 
 /*-
  * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
@@ -91,7 +91,7 @@ getcomaddr(int idx)
  * XXX only pass console parameters to kernel.
  */
 void
-consinit(int dev, int ioport, int speed)
+efi_consinit(int dev, int ioport, int speed)
 {
 	int i;
 
@@ -183,7 +183,7 @@ cninit(void)
 	eficons_init_video();
 	efi_com_probe();
 
-	consinit(boot_params.bp_consdev, boot_params.bp_consaddr,
+	efi_consinit(boot_params.bp_consdev, boot_params.bp_consaddr,
 	    boot_params.bp_conspeed);
 
 	return 0;

Index: src/sys/arch/i386/stand/efiboot/efimemory.c
diff -u src/sys/arch/i386/stand/efiboot/efimemory.c:1.8 src/sys/arch/i386/stand/efiboot/efimemory.c:1.8.2.1
--- src/sys/arch/i386/stand/efiboot/efimemory.c:1.8	Mon Jul 29 11:33:07 2019
+++ src/sys/arch/i386/stand/efiboot/efimemory.c	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: efimemory.c,v 1.8 2019/07/29 11:33:07 nonaka Exp $	*/
+/*	$NetBSD: efimemory.c,v 1.8.2.1 2019/09/17 19:32:00 martin Exp $	*/
 
 /*-
  * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
@@ -193,6 +193,40 @@ efi_memory_compact_map(EFI_MEMORY_DESCRI
 	return desc;
 }
 
+int
+efi_memory_get_memmap(struct bi_memmap_entry **memmapp, size_t *num)
+{
+	EFI_STATUS status;
+	EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next;
+	UINTN i, NoEntries, MapKey, DescriptorSize;
+	UINT32 DescriptorVersion;
+	UINTN cols, rows;
+	struct bi_memmap_entry *memmap;
+
+	status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut,
+	    ST->ConOut->Mode->Mode, &cols, &rows);
+	if (EFI_ERROR(status) || rows <= 2)
+		return -1;
+
+	mdtop = efi_memory_get_map(&NoEntries, &MapKey, &DescriptorSize,
+	    &DescriptorVersion, true);
+	efi_memory_compact_map(mdtop, &NoEntries, DescriptorSize);
+
+	memmap = alloc(sizeof(*memmap) * NoEntries);
+
+	for (i = 0, md = mdtop; i < NoEntries; i++, md = next) {
+		memmap[i].addr = md->PhysicalStart;
+		memmap[i].size = md->NumberOfPages * EFI_PAGE_SIZE;
+		memmap[i].type = getmemtype(md);
+
+		next = NextMemoryDescriptor(md, DescriptorSize);
+	}
+	
+	*memmapp = memmap;
+	*num = NoEntries;
+	return 0;
+}
+
 /*
  * get memory size below 1MB
  */

Index: src/sys/arch/i386/stand/efiboot/bootia32/Makefile
diff -u src/sys/arch/i386/stand/efiboot/bootia32/Makefile:1.2 src/sys/arch/i386/stand/efiboot/bootia32/Makefile:1.2.24.1
--- src/sys/arch/i386/stand/efiboot/bootia32/Makefile:1.2	Tue Feb 21 10:53:37 2017
+++ src/sys/arch/i386/stand/efiboot/bootia32/Makefile	Tue Sep 17 19:32:00 2019
@@ -1,9 +1,9 @@
-#	$NetBSD: Makefile,v 1.2 2017/02/21 10:53:37 nonaka Exp $
+#	$NetBSD: Makefile,v 1.2.24.1 2019/09/17 19:32:00 martin Exp $
 
 PROG=		bootia32.efi
 OBJFMT=		pei-i386
 
-EXTRA_SOURCES=	efibootia32.c startprog32.S
+EXTRA_SOURCES=	efibootia32.c startprog32.S multiboot32.S
 
 CPUFLAGS=	-march=i686 -mtune=i686
 GNUEFIARCH=	ia32
@@ -11,7 +11,7 @@ LIBKERN_ARCH=	i386
 LIBGNUEFI_ARCH=	i386
 KLINK_MACHINE=	i386
 
-CFLAGS+=	-m32
+CFLAGS+=	-m32 -DACPI_32BIT_PHYSICAL_ADDRESS
 AFLAGS+=	-m32
 
 .include "${.CURDIR}/../Makefile.efiboot"

Index: src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c
diff -u src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c:1.4 src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c:1.4.6.1
--- src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c:1.4	Tue Mar 27 14:15:05 2018
+++ src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: efibootia32.c,v 1.4 2018/03/27 14:15:05 nonaka Exp $	*/
+/*	$NetBSD: efibootia32.c,v 1.4.6.1 2019/09/17 19:32:00 martin Exp $	*/
 
 /*-
  * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
@@ -36,6 +36,10 @@ extern void (*startprog32)(physaddr_t, u
     physaddr_t, physaddr_t, u_long, void *);
 extern u_int startprog32_size;
 
+void multiboot32_start(physaddr_t, physaddr_t, uint32_t);
+extern void (*multiboot32)(physaddr_t, physaddr_t, uint32_t);
+extern u_int multiboot32_size;
+
 void
 efi_md_init(void)
 {
@@ -43,6 +47,8 @@ efi_md_init(void)
 	EFI_PHYSICAL_ADDRESS addr = EFI_ALLOCATE_MAX_ADDRESS;
 	u_int sz = EFI_SIZE_TO_PAGES(startprog32_size);
 
+	addr = EFI_ALLOCATE_MAX_ADDRESS;
+	sz = EFI_SIZE_TO_PAGES(startprog32_size);
 	status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress,
 	    EfiLoaderData, sz, &addr);
 	if (EFI_ERROR(status))
@@ -50,6 +56,17 @@ efi_md_init(void)
 		    __func__, sz, (uintmax_t)status);
 	startprog32 = (void *)(u_long)addr;
 	CopyMem(startprog32, startprog32_start, startprog32_size);
+
+        addr = EFI_ALLOCATE_MAX_ADDRESS;
+        sz = EFI_SIZE_TO_PAGES(multiboot32_size);
+        status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress,
+            EfiLoaderData, sz, &addr); 
+        if (EFI_ERROR(status))
+                panic("%s: AllocatePages() failed: %d page(s): %" PRIxMAX,
+                    __func__, sz, (uintmax_t)status);
+        multiboot32 = (void *)(u_long)addr;
+        CopyMem(multiboot32, multiboot32_start, multiboot32_size);
+
 }
 
 /* ARGSUSED */
@@ -65,7 +82,7 @@ startprog(physaddr_t entry, uint32_t arg
 
 /* ARGSUSED */
 void
-multiboot(physaddr_t entry, physaddr_t header, physaddr_t sp)
+multiboot(physaddr_t entry, physaddr_t header, physaddr_t sp, uint32_t magic)
 {
-	panic("%s: not implemented", __func__);
+	(*multiboot32)(entry, header, magic);
 }

Index: src/sys/arch/i386/stand/efiboot/bootx64/Makefile
diff -u src/sys/arch/i386/stand/efiboot/bootx64/Makefile:1.1 src/sys/arch/i386/stand/efiboot/bootx64/Makefile:1.1.26.1
--- src/sys/arch/i386/stand/efiboot/bootx64/Makefile:1.1	Tue Jan 24 11:09:14 2017
+++ src/sys/arch/i386/stand/efiboot/bootx64/Makefile	Tue Sep 17 19:32:00 2019
@@ -1,10 +1,10 @@
-#	$NetBSD: Makefile,v 1.1 2017/01/24 11:09:14 nonaka Exp $
+#	$NetBSD: Makefile,v 1.1.26.1 2019/09/17 19:32:00 martin Exp $
 
 PROG=		bootx64.efi
 OBJFMT=		pei-x86-64
 NEWVERSWHAT=	"EFI Boot (x64)"
 
-EXTRA_SOURCES=	efibootx64.c startprog64.S
+EXTRA_SOURCES=	efibootx64.c startprog64.S multiboot64.S
 
 COPTS+=		-mno-red-zone
 CPPFLAGS+=	-DEFI_FUNCTION_WRAPPER

Index: src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c
diff -u src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c:1.4 src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c:1.4.6.1
--- src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c:1.4	Tue Mar 27 14:15:05 2018
+++ src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: efibootx64.c,v 1.4 2018/03/27 14:15:05 nonaka Exp $	*/
+/*	$NetBSD: efibootx64.c,v 1.4.6.1 2019/09/17 19:32:00 martin Exp $	*/
 
 /*-
  * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
@@ -36,13 +36,19 @@ extern void (*startprog64)(physaddr_t, p
     void *, physaddr_t);
 extern u_int startprog64_size;
 
+void multiboot64_start(physaddr_t, physaddr_t, uint32_t);
+extern void (*multiboot64)(physaddr_t, physaddr_t, uint32_t);
+extern u_int multiboot64_size;
+
 void
 efi_md_init(void)
 {
 	EFI_STATUS status;
-	EFI_PHYSICAL_ADDRESS addr = EFI_ALLOCATE_MAX_ADDRESS;
-	u_int sz = EFI_SIZE_TO_PAGES(startprog64_size);
+	EFI_PHYSICAL_ADDRESS addr;
+	u_int sz;
 
+	addr = EFI_ALLOCATE_MAX_ADDRESS;
+	sz = EFI_SIZE_TO_PAGES(startprog64_size);
 	status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress,
 	    EfiLoaderData, sz, &addr);
 	if (EFI_ERROR(status))
@@ -50,6 +56,16 @@ efi_md_init(void)
 		    __func__, sz, (uintmax_t)status);
 	startprog64 = (void *)addr;
 	CopyMem(startprog64, startprog64_start, startprog64_size);
+
+	addr = EFI_ALLOCATE_MAX_ADDRESS;
+	sz = EFI_SIZE_TO_PAGES(multiboot64_size);
+	status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress,
+	    EfiLoaderData, sz, &addr);
+	if (EFI_ERROR(status))
+		panic("%s: AllocatePages() failed: %d page(s): %" PRIxMAX,
+		    __func__, sz, (uintmax_t)status);
+	multiboot64 = (void *)addr;
+	CopyMem(multiboot64, multiboot64_start, multiboot64_size);
 }
 
 /* ARGSUSED */
@@ -70,7 +86,7 @@ startprog(physaddr_t entry, uint32_t arg
 
 /* ARGSUSED */
 void
-multiboot(physaddr_t entry, physaddr_t header, physaddr_t sp)
+multiboot(physaddr_t entry, physaddr_t header, physaddr_t sp, uint32_t magic)
 {
-	panic("%s: not implemented", __func__);
+	(*multiboot64)(entry, header, magic);
 }

Index: src/sys/arch/i386/stand/lib/Makefile
diff -u src/sys/arch/i386/stand/lib/Makefile:1.45.8.1 src/sys/arch/i386/stand/lib/Makefile:1.45.8.2
--- src/sys/arch/i386/stand/lib/Makefile:1.45.8.1	Fri Sep 13 07:00:13 2019
+++ src/sys/arch/i386/stand/lib/Makefile	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.45.8.1 2019/09/13 07:00:13 martin Exp $
+#	$NetBSD: Makefile,v 1.45.8.2 2019/09/17 19:32:00 martin Exp $
 
 S?=	${.CURDIR}/../../../..
 
@@ -18,6 +18,7 @@ CPPFLAGS= -I$S/lib/libsa ${I386CPPFLAGS}
 #CPPFLAGS+= -DNO_DISKLABEL
 #CPPFLAGS+= -DNO_GPT
 #CPPFLAGS+= -DNO_RAIDFRAME
+#CPPFLAGS+= -DNO_MULTIBOOT2
 #CPPFLAGS+= -DSAVE_MEMORY
 
 SRCS= pcio.c conio.S comio.S comio_direct.c biosvideomode.S

Index: src/sys/arch/i386/stand/lib/biosdisk.c
diff -u src/sys/arch/i386/stand/lib/biosdisk.c:1.49.6.1 src/sys/arch/i386/stand/lib/biosdisk.c:1.49.6.2
--- src/sys/arch/i386/stand/lib/biosdisk.c:1.49.6.1	Fri Sep 13 07:00:13 2019
+++ src/sys/arch/i386/stand/lib/biosdisk.c	Tue Sep 17 19:31:59 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: biosdisk.c,v 1.49.6.1 2019/09/13 07:00:13 martin Exp $	*/
+/*	$NetBSD: biosdisk.c,v 1.49.6.2 2019/09/17 19:31:59 martin Exp $	*/
 
 /*
  * Copyright (c) 1996, 1998
@@ -184,10 +184,8 @@ const struct gpt_part gpt_parts[] = {
 };
 #endif /* NO_GPT */
 
-#ifdef _STANDALONE
-static struct btinfo_bootdisk bi_disk;
-static struct btinfo_bootwedge bi_wedge;
-#endif
+struct btinfo_bootdisk bi_disk;
+struct btinfo_bootwedge bi_wedge;
 
 #define MBR_PARTS(buf) ((char *)(buf) + offsetof(struct mbr_sector, mbr_parts))
 
@@ -568,7 +566,6 @@ check_label(struct biosdisk *d, daddr_t 
 
 	ingest_label(d, lp);
 
-#ifdef _STANDALONE
 	bi_disk.labelsector = sector + LABELSECTOR;
 	bi_disk.label.type = lp->d_type;
 	memcpy(bi_disk.label.packname, lp->d_packname, 16);
@@ -578,7 +575,6 @@ check_label(struct biosdisk *d, daddr_t 
 	bi_wedge.matchnblks = 1;
 
 	md5(bi_wedge.matchhash, d->buf, d->ll.secsize);
-#endif
 
 	return 0;
 }
@@ -1257,14 +1253,12 @@ biosdisk_open(struct open_file *f, ...)
 	}
 
 	partition = va_arg(ap, int);
-#ifdef _STANDALONE
 	bi_disk.biosdev = d->ll.dev;
 	bi_disk.partition = partition;
 	bi_disk.labelsector = -1;
 
 	bi_wedge.biosdev = d->ll.dev;
 	bi_wedge.matchblk = -1;
-#endif
 
 #if !defined(NO_DISKLABEL) || !defined(NO_GPT)
 	error = read_partitions(d, 0, 0);
@@ -1587,7 +1581,6 @@ biosdisk_open_name(struct open_file *f, 
 		goto out;
 	}
 
-#ifdef _STANDALONE
 	bi_disk.biosdev = d->ll.dev;
 	bi_disk.partition = 0;
 	bi_disk.labelsector = -1;
@@ -1612,14 +1605,13 @@ biosdisk_open_name(struct open_file *f, 
 
 		md5(bi_wedge.matchhash, d->buf, d->ll.secsize);
 	}
-#endif
 
 	d->boff = offset;
 
-#ifdef _STANDALONE
 	bi_wedge.startblk = offset;
 	bi_wedge.nblks = size;
 
+#ifdef _STANDALONE
 	add_biosdisk_bootinfo();
 #endif
 

Index: src/sys/arch/i386/stand/lib/biosdisk.h
diff -u src/sys/arch/i386/stand/lib/biosdisk.h:1.10.6.1 src/sys/arch/i386/stand/lib/biosdisk.h:1.10.6.2
--- src/sys/arch/i386/stand/lib/biosdisk.h:1.10.6.1	Fri Sep 13 07:00:13 2019
+++ src/sys/arch/i386/stand/lib/biosdisk.h	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: biosdisk.h,v 1.10.6.1 2019/09/13 07:00:13 martin Exp $	*/
+/*	$NetBSD: biosdisk.h,v 1.10.6.2 2019/09/17 19:32:00 martin Exp $	*/
 
 /*
  * Copyright (c) 1996
@@ -41,6 +41,9 @@ struct biosdisk_partition {
 #endif
 };
 
+extern struct btinfo_bootdisk bi_disk; 
+extern struct btinfo_bootwedge bi_wedge;
+
 int biosdisk_strategy(void *, int, daddr_t, size_t, void *, size_t *);
 int biosdisk_open(struct open_file *, ...);
 int biosdisk_open_name(struct open_file *, const char *);

Index: src/sys/arch/i386/stand/lib/bootinfo_memmap.c
diff -u src/sys/arch/i386/stand/lib/bootinfo_memmap.c:1.5 src/sys/arch/i386/stand/lib/bootinfo_memmap.c:1.5.70.1
--- src/sys/arch/i386/stand/lib/bootinfo_memmap.c:1.5	Sun Dec 14 17:03:43 2008
+++ src/sys/arch/i386/stand/lib/bootinfo_memmap.c	Tue Sep 17 19:31:59 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: bootinfo_memmap.c,v 1.5 2008/12/14 17:03:43 christos Exp $	*/
+/*	$NetBSD: bootinfo_memmap.c,v 1.5.70.1 2019/09/17 19:31:59 martin Exp $	*/
 
 /*
  * Copyright (c) 1999
@@ -30,13 +30,14 @@
 #include "libi386.h"
 #include "bootinfo.h"
 
+struct btinfo_memmap *btinfo_memmap = NULL;
+
 extern int getmementry(int *, int *);
 
 void
 bi_getmemmap(void)
 {
 	int buf[5], i, nranges, n;
-	struct btinfo_memmap *bimm;
 
 	nranges = 0;
 	i = 0;
@@ -46,16 +47,17 @@ bi_getmemmap(void)
 		nranges++;
 	} while (i);
 
-	bimm = alloc(sizeof(struct btinfo_memmap)
+	btinfo_memmap = alloc(sizeof(struct btinfo_memmap)
 		+ (nranges - 1) * sizeof(struct bi_memmap_entry));
 
 	i = 0;
 	for (n = 0; n < nranges; n++) {
 		getmementry(&i, buf);
-		memcpy(&bimm->entry[n], buf, sizeof(struct bi_memmap_entry));
+		memcpy(&btinfo_memmap->entry[n], buf,
+		       sizeof(struct bi_memmap_entry));
 	}
-	bimm->num = nranges;
+	btinfo_memmap->num = nranges;
 
-	BI_ADD(bimm, BTINFO_MEMMAP, sizeof(struct btinfo_memmap)
+	BI_ADD(btinfo_memmap, BTINFO_MEMMAP, sizeof(struct btinfo_memmap)
 	       + (nranges - 1) * sizeof(struct bi_memmap_entry));
 }

Index: src/sys/arch/i386/stand/lib/exec.c
diff -u src/sys/arch/i386/stand/lib/exec.c:1.73 src/sys/arch/i386/stand/lib/exec.c:1.73.2.1
--- src/sys/arch/i386/stand/lib/exec.c:1.73	Fri Jul 26 12:09:48 2019
+++ src/sys/arch/i386/stand/lib/exec.c	Tue Sep 17 19:31:59 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: exec.c,v 1.73 2019/07/26 12:09:48 nonaka Exp $	 */
+/*	$NetBSD: exec.c,v 1.73.2.1 2019/09/17 19:31:59 martin Exp $	 */
 
 /*
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -95,8 +95,6 @@
 #include <sys/param.h>
 #include <sys/reboot.h>
 
-#include <i386/multiboot.h>
-
 #include <lib/libsa/stand.h>
 #include <lib/libkern/libkern.h>
 
@@ -136,9 +134,9 @@ typedef struct userconf_command {
 } userconf_command_t;
 userconf_command_t *userconf_commands = NULL;
 
-static struct btinfo_framebuffer btinfo_framebuffer;
+struct btinfo_framebuffer btinfo_framebuffer;
 
-static struct btinfo_modulelist *btinfo_modulelist;
+struct btinfo_modulelist *btinfo_modulelist;
 static size_t btinfo_modulelist_size;
 static uint32_t image_end;
 static char module_base[64] = "/";
@@ -832,75 +830,57 @@ userconf_init(void)
 int
 exec_multiboot(const char *file, char *args)
 {
-	struct multiboot_info *mbi;
-	struct multiboot_module *mbm;
-	struct bi_modulelist_entry *bim;
-	int i, len;
+	physaddr_t loadaddr = 0;
 	u_long marks[MARK_MAX];
 	u_long extmem;
 	u_long basemem;
-	char *cmdline;
+	struct multiboot_package *mbp = NULL;
 
-	mbi = alloc(sizeof(struct multiboot_info));
-	mbi->mi_flags = MULTIBOOT_INFO_HAS_MEMORY;
+#ifndef NO_MULTIBOOT2
+	if ((mbp = probe_multiboot2(file)) != NULL)
+		goto is_multiboot;
+#endif
 
-	if (common_load_kernel(file, &basemem, &extmem, 0, 0, marks))
+	if ((mbp = probe_multiboot1(file)) != NULL) {
+#ifdef EFIBOOT
+		printf("EFI boot requires multiboot 2 kernel\n");
 		goto out;
-
-	mbi->mi_mem_upper = extmem;
-	mbi->mi_mem_lower = basemem;
-
-	if (args) {
-		mbi->mi_flags |= MULTIBOOT_INFO_HAS_CMDLINE;
-		len = strlen(file) + 1 + strlen(args) + 1;
-		cmdline = alloc(len);
-		snprintf(cmdline, len, "%s %s", file, args);
-		mbi->mi_cmdline = (char *) vtophys(cmdline);
-	}
-
-	/* pull in any modules if necessary */
-	if (boot_modules_enabled) {
-		module_init(file);
-		if (btinfo_modulelist) {
-			mbm = alloc(sizeof(struct multiboot_module) *
-					   btinfo_modulelist->num);
-
-			bim = (struct bi_modulelist_entry *)
-			  (((char *) btinfo_modulelist) +
-			   sizeof(struct btinfo_modulelist));
-			for (i = 0; i < btinfo_modulelist->num; i++) {
-				mbm[i].mmo_start = bim->base;
-				mbm[i].mmo_end = bim->base + bim->len;
-				mbm[i].mmo_string = (char *)vtophys(bim->path);
-				mbm[i].mmo_reserved = 0;
-				bim++;
-			}
-			mbi->mi_flags |= MULTIBOOT_INFO_HAS_MODS;
-			mbi->mi_mods_count = btinfo_modulelist->num;
-			mbi->mi_mods_addr = vtophys(mbm);
-		}
+#else
+		goto is_multiboot;
+#endif
 	}
 
-#ifdef DEBUG
-	printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY],
-	    marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]);
+#ifndef NO_MULTIBOOT2
+	printf("%s is not a multiboot kernel\n", file);
+#else
+	printf("%s is not a multiboot 1 kernel "
+	    "(multiboot 2 support is not built in)\n", file);
 #endif
+	goto out;
 
-#if 0
-	if (btinfo_symtab.nsym) {
-		mbi->mi_flags |= MULTIBOOT_INFO_HAS_ELF_SYMS;
-		mbi->mi_elfshdr_addr = marks[MARK_SYM];
-	btinfo_symtab.nsym = marks[MARK_NSYM];
-	btinfo_symtab.ssym = marks[MARK_SYM];
-	btinfo_symtab.esym = marks[MARK_END];
+is_multiboot:
+#ifdef EFIBOOT
+	loadaddr = efi_loadaddr;
 #endif
+	if (common_load_kernel(file, &basemem, &extmem, loadaddr, 0, marks))
+		goto out;
 
-	multiboot(marks[MARK_ENTRY], vtophys(mbi),
-	    x86_trunc_page(mbi->mi_mem_lower * 1024));
-	panic("exec returned");
+	if (boot_modules_enabled)
+		module_init(file);
+
+	mbp->mbp_args = args;
+	mbp->mbp_basemem = basemem;
+	mbp->mbp_extmem = extmem;
+	mbp->mbp_loadaddr = loadaddr;
+	mbp->mbp_marks = marks;
+
+	/* Only returns on error */
+	(void)mbp->mbp_exec(mbp);
 
 out:
-	dealloc(mbi, 0);
+	if (mbp != NULL)
+		mbp->mbp_cleanup(mbp);
+
 	return -1;
 }
 

Index: src/sys/arch/i386/stand/lib/libi386.h
diff -u src/sys/arch/i386/stand/lib/libi386.h:1.44 src/sys/arch/i386/stand/lib/libi386.h:1.44.2.1
--- src/sys/arch/i386/stand/lib/libi386.h:1.44	Fri Jul 26 12:09:48 2019
+++ src/sys/arch/i386/stand/lib/libi386.h	Tue Sep 17 19:31:59 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: libi386.h,v 1.44 2019/07/26 12:09:48 nonaka Exp $	*/
+/*	$NetBSD: libi386.h,v 1.44.2.1 2019/09/17 19:31:59 martin Exp $	*/
 
 /*
  * Copyright (c) 1996
@@ -39,7 +39,7 @@ physaddr_t vtophys(void *);
 
 ssize_t pread(int, void *, size_t);
 void startprog(physaddr_t, uint32_t, uint32_t *, physaddr_t);
-void multiboot(physaddr_t, physaddr_t, physaddr_t);
+void multiboot(physaddr_t, physaddr_t, physaddr_t, uint32_t);
 
 int exec_netbsd(const char *, physaddr_t, int, int, void (*)(void));
 int exec_multiboot(const char *, char *);
@@ -74,6 +74,28 @@ int iskey(int);
 char awaitkey(int, int);
 void wait_sec(int);
 
+/* multiboot */
+struct multiboot_package;
+struct multiboot_package_priv;
+
+struct multiboot_package {
+	int			 mbp_version;
+	struct multiboot_header	*mbp_header;
+	const char		*mbp_file;
+	char			*mbp_args;
+	u_long			 mbp_basemem;
+	u_long			 mbp_extmem;
+	u_long			 mbp_loadaddr;
+	u_long			*mbp_marks;
+	struct multiboot_package_priv*mbp_priv;
+	struct multiboot_package*(*mbp_probe)(const char *);
+	int			(*mbp_exec)(struct multiboot_package *);
+	void			(*mbp_cleanup)(struct multiboot_package *);
+};
+
+struct multiboot_package *probe_multiboot1(const char *);
+struct multiboot_package *probe_multiboot2(const char *);
+
 /* this is in "user code"! */
 int parsebootfile(const char *, char **, char **, int *, int *, const char **);
 

Index: src/sys/arch/i386/stand/lib/multiboot.S
diff -u src/sys/arch/i386/stand/lib/multiboot.S:1.2 src/sys/arch/i386/stand/lib/multiboot.S:1.2.20.1
--- src/sys/arch/i386/stand/lib/multiboot.S:1.2	Sun Dec  4 08:21:08 2016
+++ src/sys/arch/i386/stand/lib/multiboot.S	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: multiboot.S,v 1.2 2016/12/04 08:21:08 maxv Exp $	*/
+/*	$NetBSD: multiboot.S,v 1.2.20.1 2019/09/17 19:32:00 martin Exp $	*/
 
 /*
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -78,7 +78,6 @@
  */
 
 #include <machine/asm.h>
-#define MULTIBOOT_INFO_MAGIC		0x2BADB002
 
 /*
  * Starts program in protected mode / flat space with given stackframe.
@@ -87,8 +86,8 @@
  */
 
 /*
- * multiboot(phyaddr, header, stack)
- *	start the program on protected mode where phyaddr is the entry point
+ * multiboot(entry, header, stack, magic)
+ *	start the program on protected mode, entry is phyaddr.
  */
 ENTRY(multiboot)
 	pushl	%ebp
@@ -101,6 +100,7 @@ ENTRY(multiboot)
 	subl	$4,%ebx
 	movl	%ebx,%edi
 
+	movl	20(%ebp),%edx	/* magic */
 	movl	12(%ebp),%ebx	/* header */
 	movl	8(%ebp),%ecx	/* entry */
 
@@ -118,7 +118,7 @@ ENTRY(multiboot)
 	mov	%ax,%ds
 	mov	%ax,%es
 
-	movl	$MULTIBOOT_INFO_MAGIC,%eax
+	movl	%edx,%eax	/* magic */
 
 	/* Jump to phyaddr, with the new code segment */
 	lret

Index: src/sys/arch/i386/stand/lib/pread.c
diff -u src/sys/arch/i386/stand/lib/pread.c:1.7 src/sys/arch/i386/stand/lib/pread.c:1.7.70.1
--- src/sys/arch/i386/stand/lib/pread.c:1.7	Sun Dec 14 17:03:43 2008
+++ src/sys/arch/i386/stand/lib/pread.c	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: pread.c,v 1.7 2008/12/14 17:03:43 christos Exp $	 */
+/*	$NetBSD: pread.c,v 1.7.70.1 2019/09/17 19:32:00 martin Exp $	 */
 
 /*
  * Copyright (c) 1996
@@ -43,14 +43,15 @@ static char     *buf;
 ssize_t
 pread(int fd, void *dest, size_t size)
 {
-	int             rsize;
+	size_t             rsize;
 
 	if (!buf)
 		buf = alloc(BUFSIZE);
 
 	rsize = size;
 	while (rsize > 0) {
-		int             count, got;
+		size_t count;
+		ssize_t got;
 
 		count = (rsize < BUFSIZE ? rsize : BUFSIZE);
 

Index: src/sys/arch/i386/stand/netboot/Makefile.netboot
diff -u src/sys/arch/i386/stand/netboot/Makefile.netboot:1.10 src/sys/arch/i386/stand/netboot/Makefile.netboot:1.10.34.1
--- src/sys/arch/i386/stand/netboot/Makefile.netboot:1.10	Wed Jan 15 22:25:22 2014
+++ src/sys/arch/i386/stand/netboot/Makefile.netboot	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile.netboot,v 1.10 2014/01/15 22:25:22 joerg Exp $
+#	$NetBSD: Makefile.netboot,v 1.10.34.1 2019/09/17 19:32:00 martin Exp $
 
 NOMAN=	# defined
 
@@ -20,6 +20,7 @@ RELOC=		0x90000
 .PATH: ${.CURDIR}/..
 
 SRCS= main.c devopen.c conf.c dev_net.c exec.c
+SRCS+=exec_multiboot1.c exec_multiboot2.c
 
 CPPFLAGS+= -DSLOW	# for libz
 #CPPFLAGS+= -DDEBUG

Index: src/sys/arch/i386/stand/pxeboot/Makefile
diff -u src/sys/arch/i386/stand/pxeboot/Makefile:1.25 src/sys/arch/i386/stand/pxeboot/Makefile:1.25.6.1
--- src/sys/arch/i386/stand/pxeboot/Makefile:1.25	Sat Jun  2 14:30:07 2018
+++ src/sys/arch/i386/stand/pxeboot/Makefile	Tue Sep 17 19:32:00 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.25 2018/06/02 14:30:07 christos Exp $
+#	$NetBSD: Makefile,v 1.25.6.1 2019/09/17 19:32:00 martin Exp $
 
 S=	${.CURDIR}/../../../..
 
@@ -13,7 +13,8 @@ RELOC=		0x0
 .PATH.S: ${.CURDIR}/../pxeboot
 .endif
 
-SRCS= main.c dev_net.c devopen.c conf.c exec.c pxe.c pxe_call.S
+SRCS= main.c dev_net.c devopen.c conf.c 
+SRCS+=exec.c exec_multiboot1.c exec_multiboot2.c pxe.c pxe_call.S
 # use our own nfs implementation
 .PATH: ${.CURDIR}/../libsa
 SRCS+= nfs.c

Added files:

Index: src/sys/arch/i386/include/multiboot2.h
diff -u /dev/null src/sys/arch/i386/include/multiboot2.h:1.1.2.2
--- /dev/null	Tue Sep 17 19:32:01 2019
+++ src/sys/arch/i386/include/multiboot2.h	Tue Sep 17 19:31:59 2019
@@ -0,0 +1,417 @@
+/*  multiboot2.h - Multiboot 2 header file.  */
+/*  Copyright (C) 1999,2003,2007,2008,2009,2010  Free Software Foundation, Inc.
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to
+ *  deal in the Software without restriction, including without limitation the
+ *  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ *  sell copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in
+ *  all copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL ANY
+ *  DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ *  IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef MULTIBOOT_HEADER
+#define MULTIBOOT_HEADER 1
+
+/* How many bytes from the start of the file we search for the header.  */
+#define MULTIBOOT_SEARCH			32768
+#define MULTIBOOT_HEADER_ALIGN			8
+
+/* The magic field should contain this.  */
+#define MULTIBOOT2_HEADER_MAGIC			0xe85250d6
+
+/* This should be in %eax.  */
+#define MULTIBOOT2_BOOTLOADER_MAGIC		0x36d76289
+
+/* Alignment of multiboot modules.  */
+#define MULTIBOOT_MOD_ALIGN			0x00001000
+
+/* Alignment of the multiboot info structure.  */
+#define MULTIBOOT_INFO_ALIGN			0x00000008
+
+/* Flags set in the 'flags' member of the multiboot header.  */
+
+#define MULTIBOOT_TAG_ALIGN                  8
+#define MULTIBOOT_TAG_TYPE_END               0
+#define MULTIBOOT_TAG_TYPE_CMDLINE           1
+#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME  2
+#define MULTIBOOT_TAG_TYPE_MODULE            3
+#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO     4
+#define MULTIBOOT_TAG_TYPE_BOOTDEV           5
+#define MULTIBOOT_TAG_TYPE_MMAP              6
+#define MULTIBOOT_TAG_TYPE_VBE               7
+#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER       8
+#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS      9
+#define MULTIBOOT_TAG_TYPE_APM               10
+#define MULTIBOOT_TAG_TYPE_EFI32             11
+#define MULTIBOOT_TAG_TYPE_EFI64             12
+#define MULTIBOOT_TAG_TYPE_SMBIOS            13
+#define MULTIBOOT_TAG_TYPE_ACPI_OLD          14
+#define MULTIBOOT_TAG_TYPE_ACPI_NEW          15
+#define MULTIBOOT_TAG_TYPE_NETWORK           16
+#define MULTIBOOT_TAG_TYPE_EFI_MMAP          17
+#define MULTIBOOT_TAG_TYPE_EFI_BS            18
+#define MULTIBOOT_TAG_TYPE_EFI32_IH          19
+#define MULTIBOOT_TAG_TYPE_EFI64_IH          20
+#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR    21
+
+#define MULTIBOOT_HEADER_TAG_END  0
+#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST  1
+#define MULTIBOOT_HEADER_TAG_ADDRESS  2
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS  3
+#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS  4
+#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER  5
+#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN  6
+#define MULTIBOOT_HEADER_TAG_EFI_BS  7
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32  8
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64  9
+#define MULTIBOOT_HEADER_TAG_RELOCATABLE  10
+
+#define MULTIBOOT_ARCHITECTURE_I386  0
+#define MULTIBOOT_ARCHITECTURE_MIPS32  4
+#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
+
+#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
+#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
+#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
+
+#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
+#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
+
+#ifndef ASM_FILE
+
+typedef unsigned char		multiboot_uint8_t;
+typedef unsigned short		multiboot_uint16_t;
+typedef unsigned int		multiboot_uint32_t;
+typedef unsigned long long	multiboot_uint64_t;
+
+struct multiboot_header
+{
+  /* Must be MULTIBOOT_MAGIC - see above.  */
+  multiboot_uint32_t magic;
+
+  /* ISA */
+  multiboot_uint32_t architecture;
+
+  /* Total header length.  */
+  multiboot_uint32_t header_length;
+
+  /* The above fields plus this one must equal 0 mod 2^32. */
+  multiboot_uint32_t checksum;
+};
+
+struct multiboot_header_tag
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+};
+
+struct multiboot_header_tag_information_request
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t requests[0];
+};
+
+struct multiboot_header_tag_address
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t header_addr;
+  multiboot_uint32_t load_addr;
+  multiboot_uint32_t load_end_addr;
+  multiboot_uint32_t bss_end_addr;
+};
+
+struct multiboot_header_tag_entry_address
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t entry_addr;
+};
+
+struct multiboot_header_tag_console_flags
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t console_flags;
+};
+
+struct multiboot_header_tag_framebuffer
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t width;
+  multiboot_uint32_t height;
+  multiboot_uint32_t depth;
+};
+
+struct multiboot_header_tag_module_align
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+};
+
+struct multiboot_header_tag_relocatable
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t min_addr;
+  multiboot_uint32_t max_addr;
+  multiboot_uint32_t align;
+  multiboot_uint32_t preference;
+};
+
+struct multiboot_color
+{
+  multiboot_uint8_t red;
+  multiboot_uint8_t green;
+  multiboot_uint8_t blue;
+};
+
+struct multiboot_mmap_entry
+{
+  multiboot_uint64_t addr;
+  multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE		1
+#define MULTIBOOT_MEMORY_RESERVED		2
+#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE       3
+#define MULTIBOOT_MEMORY_NVS                    4
+#define MULTIBOOT_MEMORY_BADRAM                 5
+  multiboot_uint32_t type;
+  multiboot_uint32_t zero;
+};
+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
+
+struct multiboot_tag
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+};
+
+struct multiboot_tag_string
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  char string[0];
+};
+
+struct multiboot_tag_module
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t mod_start;
+  multiboot_uint32_t mod_end;
+  char cmdline[0];
+};
+
+struct multiboot_tag_basic_meminfo
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t mem_lower;
+  multiboot_uint32_t mem_upper;
+};
+
+struct multiboot_tag_bootdev
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t biosdev;
+  multiboot_uint32_t slice;
+  multiboot_uint32_t part;
+};
+
+struct multiboot_tag_mmap
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t entry_size;
+  multiboot_uint32_t entry_version;
+  struct multiboot_mmap_entry entries[0];  
+};
+
+struct multiboot_vbe_info_block
+{
+  multiboot_uint8_t external_specification[512];
+};
+
+struct multiboot_vbe_mode_info_block
+{
+  multiboot_uint8_t external_specification[256];
+};
+
+struct multiboot_tag_vbe
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+
+  multiboot_uint16_t vbe_mode;
+  multiboot_uint16_t vbe_interface_seg;
+  multiboot_uint16_t vbe_interface_off;
+  multiboot_uint16_t vbe_interface_len;
+
+  struct multiboot_vbe_info_block vbe_control_info;
+  struct multiboot_vbe_mode_info_block vbe_mode_info;
+};
+
+struct multiboot_tag_framebuffer_common
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+
+  multiboot_uint64_t framebuffer_addr;
+  multiboot_uint32_t framebuffer_pitch;
+  multiboot_uint32_t framebuffer_width;
+  multiboot_uint32_t framebuffer_height;
+  multiboot_uint8_t framebuffer_bpp;
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB     1
+#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT	2
+  multiboot_uint8_t framebuffer_type;
+  multiboot_uint16_t reserved;
+};
+
+struct multiboot_tag_framebuffer
+{
+  struct multiboot_tag_framebuffer_common common;
+
+  union
+  {
+    struct
+    {
+      multiboot_uint16_t framebuffer_palette_num_colors;
+      struct multiboot_color framebuffer_palette[0];
+    };
+    struct
+    {
+      multiboot_uint8_t framebuffer_red_field_position;
+      multiboot_uint8_t framebuffer_red_mask_size;
+      multiboot_uint8_t framebuffer_green_field_position;
+      multiboot_uint8_t framebuffer_green_mask_size;
+      multiboot_uint8_t framebuffer_blue_field_position;
+      multiboot_uint8_t framebuffer_blue_mask_size;
+    };
+  };
+};
+
+struct multiboot_tag_elf_sections
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t num;
+  multiboot_uint32_t entsize;
+  multiboot_uint32_t shndx;
+  char sections[0];
+};
+
+struct multiboot_tag_apm
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint16_t version;
+  multiboot_uint16_t cseg;
+  multiboot_uint32_t offset;
+  multiboot_uint16_t cseg_16;
+  multiboot_uint16_t dseg;
+  multiboot_uint16_t flags;
+  multiboot_uint16_t cseg_len;
+  multiboot_uint16_t cseg_16_len;
+  multiboot_uint16_t dseg_len;
+};
+
+struct multiboot_tag_efi32
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t pointer;
+};
+
+struct multiboot_tag_efi64
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint64_t pointer;
+};
+
+struct multiboot_tag_smbios
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint8_t major;
+  multiboot_uint8_t minor;
+  multiboot_uint8_t reserved[6];
+  multiboot_uint8_t tables[0];
+};
+
+struct multiboot_tag_old_acpi
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint8_t rsdp[0];
+};
+
+struct multiboot_tag_new_acpi
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint8_t rsdp[0];
+};
+
+struct multiboot_tag_network
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint8_t dhcpack[0];
+};
+
+struct multiboot_tag_efi_mmap
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t descr_size;
+  multiboot_uint32_t descr_vers;
+  multiboot_uint8_t efi_mmap[0];
+}; 
+
+struct multiboot_tag_efi32_ih
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t pointer;
+};
+
+struct multiboot_tag_efi64_ih
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint64_t pointer;
+};
+
+struct multiboot_tag_load_base_addr
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t load_base_addr;
+};
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! MULTIBOOT_HEADER */

Index: src/sys/arch/i386/stand/efiboot/bootia32/multiboot32.S
diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootia32/multiboot32.S:1.1.2.2
--- /dev/null	Tue Sep 17 19:32:01 2019
+++ src/sys/arch/i386/stand/efiboot/bootia32/multiboot32.S	Tue Sep 17 19:32:00 2019
@@ -0,0 +1,27 @@
+/*	$NetBSD: multiboot32.S,v 1.1.2.2 2019/09/17 19:32:00 martin Exp $ */
+
+#include <machine/asm.h>
+#include <machine/specialreg.h>
+
+	.align	16
+	.globl _C_LABEL(multiboot32)
+_C_LABEL(multiboot32):
+	.quad 0
+
+	.globl _C_LABEL(multiboot32_size)
+_C_LABEL(multiboot32_size):
+	.long multiboot32_end - _C_LABEL(multiboot32_start)
+
+	.text
+	.p2align 4,,15
+
+/*
+ * multiboot32(entry 8(%esp), multiboot2_info 12(%esp), magic 16(%esp))
+ */
+ENTRY(multiboot32_start)
+start:
+        movl    16(%esp),%eax
+        movl    12(%esp),%ebx
+        movl    8(%esp),%edx
+        jmp    *%edx
+multiboot32_end:

Index: src/sys/arch/i386/stand/efiboot/bootx64/multiboot64.S
diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootx64/multiboot64.S:1.1.2.2
--- /dev/null	Tue Sep 17 19:32:01 2019
+++ src/sys/arch/i386/stand/efiboot/bootx64/multiboot64.S	Tue Sep 17 19:32:00 2019
@@ -0,0 +1,29 @@
+/*	$NetBSD: multiboot64.S,v 1.1.2.2 2019/09/17 19:32:00 martin Exp $ */
+#include <machine/asm.h>
+#include <machine/specialreg.h>
+
+#define CODE_SEGMENT    0x08
+#define DATA_SEGMENT    0x10
+
+	.align	16
+	.globl _C_LABEL(multiboot64)
+_C_LABEL(multiboot64):
+	.quad 0
+
+	.globl _C_LABEL(multiboot64_size)
+_C_LABEL(multiboot64_size):
+	.long multiboot64_end - _C_LABEL(multiboot64_start)
+
+	.text
+	.p2align 4,,15
+
+/*
+ * multiboot64(entry %rdi, multiboot2_info %rsi, magic %rdx);
+ */
+ENTRY(multiboot64_start)
+start:
+
+        movq    %rdx, %rax
+	movq    %rsi, %rbx
+	jmp    *%rdi
+multiboot64_end:

Index: src/sys/arch/i386/stand/lib/exec_multiboot1.c
diff -u /dev/null src/sys/arch/i386/stand/lib/exec_multiboot1.c:1.1.2.2
--- /dev/null	Tue Sep 17 19:32:01 2019
+++ src/sys/arch/i386/stand/lib/exec_multiboot1.c	Tue Sep 17 19:32:00 2019
@@ -0,0 +1,159 @@
+/* $NetBSD: exec_multiboot1.c,v 1.1.2.2 2019/09/17 19:32:00 martin Exp $ */
+
+/*
+ * Copyright (c) 2019 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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/param.h>
+#include <sys/reboot.h> 
+ 
+#include <i386/multiboot.h>
+ 
+#include <lib/libsa/stand.h> 
+#include <lib/libkern/libkern.h> 
+ 
+#include "loadfile.h"
+#include "libi386.h"
+#include "bootinfo.h"
+#include "bootmod.h"
+#include "vbe.h"
+
+extern struct btinfo_modulelist *btinfo_modulelist;
+
+static int
+exec_multiboot1(struct multiboot_package *mbp)
+{
+	struct multiboot_info *mbi;
+	struct multiboot_module *mbm;
+	int i, len;
+	char *cmdline;
+	struct bi_modulelist_entry *bim;
+
+	mbi = alloc(sizeof(struct multiboot_info));
+	mbi->mi_flags = MULTIBOOT_INFO_HAS_MEMORY;
+
+	mbi->mi_mem_upper = mbp->mbp_extmem;
+	mbi->mi_mem_lower = mbp->mbp_basemem;
+
+	if (mbp->mbp_args) {
+		mbi->mi_flags |= MULTIBOOT_INFO_HAS_CMDLINE;
+		len = strlen(mbp->mbp_file) + 1 + strlen(mbp->mbp_args) + 1;
+		cmdline = alloc(len);
+		snprintf(cmdline, len, "%s %s", mbp->mbp_file, mbp->mbp_args);
+		mbi->mi_cmdline = (char *) vtophys(cmdline);
+	}
+
+	/* pull in any modules if necessary */
+	if (btinfo_modulelist) {
+		mbm = alloc(sizeof(struct multiboot_module) *
+				   btinfo_modulelist->num);
+
+		bim = (struct bi_modulelist_entry *)
+		  (((char *) btinfo_modulelist) +
+		   sizeof(struct btinfo_modulelist));
+		for (i = 0; i < btinfo_modulelist->num; i++) {
+			mbm[i].mmo_start = bim->base;
+			mbm[i].mmo_end = bim->base + bim->len;
+			mbm[i].mmo_string = (char *)vtophys(bim->path);
+			mbm[i].mmo_reserved = 0;
+			bim++;
+		}
+		mbi->mi_flags |= MULTIBOOT_INFO_HAS_MODS;
+		mbi->mi_mods_count = btinfo_modulelist->num;
+		mbi->mi_mods_addr = vtophys(mbm);
+	}
+
+#ifdef DEBUG
+	printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n",
+	    mbp->mbp_marks[MARK_ENTRY],
+	    mbp->mbp_marks[MARK_NSYM], 
+	    mbp->mbp_marks[MARK_SYM],
+	    mbp->mbp_marks[MARK_END]);
+#endif
+
+	/* Does not return */
+	multiboot(mbp->mbp_marks[MARK_ENTRY], vtophys(mbi),
+	    x86_trunc_page(mbi->mi_mem_lower * 1024), MULTIBOOT_INFO_MAGIC);
+
+	return 0;
+}
+
+static void
+cleanup_multiboot1(struct multiboot_package *mbp)
+{
+	dealloc(mbp->mbp_header, sizeof(*mbp->mbp_header));
+	dealloc(mbp, sizeof(*mbp));
+
+	return;
+}
+
+
+struct multiboot_package *
+probe_multiboot1(const char *path)
+{
+	int fd = -1;
+	size_t i;
+	char buf[8192 + sizeof(struct multiboot_header)];
+	ssize_t readen;
+	struct multiboot_package *mbp = NULL;
+
+	if ((fd = open(path, 0)) == -1)
+		goto out;
+
+	readen = read(fd, buf, sizeof(buf));
+	if (readen < sizeof(struct multiboot_header))
+		goto out;
+
+	for (i = 0; i < readen; i += 8) {
+		struct multiboot_header *mbh;
+
+		mbh = (struct multiboot_header *)(buf + i);
+		
+		if (mbh->mh_magic != MULTIBOOT_HEADER_MAGIC)
+			continue;
+		
+		if (mbh->mh_magic + mbh->mh_flags + mbh->mh_checksum)
+			continue;
+
+		mbp = alloc(sizeof(*mbp));
+		mbp->mbp_version	= 1;
+		mbp->mbp_file		= path;
+		mbp->mbp_header		= alloc(sizeof(*mbp->mbp_header));
+		mbp->mbp_probe		= *probe_multiboot1;
+		mbp->mbp_exec		= *exec_multiboot1;
+		mbp->mbp_cleanup	= *cleanup_multiboot1;
+
+		memcpy(mbp->mbp_header, mbh, sizeof(*mbp->mbp_header));
+
+		goto out;
+
+	}
+		
+out:
+	if (fd != -1)
+		close(fd);
+
+	return mbp;
+}

Index: src/sys/arch/i386/stand/lib/exec_multiboot2.c
diff -u /dev/null src/sys/arch/i386/stand/lib/exec_multiboot2.c:1.2.2.2
--- /dev/null	Tue Sep 17 19:32:01 2019
+++ src/sys/arch/i386/stand/lib/exec_multiboot2.c	Tue Sep 17 19:32:00 2019
@@ -0,0 +1,1642 @@
+/* $NetBSD: exec_multiboot2.c,v 1.2.2.2 2019/09/17 19:32:00 martin Exp $ */
+
+/*
+ * Copyright (c) 2019 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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/param.h>
+#include <sys/reboot.h> 
+#include <sys/types.h> 
+ 
+#include <i386/multiboot2.h>
+
+#include <dev/acpi/acpica.h>
+#include <x86/acpi_machdep.h>
+#include <x86/smbiosvar.h>
+
+#include <lib/libsa/stand.h> 
+#include <lib/libkern/libkern.h> 
+
+
+#include "loadfile.h"
+#include "libi386.h"
+#include "biosdisk.h"
+#include "bootinfo.h"
+#include "bootmod.h"
+#include "vbe.h"
+#ifdef EFIBOOT
+#include "efiboot.h"
+#endif
+
+#define CGA_BUF 0xb8000 /* From isa_machdep.h */
+
+extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
+extern const uint8_t rasops_cmap[];
+extern struct btinfo_framebuffer btinfo_framebuffer;
+extern struct btinfo_modulelist *btinfo_modulelist;
+#ifdef EFIBOOT
+extern struct btinfo_efimemmap *btinfo_efimemmap;
+#else
+extern struct btinfo_memmap *btinfo_memmap;
+#endif
+
+
+struct multiboot_package_priv {
+	struct multiboot_tag 			       *mpp_mbi;
+	size_t						mpp_mbi_len;
+	struct multiboot_header_tag_information_request*mpp_info_req;
+	struct multiboot_header_tag_address		*mpp_address;
+	struct multiboot_header_tag_entry_address	*mpp_entry;
+	struct multiboot_header_tag_console_flags	*mpp_console;
+	struct multiboot_header_tag_framebuffer		*mpp_framebuffer;
+	struct multiboot_header_tag			*mpp_module_align;
+	struct multiboot_header_tag			*mpp_efi_bs;
+	struct multiboot_header_tag_entry_address	*mpp_entry_elf32;
+	struct multiboot_header_tag_entry_address	*mpp_entry_elf64;
+	struct multiboot_header_tag_relocatable		*mpp_relocatable;
+};
+
+#ifndef NO_MULTIBOOT2
+
+#ifdef MULTIBOOT2_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;
+}
+
+static const char *
+mbi_tag_name(uint32_t type)
+{
+	const char *tag_name;
+
+	switch (type) {
+	case MULTIBOOT_TAG_TYPE_END:
+		tag_name = "END"; break;
+	case MULTIBOOT_TAG_TYPE_CMDLINE:
+		tag_name = "CMDLINE"; 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 = "BOOTDEV"; break;
+	case MULTIBOOT_TAG_TYPE_MMAP:
+		tag_name = "MMAP"; break;
+	case MULTIBOOT_TAG_TYPE_VBE:
+		tag_name = "VBE"; 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 = "EFI32"; break;
+	case MULTIBOOT_TAG_TYPE_EFI64:
+		tag_name = "EFI64"; break;
+	case MULTIBOOT_TAG_TYPE_SMBIOS:
+		tag_name = "SMBIOS"; break;
+	case MULTIBOOT_TAG_TYPE_ACPI_OLD:
+		tag_name = "ACPI_OLD"; break;
+	case MULTIBOOT_TAG_TYPE_ACPI_NEW:
+		tag_name = "ACPI_NEW"; break;
+	case MULTIBOOT_TAG_TYPE_NETWORK:
+		tag_name = "NETWORK"; break;
+	case MULTIBOOT_TAG_TYPE_EFI_MMAP:
+		tag_name = "EFI_MMAP"; break;
+	case MULTIBOOT_TAG_TYPE_EFI_BS:
+		tag_name = "EFI_BS"; break;
+	case MULTIBOOT_TAG_TYPE_EFI32_IH:
+		tag_name = "EFI32_IH"; break;
+	case MULTIBOOT_TAG_TYPE_EFI64_IH:
+		tag_name = "EFI64_IH"; break;
+	case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
+		tag_name = "LOAD_BASE_ADDR"; break;
+	default:
+		tag_name = "unknown"; break;
+	}
+
+	return tag_name;
+}
+
+static void
+multiboot2_info_dump(uint32_t magic, char *mbi)
+{
+	struct multiboot_tag *mbt;
+	char *cp;
+	uint32_t total_size;
+	uint32_t actual_size;
+	uint32_t reserved;
+	int i = 0;
+
+	printf("=== multiboot2 info dump start  ===\n");
+
+	if (magic != MULTIBOOT2_BOOTLOADER_MAGIC) {
+		printf("Unexpected multiboot2 magic number: 0x%x\n", magic);
+		goto out;
+	}
+
+	if (mbi != (char *)rounddown((vaddr_t)mbi, MULTIBOOT_TAG_ALIGN)) {
+		printf("mbi at %p is not properly aligned\n", mbi);
+		goto out;
+	}
+
+	total_size = *(uint32_t *)mbi;
+	reserved = *(uint32_t *)mbi + 1;
+	mbt = (struct multiboot_tag *)(uint32_t *)mbi + 2;
+	actual_size = (char *)mbt - mbi;
+	printf("mbi.total_size = %d\n", total_size);
+	printf("mbi.reserved = %d\n", reserved);
+
+	for (cp = mbi + sizeof(total_size) + sizeof(reserved);
+	     cp - mbi < total_size;
+	     cp = cp + roundup(mbt->size, MULTIBOOT_TAG_ALIGN)) {
+		mbt = (struct multiboot_tag *)cp;
+		actual_size += roundup(mbt->size, MULTIBOOT_TAG_ALIGN);
+
+		printf("mbi[%d].type = %d(%s), .size = %d ",
+		    i++, mbt->type, mbi_tag_name(mbt->type), mbt->size);
+
+		switch (mbt->type) {
+		case MULTIBOOT_TAG_TYPE_CMDLINE:
+			printf(".string = \"%s\"\n",
+			    ((struct multiboot_tag_string *)mbt)->string);
+			break;
+		case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
+			printf(".string = \"%s\"\n",
+			    ((struct multiboot_tag_string *)mbt)->string);
+			break;
+		case MULTIBOOT_TAG_TYPE_MODULE:
+			printf(".mod_start = 0x%x, mod_end = 0x%x, "
+			    "string = \"%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(".mem_lower = %uKB, .mem_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;
+			int j = 0;
+
+			memmap = (struct multiboot_tag_mmap *)mbt;
+			entry_size = memmap->entry_size;
+			entry_version = memmap->entry_version;
+			printf (".entry_size = %d, .entry_version = %d\n",
+			    entry_size, entry_version);
+			
+			for (mmap = ((struct multiboot_tag_mmap *)mbt)->entries;
+		 	    (char *)mmap - (char *)mbt < mbt->size;
+		 	    mmap = (void *)((char *)mmap + entry_size))
+				printf("  entry[%d].addr = 0x%"PRIx64",\t" 
+				    ".len = 0x%"PRIx64",\t.type = 0x%x\n",
+				    j++, (uint64_t)mmap->addr,
+				    (uint64_t)mmap->len,
+				    mmap->type);
+			break;
+		}
+		case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: {
+			struct multiboot_tag_framebuffer *fb = (void *)mbt;
+
+			printf ("%dx%dx%d at 0x%"PRIx64"\n",
+			    fb->common.framebuffer_width,
+			    fb->common.framebuffer_height,
+			    fb->common.framebuffer_bpp,
+			    (uint64_t)fb->common.framebuffer_addr);
+			mbi_hexdump((char *)mbt, mbt->size);
+			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);
+			mbi_hexdump((char *)mbt, mbt->size);
+			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(".pointer = 0x%x\n",
+			    ((struct multiboot_tag_efi32 *)mbt)->pointer);
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI64:
+			printf(".pointer = 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);
+			mbi_hexdump((char *)mbt, mbt->size);
+			break;
+		case MULTIBOOT_TAG_TYPE_ACPI_OLD:
+			printf("\n");
+			mbi_hexdump((char *)mbt, mbt->size);
+			break;
+		case MULTIBOOT_TAG_TYPE_ACPI_NEW:
+			printf("\n");
+			mbi_hexdump((char *)mbt, mbt->size);
+			break;
+		case MULTIBOOT_TAG_TYPE_NETWORK:
+			printf("\n");
+			mbi_hexdump((char *)mbt, mbt->size);
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI_MMAP:
+			printf("\n");
+			mbi_hexdump((char *)mbt, mbt->size);
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI_BS:
+			printf("\n");
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI32_IH:
+			printf(".pointer = 0x%"PRIx32"\n", 
+			    ((struct multiboot_tag_efi32_ih *)mbt)->pointer);
+			break;
+		case MULTIBOOT_TAG_TYPE_EFI64_IH:
+			printf(".pointer = 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(".load_base_addr = 0x%x\n", ld->load_base_addr);
+			break;
+		}
+		case MULTIBOOT_TAG_TYPE_END:
+			break;
+		default:
+			printf("\n");
+			mbi_hexdump((char *)mbt, mbt->size);
+			break;
+		}
+	}
+
+	if (total_size != actual_size)
+		printf("Size mismatch: announded %d, actual %d\n",
+		    total_size, actual_size);
+
+out:
+	printf("=== multiboot2 info dump start  ===\n");
+	return;
+}
+
+#define MPP_OPT(flags) \
+    (flags & MULTIBOOT_HEADER_TAG_OPTIONAL) ? " (opt)" : " (req)"
+
+static
+void multiboot2_header_dump(struct multiboot_package *mbp)
+{
+	struct multiboot_package_priv *mpp = mbp->mbp_priv;
+
+	printf("=== multiboot2 header dump start ===\n");
+	if (mpp->mpp_info_req) {
+		struct multiboot_header_tag_information_request *info_req;	
+		size_t nreq;
+		int i;
+
+		info_req = mpp->mpp_info_req;
+
+		nreq = (info_req->size - sizeof(*info_req))
+		     / sizeof(info_req->requests[0]);
+
+		printf("Information tag request%s: ",
+		       MPP_OPT(info_req->flags));	
+		for (i = 0; i < nreq; i++)
+			printf("%d(%s) ",
+			    info_req->requests[i],
+			    mbi_tag_name(info_req->requests[i]));
+		printf("\n");
+	}
+
+	if (mpp->mpp_address)
+		printf("Addresses%s: header = %"PRIx32", load = %"PRIx32", "
+		       "end = %"PRIx32", bss = %"PRIx32"\n", 
+		       MPP_OPT(mpp->mpp_address->flags),
+		       mpp->mpp_address->header_addr,
+		       mpp->mpp_address->load_addr,
+		       mpp->mpp_address->load_end_addr,
+		       mpp->mpp_address->bss_end_addr);
+
+	if (mpp->mpp_entry)
+		printf("Entry point%s: %"PRIx32"\n", 
+		       MPP_OPT(mpp->mpp_entry->flags),
+		       mpp->mpp_entry->entry_addr);
+
+	if (mpp->mpp_console) {
+		int flags = mpp->mpp_console->console_flags;
+		char *req_flag = "";
+		char *ega_flag = "";
+
+		if (flags & MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED)
+			ega_flag = " EGA";
+		if (flags & MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED)
+			req_flag = " required";
+
+		printf("Console flags%s: %s %s\n",
+		       MPP_OPT(mpp->mpp_console->flags), 
+		       ega_flag, req_flag);
+	}
+
+	if (mpp->mpp_framebuffer)
+		printf("Framebuffer%s: width = %d, height = %d, depth = %d\n",
+		       MPP_OPT(mpp->mpp_framebuffer->flags),
+		       mpp->mpp_framebuffer->width,
+		       mpp->mpp_framebuffer->height,
+		       mpp->mpp_framebuffer->depth);
+
+	if (mpp->mpp_module_align)
+		printf("Module alignmenet%s\n",
+		       MPP_OPT(mpp->mpp_module_align->flags));
+	
+	if (mpp->mpp_efi_bs)
+		printf("Do not call EFI Boot service exit%s\n",
+		       MPP_OPT(mpp->mpp_efi_bs->flags));
+	
+	if (mpp->mpp_entry_elf32)
+		printf("EFI32 entry point%s: %"PRIx32"\n", 
+		       MPP_OPT(mpp->mpp_entry_elf32->flags),
+		       mpp->mpp_entry_elf32->entry_addr);
+
+	if (mpp->mpp_entry_elf64)
+		printf("EFI64 entry point%s: %"PRIx32"\n", 
+		       MPP_OPT(mpp->mpp_entry_elf64->flags),
+		       mpp->mpp_entry_elf64->entry_addr);
+
+	if (mpp->mpp_relocatable) {
+		char *pref;
+
+		switch (mpp->mpp_relocatable->preference) {
+		case MULTIBOOT_LOAD_PREFERENCE_NONE: pref = "none"; break;
+		case MULTIBOOT_LOAD_PREFERENCE_LOW:  pref = "low"; break;
+		case MULTIBOOT_LOAD_PREFERENCE_HIGH: pref = "high"; break;
+		default:
+			pref = "(unknown)"; break;
+		}
+		printf("Relocatable%s: min_addr = %"PRIx32", "
+		       "max_addr = %"PRIx32", align = %"PRIx32", pref %s\n",
+		       MPP_OPT(mpp->mpp_relocatable->flags),
+		       mpp->mpp_relocatable->min_addr,
+		       mpp->mpp_relocatable->max_addr,
+		       mpp->mpp_relocatable->align, pref);
+	}
+
+	printf("=== multiboot2 header dump end  ===\n");
+	return;
+}
+#endif /* MULTIBOOT2_DEBUG */
+
+static size_t
+mbi_cmdline(struct multiboot_package *mbp, void *buf)
+{
+	struct multiboot_tag_string *mbt = buf;
+	size_t cmdlen;
+	size_t len;
+	const char fmt[] = "%s %s";
+
+	/* +1 for trailing \0 */
+	cmdlen = snprintf(NULL, SIZE_T_MAX, fmt, mbp->mbp_file, mbp->mbp_args)
+	       + 1;
+	len = sizeof(*mbt) + cmdlen;
+
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_CMDLINE;
+		mbt->size = len;
+		(void)snprintf(mbt->string, cmdlen, fmt, 
+			       mbp->mbp_file, mbp->mbp_args);
+	}
+
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_boot_loader_name(struct multiboot_package *mbp, void *buf)
+{
+	struct multiboot_tag_string *mbt = buf;
+	size_t len;
+	size_t strlen;
+	const char fmt[] = "%s, Revision %s (from NetBSD %s)";
+
+
+	/* +1 for trailing \0 */
+	strlen = snprintf(NULL, SIZE_T_MAX, fmt,
+			  bootprog_name, bootprog_rev, bootprog_kernrev)
+	       + 1;
+	len = sizeof(*mbt) + strlen;
+
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME;
+		mbt->size = len;
+	    	(void)snprintf(mbt->string, strlen, fmt, bootprog_name, 
+			       bootprog_rev, bootprog_kernrev);
+	}
+
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_modules(struct multiboot_package *mbp, void *buf)
+{
+	struct multiboot_tag_module *mbt = buf;
+	struct bi_modulelist_entry *bim;
+	size_t len;
+	int i;
+
+	if (btinfo_modulelist == NULL)
+		return 0;
+
+	len = 0;
+		
+	bim = (struct bi_modulelist_entry *)(btinfo_modulelist + 1);
+	for (i = 0; i < btinfo_modulelist->num; i++) {
+		size_t pathlen = strlen(bim->path) + 1;
+		size_t mbt_len = sizeof(*mbt) + pathlen;
+		size_t mbt_len_align = roundup(mbt_len, MULTIBOOT_TAG_ALIGN);
+		len += mbt_len_align;
+
+		if (mbt) {
+			mbt->type = MULTIBOOT_TAG_TYPE_MODULE;
+			mbt->size = mbt_len;
+			mbt->mod_start = bim->base;
+			mbt->mod_end = bim->base + bim->len;
+			strncpy(mbt->cmdline, bim->path, pathlen);
+
+			mbt = (struct multiboot_tag_module *)
+			    ((char *)mbt + mbt_len_align);
+		}
+	}
+
+	return len;
+}
+
+static size_t
+mbi_basic_meminfo(struct multiboot_package *mbp, void *buf)
+{
+	struct multiboot_tag_basic_meminfo *mbt = buf;
+	size_t len;
+
+	len = sizeof(*mbt);
+		
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
+		mbt->size = len;
+		mbt->mem_lower = mbp->mbp_basemem;
+		mbt->mem_upper = mbp->mbp_extmem;
+	}
+
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_bootdev(struct multiboot_package *mbp, void *buf)
+{
+	struct multiboot_tag_bootdev *mbt = buf;
+	size_t len;
+
+	len = sizeof(*mbt);
+		
+	/*
+	 * According to the specification:
+	 * - sub_partition is used for BSD disklabel.
+	 * - Extendded MBR partitions are counted from 4 and increasing,
+	 *   with no subpartition.
+	 */
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_BOOTDEV;
+		mbt->size = len;
+		mbt->biosdev = bi_disk.biosdev;
+		mbt->slice = bi_disk.partition;
+		mbt->part = 0xFFFFFFFF;	/* aka sub_partition, for disklabel */
+	}
+
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+	return 0;
+}
+
+static size_t
+mbi_mmap(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+	struct multiboot_tag_mmap *mbt = buf;
+	struct bi_memmap_entry *memmap;
+	size_t num;
+
+#ifndef EFIBOOT
+	bi_getmemmap();
+
+	if (btinfo_memmap == NULL)
+		goto out;
+
+	memmap = btinfo_memmap->entry;
+	num = btinfo_memmap->num;
+#else
+	if (efi_memory_get_memmap(&memmap, &num) != 0)
+		goto out;
+#endif
+
+	len = sizeof(*mbt) + num * sizeof(mbt->entries[0]);
+	
+	if (mbt) {
+		int i;
+		struct multiboot_mmap_entry *mbte;
+
+		mbt->type = MULTIBOOT_TAG_TYPE_MMAP;
+		mbt->size = len;
+		mbt->entry_size = sizeof(mbt->entries[0]);
+		mbt->entry_version = 0;
+
+		mbte = (struct multiboot_mmap_entry *)(mbt + 1);
+		for (i = 0; i < num; i++) {
+			mbte[i].addr = memmap[i].addr;
+			mbte[i].len = memmap[i].size;
+			switch(memmap[i].type) {
+			case BIM_Memory:
+				mbte[i].type = MULTIBOOT_MEMORY_AVAILABLE;
+				break;
+			case BIM_Reserved:
+				mbte[i].type = MULTIBOOT_MEMORY_RESERVED;
+				break;
+			case BIM_ACPI:
+				mbte[i].type = 
+				    MULTIBOOT_MEMORY_ACPI_RECLAIMABLE;
+				break;
+			case BIM_NVS:
+				mbte[i].type = MULTIBOOT_MEMORY_NVS;
+				break;
+			case BIM_Unusable:
+				mbte[i].type = MULTIBOOT_MEMORY_BADRAM;
+				break;
+			default:
+				mbte[i].type = MULTIBOOT_MEMORY_RESERVED;
+				break;
+			}
+			mbte[i].zero = 0;
+		}
+	}
+#ifdef EFIBOOT
+	dealloc(memmap, num * sizeof(memmap));
+#endif
+out:
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_vbe(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+
+#ifndef EFIBOOT
+	struct multiboot_tag_vbe *mbt = buf;
+
+	len = sizeof(*mbt);
+	
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_VBE;
+		mbt->size = len;
+		mbt->vbe_mode = btinfo_framebuffer.vbemode;
+		mbt->vbe_interface_seg = 0;
+		mbt->vbe_interface_off = 0;
+		mbt->vbe_interface_len = 0;
+		biosvbe_info((struct vbeinfoblock *)&mbt->vbe_control_info);
+		biosvbe_get_mode_info(mbt->vbe_mode,
+		    (struct modeinfoblock *)&mbt->vbe_mode_info);
+	}
+#endif
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_framebuffer(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+	struct multiboot_tag_framebuffer *mbt = buf;
+	struct btinfo_framebuffer *fb = &btinfo_framebuffer;
+
+#ifndef EFIBOOT
+	struct modeinfoblock mi;
+
+	if (fb->physaddr != 0) {
+		int ret;
+
+		ret = biosvbe_get_mode_info(fb->vbemode, &mi);
+		if (ret != 0x004f)
+			return 0;
+	}
+#endif
+
+	len = sizeof(*mbt);
+	
+	if (mbt) {
+		mbt->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
+		mbt->common.size = len;
+		mbt->common.reserved = 0;
+
+		/*
+		 * No framebuffer, default to 80x25 console
+		 */ 
+		if (fb->physaddr == 0) {
+			int width = 80;
+			int height = 25;
+			int charlen = 2;
+			mbt->common.framebuffer_addr = CGA_BUF;
+			mbt->common.framebuffer_width = width;
+			mbt->common.framebuffer_height = height;
+			mbt->common.framebuffer_bpp = charlen * 8;
+			mbt->common.framebuffer_pitch = width * charlen;
+			mbt->common.framebuffer_type = 
+			    MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
+		} else {
+			mbt->common.framebuffer_addr = fb->physaddr;
+			mbt->common.framebuffer_pitch = fb->stride;
+			mbt->common.framebuffer_width = fb->width;
+			mbt->common.framebuffer_height = fb->height;
+			mbt->common.framebuffer_bpp = fb->depth;
+			mbt->common.framebuffer_type =
+			    MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
+#ifndef EFIBOOT
+			if (mi.MemoryModel == 0x04)
+				mbt->common.framebuffer_type =
+				    MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED;
+#endif
+		}
+			
+		switch (mbt->common.framebuffer_type) {
+#ifndef EFIBOOT
+		case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: 
+			mbt->framebuffer_palette_num_colors = 256;
+
+			for (int i = 0; i < 256; i++) {
+				mbt->framebuffer_palette[i].red =
+				    rasops_cmap[3 * i];
+				mbt->framebuffer_palette[i].green =
+				    rasops_cmap[(3 * i) + 1];
+				mbt->framebuffer_palette[i].blue =
+				    rasops_cmap[(3 * i) + 2];
+			}	
+			break;
+#endif
+		case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
+			mbt->framebuffer_red_field_position = fb->rpos;
+			mbt->framebuffer_red_mask_size = fb->rnum;
+			mbt->framebuffer_green_field_position = fb->gpos;
+			mbt->framebuffer_green_mask_size = fb->gnum;
+			mbt->framebuffer_blue_field_position = fb->bpos;
+			mbt->framebuffer_blue_mask_size = fb->bnum;
+			break;
+		default:
+			break;
+		}
+	}
+
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_acpi_old(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+	struct multiboot_tag_old_acpi *mbt = buf;
+	ACPI_PHYSICAL_ADDRESS rsdp_phys = -1;
+	ACPI_RSDP_COMMON rsdp;
+#ifdef EFIBOOT
+	const EFI_GUID acpi_table_guid = ACPI_TABLE_GUID;
+	int i;
+
+	if (ST == NULL)
+		goto out;
+
+	for (i = 0; i < ST->NumberOfTableEntries; i++)  {
+		if (memcmp(&ST->ConfigurationTable[i].VendorGuid,
+		   &acpi_table_guid, sizeof(acpi_table_guid)) == 0) {
+			rsdp_phys = (ACPI_PHYSICAL_ADDRESS)
+			    ST->ConfigurationTable[i].VendorTable; 
+			break;
+		}
+	}
+#else
+#ifdef notyet
+	rsdp_phys = acpi_md_OsGetRootPointer();
+	pvbcopy((void *)(vaddr_t)rsdp_phys, &rsdp, sizeof(rsdp));
+
+	/* Check ACPI 1.0 */
+	if (rsdp.Revision != 0)
+		rsdp_phys = -1;
+#endif
+#endif
+
+	if (rsdp_phys == -1)
+		goto out;
+
+	len = sizeof(*mbt) + sizeof(rsdp);
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_ACPI_OLD;
+		mbt->size = len;
+		pvbcopy((void *)(vaddr_t)rsdp_phys, mbt->rsdp, sizeof(rsdp));
+	}
+out:
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_acpi_new(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+	struct multiboot_tag_new_acpi *mbt = buf;
+	ACPI_PHYSICAL_ADDRESS rsdp_phys = -1;
+	ACPI_TABLE_RSDP rsdp;
+#ifdef EFIBOOT
+	const EFI_GUID acpi_20_table_guid = ACPI_20_TABLE_GUID;
+	int i;
+
+	if (ST == NULL)
+		goto out;
+
+	for (i = 0; i < ST->NumberOfTableEntries; i++)  {
+		if (memcmp(&ST->ConfigurationTable[i].VendorGuid,
+		   &acpi_20_table_guid, sizeof(acpi_20_table_guid)) == 0) {
+			rsdp_phys = (ACPI_PHYSICAL_ADDRESS)
+			    ST->ConfigurationTable[i].VendorTable; 
+			break;
+		}
+	}
+#else
+#ifdef notyet
+	rsdp_phys = acpi_md_OsGetRootPointer();
+	pvbcopy((void *)(vaddr_t)rsdp_phys, &rsdp, sizeof(rsdp));
+
+	/* Check ACPI 2.0 */
+	if (rsdp.Revision != 2)
+		rsdp_phys = -1;
+#endif
+#endif
+	if (rsdp_phys == -1)
+		goto out;
+
+	len = sizeof(*mbt) + sizeof(rsdp);
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_ACPI_NEW;
+		mbt->size = len;
+		pvbcopy((void *)(vaddr_t)rsdp_phys, mbt->rsdp, sizeof(rsdp));
+	}
+out:
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_apm(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+#ifdef notyet
+	struct multiboot_tag_apm *mbt = buf;
+
+	len = sizeof(*mbt):
+
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_A;
+		mbt->size = len;
+		mbt->version = 0;
+		mbt->cseg = 0;
+		mbt->offset = 0;
+		mbt->cseg_16 = 0;
+		mbt->dseg = 0;; 
+		mbt->flags = 0;
+		mbt->cseg_len = 0;
+		mbt->cseg_16_len = 0;
+		mbt->dseg_len = 0;
+	}
+out:
+#endif
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_smbios(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+	struct multiboot_tag_smbios *mbt = buf;
+	void *smbios_phys;
+	struct smb3hdr *smbios3_phys = NULL;
+	struct smb3hdr smbios3;
+	struct smbhdr *smbios21_phys = NULL;
+	struct smbhdr smbios21;
+	size_t smbios_len;
+	int major;
+	int minor;
+#ifdef EFIBOOT
+	const EFI_GUID smbios3_guid = SMBIOS3_TABLE_GUID;
+	const EFI_GUID smbios21_guid = SMBIOS_TABLE_GUID;
+	int i;
+
+	if (ST == NULL)
+		goto out;
+
+	for (i = 0; i < ST->NumberOfTableEntries; i++)  {
+		if (memcmp(&ST->ConfigurationTable[i].VendorGuid,
+		   &smbios3_guid, sizeof(smbios3_guid)) == 0)
+			smbios3_phys = ST->ConfigurationTable[i].VendorTable; 
+
+		if (memcmp(&ST->ConfigurationTable[i].VendorGuid,
+		   &smbios21_guid, sizeof(smbios21_guid)) == 0)
+			smbios21_phys = ST->ConfigurationTable[i].VendorTable; 
+	}
+#else
+	char *cp;
+	char line[16];
+	const char *smbios21_anchor = "_SM_";
+	const char *smbios3_anchor = "_SM3_";
+
+	for (cp = (char *)SMBIOS_START;
+	     cp < (char *)SMBIOS_END;
+	     cp += sizeof(buf)) {
+		pvbcopy(cp, line, sizeof(line));
+		if (memcmp(line, smbios3_anchor, strlen(smbios3_anchor)) == 0)
+			smbios3_phys = (struct smb3hdr *)cp;
+		if (memcmp(line, smbios21_anchor, strlen(smbios21_anchor)) == 0)
+			smbios21_phys = (struct smbhdr *)cp;
+	}
+#endif
+	if (smbios3_phys != NULL) {
+		pvbcopy(smbios3_phys, &smbios3, sizeof(smbios3));
+		smbios_len = smbios3.len;
+		major = smbios3.majrev;
+		minor = smbios3.minrev;
+		smbios_phys = smbios3_phys;
+	} else if (smbios21_phys != NULL) {
+		pvbcopy(smbios21_phys, &smbios21, sizeof(smbios21));
+		smbios_len = smbios21.len;
+		major = smbios21.majrev;
+		minor = smbios21.minrev;
+		smbios_phys = smbios21_phys;
+	} else {
+		goto out;
+	}
+
+	len = sizeof(*mbt) + smbios_len;
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_SMBIOS;
+		mbt->size = len;
+		mbt->major = major;
+		mbt->minor = minor;
+		pvbcopy(smbios_phys, mbt->tables, smbios_len);
+	}
+out:
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_network(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+#ifdef notyet
+	struct multiboot_tag_network *mbt = buf;
+
+	if (saved_dhcpack == NULL || saved_dhcpack_len == 0)
+		goto out;
+
+	len = sizeof(*mbt) + saved_dhcpack_len;
+
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_NETWORK;
+		mbt->size = len;
+		memcpy(mbt->dhcpack, saved_dhcpack, saved_dhcpack_len);
+	}
+out:
+#endif
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_elf_sections(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+	struct multiboot_tag_elf_sections *mbt = buf;
+	Elf_Ehdr ehdr;
+	Elf32_Ehdr *ehdr32 = NULL;
+	Elf64_Ehdr *ehdr64 = NULL;
+	uint32_t shnum, shentsize, shstrndx, shoff;
+	size_t shdr_len;
+
+	if (mbp->mbp_marks[MARK_SYM] == 0)
+		goto out;
+
+	pvbcopy((void *)mbp->mbp_marks[MARK_SYM], &ehdr, sizeof(ehdr));
+
+	/*
+	 * Check this is a ELF header
+	 */
+	if (memcmp(&ehdr.e_ident, ELFMAG, SELFMAG) != 0)
+		goto out;
+
+	switch (ehdr.e_ident[EI_CLASS]) {
+	case ELFCLASS32:
+		ehdr32 = (Elf32_Ehdr *)&ehdr;
+		shnum = ehdr32->e_shnum;
+		shentsize = ehdr32->e_shentsize;
+		shstrndx = ehdr32->e_shstrndx;
+		shoff = ehdr32->e_shoff;
+		break;
+	case ELFCLASS64:
+		ehdr64 = (Elf64_Ehdr *)&ehdr;
+		shnum = ehdr64->e_shnum;
+		shentsize = ehdr64->e_shentsize;
+		shstrndx = ehdr64->e_shstrndx;
+		shoff = ehdr64->e_shoff;
+		break;
+	default:
+		goto out;
+	}
+
+	shdr_len = shnum * shentsize;
+	if (shdr_len == 0)
+		goto out;
+
+	len = sizeof(*mbt) + shdr_len;
+	if (mbt) {
+		int fd = -1;
+		int ret = -1;
+
+		mbt->type = MULTIBOOT_TAG_TYPE_ELF_SECTIONS;
+		mbt->size = len;
+		mbt->num = shnum;
+		mbt->entsize = shentsize;
+		mbt->shndx = shstrndx;
+		
+		if ((fd = open(mbp->mbp_file, 0)) == -1)
+			goto out_read;
+
+		if (lseek(fd, shoff, SEEK_SET) != shoff)
+			goto out_read;
+ 
+		if (read(fd, mbt + 1,  shdr_len) != shdr_len)
+			goto out_read;
+
+		ret = 0;
+out_read:
+		if (fd != -1)
+			close(fd);
+
+		if (ret != 0) {
+			printf("Error reading ELF sections from %s\n",
+			    mbp->mbp_file);
+			len = 0;
+		}
+	}
+out:
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_end(struct multiboot_package *mbp, void *buf)
+{
+	struct multiboot_tag *mbt = buf;
+	size_t len = sizeof(*mbt);
+
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_END;
+		mbt->size = len;
+	}
+
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_load_base_addr(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+	struct multiboot_tag_load_base_addr *mbt = buf;
+
+	len = sizeof(*mbt);
+
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR;
+		mbt->size = len;
+		mbt->load_base_addr = mbp->mbp_marks[MARK_START];
+	}
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+#ifdef EFIBOOT
+/* Set if EFI ExitBootServices was not called */
+static size_t
+mbi_efi_bs(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+	struct multiboot_tag *mbt = buf;
+
+	if (mbp->mbp_priv->mpp_efi_bs == NULL)
+		goto out;
+
+	len = sizeof(*mbt);
+
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_EFI_BS;
+		mbt->size = len;
+	}
+
+out:
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+
+static size_t
+mbi_efi_mmap(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+	struct multiboot_tag_efi_mmap *mbt = buf;
+	size_t memmap_len;
+
+	if (btinfo_efimemmap == NULL)
+		goto out;
+
+	memmap_len = btinfo_efimemmap->num * btinfo_efimemmap->size;
+	len = sizeof(*mbt) + memmap_len;
+
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_EFI_MMAP;
+		mbt->size = len;
+		mbt->descr_size = btinfo_efimemmap->size;
+		mbt->descr_vers = btinfo_efimemmap->version;
+		memcpy(mbt + 1, btinfo_efimemmap->memmap, memmap_len);
+	}
+
+out:
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+
+
+#ifndef __LP64__
+static size_t
+mbi_efi32_ih(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+	struct multiboot_tag_efi32_ih *mbt = buf;
+
+	len = sizeof(*mbt);
+
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_EFI32_IH;
+		mbt->size = len;
+		mbt->pointer = (multiboot_uint32_t)IH;
+	}
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_efi32(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+	struct multiboot_tag_efi32 *mbt = buf;
+
+	len = sizeof(*mbt);
+
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_EFI32;
+		mbt->size = len;
+		mbt->pointer = (multiboot_uint32_t)ST;
+	}
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+#endif
+
+#ifdef __LP64__
+static size_t
+mbi_efi64_ih(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+	struct multiboot_tag_efi64_ih *mbt = buf;
+
+	len = sizeof(*mbt);
+
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_EFI64_IH;
+		mbt->size = len;
+		mbt->pointer = (multiboot_uint64_t)IH;
+	}
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+
+static size_t
+mbi_efi64(struct multiboot_package *mbp, void *buf)
+{
+	size_t len = 0;
+	struct multiboot_tag_efi64 *mbt = buf;
+
+	len = sizeof(*mbt);
+
+	if (mbt) {
+		mbt->type = MULTIBOOT_TAG_TYPE_EFI64;
+		mbt->size = len;
+		mbt->pointer = (multiboot_uint64_t)ST;
+	}
+	return roundup(len, MULTIBOOT_TAG_ALIGN);
+}
+#endif /* __LP64__ */
+#endif /* EFIBOOT */
+
+static bool
+is_tag_required(struct multiboot_package *mbp, uint16_t tag)
+{
+	bool ret = false;	
+	int i;
+	struct multiboot_header_tag_information_request *info_req;
+	size_t nreq;
+
+	info_req = mbp->mbp_priv->mpp_info_req;
+
+	if (info_req == NULL)
+		goto out;
+
+	if (info_req->flags & MULTIBOOT_HEADER_TAG_OPTIONAL)
+		goto out;
+
+	nreq = (info_req->size - sizeof(*info_req))
+	     / sizeof(info_req->requests[0]);
+
+	for (i = 0; i < nreq; i++) {
+		if (info_req->requests[i] == tag) {
+			ret = true;
+			break;
+		}
+	}
+			
+out:
+	return ret;
+}
+
+static int 
+mbi_dispatch(struct multiboot_package *mbp, uint16_t type, 
+    char *bp, size_t *total_len)
+{
+	int ret = 0;
+	size_t len = 0;
+
+	switch (type) {
+	case MULTIBOOT_TAG_TYPE_END:
+		len = mbi_end(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_CMDLINE:
+		len = mbi_cmdline(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
+		len = mbi_boot_loader_name(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_MODULE:
+		len = mbi_modules(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
+		len = mbi_basic_meminfo(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_BOOTDEV:
+		len = mbi_bootdev(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_MMAP:
+		len = mbi_mmap(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_VBE:
+		len = mbi_vbe(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
+		len = mbi_framebuffer(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_ACPI_OLD:
+		len = mbi_acpi_old(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_ACPI_NEW:
+		len = mbi_acpi_new(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
+		len = mbi_elf_sections(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_APM:
+		len = mbi_apm(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_SMBIOS:
+		len = mbi_smbios(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_NETWORK:	
+		len = mbi_network(mbp, bp);
+		break;
+#ifdef EFIBOOT
+	case MULTIBOOT_TAG_TYPE_EFI_MMAP:
+		len = mbi_efi_mmap(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_EFI_BS:
+		len = mbi_efi_bs(mbp, bp);
+		break;
+#ifndef __LP64__
+	case MULTIBOOT_TAG_TYPE_EFI32_IH:
+		len = mbi_efi32_ih(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_EFI32:
+		len = mbi_efi32(mbp, bp);
+		break;
+#else /* __LP64__ */
+	case MULTIBOOT_TAG_TYPE_EFI64_IH:
+		len = mbi_efi64_ih(mbp, bp);
+		break;
+	case MULTIBOOT_TAG_TYPE_EFI64:
+		len = mbi_efi64(mbp, bp);
+		break;
+#endif /* __LP64__ */
+#endif /* EFIBOOT */
+	case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
+		len = mbi_load_base_addr(mbp, bp);
+		break;
+	default:
+		len = 0;
+		break;
+	}
+
+	if (len == 0 && is_tag_required(mbp, type))
+		ret = -1;
+
+	*total_len += len;
+	return ret;
+}
+
+static int
+exec_multiboot2(struct multiboot_package *mbp)
+{
+	size_t len, alen;
+	char *mbi = NULL;
+	struct multiboot_package_priv *mpp = mbp->mbp_priv;
+	uint16_t tags[] = {
+		MULTIBOOT_TAG_TYPE_CMDLINE,
+		MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME,
+		MULTIBOOT_TAG_TYPE_MODULE,
+		MULTIBOOT_TAG_TYPE_BASIC_MEMINFO,
+		MULTIBOOT_TAG_TYPE_BOOTDEV,
+		MULTIBOOT_TAG_TYPE_VBE,
+		MULTIBOOT_TAG_TYPE_FRAMEBUFFER,
+		MULTIBOOT_TAG_TYPE_ELF_SECTIONS,
+		MULTIBOOT_TAG_TYPE_APM,
+		MULTIBOOT_TAG_TYPE_SMBIOS,
+		MULTIBOOT_TAG_TYPE_ACPI_OLD,
+		MULTIBOOT_TAG_TYPE_ACPI_NEW,
+		MULTIBOOT_TAG_TYPE_NETWORK,
+		MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR,
+#ifdef EFIBOOT
+		MULTIBOOT_TAG_TYPE_EFI_BS,
+#ifndef __LP64__
+		MULTIBOOT_TAG_TYPE_EFI32,
+		MULTIBOOT_TAG_TYPE_EFI32_IH,
+#else
+		MULTIBOOT_TAG_TYPE_EFI64,
+		MULTIBOOT_TAG_TYPE_EFI64_IH,
+#endif /* __LP64__ */
+		/*
+		 * EFI_MMAP and MMAP at the end so that they
+		 * catch page allocation made for other tags.
+		 */
+		MULTIBOOT_TAG_TYPE_EFI_MMAP,
+#endif /* EFIGOOT */
+		MULTIBOOT_TAG_TYPE_MMAP,
+		MULTIBOOT_TAG_TYPE_END, /* Must be last */
+	};
+	physaddr_t entry;
+	int i;
+
+	BI_ALLOC(BTINFO_MAX);
+
+	/* set new video mode if text mode was not requested */
+	if (mpp->mpp_framebuffer == NULL ||
+	    mpp->mpp_framebuffer->depth != 0)
+	vbe_commit();  
+
+	len = 2 * sizeof(multiboot_uint32_t);
+	for (i = 0; i < sizeof(tags) / sizeof(*tags); i++) {
+		if (mbi_dispatch(mbp, tags[i], NULL, &len) != 0)
+			goto fail;
+	}
+
+	mpp->mpp_mbi_len = len + MULTIBOOT_TAG_ALIGN;
+	mpp->mpp_mbi = alloc(mpp->mpp_mbi_len);
+	mbi = (char *)roundup((vaddr_t)mpp->mpp_mbi, MULTIBOOT_TAG_ALIGN);
+
+	alen = 2 * sizeof(multiboot_uint32_t);
+	for (i = 0; i < sizeof(tags) / sizeof(*tags); i++) {
+		if (mbi_dispatch(mbp, tags[i], mbi + alen, &alen) != 0)
+			goto fail;
+
+		/*
+		 * It may shrink because of failure when filling
+		 * structures, but it should not grow.
+		 */
+		if (alen > len)
+			panic("multiboot2 info size mismatch");
+	}
+
+
+	((multiboot_uint32_t *)mbi)[0] = alen;	/* total size */
+	((multiboot_uint32_t *)mbi)[1] = 0;	/* reserved */
+
+#if 0
+	for (i = 0; i < len; i += 16) {
+		printf("%p ", mbi + i);
+		for (int j = 0; j < 16; j++)
+			printf("%s%s%x", 
+			       (i+j) % 4 ? "" : " ",
+			       (unsigned char)mbi[i+j] < 0x10 ? "0" : "",
+			       (unsigned char)(mbi[i+j]));
+		printf("\n");
+	}
+#endif
+
+	printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n",
+	    mbp->mbp_marks[MARK_ENTRY],
+	    mbp->mbp_marks[MARK_NSYM],
+	    mbp->mbp_marks[MARK_SYM],
+	    mbp->mbp_marks[MARK_END]);
+     
+#ifdef MULTIBOOT2_DEBUG
+	multiboot2_info_dump(MULTIBOOT2_BOOTLOADER_MAGIC, mbi);
+#endif /* MULTIBOOT2_DEBUG */
+
+	entry = mbp->mbp_marks[MARK_ENTRY];
+
+	if (mpp->mpp_entry)
+		entry = mpp->mpp_entry->entry_addr;
+#ifdef EFIBOOT
+#ifdef __LP64__
+	if (mpp->mpp_entry_elf64)
+		entry = mpp->mpp_entry_elf64->entry_addr
+		      + efi_loadaddr;
+#else
+	if (mpp->mpp_entry_elf32)
+		entry = mpp->mpp_entry_elf32->entry_addr
+		      + efi_loadaddr;
+#endif /* __LP64__ */
+	if (mpp->mpp_efi_bs == NULL)
+		efi_cleanup();
+#endif /* EFIBOOT */
+
+	/* Does not return */
+	multiboot(entry, vtophys(mbi),
+	    x86_trunc_page(mbp->mbp_basemem * 1024),
+	    MULTIBOOT2_BOOTLOADER_MAGIC);
+fail:
+	return -1;
+}
+
+static void
+cleanup_multiboot2(struct multiboot_package *mbp)
+{
+	if (mbp->mbp_header)
+		dealloc(mbp->mbp_header, mbp->mbp_header->header_length);
+	if (mbp->mbp_priv && mbp->mbp_priv->mpp_mbi)
+		dealloc(mbp->mbp_priv->mpp_mbi, mbp->mbp_priv->mpp_mbi_len);
+	if (mbp->mbp_priv)
+		dealloc(mbp->mbp_priv, sizeof(*mbp->mbp_priv));
+
+	dealloc(mbp, sizeof(*mbp));
+
+	return;
+}
+
+static bool
+is_header_required(struct multiboot_header_tag *mbt)
+{
+	bool ret = false;
+
+	if (mbt == NULL)
+		goto out;
+
+	if (mbt->flags & MULTIBOOT_HEADER_TAG_OPTIONAL)
+		goto out;
+
+	ret = true;
+out:
+	return ret;
+}
+
+#define NEXT_HEADER(mbt) ((struct multiboot_header_tag *) \
+   ((char *)mbt + roundup(mbt->size, MULTIBOOT_HEADER_ALIGN)))
+
+struct multiboot_package *
+probe_multiboot2(const char *path)
+{
+	int fd = -1;
+	size_t i;
+	char buf[MULTIBOOT_SEARCH + sizeof(struct multiboot_header)];
+	ssize_t readen;
+	struct multiboot_package *mbp = NULL;
+	struct multiboot_header *mbh;
+	struct multiboot_header_tag *mbt;
+	size_t mbh_len = 0;
+
+	if ((fd = open(path, 0)) == -1)
+		goto out;
+ 
+	readen = read(fd, buf, sizeof(buf));
+	if (readen < sizeof(struct multiboot_header))
+		goto out;
+
+	for (i = 0; i < readen; i += MULTIBOOT_HEADER_ALIGN) {
+		mbh = (struct multiboot_header *)(buf + i);
+		
+		if (mbh->magic != MULTIBOOT2_HEADER_MAGIC)
+			continue;
+
+		if (mbh->architecture != MULTIBOOT_ARCHITECTURE_I386)
+			continue;
+		
+		if (mbh->magic + mbh->architecture + 
+		    mbh->header_length + mbh->checksum)
+			continue;
+		mbh_len = mbh->header_length;
+
+		mbp = alloc(sizeof(*mbp));
+		mbp->mbp_version	= 2;
+		mbp->mbp_file		= path;
+		mbp->mbp_header		= alloc(mbh_len);
+		mbp->mbp_priv		= alloc(sizeof(*mbp->mbp_priv));
+		memset(mbp->mbp_priv, 0, sizeof (*mbp->mbp_priv));
+		mbp->mbp_probe		= *probe_multiboot2;
+		mbp->mbp_exec		= *exec_multiboot2;
+		mbp->mbp_cleanup	= *cleanup_multiboot2;
+
+		break;
+	}
+
+	if (mbp == NULL)
+		goto out;
+
+	if (lseek(fd, i, SEEK_SET) != i) {
+		printf("lseek failed");
+		mbp->mbp_cleanup(mbp);
+		mbp = NULL;
+		goto out;
+	}
+
+	mbh = mbp->mbp_header;
+	if (read(fd, mbh, mbh_len) != mbh_len) {
+		printf("read failed");
+		mbp->mbp_cleanup(mbp);
+		mbp = NULL;
+		goto out;
+	}
+
+	for (mbt = (struct multiboot_header_tag *)(mbh + 1);
+	     (char *)mbt - (char *)mbh < mbh_len;
+	     mbt = NEXT_HEADER(mbt)) {
+
+		switch(mbt->type) {
+		case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST:
+			mbp->mbp_priv->mpp_info_req = (void *)mbt;
+			break;
+		case MULTIBOOT_HEADER_TAG_ADDRESS:
+			mbp->mbp_priv->mpp_address = (void *)mbt;
+			break;
+		case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS:
+			mbp->mbp_priv->mpp_entry = (void *)mbt;
+			break;
+		case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
+			mbp->mbp_priv->mpp_console = (void *)mbt;
+
+		case MULTIBOOT_HEADER_TAG_FRAMEBUFFER:
+			mbp->mbp_priv->mpp_framebuffer = (void *)mbt;
+			break;
+		case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
+			mbp->mbp_priv->mpp_module_align = (void *)mbt;
+			break;
+#ifdef EFIBOOT
+		case MULTIBOOT_HEADER_TAG_EFI_BS:
+			mbp->mbp_priv->mpp_efi_bs = (void *)mbt;
+			break;
+		case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32:
+			mbp->mbp_priv->mpp_entry_elf32 = (void *)mbt;
+			break;
+		case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64:
+			mbp->mbp_priv->mpp_entry_elf64 = (void *)mbt;
+			break;
+#endif
+		case MULTIBOOT_HEADER_TAG_RELOCATABLE:
+			mbp->mbp_priv->mpp_relocatable = (void *)mbt;
+			break;
+		case MULTIBOOT_HEADER_TAG_END: /* FALLTHROUGH */
+		default:
+			break;
+		}
+	}
+
+#ifdef MULTIBOOT2_DEBUG
+	multiboot2_header_dump(mbp);
+#endif /* MULTIBOOT2_DEBUG */
+
+	/*
+	 * multiboot header fully supported
+	 *  MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
+	 *  MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS
+	 *  MULTIBOOT_HEADER_TAG_MODULE_ALIGN (we always load as page aligned)
+	 *  MULTIBOOT_HEADER_TAG_EFI_BS
+	 *  MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32
+	 *  MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64
+	 *  MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS (we always have a console)
+	 *
+	 * Not supported:
+	 *  MULTIBOOT_HEADER_TAG_ADDRESS
+	 *  MULTIBOOT_HEADER_TAG_FRAMEBUFFER (but spec says it is onty a hint)
+	 *  MULTIBOOT_HEADER_TAG_RELOCATABLE
+	 */
+
+	if (is_header_required((void *)mbp->mbp_priv->mpp_address)) {
+		printf("Unsupported multiboot address header\n");
+		mbp->mbp_cleanup(mbp);
+		mbp = NULL;
+		goto out;
+	}
+
+#ifdef EFIBOOT
+	/*
+	 * We do not fully support the relocatable header, but
+	 * at least we honour the alignment request. Xen requires
+	 * that to boot.
+	 */
+	struct multiboot_header_tag_relocatable *reloc = 
+	    mbp->mbp_priv->mpp_relocatable;
+	if (reloc)
+		efi_loadaddr = roundup(efi_loadaddr, reloc->align);
+#endif
+
+	if (is_header_required((void *)mbp->mbp_priv->mpp_relocatable)) {
+		printf("Unsupported multiboot relocatable header\n");
+		mbp->mbp_cleanup(mbp);
+		mbp = NULL;
+		goto out;
+	}
+
+out:
+
+	if (fd != -1)
+		close(fd);
+
+	return mbp;
+}
+
+#endif /* NO_MULTIBOOT2 */

Reply via email to