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 <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.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 <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.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 <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.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 <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.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 <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.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 <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.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 <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.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 */