Module Name:    src
Committed By:   nonaka
Date:           Tue Jan 24 11:09:15 UTC 2017

Modified Files:
        src/distrib/sets/lists/base: md.amd64
        src/sys/arch/i386/stand: Makefile
        src/sys/arch/i386/stand/lib: biosdisk.c bootinfo_biosgeom.c diskbuf.c
            exec.c libi386.h vbe.c
        src/sys/arch/x86/acpi: acpi_machdep.c
        src/sys/arch/x86/include: bootinfo.h efi.h
        src/sys/arch/x86/x86: efi.c x86_machdep.c
        src/sys/lib/libgnuefi: Makefile Makefile.inc
Added Files:
        src/sys/arch/i386/stand/efiboot: Makefile Makefile.efiboot boot.c
            conf.c devopen.c devopen.h efiboot.c efiboot.h eficons.c efidelay.c
            efidisk.c efidisk.h efidisk_ll.c efigetsecs.c efimemory.c panic.c
            self_reloc.c version
        src/sys/arch/i386/stand/efiboot/bootia32: Makefile efiboot_machdep.h
            efibootia32.c ldscript start.S
        src/sys/arch/i386/stand/efiboot/bootx64: Makefile efiboot_machdep.h
            efibootx64.c ldscript start.S startprog64.S
        src/sys/lib/libgnuefi/arch/i386: Makefile.inc
        src/sys/lib/libgnuefi/arch/x86_64: Makefile.inc

Log Message:
Initial commit of native amd64 EFI boot loader.


To generate a diff of this commit:
cvs rdiff -u -r1.267 -r1.268 src/distrib/sets/lists/base/md.amd64
cvs rdiff -u -r1.27 -r1.28 src/sys/arch/i386/stand/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/arch/i386/stand/efiboot/Makefile \
    src/sys/arch/i386/stand/efiboot/Makefile.efiboot \
    src/sys/arch/i386/stand/efiboot/boot.c \
    src/sys/arch/i386/stand/efiboot/conf.c \
    src/sys/arch/i386/stand/efiboot/devopen.c \
    src/sys/arch/i386/stand/efiboot/devopen.h \
    src/sys/arch/i386/stand/efiboot/efiboot.c \
    src/sys/arch/i386/stand/efiboot/efiboot.h \
    src/sys/arch/i386/stand/efiboot/eficons.c \
    src/sys/arch/i386/stand/efiboot/efidelay.c \
    src/sys/arch/i386/stand/efiboot/efidisk.c \
    src/sys/arch/i386/stand/efiboot/efidisk.h \
    src/sys/arch/i386/stand/efiboot/efidisk_ll.c \
    src/sys/arch/i386/stand/efiboot/efigetsecs.c \
    src/sys/arch/i386/stand/efiboot/efimemory.c \
    src/sys/arch/i386/stand/efiboot/panic.c \
    src/sys/arch/i386/stand/efiboot/self_reloc.c \
    src/sys/arch/i386/stand/efiboot/version
cvs rdiff -u -r0 -r1.1 src/sys/arch/i386/stand/efiboot/bootia32/Makefile \
    src/sys/arch/i386/stand/efiboot/bootia32/efiboot_machdep.h \
    src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c \
    src/sys/arch/i386/stand/efiboot/bootia32/ldscript \
    src/sys/arch/i386/stand/efiboot/bootia32/start.S
cvs rdiff -u -r0 -r1.1 src/sys/arch/i386/stand/efiboot/bootx64/Makefile \
    src/sys/arch/i386/stand/efiboot/bootx64/efiboot_machdep.h \
    src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c \
    src/sys/arch/i386/stand/efiboot/bootx64/ldscript \
    src/sys/arch/i386/stand/efiboot/bootx64/start.S \
    src/sys/arch/i386/stand/efiboot/bootx64/startprog64.S
cvs rdiff -u -r1.45 -r1.46 src/sys/arch/i386/stand/lib/biosdisk.c
cvs rdiff -u -r1.22 -r1.23 src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/i386/stand/lib/diskbuf.c
cvs rdiff -u -r1.62 -r1.63 src/sys/arch/i386/stand/lib/exec.c
cvs rdiff -u -r1.40 -r1.41 src/sys/arch/i386/stand/lib/libi386.h
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/i386/stand/lib/vbe.c
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/x86/acpi/acpi_machdep.c
cvs rdiff -u -r1.24 -r1.25 src/sys/arch/x86/include/bootinfo.h
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/x86/include/efi.h
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/x86/x86/efi.c
cvs rdiff -u -r1.81 -r1.82 src/sys/arch/x86/x86/x86_machdep.c
cvs rdiff -u -r1.4 -r1.5 src/sys/lib/libgnuefi/Makefile
cvs rdiff -u -r1.3 -r1.4 src/sys/lib/libgnuefi/Makefile.inc
cvs rdiff -u -r0 -r1.1 src/sys/lib/libgnuefi/arch/i386/Makefile.inc
cvs rdiff -u -r0 -r1.1 src/sys/lib/libgnuefi/arch/x86_64/Makefile.inc

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

Modified files:

Index: src/distrib/sets/lists/base/md.amd64
diff -u src/distrib/sets/lists/base/md.amd64:1.267 src/distrib/sets/lists/base/md.amd64:1.268
--- src/distrib/sets/lists/base/md.amd64:1.267	Sat Sep 26 01:46:14 2015
+++ src/distrib/sets/lists/base/md.amd64	Tue Jan 24 11:09:14 2017
@@ -1,4 +1,4 @@
-# $NetBSD: md.amd64,v 1.267 2015/09/26 01:46:14 christos Exp $
+# $NetBSD: md.amd64,v 1.268 2017/01/24 11:09:14 nonaka Exp $
 ./dev/lms0					base-obsolete		obsolete
 ./dev/mms0					base-obsolete		obsolete
 ./libexec/ld.elf_so-i386			base-sys-shlib		compat,pic
@@ -30,6 +30,8 @@
 ./usr/mdec/biosboot_com0_57600.sym		base-obsolete		obsolete
 ./usr/mdec/biosboot_com0_9600.sym		base-obsolete		obsolete
 ./usr/mdec/boot					base-sysutil-bin
+./usr/mdec/bootia32.efi				base-sysutil-bin
+./usr/mdec/bootx64.efi				base-sysutil-bin
 ./usr/mdec/bootxx_cd9660			base-sysutil-bin
 ./usr/mdec/bootxx_dosfs				base-obsolete		obsolete
 ./usr/mdec/bootxx_ext2fs			base-sysutil-bin

Index: src/sys/arch/i386/stand/Makefile
diff -u src/sys/arch/i386/stand/Makefile:1.27 src/sys/arch/i386/stand/Makefile:1.28
--- src/sys/arch/i386/stand/Makefile:1.27	Fri Jan 27 08:41:35 2012
+++ src/sys/arch/i386/stand/Makefile	Tue Jan 24 11:09:14 2017
@@ -1,8 +1,11 @@
-#	$NetBSD: Makefile,v 1.27 2012/01/27 08:41:35 jnemeth Exp $
+#	$NetBSD: Makefile,v 1.28 2017/01/24 11:09:14 nonaka Exp $
 
 SUBDIR=		mbr boot
 SUBDIR+=	bootxx cdboot fatboot
 SUBDIR+=	dosboot misc
 SUBDIR+=	pxeboot
+.if ${MACHINE} == "amd64"
+SUBDIR+=	efiboot
+.endif
 
 .include <bsd.subdir.mk>

Index: src/sys/arch/i386/stand/lib/biosdisk.c
diff -u src/sys/arch/i386/stand/lib/biosdisk.c:1.45 src/sys/arch/i386/stand/lib/biosdisk.c:1.46
--- src/sys/arch/i386/stand/lib/biosdisk.c:1.45	Sun Jun  5 14:06:31 2016
+++ src/sys/arch/i386/stand/lib/biosdisk.c	Tue Jan 24 11:09:14 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: biosdisk.c,v 1.45 2016/06/05 14:06:31 maxv Exp $	*/
+/*	$NetBSD: biosdisk.c,v 1.46 2017/01/24 11:09:14 nonaka Exp $	*/
 
 /*
  * Copyright (c) 1996, 1998
@@ -102,6 +102,13 @@ struct biosdisk {
 		daddr_t offset;
 		daddr_t size;
 		int     fstype;
+#ifdef EFIBOOT
+		const struct gpt_part {
+			const struct uuid *guid;
+			const char *name;
+		} *guid;
+		uint64_t attr;
+#endif
 	} part[BIOSDISKNPART];
 #endif
 };
@@ -111,6 +118,55 @@ const struct uuid GET_nbsd_raid = GPT_EN
 const struct uuid GET_nbsd_ffs = GPT_ENT_TYPE_NETBSD_FFS;
 const struct uuid GET_nbsd_lfs = GPT_ENT_TYPE_NETBSD_LFS;
 const struct uuid GET_nbsd_swap = GPT_ENT_TYPE_NETBSD_SWAP;
+const struct uuid GET_nbsd_ccd = GPT_ENT_TYPE_NETBSD_CCD;
+const struct uuid GET_nbsd_cgd = GPT_ENT_TYPE_NETBSD_CGD;
+#ifdef EFIBOOT
+const struct uuid GET_efi = GPT_ENT_TYPE_EFI;
+const struct uuid GET_mbr = GPT_ENT_TYPE_MBR;
+const struct uuid GET_fbsd = GPT_ENT_TYPE_FREEBSD;
+const struct uuid GET_fbsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP;
+const struct uuid GET_fbsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS;
+const struct uuid GET_fbsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM;
+const struct uuid GET_fbsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS;
+const struct uuid GET_ms_rsvd = GPT_ENT_TYPE_MS_RESERVED;
+const struct uuid GET_ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA;
+const struct uuid GET_ms_ldm_metadata = GPT_ENT_TYPE_MS_LDM_METADATA;
+const struct uuid GET_ms_ldm_data = GPT_ENT_TYPE_MS_LDM_DATA;
+const struct uuid GET_linux_data = GPT_ENT_TYPE_LINUX_DATA;
+const struct uuid GET_linux_raid = GPT_ENT_TYPE_LINUX_RAID;
+const struct uuid GET_linux_swap = GPT_ENT_TYPE_LINUX_SWAP;
+const struct uuid GET_linux_lvm = GPT_ENT_TYPE_LINUX_LVM;
+const struct uuid GET_apple_hfs = GPT_ENT_TYPE_APPLE_HFS;
+const struct uuid GET_apple_ufs = GPT_ENT_TYPE_APPLE_UFS;
+const struct uuid GET_bios = GPT_ENT_TYPE_BIOS;
+
+const struct gpt_part gpt_parts[] = {
+	{ &GET_nbsd_raid,	"NetBSD RAID" },
+	{ &GET_nbsd_ffs,	"NetBSD FFS" },
+	{ &GET_nbsd_lfs,	"NetBSD LFS" },
+	{ &GET_nbsd_swap,	"NetBSD Swap" },
+	{ &GET_nbsd_ccd,	"NetBSD ccd" },
+	{ &GET_nbsd_cgd,	"NetBSD cgd" },
+	{ &GET_efi,		"EFI System" },
+	{ &GET_mbr,		"MBR" },
+	{ &GET_fbsd,		"FreeBSD" },
+	{ &GET_fbsd_swap,	"FreeBSD Swap" },
+	{ &GET_fbsd_ufs,	"FreeBSD UFS" },
+	{ &GET_fbsd_vinum,	"FreeBSD Vinum" },
+	{ &GET_fbsd_zfs,	"FreeBSD ZFS" },
+	{ &GET_ms_rsvd,		"Microsoft Reserved" },
+	{ &GET_ms_basic_data,	"Microsoft Basic data" },
+	{ &GET_ms_ldm_metadata,	"Microsoft LDM metadata" },
+	{ &GET_ms_ldm_data,	"Microsoft LDM data" },
+	{ &GET_linux_data,	"Linux data" },
+	{ &GET_linux_raid,	"Linux RAID" },
+	{ &GET_linux_swap,	"Linux Swap" },
+	{ &GET_linux_lvm,	"Linux LVM" },
+	{ &GET_apple_hfs,	"Apple HFS" },
+	{ &GET_apple_ufs,	"Apple UFS" },
+	{ &GET_bios,		"BIOS Boot (GRUB)" },
+};
+#endif
 #endif /* NO_GPT */
 
 #ifdef _STANDALONE
@@ -273,7 +329,7 @@ check_gpt(struct biosdisk *d, daddr_t se
 		entblk += sectors;
 		crc = crc32(crc, (const void *)d->buf, size);
 
-		for (i = 0; j < BIOSDISKNPART && i < entries; i++, j++) {
+		for (i = 0; j < BIOSDISKNPART && i < entries; i++) {
 			u = (const struct uuid *)ep[i].ent_type;
 			if (!guid_is_nil(u)) {
 				d->part[j].offset = ep[i].ent_lba_start;
@@ -287,8 +343,22 @@ check_gpt(struct biosdisk *d, daddr_t se
 					d->part[j].fstype = FS_RAID;
 				else if (guid_is_equal(u, &GET_nbsd_swap))
 					d->part[j].fstype = FS_SWAP;
+				else if (guid_is_equal(u, &GET_nbsd_ccd))
+					d->part[j].fstype = FS_CCD;
+				else if (guid_is_equal(u, &GET_nbsd_cgd))
+					d->part[j].fstype = FS_CGD;
 				else
 					d->part[j].fstype = FS_OTHER;
+#ifdef EFIBOOT
+				for (int k = 0;
+				     k < __arraycount(gpt_parts);
+				     k++) {
+					if (guid_is_equal(u, gpt_parts[k].guid))
+						d->part[j].guid = &gpt_parts[k];
+				}
+				d->part[j].attr = ep[i].ent_attr;
+#endif
+				j++;
 			}
 		}
 
@@ -649,6 +719,11 @@ biosdisk_probe(void)
 				first = 0;
 			}
 			printf(" hd%d%c(", d.ll.dev & 0x7f, part + 'a');
+#ifdef EFIBOOT
+			if (d.part[part].guid != NULL)
+				printf("%s", d.part[part].guid->name);
+			else
+#endif
 			if (d.part[part].fstype < FSMAXTYPES)
 				printf("%s",
 				  fstypenames[d.part[part].fstype]);
@@ -674,6 +749,10 @@ biosdisk_findpartition(int biosdev, dadd
 #else
 	struct biosdisk *d;
 	int partition = 0;
+#ifdef EFIBOOT
+	int candidate = 0;
+#endif
+
 #ifdef DISK_DEBUG
 	printf("looking for partition device %x, sector %"PRId64"\n", biosdev, sector);
 #endif
@@ -687,9 +766,31 @@ biosdisk_findpartition(int biosdev, dadd
 		for (partition = (BIOSDISKNPART-1); --partition;) {
 			if (d->part[partition].fstype == FS_UNUSED)
 				continue;
+#ifdef EFIBOOT
+			if (d->part[partition].attr & GPT_ENT_ATTR_BOOTME) {
+				switch (d->part[partition].fstype) {
+				case FS_BSDFFS:
+				case FS_BSDLFS:
+				case FS_RAID:
+				case FS_CCD:
+				case FS_CGD:
+					break;
+
+				default:
+					candidate = partition;
+					continue;
+				}
+				break;
+			}
+#else
 			if (d->part[partition].offset == sector)
 				break;
+#endif
 		}
+#ifdef EFIBOOT
+		if (partition == 0 && candidate != 0)
+			partition = candidate;
+#endif
 	}
 
 	dealloc(d, sizeof(*d));

Index: src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c
diff -u src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c:1.22 src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c:1.23
--- src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c:1.22	Thu May 16 19:06:44 2013
+++ src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c	Tue Jan 24 11:09:14 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: bootinfo_biosgeom.c,v 1.22 2013/05/16 19:06:44 christos Exp $	*/
+/*	$NetBSD: bootinfo_biosgeom.c,v 1.23 2017/01/24 11:09:14 nonaka Exp $	*/
 
 /*
  * Copyright (c) 1997
@@ -78,7 +78,6 @@ bi_getbiosgeom(void)
 		return;
 
 	for (i = nvalid = 0; i < MAX_BIOSDISKS && nvalid < nhd; i++) {
-
 		d.dev = 0x80 + i;
 
 		if (set_geometry(&d, &ed))

Index: src/sys/arch/i386/stand/lib/diskbuf.c
diff -u src/sys/arch/i386/stand/lib/diskbuf.c:1.6 src/sys/arch/i386/stand/lib/diskbuf.c:1.7
--- src/sys/arch/i386/stand/lib/diskbuf.c:1.6	Sun Dec 11 12:17:48 2005
+++ src/sys/arch/i386/stand/lib/diskbuf.c	Tue Jan 24 11:09:14 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: diskbuf.c,v 1.6 2005/12/11 12:17:48 christos Exp $	*/
+/*	$NetBSD: diskbuf.c,v 1.7 2017/01/24 11:09:14 nonaka Exp $	*/
 
 /*
  * Copyright (c) 1996
@@ -28,6 +28,8 @@
 
 /* data buffer for BIOS disk / DOS I/O  */
 
+#include <sys/inttypes.h>
+
 #include <lib/libsa/stand.h>
 #include "diskbuf.h"
 
@@ -48,10 +50,12 @@ alloc_diskbuf(const void *user)
 	diskbuf_user = user;
 	if (!diskbufp) {
 		diskbufp = alloc(DISKBUFSIZE);
-		if (((int)diskbufp & 0xffff) + DISKBUFSIZE > 0x10000) {
-			printf("diskbufp %x\n", (unsigned)diskbufp);
+#ifndef EFIBOOT
+		if (((uintptr_t)diskbufp & 0xffff) + DISKBUFSIZE > 0x10000) {
+			printf("diskbufp %" PRIxPTR "\n", (uintptr_t)diskbufp);
 			panic("diskbuf crosses 64k boundary");
 		}
+#endif
 	}
 	return diskbufp;
 }

Index: src/sys/arch/i386/stand/lib/exec.c
diff -u src/sys/arch/i386/stand/lib/exec.c:1.62 src/sys/arch/i386/stand/lib/exec.c:1.63
--- src/sys/arch/i386/stand/lib/exec.c:1.62	Sun Dec  4 08:21:08 2016
+++ src/sys/arch/i386/stand/lib/exec.c	Tue Jan 24 11:09:14 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: exec.c,v 1.62 2016/12/04 08:21:08 maxv Exp $	 */
+/*	$NetBSD: exec.c,v 1.63 2017/01/24 11:09:14 nonaka Exp $	 */
 
 /*
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -109,6 +109,11 @@
 #ifdef SUPPORT_PS2
 #include "biosmca.h"
 #endif
+#ifdef EFIBOOT
+#include "efiboot.h"
+#undef DEBUG	/* XXX */
+static u_long efi_loadaddr;
+#endif
 
 #define BOOT_NARGS	6
 
@@ -295,6 +300,31 @@ common_load_kernel(const char *file, u_l
 			return ENOMEM;
 	}
 #endif
+#ifdef EFIBOOT
+	{
+		EFI_STATUS status;
+		EFI_PHYSICAL_ADDRESS addr;
+		UINTN kernsize;
+
+		marks[MARK_START] = loadaddr;
+		if ((fd = loadfile(file, marks, COUNT_KERNEL)) == -1)
+			return EIO;
+		close(fd);
+
+		/* Allocate temporary arena. */
+		addr = EFI_ALLOCATE_MAX_ADDRESS;
+		kernsize = marks[MARK_END] - loadaddr;
+		kernsize += 1 * 1024 * 1024;	/* XXX: kernel size COUNT_KERNEL vs LOAD_KERNL (lacked some SYMTAB?) */
+		kernsize = EFI_SIZE_TO_PAGES(kernsize);
+		status = uefi_call_wrapper(BS->AllocatePages, 4,
+		    AllocateMaxAddress, EfiLoaderData, kernsize, &addr);
+		if (EFI_ERROR(status))
+			return ENOMEM;
+		efi_loadaddr = loadaddr = addr;
+
+		memset(marks, 0, sizeof(marks[0]) * MARK_MAX);
+	}
+#endif
 	marks[MARK_START] = loadaddr;
 	if ((fd = loadfile(file, marks,
 	    LOAD_KERNEL & ~(floppy ? LOAD_BACKWARDS : 0))) == -1)
@@ -332,6 +362,15 @@ common_load_kernel(const char *file, u_l
 		ppbcopy(loadaddr, origaddr, marks[MARK_END]);
 	}
 #endif
+#ifdef EFIBOOT
+	marks[MARK_START] -= loadaddr;
+	marks[MARK_ENTRY] -= loadaddr;
+	marks[MARK_DATA] -= loadaddr;
+	/* MARK_NSYM */
+	marks[MARK_SYM] -= loadaddr;
+	marks[MARK_END] -= loadaddr;
+	/* Copy the kernel to original load address later. */
+#endif
 	marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) &
 	    (-sizeof(int));
 	image_end = marks[MARK_END];
@@ -349,6 +388,7 @@ exec_netbsd(const char *file, physaddr_t
 	struct btinfo_symtab btinfo_symtab;
 	u_long extmem;
 	u_long basemem;
+	int error;
 
 #ifdef	DEBUG
 	printf("exec: file=%s loadaddr=0x%lx\n", file ? file : "NULL",
@@ -363,8 +403,12 @@ exec_netbsd(const char *file, physaddr_t
 
 	memset(marks, 0, sizeof(marks));
 
-	if (common_load_kernel(file, &basemem, &extmem, loadaddr, floppy, marks))
+	error = common_load_kernel(file, &basemem, &extmem, loadaddr, floppy,
+	    marks);
+	if (error) {
+		errno = error;
 		goto out;
+	}
 
 	boot_argv[0] = boothowto;
 	boot_argv[1] = 0;
@@ -404,6 +448,12 @@ exec_netbsd(const char *file, physaddr_t
 
 	if (callback != NULL)
 		(*callback)();
+#ifdef EFIBOOT
+	/* Copy the kernel to original load address. */
+	memmove((void *)marks[MARK_START],
+	    (void *)(efi_loadaddr + marks[MARK_START]),
+	    marks[MARK_END] - marks[MARK_START]);
+#endif
 	startprog(marks[MARK_ENTRY], BOOT_NARGS, boot_argv,
 	    x86_trunc_page(basemem * 1024));
 	panic("exec returned");

Index: src/sys/arch/i386/stand/lib/libi386.h
diff -u src/sys/arch/i386/stand/lib/libi386.h:1.40 src/sys/arch/i386/stand/lib/libi386.h:1.41
--- src/sys/arch/i386/stand/lib/libi386.h:1.40	Sun Nov 24 17:20:00 2013
+++ src/sys/arch/i386/stand/lib/libi386.h	Tue Jan 24 11:09:14 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: libi386.h,v 1.40 2013/11/24 17:20:00 jakllsch Exp $	*/
+/*	$NetBSD: libi386.h,v 1.41 2017/01/24 11:09:14 nonaka Exp $	*/
 
 /*
  * Copyright (c) 1996
@@ -26,6 +26,9 @@
  *
  */
 
+#ifndef	__I386_STAND_LIBI386_H__
+#define	__I386_STAND_LIBI386_H__
+
 typedef unsigned long physaddr_t;
 
 /* this is in startup code */
@@ -144,3 +147,5 @@ void userconf_add(char *);
 
 struct btinfo_framebuffer;
 void framebuffer_configure(struct btinfo_framebuffer *);
+
+#endif	/* __I386_STAND_LIBI386_H__ */

Index: src/sys/arch/i386/stand/lib/vbe.c
diff -u src/sys/arch/i386/stand/lib/vbe.c:1.8 src/sys/arch/i386/stand/lib/vbe.c:1.9
--- src/sys/arch/i386/stand/lib/vbe.c:1.8	Fri May 31 15:11:07 2013
+++ src/sys/arch/i386/stand/lib/vbe.c	Tue Jan 24 11:09:14 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: vbe.c,v 1.8 2013/05/31 15:11:07 tsutsui Exp $ */
+/* $NetBSD: vbe.c,v 1.9 2017/01/24 11:09:14 nonaka Exp $ */
 
 /*-
  * Copyright (c) 2009 Jared D. McNeill <jmcne...@invisible.ca>
@@ -145,6 +145,7 @@ vbe_set_mode(int modenum)
 		for (i = 0; i < 256; i++)
 			vbe_set_palette(&rasops_cmap[i * 3], i);
 
+	memset(&fb, 0, sizeof(fb));
 	fb.physaddr = (uint64_t)mi.PhysBasePtr & 0xffffffff;
 	fb.width = mi.XResolution;
 	fb.height = mi.YResolution;

Index: src/sys/arch/x86/acpi/acpi_machdep.c
diff -u src/sys/arch/x86/acpi/acpi_machdep.c:1.14 src/sys/arch/x86/acpi/acpi_machdep.c:1.15
--- src/sys/arch/x86/acpi/acpi_machdep.c:1.14	Sat Oct 15 16:46:14 2016
+++ src/sys/arch/x86/acpi/acpi_machdep.c	Tue Jan 24 11:09:14 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_machdep.c,v 1.14 2016/10/15 16:46:14 jdolecek Exp $ */
+/* $NetBSD: acpi_machdep.c,v 1.15 2017/01/24 11:09:14 nonaka Exp $ */
 
 /*
  * Copyright 2001 Wasabi Systems, Inc.
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.14 2016/10/15 16:46:14 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.15 2017/01/24 11:09:14 nonaka Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -366,30 +366,63 @@ acpi_md_ncpus(void)
 static bool
 acpi_md_mcfg_validate(uint64_t addr, int bus_start, int *bus_end)
 {
-	struct btinfo_memmap *bim;
+	union {
+		struct btinfo_common *common;
+		struct btinfo_memmap *bios;
+		struct btinfo_efimemmap *efi;
+	} bim;
 	uint64_t size, mapaddr, mapsize;
 	uint32_t type;
-	int i, n;
+	int i, n, num;
+	bool efimemmap;
 
-	bim = lookup_bootinfo(BTINFO_MEMMAP);
-	if (bim == NULL)
-		return false;
+	bim.common = lookup_bootinfo(BTINFO_EFIMEMMAP);
+	if (bim.common == NULL) {
+		bim.common = lookup_bootinfo(BTINFO_MEMMAP);
+		if (bim.common == NULL)
+			return false;
+	}
+	efimemmap = bim.common->type == BTINFO_EFIMEMMAP;
+	num = efimemmap ? bim.efi->num : bim.bios->num;
 
 	size = *bus_end - bus_start + 1;
 	size *= ACPIMCFG_SIZE_PER_BUS;
-	for (i = 0; i < bim->num; i++) {
-		mapaddr = bim->entry[i].addr;
-		mapsize = bim->entry[i].size;
-		type = bim->entry[i].type;
-
-		aprint_debug("MCFG: MEMMAP: 0x%016" PRIx64 "-0x%016" PRIx64
-		    ", size=0x%016" PRIx64 ", type=%d(%s)\n",
-		    mapaddr, mapaddr + mapsize - 1, mapsize, type,
-		    (type == BIM_Memory) ?  "Memory" :
-		    (type == BIM_Reserved) ?  "Reserved" :
-		    (type == BIM_ACPI) ? "ACPI" :
-		    (type == BIM_NVS) ? "NVS" :
-		    "unknown");
+	for (i = 0; i < num; i++) {
+#ifndef XEN
+		if (efimemmap) {
+			struct efi_md *md = (struct efi_md *)
+			    (bim.efi->memmap + bim.efi->size * i);
+			mapaddr = md->md_phys;
+			mapsize = md->md_pages * EFI_PAGE_SIZE;
+			type = efi_getbiosmemtype(md->md_type, md->md_attr);
+
+			aprint_debug("MCFG: MEMMAP: "
+			    "p0x%016" PRIx64 "-0x%016" PRIx64
+			    ", v0x%016" PRIx64 "-0x%016" PRIx64
+			    ", size=0x%016" PRIx64 ", attr=0x%016" PRIx64
+			    ", type=%d(%s)\n",
+			    mapaddr, mapaddr + mapsize - 1,
+			    (uint64_t)(u_long)md->md_virt,
+			    (uint64_t)(u_long)md->md_virt + mapsize - 1,
+			    size, md->md_attr, md->md_type,
+			    efi_getmemtype_str(md->md_type));
+		} else
+#endif
+		{
+			mapaddr = bim.bios->entry[i].addr;
+			mapsize = bim.bios->entry[i].size;
+			type = bim.bios->entry[i].type;
+
+			aprint_debug("MCFG: MEMMAP: 0x%016" PRIx64
+			    "-0x%016" PRIx64 ", size=0x%016" PRIx64
+			    ", type=%d(%s)\n",
+			    mapaddr, mapaddr + mapsize - 1, mapsize, type,
+			    (type == BIM_Memory) ?  "Memory" :
+			    (type == BIM_Reserved) ?  "Reserved" :
+			    (type == BIM_ACPI) ? "ACPI" :
+			    (type == BIM_NVS) ? "NVS" :
+			    "unknown");
+		}
 
 		switch (type) {
 		case BIM_ACPI:

Index: src/sys/arch/x86/include/bootinfo.h
diff -u src/sys/arch/x86/include/bootinfo.h:1.24 src/sys/arch/x86/include/bootinfo.h:1.25
--- src/sys/arch/x86/include/bootinfo.h:1.24	Thu Jan 28 01:09:56 2016
+++ src/sys/arch/x86/include/bootinfo.h	Tue Jan 24 11:09:14 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: bootinfo.h,v 1.24 2016/01/28 01:09:56 christos Exp $	*/
+/*	$NetBSD: bootinfo.h,v 1.25 2017/01/24 11:09:14 nonaka Exp $	*/
 
 /*
  * Copyright (c) 1997
@@ -39,10 +39,11 @@
 #define BTINFO_FRAMEBUFFER	12
 #define BTINFO_USERCONFCOMMANDS	13
 #define BTINFO_EFI		14
+#define BTINFO_EFIMEMMAP	15
 
 #define BTINFO_STR "bootpath", "rootdevice", "bootdisk", "netif", \
     "console", "biosgeom", "symtab", "memmap", "bootwedge", "modulelist", \
-    "framebuffer", "userconfcommands", "efi",
+    "framebuffer", "userconfcommands", "efi", "efimemmap",
 
 #ifndef _LOCORE
 
@@ -221,7 +222,18 @@ struct btinfo_userconfcommands {
 /* EFI Information */
 struct btinfo_efi {
 	struct btinfo_common common;
-	paddr_t bi_systbl;	/* Physical address of the EFI System Table */
+	uint64_t systblpa;	/* Physical address of the EFI System Table */
+	uint32_t flags;
+#define BI_EFI_32BIT	__BIT(0)	/* 32bit UEFI */
+	uint8_t reserved[12];
+};
+
+struct btinfo_efimemmap {
+	struct btinfo_common common;
+	uint32_t num;		/* number of memory descriptor */
+	uint32_t version;	/* version of memory descriptor */
+	uint32_t size;		/* size of memory descriptor */
+	uint8_t memmap[1];	/* whole memory descriptors */
 };
 
 #endif /* _LOCORE */

Index: src/sys/arch/x86/include/efi.h
diff -u src/sys/arch/x86/include/efi.h:1.1 src/sys/arch/x86/include/efi.h:1.2
--- src/sys/arch/x86/include/efi.h:1.1	Thu Jan 28 01:09:56 2016
+++ src/sys/arch/x86/include/efi.h	Tue Jan 24 11:09:14 2017
@@ -1,4 +1,4 @@
-/*     $NetBSD: efi.h,v 1.1 2016/01/28 01:09:56 christos Exp $   */
+/*     $NetBSD: efi.h,v 1.2 2017/01/24 11:09:14 nonaka Exp $   */
 
 /*-
  * Copyright (c) 2004 Marcel Moolenaar
@@ -56,7 +56,7 @@ typedef unsigned long efi_status;
 
 struct efi_cfgtbl {
        struct uuid     ct_uuid;
-       uint64_t        ct_data;
+       void           *ct_data;
 };
 struct efi_md {
        uint32_t        md_type;
@@ -143,17 +143,19 @@ struct efi_systbl {
 #define        EFI_SYSTBL_SIG  0x5453595320494249UL
        efi_char        *st_fwvendor;
        uint32_t        st_fwrev;
+#ifdef __amd64__
        uint32_t        __pad;
+#endif
        void            *st_cin;
        void            *st_cinif;
        void            *st_cout;
        void            *st_coutif;
        void            *st_cerr;
        void            *st_cerrif;
-       uint64_t        st_rt;
+       struct efi_rt   *st_rt;
        void            *st_bs;
        u_long          st_entries;
-       uint64_t        st_cfgtbl;
+       struct efi_cfgtbl *st_cfgtbl;
 };
 
 bool               efi_probe(void);
@@ -161,6 +163,8 @@ paddr_t            efi_getsystblpa(void)
 struct efi_systbl *efi_getsystbl(void);
 paddr_t            efi_getcfgtblpa(const struct uuid*);
 void              *efi_getcfgtbl(const struct uuid*);
+int                efi_getbiosmemtype(uint32_t, uint64_t);
+const char        *efi_getmemtype_str(uint32_t);
 /*
 void efi_boot_finish(void);
 int efi_boot_minimal(uint64_t);

Index: src/sys/arch/x86/x86/efi.c
diff -u src/sys/arch/x86/x86/efi.c:1.4 src/sys/arch/x86/x86/efi.c:1.5
--- src/sys/arch/x86/x86/efi.c:1.4	Wed Aug 24 10:27:23 2016
+++ src/sys/arch/x86/x86/efi.c	Tue Jan 24 11:09:14 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: efi.c,v 1.4 2016/08/24 10:27:23 nonaka Exp $	*/
+/*	$NetBSD: efi.c,v 1.5 2017/01/24 11:09:14 nonaka Exp $	*/
 /*-
  * Copyright (c) 2016 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -25,7 +25,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: efi.c,v 1.4 2016/08/24 10:27:23 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: efi.c,v 1.5 2017/01/24 11:09:14 nonaka Exp $");
 #include <sys/kmem.h>
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -62,6 +62,7 @@ void 		efi_aprintcfgtbl(void);
 void 		efi_aprintuuid(const struct uuid *);
 bool 		efi_uuideq(const struct uuid *, const struct uuid *);
 
+static bool efi_is32bit = false;
 static struct efi_systbl *efi_systbl_va = NULL;
 static struct efi_cfgtbl *efi_cfgtblhead_va = NULL;
 
@@ -173,7 +174,7 @@ efi_aprintcfgtbl(void)
 	count = efi_systbl_va->st_entries;
 	aprint_debug("efi: %lu cfgtbl entries:\n", count);
 	for (; count; count--, ct++) {
-		aprint_debug("efi: %16" PRIx64 "", ct->ct_data);
+		aprint_debug("efi: %p", ct->ct_data);
 		efi_aprintuuid(&ct->ct_uuid);
 		aprint_debug("\n");
 	}
@@ -226,7 +227,15 @@ efi_getsystblpa(void)
 		/* Unable to locate the EFI System Table. */
 		return 0;
 	}
-	pa = bi->bi_systbl;
+	if (bi->common.len > 16 && (bi->flags & BI_EFI_32BIT)) {
+		/* 32Bit UEFI */
+		if (sizeof(paddr_t) == 4 &&
+		    (bi->systblpa & 0xffffffff00000000ULL))
+			/* Unable to access EFI System Table. */
+			return 0;
+		efi_is32bit = true;
+	}
+	pa = (paddr_t)bi->systblpa;
 	return pa;
 }
 
@@ -259,7 +268,7 @@ efi_getsystbl(void)
 		 * XXX Also print fwvendor, which is an UCS-2 string (use
 		 * some UTF-16 routine?)
 		 */
-		aprint_debug("efi: runtime services at pa %" PRIx64 "\n",
+		aprint_debug("efi: runtime services at pa %p\n",
 		    systbl->st_rt);
 		aprint_debug("efi: boot services at pa %p\n",
 		    systbl->st_bs);
@@ -285,3 +294,58 @@ efi_probe(void)
 	}
 	return true;
 }
+
+int
+efi_getbiosmemtype(uint32_t type, uint64_t attr)
+{
+
+	switch (type) {
+	case EFI_MD_TYPE_CODE:
+	case EFI_MD_TYPE_DATA:
+	case EFI_MD_TYPE_BS_CODE:
+	case EFI_MD_TYPE_BS_DATA:
+	case EFI_MD_TYPE_FREE:
+		return (attr & EFI_MD_ATTR_WB) ? BIM_Memory : BIM_Reserved;
+
+	case EFI_MD_TYPE_RECLAIM:
+		return BIM_ACPI;
+
+	case EFI_MD_TYPE_FIRMWARE:
+		return BIM_NVS;
+
+	case EFI_MD_TYPE_NULL:
+	case EFI_MD_TYPE_RT_CODE:
+	case EFI_MD_TYPE_RT_DATA:
+	case EFI_MD_TYPE_BAD:
+	case EFI_MD_TYPE_IOMEM:
+	case EFI_MD_TYPE_IOPORT:
+	case EFI_MD_TYPE_PALCODE:
+		return BIM_Reserved;
+	}
+	return BIM_Reserved;
+}
+
+const char *
+efi_getmemtype_str(uint32_t type)
+{
+	static const char *efimemtypes[] = {
+		"Reserved",
+		"LoaderCode",
+		"LoaderData",
+		"BootServicesCode",
+		"BootServicesData",
+		"RuntimeServicesCode",
+		"RuntimeServicesData",
+		"ConventionalMemory",
+		"UnusableMemory",
+		"ACPIReclaimMemory",
+		"ACPIMemoryNVS",
+		"MemoryMappedIO",
+		"MemoryMappedIOPortSpace",
+		"PalCode",
+	};
+
+	if (type < __arraycount(efimemtypes))
+		return efimemtypes[type];
+	return "unknown";
+}

Index: src/sys/arch/x86/x86/x86_machdep.c
diff -u src/sys/arch/x86/x86/x86_machdep.c:1.81 src/sys/arch/x86/x86/x86_machdep.c:1.82
--- src/sys/arch/x86/x86/x86_machdep.c:1.81	Tue Jan 10 09:48:22 2017
+++ src/sys/arch/x86/x86/x86_machdep.c	Tue Jan 24 11:09:14 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: x86_machdep.c,v 1.81 2017/01/10 09:48:22 cherry Exp $	*/
+/*	$NetBSD: x86_machdep.c,v 1.82 2017/01/24 11:09:14 nonaka Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2006, 2007 YAMAMOTO Takashi,
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.81 2017/01/10 09:48:22 cherry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.82 2017/01/24 11:09:14 nonaka Exp $");
 
 #include "opt_modular.h"
 #include "opt_physmem.h"
@@ -54,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: x86_machdep.
 
 #include <x86/cpuvar.h>
 #include <x86/cputypes.h>
+#include <x86/efi.h>
 #include <x86/machdep.h>
 #include <x86/nmi.h>
 #include <x86/pio.h>
@@ -628,28 +629,63 @@ x86_add_cluster(struct extent *iomem_ex,
 }
 
 static int
-x86_parse_clusters(struct btinfo_memmap *bim, struct extent *iomem_ex)
+x86_parse_clusters(struct btinfo_common *bi, struct extent *iomem_ex)
 {
+	union {
+		struct btinfo_common *common;
+		struct btinfo_memmap *bios;
+		struct btinfo_efimemmap *efi;
+	} bim;
 	uint64_t seg_start, seg_end;
 	uint64_t addr, size;
 	uint32_t type;
-	int x;
+	int x, num;
+	bool efimemmap;
 
-	KASSERT(bim != NULL);
-	KASSERT(bim->num > 0);
+	KASSERT(bi != NULL);
+	bim.common = bi;
+	efimemmap = bi->type == BTINFO_EFIMEMMAP;
+	num = efimemmap ? bim.efi->num : bim.bios->num;
+	KASSERT(num > 0);
 
 #ifdef DEBUG_MEMLOAD
-	printf("BIOS MEMORY MAP (%d ENTRIES):\n", bim->num);
+	printf("MEMMAP: %s MEMORY MAP (%d ENTRIES):\n",
+	    efimemmap ? "UEFI" : "BIOS", num);
 #endif
 
-	for (x = 0; x < bim->num; x++) {
-		addr = bim->entry[x].addr;
-		size = bim->entry[x].size;
-		type = bim->entry[x].type;
+	for (x = 0; x < num; x++) {
+		if (efimemmap) {
+			struct efi_md *md = (struct efi_md *)
+			    (bim.efi->memmap + bim.efi->size * x);
+			addr = md->md_phys;
+			size = md->md_pages * EFI_PAGE_SIZE;
+			type = efi_getbiosmemtype(md->md_type, md->md_attr);
 #ifdef DEBUG_MEMLOAD
-		printf("    addr 0x%"PRIx64"  size 0x%"PRIx64"  type 0x%x\n",
-			addr, size, type);
+			printf("MEMMAP: p0x%016" PRIx64 "-0x%016" PRIx64
+			    ", v0x%016" PRIx64 "-0x%016" PRIx64
+			    ", size=0x%016" PRIx64 ", attr=0x%016" PRIx64
+			    ", type=%d(%s)\n",
+			    addr, addr + size - 1,
+			    (uint64_t)md->md_virt,
+			    (uint64_t)md->md_virt + size - 1,
+			    size, md->md_attr, md->md_type,
+			    efi_getmemtype_str(md->md_type));
 #endif
+		} else {
+			addr = bim.bios->entry[x].addr;
+			size = bim.bios->entry[x].size;
+			type = bim.bios->entry[x].type;
+#ifdef DEBUG_MEMLOAD
+			printf("MEMMAP: 0x%016" PRIx64 "-0x%016" PRIx64
+			    ", size=0x%016" PRIx64 ", type=%d(%s)\n",
+			    addr, addr + size - 1, size, type,
+			    (type == BIM_Memory) ?  "Memory" :
+			    (type == BIM_Reserved) ?  "Reserved" :
+			    (type == BIM_ACPI) ? "ACPI" :
+			    (type == BIM_NVS) ? "NVS" :
+			    "unknown");
+#endif
+		}
 
 		/* If the segment is not memory, skip it. */
 		switch (type) {
@@ -808,7 +844,8 @@ void
 init_x86_clusters(void)
 {
 	extern struct extent *iomem_ex;
-	struct btinfo_memmap *bim;
+	struct btinfo_memmap *bim = NULL;
+	struct btinfo_efimemmap *biem;
 
 	/*
 	 * Check to see if we have a memory map from the BIOS (passed to us by
@@ -816,17 +853,23 @@ init_x86_clusters(void)
 	 */
 #ifdef i386
 	extern int biosmem_implicit;
-	bim = lookup_bootinfo(BTINFO_MEMMAP);
+	biem = lookup_bootinfo(BTINFO_EFIMEMMAP);
+	if (biem == NULL)
+		bim = lookup_bootinfo(BTINFO_MEMMAP);
 	if ((biosmem_implicit || (biosbasemem == 0 && biosextmem == 0)) &&
-	    bim != NULL && bim->num > 0)
-		x86_parse_clusters(bim, iomem_ex);
+	    ((bim != NULL && bim->num > 0) || (biem != NULL && biem->num > 0)))
+		x86_parse_clusters(biem != NULL ? &biem->common : &bim->common,
+		    iomem_ex);
 #else
 #if !defined(REALBASEMEM) && !defined(REALEXTMEM)
-	bim = lookup_bootinfo(BTINFO_MEMMAP);
-	if (bim != NULL && bim->num > 0)
-		x86_parse_clusters(bim, iomem_ex);
+	biem = lookup_bootinfo(BTINFO_EFIMEMMAP);
+	if (biem == NULL)
+		bim = lookup_bootinfo(BTINFO_MEMMAP);
+	if ((bim != NULL && bim->num > 0) || (biem != NULL && biem->num > 0))
+		x86_parse_clusters(biem != NULL ? &biem->common : &bim->common,
+		    iomem_ex);
 #else
-	(void)bim, (void)iomem_ex;
+	(void)bim, (void)biem, (void)iomem_ex;
 #endif
 #endif
 

Index: src/sys/lib/libgnuefi/Makefile
diff -u src/sys/lib/libgnuefi/Makefile:1.4 src/sys/lib/libgnuefi/Makefile:1.5
--- src/sys/lib/libgnuefi/Makefile:1.4	Tue Mar 22 08:25:23 2016
+++ src/sys/lib/libgnuefi/Makefile	Tue Jan 24 11:09:14 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.4 2016/03/22 08:25:23 mrg Exp $
+#	$NetBSD: Makefile,v 1.5 2017/01/24 11:09:14 nonaka Exp $
 
 LIB=	gnuefi
 LIBISPRIVATE?= yes
@@ -8,21 +8,47 @@ GNUEFI_INCLUDE_NET?= yes		# Netboot via 
 GNUEFI_USE_LOADFILE?= no		# Generic executable loading support
 GNUEFI_ENABLE_LS_OP?= no		# Filesystems ls operation
 
+GNUEFIDIST=	${GNUEFIDIR}/../../external/bsd/gnu-efi/dist
+
 CPPFLAGS=	-I${GNUEFIDIR} ${GNUEFICPPFLAGS} ${GNUEFIMISCCPPFLAGS}
 
-.if ${MACHINE_ARCH} == "i386"
+.if defined(GNUEFI_EXTRADIR)
+.-include "${GNUEFI_EXTRADIR}/Makefile.inc"
+.endif
+
+.include <bsd.own.mk>
+
+LIBGNUEFI_ARCH?=	${MACHINE_ARCH}
+LIBGNUEFI_CPU?=		${MACHINE_CPU}
+
+.if ${LIBGNUEFI_ARCH} == "i386"
 GNUEFIARCH=ia32
 .else
-GNUEFIARCH=${MACHINE_ARCH}
+GNUEFIARCH=${LIBGNUEFI_ARCH}
 .endif
 
-.if defined(GNUEFI_EXTRADIR)
-.-include "${GNUEFI_EXTRADIR}/Makefile.inc"
+.if defined(LIBGNUEFI_ARCH) && !empty(LIBGNUEFI_ARCH) && \
+	    exists(${GNUEFIDIR}/arch/${LIBGNUEFI_ARCH})
+ARCHSUBDIR=	${LIBGNUEFI_ARCH}
+.elif defined(MACHINE_ARCH) && !empty(MACHINE_ARCH) && \
+	    exists(${GNUEFIDIR}/arch/${MACHINE_ARCH})
+ARCHSUBDIR=	${MACHINE_ARCH}
+.elif defined(MACHINE_CPU) && !empty(MACHINE_CPU) && \
+	    exists(${GNUEFIDIR}/arch/${MACHINE_CPU})
+ARCHSUBDIR=	${MACHINE_CPU}
 .endif
 
-.include <bsd.own.mk>
+M= ${GNUEFIDIR}/arch/${ARCHSUBDIR}
+
+.if exists($M/Makefile.inc)
+CPPFLAGS+= -I$M
+.PATH.c: $M
+.PATH.S: $M
+.include "$M/Makefile.inc"
+.endif
 
-.PATH.c: ${GNUEFIDIR} ${GNUEFIDIR}/../../external/bsd/gnu-efi/dist/lib/${GNUEFIARCH} ${GNUEFIDIR}/../../external/bsd/gnu-efi/dist/lib ${GNUEFIDIR}/../../external/bsd/gnu-efi/dist/lib/runtime
+.PATH.c: ${GNUEFIDIR} ${GNUEFIDIST}/lib/${GNUEFIARCH} ${GNUEFIDIST}/lib ${GNUEFIDIST}/lib/runtime
+.PATH.S: ${GNUEFIDIR} ${GNUEFIDIST}/lib/${GNUEFIARCH} ${GNUEFIDIST}/lib ${GNUEFIDIST}/lib/runtime
 
 SRCS+=	boxdraw.c smbios.c console.c crc.c data.c debug.c dpath.c \
 	error.c event.c guid.c hand.c hw.c init.c lock.c \
@@ -33,9 +59,11 @@ SRCS+=	boxdraw.c smbios.c console.c crc.
 COPTS.boxdraw.c= -Wno-missing-field-initializers
 COPTS.guid.c= -Wno-missing-field-initializers
 COPTS.smbios.c= -Wno-int-to-pointer-cast
-COPTS.dpath.c= -Wno-missing-prototypes
+COPTS.dpath.c= -Wno-missing-prototypes -Wno-unused-but-set-variable
 COPTS.print.c= -Wno-missing-prototypes
-COPTS.hw.c= -Wno-shadow
+COPTS.hw.c= -Wno-shadow -Wno-unused-but-set-variable
+COPTS.event.c= -Wno-unused-but-set-variable
+COPTS.hand.c= -Wno-unused-but-set-variable
 
 .include <bsd.lib.mk>
 

Index: src/sys/lib/libgnuefi/Makefile.inc
diff -u src/sys/lib/libgnuefi/Makefile.inc:1.3 src/sys/lib/libgnuefi/Makefile.inc:1.4
--- src/sys/lib/libgnuefi/Makefile.inc:1.3	Tue Mar 22 08:25:23 2016
+++ src/sys/lib/libgnuefi/Makefile.inc	Tue Jan 24 11:09:14 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile.inc,v 1.3 2016/03/22 08:25:23 mrg Exp $
+#	$NetBSD: Makefile.inc,v 1.4 2017/01/24 11:09:14 nonaka Exp $
 #
 #	Configuration variables (default values are below):
 #
@@ -47,6 +47,7 @@ GNUEFIMAKE= \
 	    MACHINE=${MACHINE} MACHINE_ARCH=${MACHINE_ARCH:Q} \
 	    GNUEFICPPFLAGS=${CPPFLAGS:S@^-I.@-I${GNUEFIDOTDIR}@g:Q} \
 	    GNUEFIMISCCPPFLAGS=${GNUEFIMISCCPPFLAGS:Q} \
+	    LIBGNUEFI_ARCH=${LIBGNUEFI_ARCH:Q} \
 	    ${GNUEFIMISCMAKEFLAGS}
 
 ${GNUEFILIB}:		.NOTMAIN .MAKE __always_make_gnuefilib

Added files:

Index: src/sys/arch/i386/stand/efiboot/Makefile
diff -u /dev/null src/sys/arch/i386/stand/efiboot/Makefile:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/Makefile	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,6 @@
+#	$NetBSD: Makefile,v 1.1 2017/01/24 11:09:14 nonaka Exp $
+
+SUBDIR=		bootx64
+SUBDIR+=	bootia32
+
+.include <bsd.subdir.mk>
Index: src/sys/arch/i386/stand/efiboot/Makefile.efiboot
diff -u /dev/null src/sys/arch/i386/stand/efiboot/Makefile.efiboot:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/Makefile.efiboot	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,133 @@
+# $NetBSD: Makefile.efiboot,v 1.1 2017/01/24 11:09:14 nonaka Exp $
+
+S=		${.CURDIR}/../../../../..
+
+NOMAN=		# defined
+PROG?=		boot.efi
+NEWVERSWHAT?=	"EFI Boot"
+VERSIONFILE?=	${.CURDIR}/../version
+
+AFLAGS.start.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+
+SOURCES?= start.S conf.c devopen.c efiboot.c self_reloc.c
+LIBI386SRCS= boot.c biosdisk.c bootinfo.c bootinfo_biosgeom.c
+LIBI386SRCS+= bootmenu.c boot_params.S diskbuf.c exec.c menuutils.c
+LIBI386SRCS+= panic.c parseutils.c pread.c
+LIBI386SRCS+= eficons.c efidelay.c efidisk.c efidisk_ll.c efigetsecs.c
+LIBI386SRCS+= efimemory.c
+SRCS= ${SOURCES} ${EXTRA_SOURCES} ${LIBI386SRCS}
+.if !make(depend)
+SRCS+= vers.c
+.endif
+
+PIE_CFLAGS=
+PIE_LDFLAGS=
+PIE_AFLAGS=
+
+.include <bsd.own.mk>
+
+STRIPFLAG=	# nothing
+
+LIBCRT0=	# nothing
+LIBCRTI=	# nothing
+LIBCRTBEGIN=	# nothing
+LIBCRTEND=	# nothing
+LIBC=		# nothing
+
+BINDIR=/usr/mdec
+BINMODE=444
+
+.PATH:	${.CURDIR} ${.CURDIR}/..
+.PATH:	${.CURDIR}/../../lib
+
+LDSCRIPT?= ${.CURDIR}/ldscript
+LDFLAGS+= -nostdlib -T${LDSCRIPT} -Bsymbolic -shared -nocombreloc
+CPPFLAGS+= -I$S -I${.CURDIR} -I${.CURDIR}/.. -I$S/lib/libsa
+CPPFLAGS+= -I${.OBJDIR}
+CPPFLAGS+= -I${.CURDIR}/../../lib
+
+COPTS+= -ffreestanding -fPIC -fshort-wchar -fno-strict-aliasing -fno-builtin
+COPTS+= -fno-stack-protector -falign-functions=16
+CPPFLAGS+= -nostdinc -D_STANDALONE
+CPPFLAGS+= -DEFIBOOT
+
+CPPFLAGS+= -Wall -Wmissing-prototypes
+CPPFLAGS+= -Wno-pointer-sign
+
+CPPFLAGS+= -DEFI_ALLOCATE_MAX_ADDRESS=0x100000000ULL
+CPPFLAGS+= -DHEAP_VARIABLE
+CPPFLAGS+= -DSUPPORT_CD9660
+CPPFLAGS+= -DSUPPORT_DOSFS
+CPPFLAGS+= -DSUPPORT_EXT2FS
+CPPFLAGS+= -DPASS_BIOSGEOM
+CPPFLAGS+= -DPASS_MEMMAP
+CPPFLAGS+= -DLIBSA_ENABLE_LS_OP
+
+EFIDIR= ${S}/external/bsd/gnu-efi/dist
+GNUEFIARCH?= ${MACHINE_CPU}
+CPPFLAGS+= -I${EFIDIR}/inc -I${EFIDIR}/inc/${GNUEFIARCH}
+CPPFLAGS+= -I${EFIDIR}/inc/protocol
+
+SAMISCCPPFLAGS+= -DLIBSA_PRINTF_LONGLONG_SUPPORT
+SAMISCCPPFLAGS+= -DLIBSA_PRINTF_WIDTH_SUPPORT
+SAMISCMAKEFLAGS+= SA_USE_CREAD=yes      # Read compressed kernels
+SAMISCMAKEFLAGS+= SA_INCLUDE_NET=no     # Netboot via TFTP, NFS
+
+### find out what to use for libsa
+SA_AS= library
+SAMISCMAKEFLAGS+="SA_USE_LOADFILE=yes"
+SAMISCMAKEFLAGS+="SA_ENABLE_LS_OP=yes"
+.include "${S}/lib/libsa/Makefile.inc"
+LIBSA= ${SALIB}
+
+### find out what to use for libkern
+KERN_AS= library
+LIBKERN_ARCH?= ${MACHINE_ARCH}
+KERNMISCMAKEFLAGS+="LIBKERN_ARCH=${LIBKERN_ARCH}"
+.include "${S}/lib/libkern/Makefile.inc"
+LIBKERN= ${KERNLIB}
+
+### find out what to use for libz
+Z_AS= library
+.include "${S}/lib/libz/Makefile.inc"
+LIBZ= ${ZLIB}
+
+### find out what to use for libgnuefi
+GNUEFI_AS= library
+LIBGNUEFI_ARCH?= ${MACHINE_ARCH}
+GNUEFIMISCMAKEFLAGS+="LIBGNUEFI_ARCH=${LIBGNUEFI_ARCH}"
+GNUEFIMISCCPPFLAGS+= -I${EFIDIR}/lib
+.include "${S}/lib/libgnuefi/Makefile.inc"
+LIBGNUEFI= ${GNUEFILIB}
+
+cleandir distclean: .WAIT cleanlibdir
+
+cleanlibdir:
+	-rm -rf lib
+
+LIBLIST= ${LIBGNUEFI} ${LIBSA} ${LIBZ} ${LIBKERN} ${LIBSA}
+
+CLEANFILES+= vers.c
+
+vers.c: ${VERSIONFILE} ${SOURCES} ${LIBLIST} ${.CURDIR}/../Makefile.efiboot
+	${HOST_SH} ${S}/conf/newvers_stand.sh ${VERSIONFILE} x86 ${NEWVERSWHAT}
+
+CLEANFILES+=	${PROG}.so ${PROG}.tmp
+
+${PROG}: ${PROG}.so
+	${OBJCOPY} -j .text -j .sdata -j .data -j .dynamic -j .dynsym	\
+	    -j .rel -j .rel.* -j .rela -j .rela.* -j .reloc		\
+	    --subsystem efi-app	--target=${OBJFMT} ${PROG}.so ${.TARGET}
+
+.include <bsd.prog.mk>
+
+${PROG}.so: ${OBJS} ${LIBLIST} ${LDSCRIPT} ${.CURDIR}/../Makefile.efiboot
+	${LD} ${LDFLAGS} -o ${.TARGET}.tmp ${OBJS} ${LIBLIST}
+	@if ${OBJDUMP} -t ${.TARGET}.tmp | grep 'UND'; then		\
+	    (echo Undefined symbols; false);				\
+	fi
+	rm -f ${.TARGET}
+	mv ${.TARGET}.tmp ${.TARGET}
+
+KLINK_MACHINE?=	${MACHINE}
+.include <bsd.klinks.mk>
Index: src/sys/arch/i386/stand/efiboot/boot.c
diff -u /dev/null src/sys/arch/i386/stand/efiboot/boot.c:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/boot.c	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,619 @@
+/*	$NetBSD: boot.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
+ * 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 REGENTS 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 REGENTS 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 "efiboot.h"
+
+#include <sys/bootblock.h>
+#include <sys/boot_flag.h>
+
+#include <lib/libsa/bootcfg.h>
+
+#include <bootmod.h>
+#include <bootmenu.h>
+#include "devopen.h"
+
+int errno;
+int boot_biosdev;
+daddr_t boot_biossector;
+
+extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
+
+extern struct x86_boot_params boot_params;
+extern char twiddle_toggle;
+
+static const char * const names[][2] = {
+	{ "netbsd", "netbsd.gz" },
+	{ "onetbsd", "onetbsd.gz" },
+	{ "netbsd.old", "netbsd.old.gz" },
+};
+
+#define NUMNAMES	__arraycount(names)
+#define DEFFILENAME	names[0][0]
+
+#define	MAXDEVNAME	16
+
+void	command_help(char *);
+void	command_quit(char *);
+void	command_boot(char *);
+void	command_consdev(char *);
+void	command_dev(char *);
+void	command_devpath(char *);
+void	command_efivar(char *);
+void	command_gop(char *);
+#if LIBSA_ENABLE_LS_OP
+void	command_ls(char *);
+#endif
+void	command_memmap(char *);
+#ifndef SMALL
+void	command_menu(char *);
+#endif
+void	command_modules(char *);
+void	command_multiboot(char *);
+void	command_text(char *);
+void	command_version(char *);
+
+const struct bootblk_command commands[] = {
+	{ "help",	command_help },
+	{ "?",		command_help },
+	{ "quit",	command_quit },
+	{ "boot",	command_boot },
+	{ "consdev",	command_consdev },
+	{ "dev",	command_dev },
+	{ "devpath",	command_devpath },
+	{ "efivar",	command_efivar },
+	{ "fs",		fs_add },
+	{ "gop",	command_gop },
+	{ "load",	module_add },
+#if LIBSA_ENABLE_LS_OP
+	{ "ls",		command_ls },
+#endif
+	{ "memmap",	command_memmap },
+#ifndef SMALL
+	{ "menu",	command_menu },
+#endif
+	{ "modules",	command_modules },
+	{ "multiboot",	command_multiboot },
+	{ "rndseed",	rnd_add },
+	{ "splash",	splash_add },
+	{ "text",	command_text },
+	{ "userconf",	userconf_add },
+	{ "version",	command_version },
+	{ NULL,		NULL },
+};
+
+static char *default_devname;
+static int default_unit, default_partition;
+static const char *default_filename;
+
+static char *sprint_bootsel(const char *);
+static void bootit(const char *, int);
+
+int
+parsebootfile(const char *fname, char **fsname, char **devname, int *unit,
+    int *partition, const char **file)
+{
+	const char *col;
+
+	*fsname = "ufs";
+	*devname = default_devname;
+	*unit = default_unit;
+	*partition = default_partition;
+	*file = default_filename;
+
+	if (fname == NULL)
+		return 0;
+
+	if ((col = strchr(fname, ':')) != NULL) {	/* device given */
+		static char savedevname[MAXDEVNAME+1];
+		int devlen;
+		int u = 0, p = 0;
+		int i = 0;
+
+		devlen = col - fname;
+		if (devlen > MAXDEVNAME)
+			return EINVAL;
+
+#define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
+		if (!isvalidname(fname[i]))
+			return EINVAL;
+		do {
+			savedevname[i] = fname[i];
+			i++;
+		} while (isvalidname(fname[i]));
+		savedevname[i] = '\0';
+
+#define isnum(c) ((c) >= '0' && (c) <= '9')
+		if (i < devlen) {
+			if (!isnum(fname[i]))
+				return EUNIT;
+			do {
+				u *= 10;
+				u += fname[i++] - '0';
+			} while (isnum(fname[i]));
+		}
+
+#define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
+		if (i < devlen) {
+			if (!isvalidpart(fname[i]))
+				return EPART;
+			p = fname[i++] - 'a';
+		}
+
+		if (i != devlen)
+			return ENXIO;
+
+		*devname = savedevname;
+		*unit = u;
+		*partition = p;
+		fname = col + 1;
+	}
+
+	if (*fname)
+		*file = fname;
+
+	return 0;
+}
+
+static char *
+sprint_bootsel(const char *filename)
+{
+	char *fsname, *devname;
+	int unit, partition;
+	const char *file;
+	static char buf[80];
+
+	if (parsebootfile(filename, &fsname, &devname, &unit,
+			  &partition, &file) == 0) {
+		snprintf(buf, sizeof(buf), "%s%d%c:%s", devname, unit,
+		    'a' + partition, file);
+		return buf;
+	}
+	return "(invalid)";
+}
+
+void
+clearit(void)
+{
+
+	if (bootcfg_info.clear)
+		clear_pc_screen();
+}
+
+static void
+bootit(const char *filename, int howto)
+{
+
+	if (howto & AB_VERBOSE)
+		printf("booting %s (howto 0x%x)\n", sprint_bootsel(filename),
+		    howto);
+
+	if (exec_netbsd(filename, 0, howto, 0, efi_cleanup) < 0)
+		printf("boot: %s: %s\n", sprint_bootsel(filename),
+		       strerror(errno));
+	else
+		printf("boot returned\n");
+}
+
+void
+print_banner(void)
+{
+	int n;
+
+	clearit();
+	if (bootcfg_info.banner[0]) {
+		for (n = 0; n < BOOTCFG_MAXBANNER && bootcfg_info.banner[n];
+		    n++)
+			printf("%s\n", bootcfg_info.banner[n]);
+	} else
+		command_version("short");
+}
+
+void
+boot(void)
+{
+	int currname;
+	int c;
+
+	boot_modules_enabled = !(boot_params.bp_flags & X86_BP_FLAGS_NOMODULES);
+
+	/* try to set default device to what BIOS tells us */
+	bios2dev(boot_biosdev, boot_biossector, &default_devname, &default_unit,
+	    &default_partition);
+
+	/* if the user types "boot" without filename */
+	default_filename = DEFFILENAME;
+
+	if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) {
+		parsebootconf(BOOTCFG_FILENAME);
+	} else {
+		bootcfg_info.timeout = boot_params.bp_timeout;
+	}
+
+	/*
+	 * If console set in boot.cfg, switch to it.
+	 * This will print the banner, so we don't need to explicitly do it
+	 */
+	if (bootcfg_info.consdev)
+		command_consdev(bootcfg_info.consdev);
+	else
+		print_banner();
+
+	/* Display the menu, if applicable */
+	twiddle_toggle = 0;
+	if (bootcfg_info.nummenu > 0) {
+		/* Does not return */
+		doboottypemenu();
+	}
+
+	printf("Press return to boot now, any other key for boot menu\n");
+	for (currname = 0; currname < NUMNAMES; currname++) {
+		printf("booting %s - starting in ",
+		       sprint_bootsel(names[currname][0]));
+
+		c = awaitkey((bootcfg_info.timeout < 0) ? 0
+		    : bootcfg_info.timeout, 1);
+		if ((c != '\r') && (c != '\n') && (c != '\0')) {
+		    if ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0) {
+			/* do NOT ask for password */
+			bootmenu(); /* does not return */
+		    } else {
+			/* DO ask for password */
+			if (check_password((char *)boot_params.bp_password)) {
+			    /* password ok */
+			    printf("type \"?\" or \"help\" for help.\n");
+			    bootmenu(); /* does not return */
+			} else {
+			    /* bad password */
+			    printf("Wrong password.\n");
+			    currname = 0;
+			    continue;
+			}
+		    }
+		}
+
+		/*
+		 * try pairs of names[] entries, foo and foo.gz
+		 */
+		/* don't print "booting..." again */
+		bootit(names[currname][0], 0);
+		/* since it failed, try compressed bootfile. */
+		bootit(names[currname][1], AB_VERBOSE);
+	}
+
+	bootmenu();	/* does not return */
+}
+
+/* ARGSUSED */
+void
+command_help(char *arg)
+{
+
+	printf("commands are:\n"
+	       "boot [xdNx:][filename] [-12acdqsvxz]\n"
+	       "     (ex. \"hd0a:netbsd.old -s\"\n"
+	       "dev [xd[N[x]]:]\n"
+	       "consdev {pc|com[0123]|com[0123]kbd|auto}\n"
+	       "devpath\n"
+	       "efivar\n"
+	       "gop [{modenum|list}]\n"
+	       "load {path_to_module}\n"
+#if LIBSA_ENABLE_LS_OP
+	       "ls [path]\n"
+#endif
+	       "memmap [{sorted|unsorted}]\n"
+#ifndef SMALL
+	       "menu (reenters boot menu, if defined in boot.cfg)\n"
+#endif
+	       "modules {on|off|enabled|disabled}\n"
+	       "multiboot [xdNx:][filename] [<args>]\n"
+	       "rndseed {path_to_rndseed_file}\n"
+	       "splash {path_to_image_file}\n"
+	       "text [{modenum|list}]\n"
+	       "userconf {command}\n"
+	       "version\n"
+	       "help|?\n"
+	       "quit\n");
+}
+
+#if LIBSA_ENABLE_LS_OP
+void
+command_ls(char *arg)
+{
+	const char *save = default_filename;
+
+	default_filename = "/";
+	ls(arg);
+	default_filename = save;
+}
+#endif
+
+/* ARGSUSED */
+void
+command_quit(char *arg)
+{
+
+	printf("Exiting...\n");
+	delay(1 * 1000 * 1000);
+	reboot();
+	/* Note: we shouldn't get to this point! */
+	panic("Could not reboot!");
+}
+
+void
+command_boot(char *arg)
+{
+	char *filename;
+	int howto;
+
+	if (!parseboot(arg, &filename, &howto))
+		return;
+
+	if (filename != NULL) {
+		bootit(filename, howto);
+	} else {
+		int i;
+
+		if (howto == 0)
+			bootdefault();
+		for (i = 0; i < NUMNAMES; i++) {
+			bootit(names[i][0], howto);
+			bootit(names[i][1], howto);
+		}
+	}
+}
+
+void
+command_dev(char *arg)
+{
+	static char savedevname[MAXDEVNAME + 1];
+	char *fsname, *devname;
+	const char *file; /* dummy */
+
+	if (*arg == '\0') {
+		biosdisk_probe();
+		printf("default %s%d%c\n", default_devname, default_unit,
+		       'a' + default_partition);
+		return;
+	}
+
+	if (strchr(arg, ':') == NULL ||
+	    parsebootfile(arg, &fsname, &devname, &default_unit,
+	      &default_partition, &file)) {
+		command_help(NULL);
+		return;
+	}
+
+	/* put to own static storage */
+	strncpy(savedevname, devname, MAXDEVNAME + 1);
+	default_devname = savedevname;
+}
+
+/* ARGSUSED */
+void
+command_consdev(char *arg)
+{
+
+	/* XXX not implemented yet */
+}
+
+#ifndef SMALL
+/* ARGSUSED */
+void
+command_menu(char *arg)
+{
+
+	if (bootcfg_info.nummenu > 0) {
+		/* Does not return */
+		doboottypemenu();
+	} else
+		printf("No menu defined in boot.cfg\n");
+}
+#endif /* !SMALL */
+
+void
+command_modules(char *arg)
+{
+
+	if (strcmp(arg, "enabled") == 0 ||
+	    strcmp(arg, "on") == 0)
+		boot_modules_enabled = true;
+	else if (strcmp(arg, "disabled") == 0 ||
+	    strcmp(arg, "off") == 0)
+		boot_modules_enabled = false;
+	else
+		printf("invalid flag, must be 'enabled' or 'disabled'.\n");
+}
+
+void
+command_multiboot(char *arg)
+{
+	char *filename;
+
+	filename = arg;
+	if (exec_multiboot(filename, gettrailer(arg)) < 0)
+		printf("multiboot: %s: %s\n", sprint_bootsel(filename),
+		       strerror(errno));
+	else
+		printf("boot returned\n");
+}
+
+void
+command_version(char *arg)
+{
+
+	if (strcmp(arg, "full") == 0) {
+		printf("ImageBase: 0x%" PRIxPTR "\n",
+		    (uintptr_t)efi_li->ImageBase);
+		printf("Stack: 0x%" PRIxPTR "\n", efi_main_sp);
+		printf("EFI version: %d.%02d\n",
+		    ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
+		Print(L"EFI Firmware: %s (rev %d.%02d)\n", ST->FirmwareVendor,
+		    ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
+	}
+
+	printf("\n"
+	    ">> %s, Revision %s (from NetBSD %s)\n"
+	    ">> Memory: %d/%d k\n",
+	    bootprog_name, bootprog_rev, bootprog_kernrev,
+	    getbasemem(), getextmem());
+}
+
+void
+command_memmap(char *arg)
+{
+	bool sorted = true;
+
+	if (*arg == '\0' || strcmp(arg, "sorted") == 0)
+		/* Already sorted is true. */;
+	else if (strcmp(arg, "unsorted") == 0)
+		sorted = false;
+	else {
+		printf("invalid flag, "
+		    "must be 'sorted' or 'unsorted'.\n");
+		return;
+	}
+
+	efi_memory_show_map(sorted);
+}
+
+void
+command_devpath(char *arg)
+{
+	EFI_STATUS status;
+	UINTN i, nhandles;
+	EFI_HANDLE *handles;
+	EFI_DEVICE_PATH *dp0, *dp;
+	CHAR16 *path;
+	UINTN cols, rows, row = 0;
+
+	status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut,
+	    ST->ConOut->Mode->Mode, &cols, &rows);
+	if (EFI_ERROR(status) || rows <= 2)
+		rows = 0;
+	else
+		rows -= 2;
+
+	/*
+	 * all devices.
+	 */
+	status = LibLocateHandle(ByProtocol, &DevicePathProtocol, NULL,
+	    &nhandles, &handles);
+	if (EFI_ERROR(status))
+		return;
+
+	for (i = 0; i < nhandles; i++) {
+		status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i],
+		    &DevicePathProtocol, (void **)&dp0);
+		if (EFI_ERROR(status))
+			break;
+
+		Print(L"DevicePathType %d\n", DevicePathType(dp0));
+		for (dp = dp0;
+		     !IsDevicePathEnd(dp);
+		     dp = NextDevicePathNode(dp)) {
+			path = DevicePathToStr(dp);
+			Print(L"%d:%d:%s\n", DevicePathType(dp), DevicePathSubType(dp), path);
+			FreePool(path);
+
+			if (rows >= 0 && ++row >= rows) {
+				row = 0;
+				Print(L"Press Any Key to continue :");
+				(void) awaitkey(-1, 0);
+				Print(L"\n");
+			}
+		}
+	}
+}
+
+void
+command_efivar(char *arg)
+{
+	static const CHAR16 header[] =
+	 L"GUID                                Variable Name        Value\n"
+	 L"=================================== ==================== ========\n";
+	EFI_STATUS status;
+	UINTN sz = 64;
+	CHAR16 *name = NULL, *tmp, *val;
+	EFI_GUID vendor;
+	UINTN cols, rows, row = 0;
+
+	status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut,
+	    ST->ConOut->Mode->Mode, &cols, &rows);
+	if (EFI_ERROR(status) || rows <= 2)
+		rows = 0;
+	else
+		rows -= 2;
+
+	name = AllocatePool(sz);
+	if (name == NULL) {
+		Print(L"memory allocation failed: %ld bytes\n",
+		    (UINT64)sz);
+		return;
+	}
+
+	name[0] = 0;
+	vendor = NullGuid;
+
+	Print(L"%s", header);
+	for (;;) {
+		status = uefi_call_wrapper(RT->GetNextVariableName, 3,
+		    &sz, name, &vendor);
+		if (EFI_ERROR(status)) {
+			if (status == EFI_NOT_FOUND)
+				break;
+			if (status != EFI_BUFFER_TOO_SMALL) {
+				Print(L"GetNextVariableName failed: %r\n",
+				    status);
+				break;
+			}
+
+			tmp = AllocatePool(sz);
+			if (tmp == NULL) {
+				Print(L"memory allocation failed: %ld bytes\n",
+				    (UINT64)sz);
+				break;
+			}
+			FreePool(name);
+			name = tmp;
+		}
+
+		val = LibGetVariable(name, &vendor);
+		Print(L"%.-35g %.-20s %s\n", &vendor, name,
+		    val ? val : L"(null)");
+		FreePool(val);
+
+		if (rows >= 0 && ++row >= rows) {
+			row = 0;
+			Print(L"Press Any Key to continue :");
+			(void) awaitkey(-1, 0);
+			Print(L"\n");
+		}
+	}
+
+	FreePool(name);
+}
Index: src/sys/arch/i386/stand/efiboot/conf.c
diff -u /dev/null src/sys/arch/i386/stand/efiboot/conf.c:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/conf.c	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,69 @@
+/*	$NetBSD: conf.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	 */
+
+/*
+ * Copyright (c) 1997
+ *	Matthias Drochner.  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 AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <lib/libsa/stand.h>
+#include <lib/libsa/ufs.h>
+#include <lib/libsa/lfs.h>
+#ifdef SUPPORT_EXT2FS
+#include <lib/libsa/ext2fs.h>
+#endif
+#ifdef SUPPORT_MINIXFS3
+#include <lib/libsa/minixfs3.h>
+#endif
+#ifdef SUPPORT_DOSFS
+#include <lib/libsa/dosfs.h>
+#endif
+#ifdef SUPPORT_CD9660
+#include <lib/libsa/cd9660.h>
+#endif
+#include <biosdisk.h>
+
+struct devsw devsw[] = {
+	{ "disk", biosdisk_strategy, biosdisk_open, biosdisk_close, biosdisk_ioctl },
+};
+int ndevs = __arraycount(devsw);
+
+struct fs_ops file_system[] = {
+#ifdef SUPPORT_CD9660
+	FS_OPS(cd9660),
+#endif
+	FS_OPS(ffsv1), FS_OPS(ffsv2),
+	FS_OPS(lfsv1), FS_OPS(lfsv2),
+#ifdef SUPPORT_EXT2FS
+	FS_OPS(ext2fs),
+#endif
+#ifdef SUPPORT_MINIXFS3
+	FS_OPS(minixfs3),
+#endif
+#ifdef SUPPORT_DOSFS
+	FS_OPS(dosfs),
+#endif
+};
+int nfsys = __arraycount(file_system);
Index: src/sys/arch/i386/stand/efiboot/devopen.c
diff -u /dev/null src/sys/arch/i386/stand/efiboot/devopen.c:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/devopen.c	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,110 @@
+/*	$NetBSD: devopen.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	 */
+
+/*-
+ * Copyright (c) 2005 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Bang Jun-Young.
+ *
+ * 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.
+ */
+
+/*
+ * Copyright (c) 1996, 1997
+ *	Matthias Drochner.  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 AUTHOR ``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 AUTHOR 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 "efiboot.h"
+
+#include <biosdisk.h>
+#include "devopen.h"
+#include <bootinfo.h>
+
+static int
+dev2bios(char *devname, int unit, int *biosdev)
+{
+
+	if (strcmp(devname, "hd") == 0)
+		*biosdev = 0x80 + unit;
+	else
+		return ENXIO;
+	return 0;
+}
+
+void
+bios2dev(int biosdev, daddr_t sector, char **devname, int *unit, int *partition)
+{
+
+	*unit = biosdev & 0x7f;
+	*devname = "hd";
+	*partition = biosdisk_findpartition(biosdev, sector);
+}
+
+struct btinfo_bootpath bibp;
+extern bool kernel_loaded;
+
+/*
+ * Open the EFI disk device
+ */
+int
+devopen(struct open_file *f, const char *fname, char **file)
+{
+	char *fsname, *devname;
+	int unit, partition;
+	int biosdev;
+	int error;
+
+	if ((error = parsebootfile(fname, &fsname, &devname,
+				   &unit, &partition, (const char **) file))
+	    || (error = dev2bios(devname, unit, &biosdev)))
+		return error;
+
+	f->f_dev = &devsw[0];		/* must be biosdisk */
+
+	if (!kernel_loaded) {
+		strncpy(bibp.bootpath, *file, sizeof(bibp.bootpath));
+		BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp));
+	}
+
+	return biosdisk_open(f, biosdev, partition);
+}
Index: src/sys/arch/i386/stand/efiboot/devopen.h
diff -u /dev/null src/sys/arch/i386/stand/efiboot/devopen.h:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/devopen.h	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,31 @@
+/*	$NetBSD: devopen.h,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
+ * 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 REGENTS 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 REGENTS 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.
+ */
+
+extern int boot_biosdev;
+
+void bios2dev(int, daddr_t, char **, int *, int *);
Index: src/sys/arch/i386/stand/efiboot/efiboot.c
diff -u /dev/null src/sys/arch/i386/stand/efiboot/efiboot.c:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/efiboot.c	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,137 @@
+/*	$NetBSD: efiboot.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
+ * 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 REGENTS 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 REGENTS 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 "efiboot.h"
+
+#include "bootinfo.h"
+#include "devopen.h"
+
+EFI_HANDLE IH;
+EFI_DEVICE_PATH *efi_bootdp;
+EFI_LOADED_IMAGE *efi_li;
+uintptr_t efi_main_sp;
+
+static EFI_PHYSICAL_ADDRESS heap_start = EFI_ALLOCATE_MAX_ADDRESS;
+static UINTN heap_size = 1 * 1024 * 1024;			/* 1MB */
+static struct btinfo_efi btinfo_efi;
+
+static void efi_heap_init(void);
+
+EFI_STATUS EFIAPI efi_main(EFI_HANDLE, EFI_SYSTEM_TABLE *);
+EFI_STATUS EFIAPI
+efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable)
+{
+	EFI_STATUS status;
+	EFI_DEVICE_PATH *dp0, *dp;
+	extern char twiddle_toggle;
+
+	IH = imageHandle;
+	InitializeLib(IH, systemTable);
+
+	efi_main_sp = (uintptr_t)&status;
+	twiddle_toggle = 1;	/* no twiddling until we're ready */
+
+	cninit();
+	efi_heap_init();
+	efi_md_init();
+
+	status = uefi_call_wrapper(BS->HandleProtocol, 3, IH,
+	    &LoadedImageProtocol, (void **)&efi_li);
+	if (EFI_ERROR(status))
+		Panic(L"HandleProtocol(LoadedImageProtocol): %r", status);
+	status = uefi_call_wrapper(BS->HandleProtocol, 3, efi_li->DeviceHandle,
+	    &DevicePathProtocol, (void **)&dp0);
+	if (EFI_ERROR(status))
+		Panic(L"HandleProtocol(DevicePathProtocol): %r", status);
+	for (dp = dp0; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) {
+		if (DevicePathType(dp) == MEDIA_DEVICE_PATH)
+			continue;
+		if (DevicePathSubType(dp) == MEDIA_HARDDRIVE_DP) {
+			boot_biosdev = 0x80;
+			efi_bootdp = dp;
+			break;
+		}
+		break;
+	}
+
+	efi_disk_probe();
+
+	status = uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0, 0, NULL);
+	if (EFI_ERROR(status))
+		Panic(L"SetWatchdogTimer: %r", status);
+
+	boot();
+
+	return EFI_SUCCESS;
+}
+
+void
+efi_cleanup(void)
+{
+	EFI_STATUS status;
+	EFI_MEMORY_DESCRIPTOR *desc;
+	UINTN NoEntries, MapKey, DescriptorSize;
+	UINT32 DescriptorVersion;
+
+	clearit();
+
+	memset(&btinfo_efi, 0, sizeof(btinfo_efi));
+	btinfo_efi.systblpa = (intptr_t)ST;
+#ifdef	__i386__	/* bootia32.efi */
+	btinfo_efi.flags |= BI_EFI_32BIT;
+#endif
+	BI_ADD(&btinfo_efi, BTINFO_EFI, sizeof(btinfo_efi));
+
+	NoEntries = 0;
+	desc = LibMemoryMap(&NoEntries, &MapKey, &DescriptorSize,
+	    &DescriptorVersion);
+	status = uefi_call_wrapper(BS->ExitBootServices, 2, IH, MapKey);
+	if (EFI_ERROR(status)) {
+		FreePool(desc);
+		desc = LibMemoryMap(&NoEntries, &MapKey, &DescriptorSize,
+		    &DescriptorVersion);
+		status = uefi_call_wrapper(BS->ExitBootServices, 2, IH, MapKey);
+		if (EFI_ERROR(status))
+			Panic(L"ExitBootServices failed");
+	}
+}
+
+static void
+efi_heap_init(void)
+{
+	EFI_STATUS status;
+	u_int sz = EFI_SIZE_TO_PAGES(heap_size);
+
+	status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress,
+	    EfiLoaderData, sz, &heap_start);
+	if (EFI_ERROR(status))
+		Panic(L"%a: AllocatePages() failed: %d page(s): %r",
+		    __func__, sz, status);
+	setheap((void *)(UINTN)heap_start,
+	    (void *)(UINTN)(heap_start + heap_size));
+}
Index: src/sys/arch/i386/stand/efiboot/efiboot.h
diff -u /dev/null src/sys/arch/i386/stand/efiboot/efiboot.h:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/efiboot.h	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,66 @@
+/*	$NetBSD: efiboot.h,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
+ * 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 REGENTS 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 REGENTS 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 <efi.h>
+#include <efilib.h>
+
+#include <lib/libsa/stand.h>
+#include <lib/libkern/libkern.h>
+
+#include "libi386.h"
+
+#include "efiboot_machdep.h"
+
+extern EFI_GUID GraphicsOutputProtocol;
+
+/* boot.c */
+void boot(void);
+void clearit(void);
+void print_banner(void);
+
+/* efiboot.c */
+extern EFI_HANDLE IH;
+extern EFI_DEVICE_PATH *efi_bootdp;
+extern EFI_LOADED_IMAGE *efi_li;
+extern uintptr_t efi_main_sp;
+void efi_cleanup(void);
+
+/* eficons.c */
+int cninit(void);
+void command_text(char *);
+void command_gop(char *);
+
+/* efidisk.c */
+void efi_disk_probe(void);
+
+/* efimemory.c */
+void efi_memory_probe(void);
+void efi_memory_show_map(bool);
+
+/* panic.c */
+__dead VOID Panic(IN CHAR16 *, ...);
Index: src/sys/arch/i386/stand/efiboot/eficons.c
diff -u /dev/null src/sys/arch/i386/stand/efiboot/eficons.c:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/eficons.c	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,557 @@
+/*	$NetBSD: eficons.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
+ * 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 REGENTS 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 REGENTS 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/bitops.h>
+#include <sys/stdint.h>
+
+#include "efiboot.h"
+
+#include "bootinfo.h"
+#include "vbe.h"
+
+struct btinfo_console btinfo_console;
+
+static EFI_GRAPHICS_OUTPUT_PROTOCOL *efi_gop;
+static int efi_gop_mode = -1;
+
+static CHAR16 keybuf[16];
+static int keybuf_read = 0;
+static int keybuf_write = 0;
+
+static void eficons_init_video(void);
+static void efi_switch_video_to_text_mode(void);
+
+int
+cninit(void)
+{
+
+	efi_switch_video_to_text_mode();
+	eficons_init_video();
+
+	/* XXX serial console */
+	btinfo_console.devname[0] = 'p';
+	btinfo_console.devname[1] = 'c';
+	btinfo_console.devname[2] = 0;
+
+	return 0;
+}
+
+int
+getchar(void)
+{
+	EFI_STATUS status;
+	EFI_INPUT_KEY key;
+	int c;
+
+	if (keybuf_read != keybuf_write) {
+		c = keybuf[keybuf_read];
+		keybuf_read = (keybuf_read + 1) % __arraycount(keybuf);
+		return c;
+	}
+
+	status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn,
+	    &key);
+	while (status == EFI_NOT_READY) {
+		WaitForSingleEvent(ST->ConIn->WaitForKey, 0);
+		status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2,
+		    ST->ConIn, &key);
+	}
+	return key.UnicodeChar;
+}
+
+void
+putchar(int c)
+{
+	CHAR16 buf[2];
+
+	buf[1] = 0;
+	if (c == '\n') {
+		buf[0] = '\r';
+		Output(buf);
+	}
+	buf[0] = c;
+	Output(buf);
+}
+
+/*ARGSUSED*/
+int
+iskey(int intr)
+{
+	EFI_STATUS status;
+	EFI_INPUT_KEY key;
+
+	if (keybuf_read != keybuf_write)
+		return 1;
+
+	status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn,
+	    &key);
+	if (EFI_ERROR(status))
+		return 0;
+
+	keybuf[keybuf_write] = key.UnicodeChar;
+	keybuf_write = (keybuf_write + 1) % __arraycount(keybuf);
+	return 1;
+}
+
+char
+awaitkey(int timeout, int tell)
+{
+	char c = 0;
+
+	for (;;) {
+		if (tell) {
+			char numbuf[32];
+			int len;
+
+			len = snprintf(numbuf, sizeof(numbuf), "%d seconds. ",
+			    timeout);
+			if (len > 0 && len < sizeof(numbuf)) {
+				char *p = numbuf;
+
+				printf("%s", numbuf);
+				while (*p)
+					*p++ = '\b';
+				printf("%s", numbuf);
+			}
+		}
+		if (iskey(1)) {
+			/* flush input buffer */
+			while (iskey(0))
+				c = getchar();
+			if (c == 0)
+				c = -1;
+			goto out;
+		}
+		if (timeout--)
+			WaitForSingleEvent(ST->ConIn->WaitForKey, 10000000);
+		else
+			break;
+	}
+
+out:
+	if (tell)
+		printf("0 seconds.     \n");
+
+	return c;
+}
+
+void
+clear_pc_screen(void)
+{
+
+	uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
+}
+
+static uint8_t
+getdepth(const EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info)
+{
+
+	switch (info->PixelFormat) {
+	case PixelBlueGreenRedReserved8BitPerColor:
+	case PixelRedGreenBlueReserved8BitPerColor:
+		return 32;
+
+	case PixelBitMask:
+		return fls32(info->PixelInformation.RedMask
+		    | info->PixelInformation.GreenMask
+		    | info->PixelInformation.BlueMask
+		    | info->PixelInformation.ReservedMask);
+
+	case PixelBltOnly:
+	case PixelFormatMax:
+		return 0;
+	}
+	return 0;
+}
+
+static void
+setpixelformat(UINT32 mask, uint8_t *num, uint8_t *pos)
+{
+	uint8_t n, p;
+
+	n = popcount32(mask);
+	p = ffs32(mask);
+	if (p > 0)
+		p--;
+
+	*num = n;
+	*pos = p;
+}
+
+static void
+bi_framebuffer(void)
+{
+	EFI_STATUS status;
+	EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
+	struct btinfo_framebuffer fb;
+	UINT64 res, bestres = 0;
+	UINTN sz;
+	UINT32 i;
+	INT32 bestmode = -1;
+
+	if (efi_gop == NULL) {
+		framebuffer_configure(NULL);
+		return;
+	}
+
+	if (efi_gop_mode >= 0) {
+		bestmode = efi_gop_mode;
+	} else {
+		/* XXX EDID? EFI_EDID_DISCOVERD_PROTOCOL */
+		for (i = 0; i < efi_gop->Mode->MaxMode; i++) {
+			status = uefi_call_wrapper(efi_gop->QueryMode, 4,
+			    efi_gop, i, &sz, &info);
+			if (EFI_ERROR(status))
+				continue;
+
+			res = (UINT64)info->HorizontalResolution *
+			    (UINT64)info->VerticalResolution *
+			    (UINT64)getdepth(info);
+			if (res > bestres) {
+				bestmode = i;
+				bestres = res;
+			}
+		}
+	}
+	if (bestmode >= 0) {
+		status = uefi_call_wrapper(efi_gop->SetMode, 2, efi_gop,
+		    bestmode);
+		if (EFI_ERROR(status) || efi_gop->Mode->Mode != bestmode)
+			Print(L"GOP setmode failed: %r\n", status);
+	}
+
+	info = efi_gop->Mode->Info;
+	memset(&fb, 0, sizeof(fb));
+	fb.physaddr = efi_gop->Mode->FrameBufferBase;
+	fb.flags = 0;
+	fb.width = info->HorizontalResolution;
+	fb.height = info->VerticalResolution;
+	fb.depth = getdepth(info);
+	fb.stride = info->PixelsPerScanLine * ((fb.depth + 7) / 8);
+	fb.vbemode = 0;	/* XXX */
+
+	switch (info->PixelFormat) {
+	case PixelBlueGreenRedReserved8BitPerColor:
+		fb.rnum = 8;
+		fb.gnum = 8;
+		fb.bnum = 8;
+		fb.rpos = 16;
+		fb.gpos = 8;
+		fb.bpos = 0;
+		break;
+
+	case PixelRedGreenBlueReserved8BitPerColor:
+		fb.rnum = 8;
+		fb.gnum = 8;
+		fb.bnum = 8;
+		fb.rpos = 0;
+		fb.gpos = 8;
+		fb.bpos = 16;
+		break;
+
+	case PixelBitMask:
+		setpixelformat(info->PixelInformation.RedMask,
+		    &fb.rnum, &fb.rpos);
+		setpixelformat(info->PixelInformation.GreenMask,
+		    &fb.gnum, &fb.gpos);
+		setpixelformat(info->PixelInformation.BlueMask,
+		    &fb.bnum, &fb.bpos);
+		break;
+
+	case PixelBltOnly:
+	case PixelFormatMax:
+		Panic(L"Error: invalid pixel format (%d)", info->PixelFormat);
+		break;
+	}
+
+	framebuffer_configure(&fb);
+}
+
+int
+vbe_commit(void)
+{
+
+	bi_framebuffer();
+	return 0;
+}
+
+static void
+print_text_modes(void)
+{
+	EFI_STATUS status;
+	UINTN cols, rows;
+	INT32 i, curmode;
+
+	curmode = ST->ConOut->Mode->Mode;
+	for (i = 0; i < ST->ConOut->Mode->MaxMode; i++) {
+		status = uefi_call_wrapper(ST->ConOut->QueryMode, 4,
+		    ST->ConOut, i, &cols, &rows);
+		if (EFI_ERROR(status))
+			continue;
+		Print(L"%c%d: %dx%d\n", i == curmode ? '*' : ' ',
+		    i, cols, rows);
+	}
+}
+
+static int
+efi_find_text_mode(char *arg)
+{
+	EFI_STATUS status;
+	UINTN cols, rows;
+	INT32 i;
+	char mode[32];
+
+	for (i = 0; i < ST->ConOut->Mode->MaxMode; i++) {
+		status = uefi_call_wrapper(ST->ConOut->QueryMode, 4,
+		    ST->ConOut, i, &cols, &rows);
+		if (EFI_ERROR(status))
+			continue;
+		snprintf(mode, sizeof(mode), "%lux%lu", (long)cols, (long)rows);
+		if (strcmp(arg, mode) == 0)
+			return i;
+	}
+	return -1;
+}
+
+void
+command_text(char *arg)
+{
+	EFI_STATUS status;
+	INT32 modenum;
+
+	if (*arg == '\0' || strcmp(arg, "list") == 0) {
+		print_text_modes();
+		return;
+	}
+
+	if (strchr(arg, 'x') != NULL) {
+		modenum = efi_find_text_mode(arg);
+		if (modenum == -1) {
+			printf("mode %s not supported by firmware\n", arg);
+			return;
+		}
+	} else {
+		modenum = strtoul(arg, NULL, 0);
+	}
+
+	status = uefi_call_wrapper(ST->ConOut->SetMode, 2, ST->ConOut, modenum);
+	if (!EFI_ERROR(status))
+		return;
+
+	printf("invalid flag, must be 'list', a display mode, "
+	    "or a mode number\n");
+}
+
+static int
+print_gop_modes(void)
+{
+	EFI_STATUS status;
+	EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
+	UINTN sz;
+	UINT32 i;
+	uint8_t depth;
+
+	if (efi_gop == NULL)
+		return 1;
+
+	for (i = 0; i < efi_gop->Mode->MaxMode; i++) {
+		status = uefi_call_wrapper(efi_gop->QueryMode, 4, efi_gop, i,
+		    &sz, &info);
+		if (EFI_ERROR(status) && status == EFI_NOT_STARTED) {
+			status = uefi_call_wrapper(efi_gop->SetMode, 2,
+			    efi_gop, efi_gop->Mode->Mode);
+			status = uefi_call_wrapper(efi_gop->QueryMode, 4,
+			    efi_gop, i, &sz, &info);
+		}
+		if (EFI_ERROR(status))
+			continue;
+
+		Print(L"%c%d: %dx%d ",
+		    memcmp(info, efi_gop->Mode->Info, sizeof(*info)) == 0 ?
+		      '*' : ' ',
+		      i, info->HorizontalResolution, info->VerticalResolution);
+		switch (info->PixelFormat) {
+		case PixelRedGreenBlueReserved8BitPerColor:
+			Print(L"RGBR");
+			break;
+		case PixelBlueGreenRedReserved8BitPerColor:
+			Print(L"BGRR");
+			break;
+		case PixelBitMask:
+			Print(L"R:%08x G:%08x B:%08x X:%08x",
+			    info->PixelInformation.RedMask,
+			    info->PixelInformation.GreenMask,
+			    info->PixelInformation.BlueMask,
+			    info->PixelInformation.ReservedMask);
+			break;
+		case PixelBltOnly:
+			Print(L"(blt only)");
+			break;
+		default:
+			Print(L"(Invalid pixel format)");
+			break;
+		}
+		Print(L" pitch %d", info->PixelsPerScanLine);
+		depth = getdepth(info);
+		if (depth > 0)
+			Print(L" bpp %d", depth);
+		Print(L"\n");
+	}
+
+	return 0;
+}
+
+static int
+efi_find_gop_mode(char *arg)
+{
+	EFI_STATUS status;
+	EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
+	UINTN sz;
+	UINT32 i;
+	char mode[32];
+	uint8_t depth;
+
+	for (i = 0; i < efi_gop->Mode->MaxMode; i++) {
+		status = uefi_call_wrapper(efi_gop->QueryMode, 4, efi_gop, i,
+		    &sz, &info);
+		if (EFI_ERROR(status))
+			continue;
+
+		depth = getdepth(info);
+		if (depth == 0)
+			continue;
+
+		snprintf(mode, sizeof(mode), "%lux%lux%u",
+		    (long)info->HorizontalResolution,
+		    (long)info->HorizontalResolution,
+		    depth);
+		if (strcmp(arg, mode) == 0)
+			return i;
+	}
+	return -1;
+}
+
+void
+command_gop(char *arg)
+{
+	EFI_STATUS status;
+	INT32 modenum;
+
+	if (efi_gop == NULL) {
+		printf("GOP not supported by firmware\n");
+		return;
+	}
+
+	if (*arg == '\0' || strcmp(arg, "list") == 0) {
+		print_gop_modes();
+		return;
+	}
+
+	if (strchr(arg, 'x') != NULL) {
+		modenum = efi_find_gop_mode(arg);
+		if (modenum == -1) {
+			printf("mode %s not supported by firmware\n", arg);
+			return;
+		}
+	} else {
+		modenum = strtoul(arg, NULL, 0);
+	}
+
+	status = uefi_call_wrapper(efi_gop->SetMode, 2, efi_gop, modenum);
+	if (!EFI_ERROR(status) && efi_gop->Mode->Mode == modenum) {
+		efi_gop_mode = modenum;
+		return;
+	}
+
+	printf("invalid flag, must be 'list', a display mode, "
+	    "or a mode number\n");
+}
+
+static void
+eficons_init_video(void)
+{
+	EFI_STATUS status;
+	UINTN cols, rows, dim = 0;
+	INT32 i, best = -1;
+
+	/*
+	 * Setup text mode
+	 */
+	uefi_call_wrapper(ST->ConOut->Reset, 2, ST->ConOut, TRUE);
+
+	for (i = 0; i < ST->ConOut->Mode->MaxMode; i++) {
+		status = uefi_call_wrapper(ST->ConOut->QueryMode, 4,
+		    ST->ConOut, i, &cols, &rows);
+		if (EFI_ERROR(status))
+			continue;
+		if (dim < cols * rows) {
+			dim = cols * rows;
+			best = i;
+		}
+	}
+	if (best >= 0)
+		uefi_call_wrapper(ST->ConOut->SetMode, 2, ST->ConOut, best);
+	uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, TRUE);
+	uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
+
+	LibLocateProtocol(&GraphicsOutputProtocol, (void **)&efi_gop);
+}
+
+/*
+ * for Apple EFI
+ */
+#define	CONSOLE_CONTROL_PROTOCOL \
+	{0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21}}
+static EFI_GUID ConsoleControlProtocol = CONSOLE_CONTROL_PROTOCOL;
+
+struct _EFI_CONSOLE_CONTROL_INTERFACE;
+typedef struct _EFI_CONSOLE_CONTROL_INTERFACE EFI_CONSOLE_CONTROL_INTERFACE;
+typedef enum { EfiConsoleControlScreenText } EFI_CONSOLE_CONTROL_SCREEN_MODE;
+typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE) (
+	IN EFI_CONSOLE_CONTROL_INTERFACE *This,
+	IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
+);
+struct _EFI_CONSOLE_CONTROL_INTERFACE {
+	VOID *GetMode;
+	EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode;
+	VOID *LockStdIn;
+};
+
+static void
+efi_switch_video_to_text_mode(void)
+{
+	EFI_STATUS status;
+	EFI_CONSOLE_CONTROL_INTERFACE *cci;
+
+	/* Set up the console, so printf works. */
+	status = LibLocateProtocol(&ConsoleControlProtocol, (void **)&cci);
+	if (!EFI_ERROR(status)) {
+		uefi_call_wrapper(cci->SetMode, 2, cci,
+		    EfiConsoleControlScreenText);
+	}
+}
Index: src/sys/arch/i386/stand/efiboot/efidelay.c
diff -u /dev/null src/sys/arch/i386/stand/efiboot/efidelay.c:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/efidelay.c	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,46 @@
+/*	$NetBSD: efidelay.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
+ * 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 REGENTS 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 REGENTS 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 "efiboot.h"
+
+void
+delay(int us)
+{
+	EFI_STATUS status;
+
+	status = uefi_call_wrapper(BS->Stall, 1, us);
+	if (EFI_ERROR(status))
+		Panic(L"%a: couldn't delay %d us: %r\n", __func__, us, status);
+}
+
+void
+wait_sec(int sec)
+{
+	while (sec-- > 0)
+		delay(1000 * 1000);
+}
Index: src/sys/arch/i386/stand/efiboot/efidisk.c
diff -u /dev/null src/sys/arch/i386/stand/efiboot/efidisk.c:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/efidisk.c	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,127 @@
+/*	$NetBSD: efidisk.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
+ * 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 REGENTS 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 REGENTS 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 "efiboot.h"
+
+#include "efidisk.h"
+
+static struct efidiskinfo_lh efi_disklist;
+static int nefidisks;
+
+void
+efi_disk_probe(void)
+{
+	EFI_STATUS status;
+	UINTN i, nhandles;
+	EFI_HANDLE *handles;
+	EFI_BLOCK_IO *bio;
+	EFI_BLOCK_IO_MEDIA *media;
+	struct efidiskinfo *edi;
+	EFI_DEVICE_PATH *dp, *bdp;
+	bool bootdev;
+	int dev;
+
+	TAILQ_INIT(&efi_disklist);
+
+	status = LibLocateHandle(ByProtocol, &BlockIoProtocol, NULL,
+	    &nhandles, &handles);
+	if (EFI_ERROR(status))
+		Panic(L"LocateHandle(BlockIoProtocol): %r", status);
+
+	for (i = 0; i < nhandles; i++) {
+		status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i],
+		    &BlockIoProtocol, (void **)&bio);
+		if (EFI_ERROR(status))
+			Panic(L"HandleProtocol(BlockIoProtocol): %r", status);
+
+		media = bio->Media;
+		if (media->LogicalPartition || !media->MediaPresent)
+			continue;
+
+		edi = alloc(sizeof(struct efidiskinfo));
+		memset(edi, 0, sizeof(*edi));
+		edi->bio = bio;
+		edi->media_id = media->MediaId;
+
+		bootdev = false;
+		if (efi_bootdp == NULL)
+			goto next;
+
+		status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i],
+		    &DevicePathProtocol, (void **)&dp);
+		if (EFI_ERROR(status))
+			goto next;
+
+		bdp = efi_bootdp;
+		for (;;) {
+			if (IsDevicePathEnd(dp)) {
+				bootdev = true;
+				break;
+			}
+			if (memcmp(dp, bdp, sizeof(EFI_DEVICE_PATH)) != 0 ||
+			    memcmp(dp, bdp, DevicePathNodeLength(dp)) != 0)
+				break;
+			dp = NextDevicePathNode(dp);
+			bdp = NextDevicePathNode(bdp);
+		}
+next:
+		if (bootdev)
+			TAILQ_INSERT_HEAD(&efi_disklist, edi, list);
+		else
+			TAILQ_INSERT_TAIL(&efi_disklist, edi, list);
+	}
+
+	FreePool(handles);
+
+	dev = 0x80;
+	TAILQ_FOREACH(edi, &efi_disklist, list) {
+		edi->dev = dev++;
+		nefidisks++;
+	}
+}
+
+const struct efidiskinfo *
+efidisk_getinfo(int dev)
+{
+	const struct efidiskinfo *edi;
+
+	TAILQ_FOREACH(edi, &efi_disklist, list) {
+		if (dev == edi->dev)
+			return edi;
+	}
+	return NULL;
+}
+
+/*
+ * Return the number of hard disk drives.
+ */
+int
+get_harddrives(void)
+{
+	return nefidisks;
+}
Index: src/sys/arch/i386/stand/efiboot/efidisk.h
diff -u /dev/null src/sys/arch/i386/stand/efiboot/efidisk.h:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/efidisk.h	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,40 @@
+/*	$NetBSD: efidisk.h,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
+ * 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 REGENTS 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 REGENTS 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/queue.h>
+
+struct efidiskinfo {
+	TAILQ_ENTRY(efidiskinfo) list;
+
+	int		dev;
+	EFI_BLOCK_IO	*bio;
+	UINT32		media_id;
+};
+TAILQ_HEAD(efidiskinfo_lh, efidiskinfo);
+
+const struct efidiskinfo *efidisk_getinfo(int);
Index: src/sys/arch/i386/stand/efiboot/efidisk_ll.c
diff -u /dev/null src/sys/arch/i386/stand/efiboot/efidisk_ll.c:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/efidisk_ll.c	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,200 @@
+/*	$NetBSD: efidisk_ll.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	 */
+/*	NetBSD: biosdisk_ll.c,v 1.31 2011/02/21 02:58:02 jakllsch Exp	 */
+
+/*-
+ * Copyright (c) 2005 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Bang Jun-Young.
+ *
+ * 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.
+ */
+
+/*
+ * Copyright (c) 1996
+ * 	Matthias Drochner.  All rights reserved.
+ * Copyright (c) 1996
+ * 	Perry E. Metzger.  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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgements:
+ *	This product includes software developed for the NetBSD Project
+ *	by Matthias Drochner.
+ *	This product includes software developed for the NetBSD Project
+ *	by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * shared by bootsector startup (bootsectmain) and biosdisk.c
+ * needs lowlevel parts from bios_disk.S
+ */
+
+#include "efiboot.h"
+
+#include "biosdisk_ll.h"
+#include "diskbuf.h"
+#include "efidisk.h"
+
+static int do_read(struct biosdisk_ll *, daddr_t, int, char *);
+
+#ifndef BIOSDISK_RETRIES
+#define BIOSDISK_RETRIES 5
+#endif
+
+int
+set_geometry(struct biosdisk_ll *d, struct biosdisk_extinfo *ed)
+{
+	const struct efidiskinfo *edi;
+	EFI_BLOCK_IO_MEDIA *media;
+
+	edi = efidisk_getinfo(d->dev);
+	if (edi == NULL)
+		return 1;
+
+	media = edi->bio->Media;
+
+	d->secsize = media->BlockSize;
+	d->type = BIOSDISK_TYPE_HD;
+	d->flags = BIOSDISK_INT13EXT;
+
+	ed->totsec = media->LastBlock + 1;
+	ed->sbytes = media->BlockSize;
+	ed->flags = 0;
+	if (media->RemovableMedia)
+		ed->flags |= EXTINFO_REMOVABLE;
+
+	return 0;
+}
+
+/*
+ * Global shared "diskbuf" is used as read ahead buffer.  For reading from
+ * floppies, the bootstrap has to be loaded on a 64K boundary to ensure that
+ * this buffer doesn't cross a 64K DMA boundary.
+ */
+static int      ra_dev;
+static daddr_t  ra_end;
+static daddr_t  ra_first;
+
+static int
+do_read(struct biosdisk_ll *d, daddr_t dblk, int num, char *buf)
+{
+	EFI_STATUS status;
+	const struct efidiskinfo *edi;
+
+	edi = efidisk_getinfo(d->dev);
+	if (edi == NULL)
+		return -1;
+
+	status = uefi_call_wrapper(edi->bio->ReadBlocks, 5, edi->bio,
+	    edi->media_id, dblk, num * d->secsize, buf);
+	if (EFI_ERROR(status))
+		return -1;
+	return num;
+}
+
+/*
+ * NB if 'cold' is set below not all of the program is loaded, so
+ * mustn't use data segment, bss, call library functions or do read-ahead.
+ */
+int
+readsects(struct biosdisk_ll *d, daddr_t dblk, int num, char *buf, int cold)
+{
+	while (num) {
+		int nsec;
+
+		/* check for usable data in read-ahead buffer */
+		if (cold || diskbuf_user != &ra_dev || d->dev != ra_dev
+		    || dblk < ra_first || dblk >= ra_end) {
+
+			/* no, read from disk */
+			char *trbuf;
+			int maxsecs;
+			int retries = BIOSDISK_RETRIES;
+
+			if (cold) {
+				/* transfer directly to buffer */
+				trbuf = buf;
+				maxsecs = num;
+			} else {
+				/* fill read-ahead buffer */
+				trbuf = alloc_diskbuf(0); /* no data yet */
+				maxsecs = DISKBUFSIZE / d->secsize;
+			}
+
+			while ((nsec = do_read(d, dblk, maxsecs, trbuf)) < 0) {
+#ifdef DISK_DEBUG
+				if (!cold)
+					printf("read error dblk %"PRId64"-%"PRId64"\n",
+					    dblk, (dblk + maxsecs - 1));
+#endif
+				if (--retries >= 0)
+					continue;
+				return -1;	/* XXX cannot output here if
+						 * (cold) */
+			}
+			if (!cold) {
+				ra_dev = d->dev;
+				ra_first = dblk;
+				ra_end = dblk + nsec;
+				diskbuf_user = &ra_dev;
+			}
+		} else		/* can take blocks from end of read-ahead
+				 * buffer */
+			nsec = ra_end - dblk;
+
+		if (!cold) {
+			/* copy data from read-ahead to user buffer */
+			if (nsec > num)
+				nsec = num;
+			memcpy(buf,
+			       diskbufp + (dblk - ra_first) * d->secsize,
+			       nsec * d->secsize);
+		}
+		buf += nsec * d->secsize;
+		num -= nsec;
+		dblk += nsec;
+	}
+
+	return 0;
+}
Index: src/sys/arch/i386/stand/efiboot/efigetsecs.c
diff -u /dev/null src/sys/arch/i386/stand/efiboot/efigetsecs.c:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/efigetsecs.c	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,52 @@
+/*	$NetBSD: efigetsecs.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*
+ * Copyright (c) 2015 YASUOKA Masahiko <yasu...@yasuoka.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "efiboot.h"
+
+#include <lib/libsa/net.h>
+
+satime_t
+getsecs(void)
+{
+	static const int daytab[][14] = {
+	    { 0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 },
+	    { 0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+	};
+	EFI_TIME t;
+	satime_t r;
+	int y;
+#define isleap(_y) (((_y) % 4) == 0 && (((_y) % 100) != 0 || ((_y) % 400) == 0))
+
+	uefi_call_wrapper(RT->GetTime, 2, &t, NULL);
+
+	/* Calc days from UNIX epoch */
+	r = (t.Year - 1970) * 365;
+	for (y = 1970; y < t.Year; y++) {
+		if (isleap(y))
+			r++;
+	}
+	r += daytab[isleap(t.Year) ? 1 : 0][t.Month] + t.Day;
+
+	/* Calc secs */
+	r *= 60 * 60 * 24;
+	r += ((t.Hour * 60) + t.Minute) * 60 + t.Second;
+	if (-24 * 60 < t.TimeZone && t.TimeZone < 24 * 60)
+		r += t.TimeZone * 60;
+
+	return r;
+}
Index: src/sys/arch/i386/stand/efiboot/efimemory.c
diff -u /dev/null src/sys/arch/i386/stand/efiboot/efimemory.c:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/efimemory.c	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,350 @@
+/*	$NetBSD: efimemory.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
+ * 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 REGENTS 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 REGENTS 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 "efiboot.h"
+
+#include <bootinfo.h>
+
+static const char *memtypes[] = {
+	"unknown",
+	"available",
+	"reserved",
+	"ACPI reclaimable",
+	"ACPI NVS"
+};
+
+static const char *efimemtypes[] = {
+	"Reserved",
+	"LoaderCode",
+	"LoaderData",
+	"BootServicesCode",
+	"BootServicesData",
+	"RuntimeServicesCode",
+	"RuntimeServicesData",
+	"ConventionalMemory",
+	"UnusableMemory",
+	"ACPIReclaimMemory",
+	"ACPIMemoryNVS",
+	"MemoryMappedIO",
+	"MemoryMappedIOPortSpace",
+	"PalCode",
+};
+
+static int
+getmemtype(EFI_MEMORY_DESCRIPTOR *md)
+{
+
+	switch (md->Type) {
+	case EfiLoaderCode:
+	case EfiLoaderData:
+	case EfiBootServicesCode:
+	case EfiBootServicesData:
+	case EfiConventionalMemory:
+		return (md->Attribute & EFI_MEMORY_WB) ?
+		    BIM_Memory : BIM_Reserved;
+
+	case EfiACPIReclaimMemory:
+		return BIM_ACPI;
+
+	case EfiACPIMemoryNVS:
+		return BIM_NVS;
+
+	case EfiReservedMemoryType:
+	case EfiRuntimeServicesCode:
+	case EfiRuntimeServicesData:
+	case EfiUnusableMemory:
+	case EfiMemoryMappedIO:
+	case EfiMemoryMappedIOPortSpace:
+	case EfiPalCode:
+	case EfiMaxMemoryType:
+		return BIM_Reserved;
+	}
+	return BIM_Reserved;
+}
+
+static EFI_MEMORY_DESCRIPTOR *
+GetMemoryMap(OUT UINTN *NoEntries, OUT UINTN *MapKey, OUT UINTN *DescriptorSize,
+    OUT UINT32 *DescriptorVersion, bool sorted)
+{
+	EFI_MEMORY_DESCRIPTOR *desc, *md, *next, *target, tmp;
+	UINTN i, j;
+
+	*NoEntries = 0;
+	desc = LibMemoryMap(NoEntries, MapKey, DescriptorSize,
+	    DescriptorVersion);
+	if (desc == NULL)
+		Panic(L"LibMemoryMap failed");
+
+	if (!sorted)
+		return desc;
+
+	for (i = 0, md = desc; i < *NoEntries - 1; i++, md = next) {
+		target = next = NextMemoryDescriptor(md, *DescriptorSize);
+		for (j = i + 1; j < *NoEntries; j++) {
+			if (md->PhysicalStart > target->PhysicalStart) {
+				CopyMem(&tmp, md, sizeof(*md));
+				CopyMem(md, target, sizeof(*md));
+				CopyMem(target, &tmp, sizeof(*md));
+			}
+			target = NextMemoryDescriptor(target, *DescriptorSize);
+		}
+	}
+	return desc;
+}
+
+/*
+ * get memory size below 1MB
+ */
+int
+getbasemem(void)
+{
+	EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next;
+	UINTN i, NoEntries, MapKey, DescriptorSize, MappingSize;
+	UINT32 DescriptorVersion;
+	EFI_PHYSICAL_ADDRESS basemem = 0, epa;
+
+	mdtop = GetMemoryMap(&NoEntries, &MapKey, &DescriptorSize,
+	    &DescriptorVersion, true);
+
+	for (i = 0, md = mdtop; i < NoEntries; i++, md = next) {
+		next = NextMemoryDescriptor(md, DescriptorSize);
+		if (getmemtype(md) != BIM_Memory)
+			continue;
+		if (md->PhysicalStart >= 1 * 1024 * 1024)
+			continue;
+		if (basemem != md->PhysicalStart)
+			continue;
+
+		MappingSize = md->NumberOfPages * EFI_PAGE_SIZE;
+		epa = md->PhysicalStart + MappingSize;
+		if (epa == 0 || epa > 1 * 1024 * 1024)
+			epa = 1 * 1024 * 1024;
+		basemem = epa;
+	}
+
+	FreePool(mdtop);
+
+	return basemem / 1024;	/* KiB */
+}
+
+/*
+ * get memory size above 1MB below 4GB
+ */
+int
+getextmemx(void)
+{
+	EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next;
+	UINTN i, NoEntries, MapKey, DescriptorSize, MappingSize;
+	UINT32 DescriptorVersion;
+	EFI_PHYSICAL_ADDRESS extmem16m = 0;	/* 0-16MB */
+	EFI_PHYSICAL_ADDRESS extmem4g = 0;	/* 16MB-4GB */
+	EFI_PHYSICAL_ADDRESS pa, epa;
+	bool first16m = true, first4g = true;
+	int extmem;
+
+	mdtop = GetMemoryMap(&NoEntries, &MapKey, &DescriptorSize,
+	    &DescriptorVersion, true);
+
+	for (i = 0, md = mdtop; i < NoEntries; i++, md = next) {
+		next = NextMemoryDescriptor(md, DescriptorSize);
+		if (getmemtype(md) == BIM_Reserved)
+			continue;
+		if (md->PhysicalStart >= 4 * 1024 * 1024 * 1024ULL)
+			continue;
+
+		MappingSize = md->NumberOfPages * EFI_PAGE_SIZE;
+		epa = md->PhysicalStart + MappingSize;
+		if (epa == 0 || epa > 4 * 1024 * 1024 * 1024LL)
+			epa = 4 * 1024 * 1024 * 1024LL;
+
+		if (epa <= 1 * 1024 * 1024)
+			continue;
+
+		pa = md->PhysicalStart;
+		if (pa < 16 * 1024 * 1024) {
+			if (first16m || extmem16m == pa) {
+				first16m = false;
+				if (epa >= 16 * 1024 * 1024) {
+					extmem16m = 16 * 1024 * 1024;
+					pa = 16 * 1024 * 1024;
+				} else
+					extmem16m = epa;
+			}
+		}
+		if (pa >= 16 * 1024 * 1024) {
+			if (first4g || extmem4g == pa) {
+				first4g = false;
+				extmem4g = epa;
+			}
+		}
+	}
+
+	FreePool(mdtop);
+
+	if (extmem16m > 1 * 1024 * 1024)
+		extmem16m -= 1 * 1024 * 1024;	/* below 1MB */
+
+	extmem = extmem16m / 1024;
+	if (extmem == 15 * 1024)
+		extmem += extmem4g / 1024;
+	return extmem;
+}
+
+void
+efi_memory_probe(void)
+{
+	EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next;
+	UINTN i, n, NoEntries, MapKey, DescriptorSize, MappingSize;
+	UINT32 DescriptorVersion;
+	int memtype;
+
+	mdtop = GetMemoryMap(&NoEntries, &MapKey, &DescriptorSize,
+	    &DescriptorVersion, false);
+
+	Print(L" mem[");
+	for (i = 0, n = 0, md = mdtop; i < NoEntries; i++, md = next) {
+		next = NextMemoryDescriptor(md, DescriptorSize);
+
+		memtype = getmemtype(md);
+		if (memtype != BIM_Memory)
+			continue;
+
+		MappingSize = md->NumberOfPages * EFI_PAGE_SIZE;
+		if (MappingSize < 12 * 1024)	/* XXX Why? from OpenBSD */
+			continue;
+
+		if (n++ > 0)
+			Print(L" ");
+		Print(L"0x%lx-0x%lx", md->PhysicalStart,
+		    md->PhysicalStart + MappingSize - 1);
+	}
+	Print(L"]");
+
+	FreePool(mdtop);
+}
+
+void
+efi_memory_show_map(bool sorted)
+{
+	EFI_STATUS status;
+	EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next;
+	UINTN i, NoEntries, MapKey, DescriptorSize;
+	UINT32 DescriptorVersion;
+	char memstr[32], efimemstr[32];
+	int memtype;
+	UINTN cols, rows, row = 0;
+
+	status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut,
+	    ST->ConOut->Mode->Mode, &cols, &rows);
+	if (EFI_ERROR(status) || rows <= 2)
+		rows = 0;
+	else
+		rows -= 2;
+
+	mdtop = GetMemoryMap(&NoEntries, &MapKey, &DescriptorSize,
+	    &DescriptorVersion, sorted);
+
+	for (i = 0, md = mdtop; i < NoEntries; i++, md = next) {
+		next = NextMemoryDescriptor(md, DescriptorSize);
+
+		memtype = getmemtype(md);
+		if (memtype >= __arraycount(memtypes))
+			snprintf(memstr, sizeof(memstr), "unknown (%d)",
+			    memtype);
+		if (md->Type >= __arraycount(efimemtypes))
+			snprintf(efimemstr, sizeof(efimemstr), "unknown (%d)",
+			    md->Type);
+		printf("%016" PRIxMAX "/%016" PRIxMAX ": %s [%s]\n",
+		    (uintmax_t)md->PhysicalStart,
+		    (uintmax_t)md->PhysicalStart +
+		      md->NumberOfPages * EFI_PAGE_SIZE - 1,
+		    memtype >= __arraycount(memtypes) ?
+		      memstr : memtypes[memtype],
+		    md->Type >= __arraycount(efimemtypes) ?
+		      efimemstr : efimemtypes[md->Type]);
+
+		if (rows >= 0 && ++row >= rows) {
+			row = 0;
+			Print(L"Press Any Key to continue :");
+			(void) awaitkey(-1, 0);
+			Print(L"\n");
+		}
+	}
+
+	FreePool(mdtop);
+}
+
+void
+bi_getmemmap(void)
+{
+	EFI_MEMORY_DESCRIPTOR *md;
+	UINTN NoEntries, MapKey, DescriptorSize;
+	UINT32 DescriptorVersion;
+	struct btinfo_efimemmap *bim;
+	size_t allocsz;
+
+	md = GetMemoryMap(&NoEntries, &MapKey, &DescriptorSize,
+	    &DescriptorVersion, true);
+
+	allocsz = sizeof(struct btinfo_efimemmap) - 1
+	    + NoEntries * DescriptorSize;
+	bim = alloc(allocsz);
+
+	bim->num = NoEntries;
+	bim->version = DescriptorVersion;
+	bim->size = DescriptorSize;
+	memcpy(bim->memmap, md, NoEntries * DescriptorSize);
+
+	FreePool(md);
+
+	BI_ADD(bim, BTINFO_EFIMEMMAP, allocsz);
+}
+
+void
+vpbcopy(const void *va, void *pa, size_t n)
+{
+	memmove(pa, va, n);
+}
+
+void
+pvbcopy(const void *pa, void *va, size_t n)
+{
+	memmove(va, pa, n);
+}
+
+void
+pbzero(void *pa, size_t n)
+{
+	memset(pa, 0, n);
+}
+
+physaddr_t
+vtophys(void *va)
+{
+	return (physaddr_t)va;
+}
Index: src/sys/arch/i386/stand/efiboot/panic.c
diff -u /dev/null src/sys/arch/i386/stand/efiboot/panic.c:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/panic.c	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,69 @@
+/*	$NetBSD: panic.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
+ * 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 REGENTS 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 REGENTS 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 "efiboot.h"
+
+#include <efistdarg.h>
+
+/* from sys/external/bsd/gnu-efi/dist/lib/print.c */
+UINTN VPrint (IN CHAR16 *, va_list);
+
+__dead VOID
+Panic(
+    IN CHAR16 *fmt,
+    ...
+    )
+{
+	va_list args;
+
+	va_start(args, fmt);
+	VPrint(fmt, args);
+	Print(L"\n");
+	va_end(args);
+	reboot();
+	/*NOTREACHED*/
+}
+
+void
+reboot(void)
+{
+
+	WaitForSingleEvent(ST->ConIn->WaitForKey, 0);
+
+	uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold, EFI_SUCCESS,
+	    0, NULL);
+	for (;;)
+		continue;
+}
+
+void
+_rtt(void)
+{
+
+	reboot();
+}
Index: src/sys/arch/i386/stand/efiboot/self_reloc.c
diff -u /dev/null src/sys/arch/i386/stand/efiboot/self_reloc.c:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/self_reloc.c	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,99 @@
+/*	$NetBSD: self_reloc.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2008-2010 Rui Paulo <rpa...@freebsd.org>
+ * 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 AUTHOR 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 AUTHOR 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/types.h>
+#include <sys/exec_elf.h>
+
+#include <efi.h>
+
+void self_reloc(Elf_Addr, Elf_Dyn *);
+
+#if defined(__aarch64__)
+#define	USE_RELA
+#endif
+
+/*
+ * A simple elf relocator.
+ */
+void
+self_reloc(Elf_Addr baseaddr, Elf_Dyn *dynamic)
+{
+	Elf_Word relsz, relent;
+	Elf_Addr *newaddr;
+	Elf_Rel *rel = NULL;
+	Elf_Dyn *dynp;
+
+	/*
+	 * Find the relocation address, its size and the relocation entry.
+	 */
+	relsz = 0;
+	relent = 0;
+	for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) {
+		switch (dynp->d_tag) {
+		case DT_REL:
+		case DT_RELA:
+			rel = (Elf_Rel *)(dynp->d_un.d_ptr + baseaddr);
+			break;
+		case DT_RELSZ:
+		case DT_RELASZ:
+			relsz = dynp->d_un.d_val;
+			break;
+		case DT_RELENT:
+		case DT_RELAENT:
+			relent = dynp->d_un.d_val;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/*
+	 * Perform the actual relocation.
+	 */
+	for (; relsz > 0; relsz -= relent) {
+		switch (ELF_R_TYPE(rel->r_info)) {
+		case R_TYPE(NONE):
+			/* No relocation needs be performed. */
+			break;
+
+		case R_TYPE(RELATIVE):
+			/* Address relative to the base address. */
+			newaddr = (Elf_Addr *)(rel->r_offset + baseaddr);
+			*newaddr += baseaddr;
+#ifdef USE_RELA
+			/* Add the addend when the ABI uses them */
+			*newaddr += ((Elf_Rela *)rel)->r_addend;
+#endif
+			break;
+		default:
+			/* XXX: do we need other relocations ? */
+			break;
+		}
+		rel = (Elf_Rel *) ((char *) rel + relent);
+	}
+}
Index: src/sys/arch/i386/stand/efiboot/version
diff -u /dev/null src/sys/arch/i386/stand/efiboot/version:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/version	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,7 @@
+$NetBSD: version,v 1.1 2017/01/24 11:09:14 nonaka Exp $
+
+NOTE ANY CHANGES YOU MAKE TO THE EFI BOOTLOADER HERE.  The format of this
+file is important - make sure the entries are appended on end, last item
+is taken as the current.
+
+1.0:	Initial version.

Index: src/sys/arch/i386/stand/efiboot/bootia32/Makefile
diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootia32/Makefile:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/bootia32/Makefile	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,17 @@
+#	$NetBSD: Makefile,v 1.1 2017/01/24 11:09:14 nonaka Exp $
+
+PROG=		bootia32.efi
+OBJFMT=		pei-i386
+
+EXTRA_SOURCES=	efibootia32.c
+
+CPUFLAGS=	-march=i686 -mtune=i686
+GNUEFIARCH=	ia32
+LIBKERN_ARCH=	i386
+LIBGNUEFI_ARCH=	i386
+KLINK_MACHINE=	i386
+
+CFLAGS+=	-m32
+AFLAGS+=	-m32
+
+.include "${.CURDIR}/../Makefile.efiboot"
Index: src/sys/arch/i386/stand/efiboot/bootia32/efiboot_machdep.h
diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootia32/efiboot_machdep.h:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/bootia32/efiboot_machdep.h	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,29 @@
+/*	$NetBSD: efiboot_machdep.h,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
+ * 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 REGENTS 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 REGENTS 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.
+ */
+
+void efi_md_init(void);
Index: src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c
diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,51 @@
+/*	$NetBSD: efibootia32.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
+ * 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 REGENTS 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 REGENTS 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 "efiboot.h"
+
+#include <sys/bootblock.h>
+
+struct x86_boot_params boot_params;
+
+void
+efi_md_init(void)
+{
+	/* Nothing to do */
+}
+
+void
+startprog(physaddr_t entry, uint32_t argc, uint32_t *argv, physaddr_t sp)
+{
+	Panic(L"%a: not implemented", __func__);
+}
+
+void
+multiboot(physaddr_t entry, physaddr_t header, physaddr_t sp)
+{
+	Panic(L"%a: not implemented", __func__);
+}
Index: src/sys/arch/i386/stand/efiboot/bootia32/ldscript
diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootia32/ldscript:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/bootia32/ldscript	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,76 @@
+/*	$NetBSD: ldscript,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+SECTIONS
+{
+  . = 0;
+  ImageBase = .;
+  .hash : { *(.hash) }	/* this MUST come first! */
+  . = ALIGN(4096);
+  .text :
+  {
+   *(.text)
+   *(.text.*)
+   *(.gnu.linkonce.t.*)
+  }
+  . = ALIGN(4096);
+  .sdata :
+  {
+   *(.got.plt)
+   *(.got)
+   *(.srodata)
+   *(.sdata)
+   *(.sbss)
+   *(.scommon)
+  }
+  . = ALIGN(4096);
+  .data :
+  {
+   *(.rodata*)
+   *(.data)
+   *(.data1)
+   *(.data.*)
+   *(.sdata)
+   *(.got.plt)
+   *(.got)
+   /* the EFI loader doesn't seem to like a .bss section, so we stick
+      it all into .data: */
+   *(.sbss)
+   *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  . = ALIGN(4096);
+  .dynamic  : { *(.dynamic) }
+  . = ALIGN(4096);
+  .rel :
+  {
+    *(.rel.data)
+    *(.rel.data.*)
+    *(.rel.got)
+    *(.rel.stab)
+    *(.data.rel.ro.local)
+    *(.data.rel.local)
+    *(.data.rel.ro)
+    *(.data.rel*)
+  }
+  . = ALIGN(4096);
+  .reloc :		/* This is the PECOFF .reloc section! */
+  {
+    *(.reloc)
+  }
+  . = ALIGN(4096);
+  .dynsym   : { *(.dynsym) }
+  . = ALIGN(4096);
+  .dynstr   : { *(.dynstr) }
+  . = ALIGN(4096);
+  /DISCARD/ :
+  {
+    *(.rel.reloc)
+    *(.eh_frame)
+    *(.note.GNU-stack)
+  }
+  .comment 0 : { *(.comment) }
+}
Index: src/sys/arch/i386/stand/efiboot/bootia32/start.S
diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootia32/start.S:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/bootia32/start.S	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,74 @@
+/*	$NetBSD: start.S,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2008-2010 Rui Paulo <rpa...@freebsd.org>
+ * 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 AUTHOR 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 AUTHOR 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.
+ *
+ *	$FreeBSD: head/sys/boot/efi/loader/arch/i386/start.S 282728 2015-05-10 13:30:21Z ian $
+ */
+
+#include <machine/asm.h>
+
+	.text
+	.align	16
+
+/*
+ * EFI entry point.
+ * _start(EFI_IMAGE image_handle, EFI_SYSTEM_TABLE *system_table);
+ *
+ * We calculate the base address along with _DYNAMIC, relocate us and finally
+ * pass control to efi_main.
+ */
+
+ENTRY(_start)
+	pushl	%ebp
+	movl	%esp, %ebp
+
+	pushl	12(%ebp)	/* image_handle */
+	pushl	8(%ebp)		/* system_table */
+	call	0f
+0:	popl	%eax
+	movl	%eax, %ebx
+	addl	$ImageBase-0b, %eax
+	addl	$_DYNAMIC-0b, %ebx
+	pushl	%ebx		/* dynamic */
+	pushl	%eax		/* ImageBase */
+	call	_C_LABEL(self_reloc)
+	popl	%ebx		/* remove ImageBase from the stack */
+	popl	%ebx		/* remove dynamic from the stack */
+	call	_C_LABEL(efi_main)
+1:	leave
+	ret
+END(_start)
+
+	/*
+	 * hand-craft a dummy .reloc section so EFI knows it's a relocatable
+	 * executable:
+	 */
+
+	.data
+	.section .reloc, "a"
+	.long   0
+	.long   10
+	.word   0

Index: src/sys/arch/i386/stand/efiboot/bootx64/Makefile
diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootx64/Makefile:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/bootx64/Makefile	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,12 @@
+#	$NetBSD: Makefile,v 1.1 2017/01/24 11:09:14 nonaka Exp $
+
+PROG=		bootx64.efi
+OBJFMT=		pei-x86-64
+NEWVERSWHAT=	"EFI Boot (x64)"
+
+EXTRA_SOURCES=	efibootx64.c startprog64.S
+
+COPTS+=		-mno-red-zone
+CPPFLAGS+=	-DEFI_FUNCTION_WRAPPER
+
+.include "${.CURDIR}/../Makefile.efiboot"
Index: src/sys/arch/i386/stand/efiboot/bootx64/efiboot_machdep.h
diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootx64/efiboot_machdep.h:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/bootx64/efiboot_machdep.h	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,29 @@
+/*	$NetBSD: efiboot_machdep.h,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
+ * 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 REGENTS 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 REGENTS 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.
+ */
+
+void efi_md_init(void);
Index: src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c
diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,75 @@
+/*	$NetBSD: efibootx64.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
+ * 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 REGENTS 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 REGENTS 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 "efiboot.h"
+
+#include <sys/bootblock.h>
+
+struct x86_boot_params boot_params;
+
+void startprog64_start(void *, physaddr_t, physaddr_t);
+extern void (*startprog64)(void *, physaddr_t, physaddr_t);
+extern u_int startprog64_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);
+
+	status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress,
+	    EfiLoaderData, sz, &addr);
+	if (EFI_ERROR(status))
+		Panic(L"%a: AllocatePages() failed: %d page(s): %r",
+		    __func__, sz, status);
+	startprog64 = (void *)addr;
+	CopyMem(startprog64, startprog64_start, startprog64_size);
+}
+
+/* ARGSUSED */
+void
+startprog(physaddr_t entry, uint32_t argc, uint32_t *argv, physaddr_t sp)
+{
+	uint32_t *newsp = (void *)((char *)startprog64 + startprog64_size);
+
+	/* Copy argv to new stack pointer */
+	if (argc > 0) {
+		newsp -= argc;
+		memcpy(newsp, argv, sizeof(*argv) * argc);
+	}
+
+	(*startprog64)(startprog64, entry, (physaddr_t)newsp);
+}
+
+/* ARGSUSED */
+void
+multiboot(physaddr_t entry, physaddr_t header, physaddr_t sp)
+{
+	Panic(L"%a: not implemented", __func__);
+}
Index: src/sys/arch/i386/stand/efiboot/bootx64/ldscript
diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootx64/ldscript:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/bootx64/ldscript	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,66 @@
+/*	$NetBSD: ldscript,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+/* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+  . = 0;
+  ImageBase = .;
+  .hash : { *(.hash) }	/* this MUST come first! */
+  . = ALIGN(4096);
+  .eh_frame :
+  {
+    *(.eh_frame)
+  }
+  . = ALIGN(4096);
+  .text :
+  {
+   *(.text)
+   *(.text.*)
+   *(.gnu.linkonce.t.*)
+  }
+  . = ALIGN(4096);
+  .reloc :
+  {
+   *(.reloc)
+  }
+  . = ALIGN(4096);
+  .data :
+  {
+   *(.rodata*)
+   *(.got.plt)
+   *(.got)
+   *(.data*)
+   *(.sdata)
+   /* the EFI loader doesn't seem to like a .bss section, so we stick
+      it all into .data: */
+   *(.sbss)
+   *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+   *(.rel.local)
+  }
+  . = ALIGN(4096);
+  .dynamic  : { *(.dynamic) }
+  . = ALIGN(4096);
+  .rela :
+  {
+    *(.rela.data*)
+    *(.rela.got)
+    *(.rela.stab)
+  }
+  . = ALIGN(4096);
+  .dynsym   : { *(.dynsym) }
+  . = ALIGN(4096);
+  .dynstr   : { *(.dynstr) }
+  . = ALIGN(4096);
+  .ignored.reloc :
+  {
+    *(.rela.reloc)
+    *(.eh_frame)
+    *(.note.GNU-stack)
+  }
+  .comment 0 : { *(.comment) }
+}
Index: src/sys/arch/i386/stand/efiboot/bootx64/start.S
diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootx64/start.S:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/bootx64/start.S	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,79 @@
+/*	$NetBSD: start.S,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+
+/*-
+ * Copyright (C) 1999 Hewlett-Packard Co.
+ *     Contributed by David Mosberger <dav...@hpl.hp.com>.
+ * Copyright (C) 2005 Intel Co.
+ *     Contributed by Fenghua Yu <fenghua...@intel.com>.
+ * 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.
+ * 3. Neither the name of Hewlett-Packard Co. nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ */
+
+/*
+ * crt0-efi-x86_64.S - x86_64 EFI startup code.
+ * $FreeBSD: head/sys/boot/efi/loader/arch/amd64/start.S 282727 2015-05-10 13:24:26Z ian $
+ */
+
+#include <machine/asm.h>
+
+	.text
+	.align 16
+	.globl _start
+_start:
+	subq	$8, %rsp
+	pushq	%rcx
+	pushq	%rdx
+
+0:
+	lea	ImageBase(%rip), %rdi
+	lea	_DYNAMIC(%rip), %rsi
+
+	popq	%rcx
+	popq	%rdx
+	pushq	%rcx
+	pushq	%rdx
+	call	_C_LABEL(self_reloc)
+
+	popq	%rdi
+	popq	%rsi
+
+	call	_C_LABEL(efi_main)
+	addq	$8, %rsp
+
+.Lexit:
+	ret
+
+	/*
+	 * hand-craft a dummy .reloc section so EFI knows it's a relocatable
+	 * executable:
+	 */
+
+	.data
+	.section .reloc, "a"
+	.long   0
+	.long   10
+	.word   0
Index: src/sys/arch/i386/stand/efiboot/bootx64/startprog64.S
diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootx64/startprog64.S:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/arch/i386/stand/efiboot/bootx64/startprog64.S	Tue Jan 24 11:09:14 2017
@@ -0,0 +1,155 @@
+/*	$NetBSD: startprog64.S,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
+/*	NetBSD: startprog.S,v 1.3 2003/02/01 14:48:18 dsl Exp	*/
+
+/* starts program in protected mode / flat space
+ with given stackframe
+ needs global variables flatcodeseg and flatdataseg
+ (gdt offsets)
+  derived from: NetBSD:sys/arch/i386/boot/asm.S
+ */
+
+/*
+ * Ported to boot 386BSD by Julian Elischer (jul...@tfs.com) Sept 1992
+ *
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  software.distribut...@cs.cmu.edu
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+  Copyright 1988, 1989, 1990, 1991, 1992
+   by Intel Corporation, Santa Clara, California.
+
+                All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include <machine/asm.h>
+#include <machine/specialreg.h>
+
+#define	CODE_SEGMENT	0x08
+#define	DATA_SEGMENT	0x10
+
+	.align	16
+	.globl _C_LABEL(startprog64)
+_C_LABEL(startprog64):
+	.quad 0
+
+	.globl _C_LABEL(startprog64_size)
+_C_LABEL(startprog64_size):
+	.long startprog64_end - _C_LABEL(startprog64_start)
+
+	.text
+	.p2align 4,,15
+
+/*
+ * startprog64(loadddr,entry,stack)
+ */
+ENTRY(startprog64_start)
+start:
+	/*
+	 * This function is to call the loaded kernel's start() with
+	 * 32bit segment mode from x64 mode.
+	 * %rdi: loaded start address
+	 * %rsi: kernel entry address
+	 * %rdx: stack address
+	 */
+
+	cld		# LynxOS depends on it
+
+	/* Prepare jump address */
+	lea	(start32a - start)(%rdi), %rax
+	movl	%eax, (start32r - start)(%rdi)
+
+	cli
+
+	/* Setup GDT */
+	lea	(gdt - start)(%rdi), %rax
+	mov	%rax, (gdtrr - start)(%rdi)
+	lgdt	(gdtr - start)(%rdi)
+
+	/* Jump to set %cs */
+	ljmp	*(start32r - start)(%rdi)
+
+	.align	4
+	.code32
+start32a:
+	movl	$DATA_SEGMENT, %eax
+	movw	%eax, %ds
+	movw	%eax, %es
+	movw	%eax, %fs
+	movw	%eax, %gs
+	movw	%eax, %ss
+
+	movl	%edx, %esp
+
+	/* Disable Paging in CR0 */
+	movl	%cr0, %eax
+	andl	$(~CR0_PG), %eax
+	movl	%eax, %cr0
+
+	/* Disable PAE in CR4 */
+	movl	%cr4, %eax
+	andl	$(~CR4_PAE), %eax
+	movl	%eax, %cr4
+
+	jmp	start32b
+
+	.align	4
+start32b:
+	xor	%eax, %eax
+	call	*%esi
+
+	.align	16
+start32r:
+	.long	0
+	.long	CODE_SEGMENT
+	.align	16
+gdt:
+	.long	0, 0
+	.byte	0xff, 0xff, 0x00, 0x00, 0x00, 0x9f, 0xcf, 0x00
+	.byte	0xff, 0xff, 0x00, 0x00, 0x00, 0x93, 0xcf, 0x00
+gdtr:
+	.word	gdtr - gdt
+gdtrr:
+	.quad
+start32end:
+	/* Space for the stack */
+	.align	16
+	.space	8192
+startprog64_end:

Index: src/sys/lib/libgnuefi/arch/i386/Makefile.inc
diff -u /dev/null src/sys/lib/libgnuefi/arch/i386/Makefile.inc:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/lib/libgnuefi/arch/i386/Makefile.inc	Tue Jan 24 11:09:15 2017
@@ -0,0 +1,3 @@
+#	$NetBSD: Makefile.inc,v 1.1 2017/01/24 11:09:15 nonaka Exp $
+
+SRCS+=	efi_stub.S

Index: src/sys/lib/libgnuefi/arch/x86_64/Makefile.inc
diff -u /dev/null src/sys/lib/libgnuefi/arch/x86_64/Makefile.inc:1.1
--- /dev/null	Tue Jan 24 11:09:15 2017
+++ src/sys/lib/libgnuefi/arch/x86_64/Makefile.inc	Tue Jan 24 11:09:15 2017
@@ -0,0 +1,3 @@
+#	$NetBSD: Makefile.inc,v 1.1 2017/01/24 11:09:15 nonaka Exp $
+
+SRCS+=	callwrap.c efi_stub.S

Reply via email to