# HG changeset patch
# User cegger@powermacg5.local
# Date 1263371142 -3600
Make boot(8) multiboot capable.
This is useful to boot boot(8) from grub, for example.
You can boot NetBSD/i386 and NetBSD/Xen from grub directly
but no NetBSD/amd64.
Further, you can boot diskless w/o tftp support in boot(8) from pxegrub
by specifiying NetBSD/amd64 kernel as module in pxegrub config.

diff -r 6b74bbd36e0d -r d15bd1cc85e7 sys/arch/i386/stand/boot/Makefile
--- a/sys/arch/i386/stand/boot/Makefile
+++ b/sys/arch/i386/stand/boot/Makefile
@@ -1,14 +1,5 @@
 # $NetBSD: Makefile,v 1.7 2006/11/14 14:03:12 drochner Exp $
 
-SUBDIR= biosboot
-
-LIBOBJ= ${.OBJDIR}
-.MAKEOVERRIDES+= LIBOBJ
+SUBDIR= biosboot multiboot
 
 .include <bsd.subdir.mk>
-.include <bsd.obj.mk>
-
-cleandir distclean: cleanlibdir
-
-cleanlibdir:
-	-rm -rf lib
diff -r 6b74bbd36e0d -r d15bd1cc85e7 sys/arch/i386/stand/boot/Makefile.boot
--- a/sys/arch/i386/stand/boot/Makefile.boot
+++ b/sys/arch/i386/stand/boot/Makefile.boot
@@ -7,7 +7,7 @@ PROG?= boot
 NEWVERSWHAT?= "BIOS Boot"
 VERSIONFILE?= ${.CURDIR}/../version
 
-SOURCES?= biosboot.S boot2.c conf.c devopen.c exec.c
+SOURCES+= main.c conf.c devopen.c exec.c
 SRCS= ${SOURCES}
 .if !make(depend)
 SRCS+= vers.c
@@ -63,17 +63,11 @@ CPPFLAGS+= -I$S
 
 CPPFLAGS+= -DSUPPORT_PS2
 CPPFLAGS+= -DDIRECT_SERIAL
-CPPFLAGS+= -DSUPPORT_SERIAL=boot_params.bp_consdev
-
-CPPFLAGS+= -DCONSPEED=boot_params.bp_conspeed
-CPPFLAGS+= -DCONSADDR=boot_params.bp_consaddr
-CPPFLAGS+= -DCONSOLE_KEYMAP=boot_params.bp_keymap
 
 CPPFLAGS+= -DSUPPORT_CD9660
 CPPFLAGS+= -DSUPPORT_USTARFS
 CPPFLAGS+= -DSUPPORT_DOSFS
 #CPPFLAGS+= -DSUPPORT_EXT2FS
-CPPFLAGS+= -DPASS_BIOSGEOM
 CPPFLAGS+= -DPASS_MEMMAP
 #CPPFLAGS+= -DBOOTPASSWD
 CPPFLAGS+= -DEPIA_HACK
@@ -100,7 +94,6 @@ CLEANFILES+= machine x86
 	-rm -f machine && ln -s $S/arch/i386/include machine
 	-rm -f x86 && ln -s $S/arch/x86/include x86
 .ifdef LIBOBJ
-	-rm -f lib && ln -s ${LIBOBJ}/lib lib
 	mkdir -p ${LIBOBJ}/lib
 .endif
 .endif
@@ -139,30 +132,3 @@ CLEANFILES+= ${PROG}.tmp ${PROG}.map ver
 
 vers.c: ${VERSIONFILE} ${SOURCES} ${LIBLIST} ${.CURDIR}/../Makefile.boot
 	${HOST_SH} ${S}/conf/newvers_stand.sh -DM ${VERSIONFILE} x86 ${NEWVERSWHAT}
-
-# Anything that calls 'real_to_prot' must have a %pc < 0x10000.
-# We link the program, find the callers (all in libi386), then
-# explicitly pull in the required objects before any other library code.
-${PROG}: ${OBJS} ${LIBLIST} ${.CURDIR}/../Makefile.boot
-	${_MKTARGET_LINK}
-	bb="$$( ${CC} -o ${PROG}.syms ${LDFLAGS} -Wl,-Ttext,0 -Wl,-cref \
-	    ${OBJS} ${LIBLIST} | ( \
-		while read symbol file; do \
-			[ -z "$$file" ] && continue; \
-			[ "$$symbol" = real_to_prot ] && break; \
-		done; \
-		while \
-			oifs="$$IFS"; \
-			IFS='()'; \
-			set -- $$file; \
-			IFS="$$oifs"; \
-			[ -n "$$2" ] && echo "${I386DST}/$$2"; \
-			read file rest && [ -z "$$rest" ]; \
-		do :; \
-		done; \
-	) )"; \
-	${CC} -o ${PROG}.syms ${LDFLAGS} -Wl,-Ttext,0 \
-		-Wl,-Map,${PROG}.map -Wl,-cref ${OBJS} $$bb ${LIBLIST}
-	${OBJCOPY} -O binary ${PROG}.syms ${PROG}
-
-.include <bsd.prog.mk>
diff -r 6b74bbd36e0d -r d15bd1cc85e7 sys/arch/i386/stand/boot/biosboot/Makefile
--- a/sys/arch/i386/stand/boot/biosboot/Makefile
+++ b/sys/arch/i386/stand/boot/biosboot/Makefile
@@ -2,4 +2,47 @@
 
 PROG=	boot
 
+SOURCES= biosboot.S boot2.c
+
+RELOC=0
+
+CPPFLAGS+= -DRELOC=${RELOC}
+CPPFLAGS+= -DPASS_BIOSGEOM
+
+CPPFLAGS+= -DSUPPORT_SERIAL=boot_params.bp_consdev
+CPPFLAGS+= -DCONSPEED=boot_params.bp_conspeed
+CPPFLAGS+= -DCONSADDR=boot_params.bp_consaddr
+CPPFLAGS+= -DCONSOLE_KEYMAP=boot_params.bp_keymap
+
+LIBOBJ= ${.OBJDIR}
+.MAKEOVERRIDES+= LIBOBJ
+
 .include <../Makefile.boot>
+.include <bsd.obj.mk>
+
+# Anything that calls 'real_to_prot' must have a %pc < 0x10000.
+# We link the program, find the callers (all in libi386), then
+# explicitly pull in the required objects before any other library code.
+${PROG}: ${OBJS} ${LIBLIST} ${.CURDIR}/../Makefile.boot
+	${_MKTARGET_LINK}
+	bb="$$( ${CC} -o ${PROG}.syms ${LDFLAGS} -Wl,-Ttext,${RELOC} -Wl,-cref \
+	    ${OBJS} ${LIBLIST} | ( \
+		while read symbol file; do \
+			[ -z "$$file" ] && continue; \
+			[ "$$symbol" = real_to_prot ] && break; \
+		done; \
+		while \
+			oifs="$$IFS"; \
+			IFS='()'; \
+			set -- $$file; \
+			IFS="$$oifs"; \
+			[ -n "$$2" ] && echo "${I386DST}/$$2"; \
+			read file rest && [ -z "$$rest" ]; \
+		do :; \
+		done; \
+	) )"; \
+	${CC} -o ${PROG}.syms ${LDFLAGS} -Wl,-Ttext,${RELOC} \
+		-Wl,-Map,${PROG}.map -Wl,-cref ${OBJS} $$bb ${LIBLIST}
+	${OBJCOPY} -O binary ${PROG}.syms ${PROG}
+
+.include <bsd.prog.mk>
diff -r 6b74bbd36e0d -r d15bd1cc85e7 sys/arch/i386/stand/boot/boot2.c
--- a/sys/arch/i386/stand/boot/boot2.c
+++ b/sys/arch/i386/stand/boot/boot2.c
@@ -80,6 +80,7 @@
 #include <bootmenu.h>
 #include <vbe.h>
 #include "devopen.h"
+#include "main.h"
 
 #ifdef SUPPORT_PS2
 #include <biosmca.h>
@@ -109,166 +110,8 @@ static char *default_devname;
 static int default_unit, default_partition;
 static const char *default_filename;
 
-char *sprint_bootsel(const char *);
-void bootit(const char *, int, int);
-void print_banner(void);
 void boot2(int, u_int);
 
-void	command_help(char *);
-void	command_ls(char *);
-void	command_quit(char *);
-void	command_boot(char *);
-void	command_dev(char *);
-void	command_consdev(char *);
-void	command_modules(char *);
-void	command_multiboot(char *);
-
-const struct bootblk_command commands[] = {
-	{ "help",	command_help },
-	{ "?",		command_help },
-	{ "ls",		command_ls },
-	{ "quit",	command_quit },
-	{ "boot",	command_boot },
-	{ "dev",	command_dev },
-	{ "consdev",	command_consdev },
-	{ "modules",	command_modules },
-	{ "load",	module_add },
-	{ "multiboot",	command_multiboot },
-	{ "vesa",	command_vesa },
-	{ NULL,		NULL },
-};
-
-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;
-}
-
-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) {
-		sprintf(buf, "%s%d%c:%s", devname, unit, 'a' + partition, file);
-		return buf;
-	}
-	return "(invalid)";
-}
-
-static void
-clearit(void)
-{
-
-	if (bootconf.clear)
-		clear_pc_screen();
-}
-
-void
-bootit(const char *filename, int howto, int tell)
-{
-
-	if (tell) {
-		printf("booting %s", sprint_bootsel(filename));
-		if (howto)
-			printf(" (howto 0x%x)", howto);
-		printf("\n");
-	}
-
-	if (exec_netbsd(filename, 0, howto, boot_biosdev < 0x80, clearit) < 0)
-		printf("boot: %s: %s\n", sprint_bootsel(filename),
-		       strerror(errno));
-	else
-		printf("boot returned\n");
-}
-
-void
-print_banner(void)
-{
-
-	clearit();
-#ifndef SMALL
-	int n;
-	if (bootconf.banner[0]) {
-		for (n = 0; bootconf.banner[n] && n < MAXBANNER; n++) 
-			printf("%s\n", bootconf.banner[n]);
-	} else {
-#endif /* !SMALL */
-		printf("\n"
-		       ">> %s, Revision %s (from NetBSD %s)\n"
-		       ">> Memory: %d/%d k\n",
-		       bootprog_name, bootprog_rev, bootprog_kernrev,
-		       getbasemem(), getextmem());
-
-#ifndef SMALL
-	}
-#endif /* !SMALL */
-}
-
 /*
  * Called from the initial entry point boot_start in biosboot.S
  *
@@ -359,141 +202,3 @@ boot2(int biosdev, u_int biossector)
 
 	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"
-	       "ls [path]\n"
-	       "dev xd[N[x]]:\n"
-	       "consdev {pc|com[0123]|com[0123]kbd|auto}\n"
-	       "vesa {enabled|disabled|list|modenum}\n"
-	       "modules {enabled|disabled}\n"
-	       "load {path_to_module}\n"
-	       "multiboot [xdNx:][filename] [<args>]\n"
-	       "help|?\n"
-	       "quit\n");
-}
-
-void
-command_ls(char *arg)
-{
-	const char *save = default_filename;
-
-	default_filename = "/";
-	ufs_ls(arg);
-	default_filename = save;
-}
-
-/* ARGSUSED */
-void
-command_quit(char *arg)
-{
-
-	printf("Exiting...\n");
-	delay(1000000);
-	reboot();
-	/* Note: we shouldn't get to this point! */
-	panic("Could not reboot!");
-	exit(0);
-}
-
-void
-command_boot(char *arg)
-{
-	char *filename;
-	int howto;
-
-	if (parseboot(arg, &filename, &howto))
-		bootit(filename, howto, (howto & AB_VERBOSE) != 0);
-}
-
-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;
-}
-
-static const struct cons_devs {
-	const char	*name;
-	u_int		tag;
-} cons_devs[] = {
-	{ "pc",		CONSDEV_PC },
-	{ "com0",	CONSDEV_COM0 },
-	{ "com1",	CONSDEV_COM1 },
-	{ "com2",	CONSDEV_COM2 },
-	{ "com3",	CONSDEV_COM3 },
-	{ "com0kbd",	CONSDEV_COM0KBD },
-	{ "com1kbd",	CONSDEV_COM1KBD },
-	{ "com2kbd",	CONSDEV_COM2KBD },
-	{ "com3kbd",	CONSDEV_COM3KBD },
-	{ "auto",	CONSDEV_AUTO },
-	{ NULL,		0 }
-};
-
-void
-command_consdev(char *arg)
-{
-	const struct cons_devs *cdp;
-
-	for (cdp = cons_devs; cdp->name; cdp++) {
-		if (strcmp(arg, cdp->name) == 0) {
-			initio(cdp->tag);
-			print_banner();
-			return;
-		}
-	}
-	printf("invalid console device.\n");
-}
-
-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");
-}
-
diff -r 6b74bbd36e0d -r d15bd1cc85e7 sys/arch/i386/stand/boot/main.c
--- /dev/null
+++ b/sys/arch/i386/stand/boot/main.c
@@ -0,0 +1,395 @@
+/*	$NetBSD: boot2.c,v 1.45 2009/09/13 22:45:27 jmcneill Exp $	*/
+
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2003
+ *	David Laight.  All rights reserved
+ * Copyright (c) 1996, 1997, 1999
+ * 	Matthias Drochner.  All rights reserved.
+ * Copyright (c) 1996, 1997
+ * 	Perry E. Metzger.  All rights reserved.
+ * Copyright (c) 1997
+ *	Jason R. Thorpe.  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.
+ */
+
+/* Based on stand/biosboot/main.c */
+
+#include <sys/types.h>
+#include <sys/reboot.h>
+#include <sys/bootblock.h>
+
+#include <lib/libsa/stand.h>
+#include <lib/libsa/ufs.h>
+#include <lib/libkern/libkern.h>
+
+#include <libi386.h>
+#include <bootmod.h>
+#include <bootmenu.h>
+#include <vbe.h>
+#include "devopen.h"
+#include "main.h"
+
+#ifdef SUPPORT_PS2
+#include <biosmca.h>
+#endif
+
+extern struct x86_boot_params boot_params;
+
+extern	const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
+
+int errno;
+
+int boot_biosdev;
+u_int boot_biossector;
+
+static const char * const names[][2] = {
+	{ "netbsd", "netbsd.gz" },
+	{ "onetbsd", "onetbsd.gz" },
+	{ "netbsd.old", "netbsd.old.gz" },
+};
+
+#define NUMNAMES (sizeof(names)/sizeof(names[0]))
+#define DEFFILENAME names[0][0]
+
+#define MAXDEVNAME 16
+
+static char *default_devname;
+static int default_unit, default_partition;
+static const char *default_filename;
+
+const struct bootblk_command commands[] = {
+	{ "help",	command_help },
+	{ "?",		command_help },
+	{ "ls",		command_ls },
+	{ "quit",	command_quit },
+	{ "boot",	command_boot },
+	{ "dev",	command_dev },
+	{ "consdev",	command_consdev },
+	{ "modules",	command_modules },
+	{ "load",	module_add },
+	{ "multiboot",	command_multiboot },
+	{ "vesa",	command_vesa },
+	{ NULL,		NULL },
+};
+
+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;
+}
+
+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) {
+		sprintf(buf, "%s%d%c:%s", devname, unit, 'a' + partition, file);
+		return buf;
+	}
+	return "(invalid)";
+}
+
+static void
+clearit(void)
+{
+
+	if (bootconf.clear)
+		clear_pc_screen();
+}
+
+void
+bootit(const char *filename, int howto, int tell)
+{
+
+	if (tell) {
+		printf("booting %s", sprint_bootsel(filename));
+		if (howto)
+			printf(" (howto 0x%x)", howto);
+		printf("\n");
+	}
+
+	if (exec_netbsd(filename, 0, howto, boot_biosdev < 0x80, clearit) < 0)
+		printf("boot: %s: %s\n", sprint_bootsel(filename),
+		       strerror(errno));
+	else
+		printf("boot returned\n");
+}
+
+void
+print_banner(void)
+{
+
+	clearit();
+#ifndef SMALL
+	int n;
+	if (bootconf.banner[0]) {
+		for (n = 0; bootconf.banner[n] && n < MAXBANNER; n++) 
+			printf("%s\n", bootconf.banner[n]);
+	} else {
+#endif /* !SMALL */
+		printf("\n"
+		       ">> %s, Revision %s (from NetBSD %s)\n"
+		       ">> Memory: %d/%d k\n",
+		       bootprog_name, bootprog_rev, bootprog_kernrev,
+		       getbasemem(), getextmem());
+
+#ifndef SMALL
+	}
+#endif /* !SMALL */
+}
+
+/* ARGSUSED */
+void
+command_help(char *arg)
+{
+
+	printf("commands are:\n"
+	       "boot [xdNx:][filename] [-12acdqsvxz]\n"
+	       "     (ex. \"hd0a:netbsd.old -s\"\n"
+	       "ls [path]\n"
+	       "dev xd[N[x]]:\n"
+	       "consdev {pc|com[0123]|com[0123]kbd|auto}\n"
+	       "vesa {enabled|disabled|list|modenum}\n"
+	       "modules {enabled|disabled}\n"
+	       "load {path_to_module}\n"
+	       "multiboot [xdNx:][filename] [<args>]\n"
+	       "help|?\n"
+	       "quit\n");
+}
+
+void
+command_ls(char *arg)
+{
+	const char *save = default_filename;
+
+	default_filename = "/";
+	ufs_ls(arg);
+	default_filename = save;
+}
+
+/* ARGSUSED */
+void
+command_quit(char *arg)
+{
+
+	printf("Exiting...\n");
+	delay(1000000);
+	reboot();
+	/* Note: we shouldn't get to this point! */
+	panic("Could not reboot!");
+	exit(0);
+}
+
+void
+command_boot(char *arg)
+{
+	char *filename;
+	int howto;
+
+	if (parseboot(arg, &filename, &howto))
+		bootit(filename, howto, (howto & AB_VERBOSE) != 0);
+}
+
+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;
+}
+
+static const struct cons_devs {
+	const char	*name;
+	u_int		tag;
+} cons_devs[] = {
+	{ "pc",		CONSDEV_PC },
+	{ "com0",	CONSDEV_COM0 },
+	{ "com1",	CONSDEV_COM1 },
+	{ "com2",	CONSDEV_COM2 },
+	{ "com3",	CONSDEV_COM3 },
+	{ "com0kbd",	CONSDEV_COM0KBD },
+	{ "com1kbd",	CONSDEV_COM1KBD },
+	{ "com2kbd",	CONSDEV_COM2KBD },
+	{ "com3kbd",	CONSDEV_COM3KBD },
+	{ "auto",	CONSDEV_AUTO },
+	{ NULL,		0 }
+};
+
+void
+command_consdev(char *arg)
+{
+	const struct cons_devs *cdp;
+
+	for (cdp = cons_devs; cdp->name; cdp++) {
+		if (strcmp(arg, cdp->name) == 0) {
+			initio(cdp->tag);
+			print_banner();
+			return;
+		}
+	}
+	printf("invalid console device.\n");
+}
+
+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");
+}
+
diff -r 6b74bbd36e0d -r d15bd1cc85e7 sys/arch/i386/stand/boot/main.h
--- /dev/null
+++ b/sys/arch/i386/stand/boot/main.h
@@ -0,0 +1,14 @@
+/*	$NetBSD: $ */
+
+void	command_help(char *);
+void	command_ls(char *);
+void	command_quit(char *);
+void	command_boot(char *);
+void	command_dev(char *);
+void	command_consdev(char *);
+void	command_modules(char *);
+void	command_multiboot(char *);
+
+char *sprint_bootsel(const char *);
+void bootit(const char *, int, int);
+void print_banner(void);
diff -r 6b74bbd36e0d -r d15bd1cc85e7 sys/arch/i386/stand/boot/multi.c
--- /dev/null
+++ b/sys/arch/i386/stand/boot/multi.c
@@ -0,0 +1,178 @@
+/*	$NetBSD: boot2.c,v 1.45 2009/09/13 22:45:27 jmcneill Exp $	*/
+
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2003
+ *	David Laight.  All rights reserved
+ * Copyright (c) 1996, 1997, 1999
+ * 	Matthias Drochner.  All rights reserved.
+ * Copyright (c) 1996, 1997
+ * 	Perry E. Metzger.  All rights reserved.
+ * Copyright (c) 1997
+ *	Jason R. Thorpe.  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.
+ */
+
+/* Based on stand/biosboot/main.c */
+
+#include <sys/types.h>
+#include <sys/bootblock.h>
+
+#include <lib/libsa/stand.h>
+#include <lib/libsa/ufs.h>
+#include <lib/libkern/libkern.h>
+
+#include <libi386.h>
+#include <bootmod.h>
+#include <bootmenu.h>
+#include <vbe.h>
+#include "devopen.h"
+#include "main.h"
+
+#ifdef SUPPORT_PS2
+#include <biosmca.h>
+#endif
+
+struct x86_boot_params boot_params;
+int errno;
+
+static const char * const names[][2] = {
+	{ "netbsd", "netbsd.gz" },
+	{ "onetbsd", "onetbsd.gz" },
+	{ "netbsd.old", "netbsd.old.gz" },
+};
+
+#define NUMNAMES (sizeof(names)/sizeof(names[0]))
+#define DEFFILENAME names[0][0]
+
+#define MAXDEVNAME 16
+
+static const char *default_filename;
+
+void __multiboot(void);
+
+/*
+ * Called from the initial entry point boot_start in multiboot.S
+ */
+void
+__multiboot(void)
+{
+	extern char twiddle_toggle;
+	int currname;
+	char c;
+
+	twiddle_toggle = 1;	/* no twiddling until we're ready */
+
+	initio(CONSDEV_AUTO);
+#ifdef SUPPORT_PS2
+	biosmca();
+#endif
+	gateA20();
+
+	vbe_init();
+
+	/* if the user types "boot" without filename */
+	default_filename = DEFFILENAME;
+
+#ifndef SMALL
+	parsebootconf(BOOTCONF);
+
+	/*
+	 * If console set in boot.cfg, switch to it.
+	 * This will print the banner, so we don't need to explicitly do it
+	 */
+	if (bootconf.consdev)
+		command_consdev(bootconf.consdev);
+	else 
+		print_banner();
+
+	/* Display the menu, if applicable */
+	twiddle_toggle = 0;
+	if (bootconf.nummenu > 0) {
+		/* Does not return */
+		doboottypemenu();
+	}
+
+#else
+	twiddle_toggle = 0;
+	print_banner();
+#endif
+
+	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]));
+
+#ifdef SMALL
+		c = awaitkey(boot_params.bp_timeout, 1);
+#else
+		c = awaitkey((bootconf.timeout < 0) ? 0 : bootconf.timeout, 1);
+#endif
+		if ((c != '\r') && (c != '\n') && (c != '\0')) {
+			printf("type \"?\" or \"help\" for help.\n");
+			bootmenu(); /* does not return */
+		}
+
+		/*
+		 * try pairs of names[] entries, foo and foo.gz
+		 */
+		/* don't print "booting..." again */
+		bootit(names[currname][0], 0, 0);
+		/* since it failed, try compressed bootfile. */
+		bootit(names[currname][1], 0, 1);
+	}
+
+	bootmenu();	/* does not return */
+}
diff -r 6b74bbd36e0d -r d15bd1cc85e7 sys/arch/i386/stand/boot/multiboot.S
--- /dev/null
+++ b/sys/arch/i386/stand/boot/multiboot.S
@@ -0,0 +1,105 @@
+/*	$NetBSD: biosboot.S,v 1.6 2008/04/28 20:23:25 martin Exp $	*/
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+#include <machine/multiboot.h>
+
+#ifndef RELOC
+#error RELOC not defined
+#endif
+
+reloc = RELOC
+
+#define _RELOC(x)	((x) - reloc)
+
+	.text
+textstart:
+
+	.code32
+ENTRY(boot_start)
+	jmp	boot_start_1
+
+	.align	4
+	.globl	Multiboot_Header
+_C_LABEL(Multiboot_Header):
+#define MULTIBOOT_HEADER_FLAGS	(MULTIBOOT_HEADER_MODS_ALIGNED | \
+				 MULTIBOOT_HEADER_WANT_MEMORY)
+	/* Magic number indication a Multiboot header. */
+	.long	MULTIBOOT_HEADER_MAGIC
+	/* Flags to bootloader (see Multiboot spec). */
+	.long	MULTIBOOT_HEADER_FLAGS
+	/* Checksum: must be the negated sum of the first two fields. */
+	.long	-(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
+
+boot_start_1:
+	/* Check if we are being executed by a Multiboot-compliant boot
+	 * loader. */
+	cmpl	$MULTIBOOT_INFO_MAGIC,%eax
+	je	boot_start_2
+
+	push	%ax
+	movw	$(err1 - textstart), %si
+	call	_RELOC(message)
+	pop	%si
+	call	_RELOC(message)
+	jmp	loopstop
+err1:	.asciz	"Not a Multiboot bootloader"
+
+
+boot_start_2:
+#if 0
+	/*
+	 * Indeed, a multiboot-compliant boot loader executed us.  We copy
+	 * the received Multiboot information structure into kernel's data
+	 * space to process it later -- after we are relocated.  It will
+	 * be safer to run complex C code than doing it at this point.
+	 */
+	push	%ebx	# Address of Multiboot information
+	call	_RELOC(_C_LABEL(multiboot_pre_reloc))
+	addl	$4,%esp
+#endif
+
+	call	_RELOC(_C_LABEL(__multiboot))		/* C bootstrap code */
+	add	$8, %esp
+
+boot_fail:
+	push	%ax
+	movw	$(err2 - textstart), %si
+	call	_RELOC(message)
+	pop	%si
+	call	_RELOC(message)
+	jmp	loopstop
+err2:	.asciz	"Boot2 failed: "
+
+loopstop:
+1:	sti
+	hlt
+	jmp 1b
diff -r 6b74bbd36e0d -r d15bd1cc85e7 sys/arch/i386/stand/boot/multiboot/Makefile
--- /dev/null
+++ b/sys/arch/i386/stand/boot/multiboot/Makefile
@@ -0,0 +1,27 @@
+# $NetBSD: Makefile,v 1.3 2005/12/11 12:17:48 christos Exp $
+
+PROG=	boot.multiboot
+NEWVERSWHAT= "MULTI Boot"
+SOURCES= multiboot.S multi.c
+
+RELOC=0x100000
+
+CPPFLAGS += -DSUPPORT_TFTP -DRELOC=${RELOC}
+CPPFLAGS.multiboot.S += -D_LOCORE
+
+LIBOBJ= ${.OBJDIR}
+.MAKEOVERRIDES+= LIBOBJ
+
+.include <../Makefile.boot>
+.include <bsd.obj.mk>
+
+# Anything that calls 'real_to_prot' must have a %pc < 0x10000.
+# We link the program, find the callers (all in libi386), then
+# explicitly pull in the required objects before any other library code.
+${PROG}: ${OBJS} ${LIBLIST} ${.CURDIR}/../Makefile.boot
+	${_MKTARGET_LINK}
+	${CC} -o ${PROG}.syms ${LDFLAGS} -Wl,-Ttext,${RELOC} \
+		-Wl,-Map,${PROG}.map -Wl,-cref ${OBJS} ${LIBLIST}
+	${OBJCOPY} -O binary ${PROG}.syms ${PROG}
+
+.include <bsd.prog.mk>
diff -r 6b74bbd36e0d -r d15bd1cc85e7 sys/arch/i386/stand/lib/realprot.S
--- a/sys/arch/i386/stand/lib/realprot.S
+++ b/sys/arch/i386/stand/lib/realprot.S
@@ -35,10 +35,21 @@
 
 #include <machine/asm.h>
 
+#ifndef RELOC
+#error RELOC not defined
+#endif
+
+reloc = RELOC
+
+#define _RELOC(x)	((x) - reloc)
+#define GDT_RELOC(x)	((x) - gdt)
+#define TEXT_RELOC(x)	((x) - textstart)
+
 #define	CR0_PE		1
 
 	.text
 	.align  16
+textstart:
 gdt:
 	.word	0, 0
 	.byte	0, 0x00, 0x00, 0
@@ -95,14 +106,14 @@ gdt_fixup:
 
 	xorl	%eax, %eax
 	mov	%cs, %ax
-	mov	%ax, ourseg
+	mov	%ax, GDT_RELOC(ourseg)
 	/* sort out stuff for %ss != %ds */
 	movw	%ss, %dx
-	movw	%dx, stkseg
+	movw	%dx, GDT_RELOC(stkseg)
 	subw	%ax, %dx
 	shll	$16, %edx
 	shrl	$12, %edx
-	movl	%edx, stkdif
+	movl	%edx, GDT_RELOC(stkdif)
 
 	/* fix up GDT entries for bootstrap */
 	mov	%ax, %dx
@@ -110,16 +121,16 @@ gdt_fixup:
 	shr	$12, %dx
 
 #define FIXUP(gdt_index) \
-	movw	%ax, gdt+gdt_index+2; \
-	movb	%dl, gdt+gdt_index+4
+	movw	%ax, GDT_RELOC(gdt+gdt_index+2); \
+	movb	%dl, GDT_RELOC(gdt+gdt_index+4)
 
 	FIXUP(bootcodeseg)
 	FIXUP(bootrealseg)
 	FIXUP(bootdataseg)
 
 	/* fix up GDT pointer */
-	addl	$gdt, %eax
-	movl	%eax, gdtarg+2
+	addl	$GDT_RELOC(gdt), %eax
+	movl	%eax, GDT_RELOC(gdtarg+2)
 
 	pop	%dx
 	pop	%ax
@@ -146,13 +157,14 @@ ENTRY(real_to_prot)
 	pushl	%eax
 	cli
 
-	lgdt	%cs:gdtarg		/* Global descriptor table */
+	lgdt	%cs:GDT_RELOC(gdtarg)	/* Global descriptor table */
 
 	movl	%cr0, %eax
 	or	$CR0_PE, %ax
 	movl	%eax, %cr0 		/* Enter 'protected mode' */
 
-	ljmp	$bootcodeseg, $1f	/* Jump into a 32bit segment */
+	/* Jump into a 32bit segment */
+	ljmp	$bootcodeseg, $1f
 1:
 
 	.code32
@@ -161,7 +173,12 @@ 1:
 	mov	%ax, %ds
 	mov	%ax, %es
 	mov	%ax, %ss
-	addl	stkdif, %esp		/* Allow for real %ss != %ds */
+	add	$reloc, %esp	/* Fix up stack pointer */
+	addl	GDT_RELOC(stkdif), %esp	/* Allow for real %ss != %ds */
+
+	movl	4(%esp), %eax	/* Fix up return address */
+	add	$reloc, %eax
+	movl	%eax, 4(%esp)
 
 	popl	%eax
 	ret
@@ -201,6 +218,11 @@ 1:
 ENTRY(prot_to_real)
 	.code32
 	pushl	%eax
+	movl	4(%esp), %eax	/* Fix up return Address */
+	sub	$reloc, %eax
+	movl	%eax, 4(%esp)
+	sub	$reloc, %esp	/* Adjust stack pointer */
+
 #ifdef EPIA_HACK
 	push	%ecx
 	push	$0x10
@@ -234,6 +256,8 @@ 1:
 
 	/* Jump far indirect to load real mode %cs */
 	ljmp	*%cs:toreal
+	#ljmp	$(reloc)>>4,$_RELOC(1f)
+#1:
 xreal:
 	/*
 	 * CPU is now in real mode, load the other segment registers
@@ -246,9 +270,9 @@ xreal:
 	 * If stack was above 64k, 16bit %ss needs to be different from
 	 * 32bit %ss (and the other segment registers).
 	 */
-	mov	stkseg, %ax
+	mov	GDT_RELOC(stkseg), %ax
 	mov	%ax, %ss
-	subl	stkdif, %esp
+	subl	GDT_RELOC(stkdif), %esp
 
 	/* Check we are returning to an address below 64k */
 	push	%bp
@@ -262,7 +286,7 @@ xreal:
 	popl	%eax
 	retl
 
-1:	movw	$3f, %si
+1:	movw	$TEXT_RELOC(3f), %si
 	call	message
 	movl	2/*bp*/ + 4/*eax*/(%bp), %eax		/*  return address */
 	call	dump_eax