Module Name: src
Committed By: manu
Date: Fri Sep 13 02:19:46 UTC 2019
Modified Files:
src/sys/arch/i386/include: Makefile
src/sys/arch/i386/stand/boot: Makefile.boot
src/sys/arch/i386/stand/dosboot: Makefile
src/sys/arch/i386/stand/efiboot: Makefile.efiboot boot.c efiboot.c
efiboot.h eficons.c efimemory.c
src/sys/arch/i386/stand/efiboot/bootia32: Makefile efibootia32.c
src/sys/arch/i386/stand/efiboot/bootx64: Makefile efibootx64.c
src/sys/arch/i386/stand/lib: Makefile biosdisk.c biosdisk.h
bootinfo_memmap.c exec.c libi386.h multiboot.S pread.c
src/sys/arch/i386/stand/netboot: Makefile.netboot
src/sys/arch/i386/stand/pxeboot: Makefile
Added Files:
src/sys/arch/i386/include: multiboot2.h
src/sys/arch/i386/stand/efiboot/bootia32: multiboot32.S
src/sys/arch/i386/stand/efiboot/bootx64: multiboot64.S
src/sys/arch/i386/stand/lib: exec_multiboot1.c exec_multiboot2.c
Log Message:
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
To generate a diff of this commit:
cvs rdiff -u -r1.49 -r1.50 src/sys/arch/i386/include/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/arch/i386/include/multiboot2.h
cvs rdiff -u -r1.72 -r1.73 src/sys/arch/i386/stand/boot/Makefile.boot
cvs rdiff -u -r1.31 -r1.32 src/sys/arch/i386/stand/dosboot/Makefile
cvs rdiff -u -r1.15 -r1.16 src/sys/arch/i386/stand/efiboot/Makefile.efiboot \
src/sys/arch/i386/stand/efiboot/boot.c
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/i386/stand/efiboot/efiboot.c
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/i386/stand/efiboot/efiboot.h
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/i386/stand/efiboot/eficons.c
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/i386/stand/efiboot/efimemory.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/i386/stand/efiboot/bootia32/Makefile
cvs rdiff -u -r1.4 -r1.5 \
src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/i386/stand/efiboot/bootia32/multiboot32.S
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/i386/stand/efiboot/bootx64/Makefile
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/i386/stand/efiboot/bootx64/multiboot64.S
cvs rdiff -u -r1.46 -r1.47 src/sys/arch/i386/stand/lib/Makefile
cvs rdiff -u -r1.51 -r1.52 src/sys/arch/i386/stand/lib/biosdisk.c
cvs rdiff -u -r1.11 -r1.12 src/sys/arch/i386/stand/lib/biosdisk.h
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/i386/stand/lib/bootinfo_memmap.c
cvs rdiff -u -r1.73 -r1.74 src/sys/arch/i386/stand/lib/exec.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/i386/stand/lib/exec_multiboot1.c \
src/sys/arch/i386/stand/lib/exec_multiboot2.c
cvs rdiff -u -r1.44 -r1.45 src/sys/arch/i386/stand/lib/libi386.h
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/i386/stand/lib/multiboot.S
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/i386/stand/lib/pread.c
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/i386/stand/netboot/Makefile.netboot
cvs rdiff -u -r1.25 -r1.26 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/sys/arch/i386/include/Makefile
diff -u src/sys/arch/i386/include/Makefile:1.49 src/sys/arch/i386/include/Makefile:1.50
--- src/sys/arch/i386/include/Makefile:1.49 Thu Jul 12 10:46:44 2018
+++ src/sys/arch/i386/include/Makefile Fri Sep 13 02:19:45 2019
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.49 2018/07/12 10:46:44 maxv Exp $
+# $NetBSD: Makefile,v 1.50 2019/09/13 02:19:45 manu 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.73
--- 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 Fri Sep 13 02:19:45 2019
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.boot,v 1.72 2018/07/25 23:45:32 kamil Exp $
+# $NetBSD: Makefile.boot,v 1.73 2019/09/13 02:19:45 manu 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.32
--- src/sys/arch/i386/stand/dosboot/Makefile:1.31 Sat Jun 2 14:30:07 2018
+++ src/sys/arch/i386/stand/dosboot/Makefile Fri Sep 13 02:19:45 2019
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.31 2018/06/02 14:30:07 christos Exp $
+# $NetBSD: Makefile,v 1.32 2019/09/13 02:19:45 manu 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.16
--- 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 Fri Sep 13 02:19:45 2019
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.efiboot,v 1.15 2019/07/26 11:30:31 nonaka Exp $
+# $NetBSD: Makefile.efiboot,v 1.16 2019/09/13 02:19:45 manu 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.15 src/sys/arch/i386/stand/efiboot/boot.c:1.16
--- src/sys/arch/i386/stand/efiboot/boot.c:1.15 Mon Sep 2 06:10:24 2019
+++ src/sys/arch/i386/stand/efiboot/boot.c Fri Sep 13 02:19:45 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: boot.c,v 1.15 2019/09/02 06:10:24 manu Exp $ */
+/* $NetBSD: boot.c,v 1.16 2019/09/13 02:19:45 manu Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <[email protected]>
@@ -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.11
--- 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 Fri Sep 13 02:19:45 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: efiboot.c,v 1.10 2019/07/29 12:37:26 nonaka Exp $ */
+/* $NetBSD: efiboot.c,v 1.11 2019/09/13 02:19:45 manu Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <[email protected]>
@@ -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.10
--- 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 Fri Sep 13 02:19:45 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: efiboot.h,v 1.9 2019/07/29 11:28:51 nonaka Exp $ */
+/* $NetBSD: efiboot.h,v 1.10 2019/09/13 02:19:45 manu Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <[email protected]>
@@ -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.7
--- 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 Fri Sep 13 02:19:45 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: eficons.c,v 1.6 2018/05/16 19:53:54 jakllsch Exp $ */
+/* $NetBSD: eficons.c,v 1.7 2019/09/13 02:19:45 manu Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <[email protected]>
@@ -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.9
--- 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 Fri Sep 13 02:19:45 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: efimemory.c,v 1.8 2019/07/29 11:33:07 nonaka Exp $ */
+/* $NetBSD: efimemory.c,v 1.9 2019/09/13 02:19:45 manu Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <[email protected]>
@@ -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.3
--- 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 Fri Sep 13 02:19:45 2019
@@ -1,9 +1,9 @@
-# $NetBSD: Makefile,v 1.2 2017/02/21 10:53:37 nonaka Exp $
+# $NetBSD: Makefile,v 1.3 2019/09/13 02:19:45 manu 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.5
--- 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 Fri Sep 13 02:19:45 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: efibootia32.c,v 1.4 2018/03/27 14:15:05 nonaka Exp $ */
+/* $NetBSD: efibootia32.c,v 1.5 2019/09/13 02:19:45 manu Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <[email protected]>
@@ -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.2
--- 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 Fri Sep 13 02:19:46 2019
@@ -1,10 +1,10 @@
-# $NetBSD: Makefile,v 1.1 2017/01/24 11:09:14 nonaka Exp $
+# $NetBSD: Makefile,v 1.2 2019/09/13 02:19:46 manu 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.5
--- 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 Fri Sep 13 02:19:46 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: efibootx64.c,v 1.4 2018/03/27 14:15:05 nonaka Exp $ */
+/* $NetBSD: efibootx64.c,v 1.5 2019/09/13 02:19:46 manu Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <[email protected]>
@@ -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.46 src/sys/arch/i386/stand/lib/Makefile:1.47
--- src/sys/arch/i386/stand/lib/Makefile:1.46 Sun Aug 18 02:18:25 2019
+++ src/sys/arch/i386/stand/lib/Makefile Fri Sep 13 02:19:46 2019
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.46 2019/08/18 02:18:25 manu Exp $
+# $NetBSD: Makefile,v 1.47 2019/09/13 02:19:46 manu 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.51 src/sys/arch/i386/stand/lib/biosdisk.c:1.52
--- src/sys/arch/i386/stand/lib/biosdisk.c:1.51 Sun Aug 18 16:49:30 2019
+++ src/sys/arch/i386/stand/lib/biosdisk.c Fri Sep 13 02:19:46 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: biosdisk.c,v 1.51 2019/08/18 16:49:30 kamil Exp $ */
+/* $NetBSD: biosdisk.c,v 1.52 2019/09/13 02:19:46 manu 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.11 src/sys/arch/i386/stand/lib/biosdisk.h:1.12
--- src/sys/arch/i386/stand/lib/biosdisk.h:1.11 Sun Aug 18 02:18:25 2019
+++ src/sys/arch/i386/stand/lib/biosdisk.h Fri Sep 13 02:19:46 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: biosdisk.h,v 1.11 2019/08/18 02:18:25 manu Exp $ */
+/* $NetBSD: biosdisk.h,v 1.12 2019/09/13 02:19:46 manu 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.6
--- 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 Fri Sep 13 02:19:46 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.6 2019/09/13 02:19:46 manu 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.74
--- 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 Fri Sep 13 02:19:46 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: exec.c,v 1.73 2019/07/26 12:09:48 nonaka Exp $ */
+/* $NetBSD: exec.c,v 1.74 2019/09/13 02:19:46 manu 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.45
--- 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 Fri Sep 13 02:19:46 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: libi386.h,v 1.44 2019/07/26 12:09:48 nonaka Exp $ */
+/* $NetBSD: libi386.h,v 1.45 2019/09/13 02:19:46 manu 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.3
--- 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 Fri Sep 13 02:19:46 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: multiboot.S,v 1.2 2016/12/04 08:21:08 maxv Exp $ */
+/* $NetBSD: multiboot.S,v 1.3 2019/09/13 02:19:46 manu 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.8
--- 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 Fri Sep 13 02:19:46 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: pread.c,v 1.7 2008/12/14 17:03:43 christos Exp $ */
+/* $NetBSD: pread.c,v 1.8 2019/09/13 02:19:46 manu 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.11
--- 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 Fri Sep 13 02:19:46 2019
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.netboot,v 1.10 2014/01/15 22:25:22 joerg Exp $
+# $NetBSD: Makefile.netboot,v 1.11 2019/09/13 02:19:46 manu 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.26
--- src/sys/arch/i386/stand/pxeboot/Makefile:1.25 Sat Jun 2 14:30:07 2018
+++ src/sys/arch/i386/stand/pxeboot/Makefile Fri Sep 13 02:19:46 2019
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.25 2018/06/02 14:30:07 christos Exp $
+# $NetBSD: Makefile,v 1.26 2019/09/13 02:19:46 manu 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
--- /dev/null Fri Sep 13 02:19:46 2019
+++ src/sys/arch/i386/include/multiboot2.h Fri Sep 13 02:19:45 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
--- /dev/null Fri Sep 13 02:19:46 2019
+++ src/sys/arch/i386/stand/efiboot/bootia32/multiboot32.S Fri Sep 13 02:19:45 2019
@@ -0,0 +1,27 @@
+/* $NetBSD: multiboot32.S,v 1.1 2019/09/13 02:19:45 manu 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
--- /dev/null Fri Sep 13 02:19:46 2019
+++ src/sys/arch/i386/stand/efiboot/bootx64/multiboot64.S Fri Sep 13 02:19:46 2019
@@ -0,0 +1,29 @@
+/* $NetBSD: multiboot64.S,v 1.1 2019/09/13 02:19:46 manu 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
--- /dev/null Fri Sep 13 02:19:46 2019
+++ src/sys/arch/i386/stand/lib/exec_multiboot1.c Fri Sep 13 02:19:46 2019
@@ -0,0 +1,159 @@
+/* $NetBSD: exec_multiboot1.c,v 1.1 2019/09/13 02:19:46 manu 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.1
--- /dev/null Fri Sep 13 02:19:46 2019
+++ src/sys/arch/i386/stand/lib/exec_multiboot2.c Fri Sep 13 02:19:46 2019
@@ -0,0 +1,1643 @@
+/* $NetBSD: exec_multiboot2.c,v 1.1 2019/09/13 02:19:46 manu Exp $ */
+#define MULTIBBOT2_DEBUG
+
+/*
+ * 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 */