* Updating common/lib * Updating lib/csu * Updating lib/libc * Updating libexec/ld.elf_so * Corrected test on __minix in featuretest to actually follow the meaning of the comment. * Cleaned up _REENTRANT-related defintions. * Disabled -D_REENTRANT for libfetch * Removing some unneeded __NBSD_LIBC defines and tests Change-Id: Ic1394baef74d11b9f86b312f5ff4bbc3cbf72ce2
565 lines
13 KiB
C
565 lines
13 KiB
C
/* $NetBSD: boot2.c,v 1.58 2012/08/04 03:51:27 riastradh Exp $ */
|
|
|
|
/*-
|
|
* Copyright (c) 2008, 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/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"
|
|
|
|
#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;
|
|
daddr_t 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;
|
|
|
|
char *sprint_bootsel(const char *);
|
|
void bootit(const char *, int, int);
|
|
void print_banner(void);
|
|
void boot2(int, uint64_t);
|
|
|
|
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 *);
|
|
#ifdef __minix
|
|
void command_load_mods(char *);
|
|
#endif
|
|
|
|
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 },
|
|
#ifdef __minix
|
|
{ "load_mods", command_load_mods },
|
|
#endif
|
|
{ "multiboot", command_multiboot },
|
|
{ "vesa", command_vesa },
|
|
{ "splash", splash_add },
|
|
{ "rndseed", rnd_add },
|
|
{ "userconf", userconf_add },
|
|
{ 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 */
|
|
#ifndef __minix
|
|
printf("\n"
|
|
">> %s, Revision %s (from NetBSD %s)\n"
|
|
">> Memory: %d/%d k\n",
|
|
bootprog_name, bootprog_rev, bootprog_kernrev,
|
|
getbasemem(), getextmem());
|
|
#else
|
|
printf("\n"
|
|
"--- Welcome to MINIX 3. This is the boot monitor. ---\n"
|
|
"Memory: %d/%d k\n",
|
|
getbasemem(), getextmem());
|
|
#endif
|
|
|
|
#ifndef SMALL
|
|
}
|
|
#endif /* !SMALL */
|
|
}
|
|
|
|
/*
|
|
* Called from the initial entry point boot_start in biosboot.S
|
|
*
|
|
* biosdev: BIOS drive number the system booted from
|
|
* biossector: Sector number of the NetBSD partition
|
|
*/
|
|
void
|
|
boot2(int biosdev, uint64_t biossector)
|
|
{
|
|
extern char twiddle_toggle;
|
|
int currname;
|
|
char c;
|
|
|
|
twiddle_toggle = 1; /* no twiddling until we're ready */
|
|
|
|
initio(boot_params.bp_consdev);
|
|
|
|
#ifdef SUPPORT_PS2
|
|
biosmca();
|
|
#endif
|
|
gateA20();
|
|
|
|
boot_modules_enabled = !(boot_params.bp_flags
|
|
& X86_BP_FLAGS_NOMODULES);
|
|
if (boot_params.bp_flags & X86_BP_FLAGS_RESET_VIDEO)
|
|
biosvideomode();
|
|
|
|
vbe_init();
|
|
|
|
/* need to remember these */
|
|
boot_biosdev = biosdev;
|
|
boot_biossector = biossector;
|
|
|
|
/* try to set default device to what BIOS tells us */
|
|
bios2dev(biosdev, biossector, &default_devname, &default_unit,
|
|
&default_partition);
|
|
|
|
/* if the user types "boot" without filename */
|
|
default_filename = DEFFILENAME;
|
|
|
|
#ifndef SMALL
|
|
if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) {
|
|
parsebootconf(BOOTCONF);
|
|
} else {
|
|
bootconf.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 (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')) {
|
|
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, 0);
|
|
/* since it failed, try compressed bootfile. */
|
|
bootit(names[currname][1], 0, 1);
|
|
}
|
|
|
|
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 {modenum|on|off|enabled|disabled|list}\n"
|
|
"modules {on|off|enabled|disabled}\n"
|
|
"load {path_to_module}\n"
|
|
#ifdef __minix
|
|
"load_mods {path_to_modules}, pattern might be used\n"
|
|
#endif
|
|
"multiboot [xdNx:][filename] [<args>]\n"
|
|
"userconf {command}\n"
|
|
"rndseed {path_to_rndseed_file}\n"
|
|
"help|?\n"
|
|
"quit\n");
|
|
}
|
|
|
|
void
|
|
command_ls(char *arg)
|
|
{
|
|
const char *save = default_filename;
|
|
|
|
default_filename = "/";
|
|
#ifndef __minix
|
|
ls(arg);
|
|
#else
|
|
ls(arg, NULL);
|
|
#endif
|
|
default_filename = save;
|
|
}
|
|
|
|
#ifdef __minix
|
|
void
|
|
command_load_mods(char *arg)
|
|
{
|
|
const char *save = default_filename;
|
|
|
|
default_filename = "/";
|
|
ls(arg, module_add);
|
|
default_filename = save;
|
|
}
|
|
#endif
|
|
|
|
/* ARGSUSED */
|
|
void
|
|
command_quit(char *arg)
|
|
{
|
|
|
|
printf("Exiting...\n");
|
|
delay(1000000);
|
|
reboot();
|
|
/* Note: we shouldn't get to this point! */
|
|
panic("Could not reboot!");
|
|
}
|
|
|
|
void
|
|
command_boot(char *arg)
|
|
{
|
|
char *filename;
|
|
int howto, tell;
|
|
|
|
if (!parseboot(arg, &filename, &howto))
|
|
return;
|
|
|
|
tell = ((howto & AB_VERBOSE) != 0);
|
|
if (filename != NULL) {
|
|
bootit(filename, howto, tell);
|
|
} else {
|
|
int i;
|
|
for (i = 0; i < NUMNAMES; i++) {
|
|
bootit(names[i][0], howto, tell);
|
|
bootit(names[i][1], howto, tell);
|
|
}
|
|
}
|
|
}
|
|
|
|
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");
|
|
}
|
|
|