# 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