xref: /minix3/sys/arch/i386/stand/boot/boot2.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: boot2.c,v 1.65 2015/06/11 15:56:53 khorben Exp $	*/
258a2b000SEvgeniy Ivanov 
358a2b000SEvgeniy Ivanov /*-
458a2b000SEvgeniy Ivanov  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
558a2b000SEvgeniy Ivanov  * All rights reserved.
658a2b000SEvgeniy Ivanov  *
758a2b000SEvgeniy Ivanov  * Redistribution and use in source and binary forms, with or without
858a2b000SEvgeniy Ivanov  * modification, are permitted provided that the following conditions
958a2b000SEvgeniy Ivanov  * are met:
1058a2b000SEvgeniy Ivanov  * 1. Redistributions of source code must retain the above copyright
1158a2b000SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer.
1258a2b000SEvgeniy Ivanov  * 2. Redistributions in binary form must reproduce the above copyright
1358a2b000SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer in the
1458a2b000SEvgeniy Ivanov  *    documentation and/or other materials provided with the distribution.
1558a2b000SEvgeniy Ivanov  *
1658a2b000SEvgeniy Ivanov  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1758a2b000SEvgeniy Ivanov  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1858a2b000SEvgeniy Ivanov  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1958a2b000SEvgeniy Ivanov  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2058a2b000SEvgeniy Ivanov  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2158a2b000SEvgeniy Ivanov  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2258a2b000SEvgeniy Ivanov  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2358a2b000SEvgeniy Ivanov  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2458a2b000SEvgeniy Ivanov  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2558a2b000SEvgeniy Ivanov  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2658a2b000SEvgeniy Ivanov  * POSSIBILITY OF SUCH DAMAGE.
2758a2b000SEvgeniy Ivanov  */
2858a2b000SEvgeniy Ivanov 
2958a2b000SEvgeniy Ivanov /*
3058a2b000SEvgeniy Ivanov  * Copyright (c) 2003
3158a2b000SEvgeniy Ivanov  *	David Laight.  All rights reserved
3258a2b000SEvgeniy Ivanov  * Copyright (c) 1996, 1997, 1999
3358a2b000SEvgeniy Ivanov  * 	Matthias Drochner.  All rights reserved.
3458a2b000SEvgeniy Ivanov  * Copyright (c) 1996, 1997
3558a2b000SEvgeniy Ivanov  * 	Perry E. Metzger.  All rights reserved.
3658a2b000SEvgeniy Ivanov  * Copyright (c) 1997
3758a2b000SEvgeniy Ivanov  *	Jason R. Thorpe.  All rights reserved
3858a2b000SEvgeniy Ivanov  *
3958a2b000SEvgeniy Ivanov  * Redistribution and use in source and binary forms, with or without
4058a2b000SEvgeniy Ivanov  * modification, are permitted provided that the following conditions
4158a2b000SEvgeniy Ivanov  * are met:
4258a2b000SEvgeniy Ivanov  * 1. Redistributions of source code must retain the above copyright
4358a2b000SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer.
4458a2b000SEvgeniy Ivanov  * 2. Redistributions in binary form must reproduce the above copyright
4558a2b000SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer in the
4658a2b000SEvgeniy Ivanov  *    documentation and/or other materials provided with the distribution.
4758a2b000SEvgeniy Ivanov  * 3. All advertising materials mentioning features or use of this software
4858a2b000SEvgeniy Ivanov  *    must display the following acknowledgements:
4958a2b000SEvgeniy Ivanov  *	This product includes software developed for the NetBSD Project
5058a2b000SEvgeniy Ivanov  *	by Matthias Drochner.
5158a2b000SEvgeniy Ivanov  *	This product includes software developed for the NetBSD Project
5258a2b000SEvgeniy Ivanov  *	by Perry E. Metzger.
5358a2b000SEvgeniy Ivanov  * 4. The names of the authors may not be used to endorse or promote products
5458a2b000SEvgeniy Ivanov  *    derived from this software without specific prior written permission.
5558a2b000SEvgeniy Ivanov  *
5658a2b000SEvgeniy Ivanov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
5758a2b000SEvgeniy Ivanov  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
5858a2b000SEvgeniy Ivanov  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5958a2b000SEvgeniy Ivanov  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
6058a2b000SEvgeniy Ivanov  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
6158a2b000SEvgeniy Ivanov  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
6258a2b000SEvgeniy Ivanov  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
6358a2b000SEvgeniy Ivanov  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6458a2b000SEvgeniy Ivanov  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
6558a2b000SEvgeniy Ivanov  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6658a2b000SEvgeniy Ivanov  */
6758a2b000SEvgeniy Ivanov 
6858a2b000SEvgeniy Ivanov /* Based on stand/biosboot/main.c */
6958a2b000SEvgeniy Ivanov 
7058a2b000SEvgeniy Ivanov #include <sys/types.h>
7158a2b000SEvgeniy Ivanov #include <sys/reboot.h>
7258a2b000SEvgeniy Ivanov #include <sys/bootblock.h>
7358a2b000SEvgeniy Ivanov 
7458a2b000SEvgeniy Ivanov #include <lib/libsa/stand.h>
75*0a6a1f1dSLionel Sambuc #include <lib/libsa/bootcfg.h>
7658a2b000SEvgeniy Ivanov #include <lib/libsa/ufs.h>
7758a2b000SEvgeniy Ivanov #include <lib/libkern/libkern.h>
7858a2b000SEvgeniy Ivanov 
7958a2b000SEvgeniy Ivanov #include <libi386.h>
8058a2b000SEvgeniy Ivanov #include <bootmod.h>
8158a2b000SEvgeniy Ivanov #include <bootmenu.h>
8258a2b000SEvgeniy Ivanov #include <vbe.h>
8358a2b000SEvgeniy Ivanov #include "devopen.h"
8458a2b000SEvgeniy Ivanov 
8558a2b000SEvgeniy Ivanov #ifdef SUPPORT_PS2
8658a2b000SEvgeniy Ivanov #include <biosmca.h>
8758a2b000SEvgeniy Ivanov #endif
8858a2b000SEvgeniy Ivanov 
8958a2b000SEvgeniy Ivanov extern struct x86_boot_params boot_params;
9058a2b000SEvgeniy Ivanov 
9158a2b000SEvgeniy Ivanov extern	const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
9258a2b000SEvgeniy Ivanov 
9358a2b000SEvgeniy Ivanov int errno;
9458a2b000SEvgeniy Ivanov 
9558a2b000SEvgeniy Ivanov int boot_biosdev;
9658a2b000SEvgeniy Ivanov daddr_t boot_biossector;
9758a2b000SEvgeniy Ivanov 
9858a2b000SEvgeniy Ivanov static const char * const names[][2] = {
9958a2b000SEvgeniy Ivanov 	{ "netbsd", "netbsd.gz" },
10058a2b000SEvgeniy Ivanov 	{ "onetbsd", "onetbsd.gz" },
10158a2b000SEvgeniy Ivanov 	{ "netbsd.old", "netbsd.old.gz" },
10258a2b000SEvgeniy Ivanov };
10358a2b000SEvgeniy Ivanov 
10458a2b000SEvgeniy Ivanov #define NUMNAMES (sizeof(names)/sizeof(names[0]))
10558a2b000SEvgeniy Ivanov #define DEFFILENAME names[0][0]
10658a2b000SEvgeniy Ivanov 
10758a2b000SEvgeniy Ivanov #define MAXDEVNAME 16
10858a2b000SEvgeniy Ivanov 
10958a2b000SEvgeniy Ivanov static char *default_devname;
11058a2b000SEvgeniy Ivanov static int default_unit, default_partition;
11158a2b000SEvgeniy Ivanov static const char *default_filename;
11258a2b000SEvgeniy Ivanov 
11358a2b000SEvgeniy Ivanov char *sprint_bootsel(const char *);
114*0a6a1f1dSLionel Sambuc static void bootit(const char *, int);
11558a2b000SEvgeniy Ivanov void print_banner(void);
11658a2b000SEvgeniy Ivanov void boot2(int, uint64_t);
11758a2b000SEvgeniy Ivanov 
11858a2b000SEvgeniy Ivanov void	command_help(char *);
119*0a6a1f1dSLionel Sambuc #if LIBSA_ENABLE_LS_OP
12058a2b000SEvgeniy Ivanov void	command_ls(char *);
121*0a6a1f1dSLionel Sambuc #endif
12258a2b000SEvgeniy Ivanov void	command_quit(char *);
12358a2b000SEvgeniy Ivanov void	command_boot(char *);
12458a2b000SEvgeniy Ivanov void	command_dev(char *);
12558a2b000SEvgeniy Ivanov void	command_consdev(char *);
12684d9c625SLionel Sambuc #ifndef SMALL
12784d9c625SLionel Sambuc void	command_menu(char *);
12884d9c625SLionel Sambuc #endif
12958a2b000SEvgeniy Ivanov void	command_modules(char *);
13058a2b000SEvgeniy Ivanov void	command_multiboot(char *);
131*0a6a1f1dSLionel Sambuc #if defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP
13260223321SEvgeniy Ivanov void	command_load_mods(char *);
133*0a6a1f1dSLionel Sambuc #endif /* defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP */
13458a2b000SEvgeniy Ivanov 
13558a2b000SEvgeniy Ivanov const struct bootblk_command commands[] = {
13658a2b000SEvgeniy Ivanov 	{ "help",	command_help },
13758a2b000SEvgeniy Ivanov 	{ "?",		command_help },
138*0a6a1f1dSLionel Sambuc #if LIBSA_ENABLE_LS_OP
13958a2b000SEvgeniy Ivanov 	{ "ls",		command_ls },
140*0a6a1f1dSLionel Sambuc #endif
14158a2b000SEvgeniy Ivanov 	{ "quit",	command_quit },
14258a2b000SEvgeniy Ivanov 	{ "boot",	command_boot },
14358a2b000SEvgeniy Ivanov 	{ "dev",	command_dev },
14458a2b000SEvgeniy Ivanov 	{ "consdev",	command_consdev },
14584d9c625SLionel Sambuc #ifndef SMALL
14684d9c625SLionel Sambuc 	{ "menu",	command_menu },
14784d9c625SLionel Sambuc #endif
14858a2b000SEvgeniy Ivanov 	{ "modules",	command_modules },
14958a2b000SEvgeniy Ivanov 	{ "load",	module_add },
150*0a6a1f1dSLionel Sambuc #if defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP
15160223321SEvgeniy Ivanov 	{ "load_mods",  command_load_mods },
152*0a6a1f1dSLionel Sambuc #endif /* defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP */
15358a2b000SEvgeniy Ivanov 	{ "multiboot",	command_multiboot },
15458a2b000SEvgeniy Ivanov 	{ "vesa",	command_vesa },
15558a2b000SEvgeniy Ivanov 	{ "splash",	splash_add },
15658a2b000SEvgeniy Ivanov 	{ "rndseed",	rnd_add },
15784d9c625SLionel Sambuc 	{ "fs",		fs_add },
15858a2b000SEvgeniy Ivanov 	{ "userconf",	userconf_add },
15958a2b000SEvgeniy Ivanov 	{ NULL,		NULL },
16058a2b000SEvgeniy Ivanov };
16158a2b000SEvgeniy Ivanov 
16258a2b000SEvgeniy Ivanov int
parsebootfile(const char * fname,char ** fsname,char ** devname,int * unit,int * partition,const char ** file)16358a2b000SEvgeniy Ivanov parsebootfile(const char *fname, char **fsname, char **devname,
16458a2b000SEvgeniy Ivanov 	      int *unit, int *partition, const char **file)
16558a2b000SEvgeniy Ivanov {
16658a2b000SEvgeniy Ivanov 	const char *col;
16758a2b000SEvgeniy Ivanov 
16858a2b000SEvgeniy Ivanov 	*fsname = "ufs";
16958a2b000SEvgeniy Ivanov 	*devname = default_devname;
17058a2b000SEvgeniy Ivanov 	*unit = default_unit;
17158a2b000SEvgeniy Ivanov 	*partition = default_partition;
17258a2b000SEvgeniy Ivanov 	*file = default_filename;
17358a2b000SEvgeniy Ivanov 
17458a2b000SEvgeniy Ivanov 	if (fname == NULL)
17558a2b000SEvgeniy Ivanov 		return 0;
17658a2b000SEvgeniy Ivanov 
17758a2b000SEvgeniy Ivanov 	if ((col = strchr(fname, ':')) != NULL) {	/* device given */
17858a2b000SEvgeniy Ivanov 		static char savedevname[MAXDEVNAME+1];
17958a2b000SEvgeniy Ivanov 		int devlen;
18058a2b000SEvgeniy Ivanov 		int u = 0, p = 0;
18158a2b000SEvgeniy Ivanov 		int i = 0;
18258a2b000SEvgeniy Ivanov 
18358a2b000SEvgeniy Ivanov 		devlen = col - fname;
18458a2b000SEvgeniy Ivanov 		if (devlen > MAXDEVNAME)
18558a2b000SEvgeniy Ivanov 			return EINVAL;
18658a2b000SEvgeniy Ivanov 
18758a2b000SEvgeniy Ivanov #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
18858a2b000SEvgeniy Ivanov 		if (!isvalidname(fname[i]))
18958a2b000SEvgeniy Ivanov 			return EINVAL;
19058a2b000SEvgeniy Ivanov 		do {
19158a2b000SEvgeniy Ivanov 			savedevname[i] = fname[i];
19258a2b000SEvgeniy Ivanov 			i++;
19358a2b000SEvgeniy Ivanov 		} while (isvalidname(fname[i]));
19458a2b000SEvgeniy Ivanov 		savedevname[i] = '\0';
19558a2b000SEvgeniy Ivanov 
19658a2b000SEvgeniy Ivanov #define isnum(c) ((c) >= '0' && (c) <= '9')
19758a2b000SEvgeniy Ivanov 		if (i < devlen) {
19858a2b000SEvgeniy Ivanov 			if (!isnum(fname[i]))
19958a2b000SEvgeniy Ivanov 				return EUNIT;
20058a2b000SEvgeniy Ivanov 			do {
20158a2b000SEvgeniy Ivanov 				u *= 10;
20258a2b000SEvgeniy Ivanov 				u += fname[i++] - '0';
20358a2b000SEvgeniy Ivanov 			} while (isnum(fname[i]));
20458a2b000SEvgeniy Ivanov 		}
20558a2b000SEvgeniy Ivanov 
20658a2b000SEvgeniy Ivanov #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
20758a2b000SEvgeniy Ivanov 		if (i < devlen) {
20858a2b000SEvgeniy Ivanov 			if (!isvalidpart(fname[i]))
20958a2b000SEvgeniy Ivanov 				return EPART;
21058a2b000SEvgeniy Ivanov 			p = fname[i++] - 'a';
21158a2b000SEvgeniy Ivanov 		}
21258a2b000SEvgeniy Ivanov 
21358a2b000SEvgeniy Ivanov 		if (i != devlen)
21458a2b000SEvgeniy Ivanov 			return ENXIO;
21558a2b000SEvgeniy Ivanov 
21658a2b000SEvgeniy Ivanov 		*devname = savedevname;
21758a2b000SEvgeniy Ivanov 		*unit = u;
21858a2b000SEvgeniy Ivanov 		*partition = p;
21958a2b000SEvgeniy Ivanov 		fname = col + 1;
22058a2b000SEvgeniy Ivanov 	}
22158a2b000SEvgeniy Ivanov 
22258a2b000SEvgeniy Ivanov 	if (*fname)
22358a2b000SEvgeniy Ivanov 		*file = fname;
22458a2b000SEvgeniy Ivanov 
22558a2b000SEvgeniy Ivanov 	return 0;
22658a2b000SEvgeniy Ivanov }
22758a2b000SEvgeniy Ivanov 
22858a2b000SEvgeniy Ivanov char *
sprint_bootsel(const char * filename)22958a2b000SEvgeniy Ivanov sprint_bootsel(const char *filename)
23058a2b000SEvgeniy Ivanov {
23158a2b000SEvgeniy Ivanov 	char *fsname, *devname;
23258a2b000SEvgeniy Ivanov 	int unit, partition;
23358a2b000SEvgeniy Ivanov 	const char *file;
23458a2b000SEvgeniy Ivanov 	static char buf[80];
23558a2b000SEvgeniy Ivanov 
23658a2b000SEvgeniy Ivanov 	if (parsebootfile(filename, &fsname, &devname, &unit,
23758a2b000SEvgeniy Ivanov 			  &partition, &file) == 0) {
238*0a6a1f1dSLionel Sambuc 		snprintf(buf, sizeof(buf), "%s%d%c:%s", devname, unit,
239*0a6a1f1dSLionel Sambuc 		    'a' + partition, file);
24058a2b000SEvgeniy Ivanov 		return buf;
24158a2b000SEvgeniy Ivanov 	}
24258a2b000SEvgeniy Ivanov 	return "(invalid)";
24358a2b000SEvgeniy Ivanov }
24458a2b000SEvgeniy Ivanov 
24558a2b000SEvgeniy Ivanov static void
clearit(void)24658a2b000SEvgeniy Ivanov clearit(void)
24758a2b000SEvgeniy Ivanov {
24858a2b000SEvgeniy Ivanov 
249*0a6a1f1dSLionel Sambuc 	if (bootcfg_info.clear)
25058a2b000SEvgeniy Ivanov 		clear_pc_screen();
25158a2b000SEvgeniy Ivanov }
25258a2b000SEvgeniy Ivanov 
253*0a6a1f1dSLionel Sambuc static void
bootit(const char * filename,int howto)254*0a6a1f1dSLionel Sambuc bootit(const char *filename, int howto)
25558a2b000SEvgeniy Ivanov {
256*0a6a1f1dSLionel Sambuc 	if (howto & AB_VERBOSE)
257*0a6a1f1dSLionel Sambuc 		printf("booting %s (howto 0x%x)\n", sprint_bootsel(filename),
258*0a6a1f1dSLionel Sambuc 		    howto);
25958a2b000SEvgeniy Ivanov 
26058a2b000SEvgeniy Ivanov 	if (exec_netbsd(filename, 0, howto, boot_biosdev < 0x80, clearit) < 0)
26158a2b000SEvgeniy Ivanov 		printf("boot: %s: %s\n", sprint_bootsel(filename),
26258a2b000SEvgeniy Ivanov 		       strerror(errno));
26358a2b000SEvgeniy Ivanov 	else
26458a2b000SEvgeniy Ivanov 		printf("boot returned\n");
26558a2b000SEvgeniy Ivanov }
26658a2b000SEvgeniy Ivanov 
26758a2b000SEvgeniy Ivanov void
print_banner(void)26858a2b000SEvgeniy Ivanov print_banner(void)
26958a2b000SEvgeniy Ivanov {
27058a2b000SEvgeniy Ivanov 
27158a2b000SEvgeniy Ivanov 	clearit();
27258a2b000SEvgeniy Ivanov #ifndef SMALL
27358a2b000SEvgeniy Ivanov 	int n;
274*0a6a1f1dSLionel Sambuc 	if (bootcfg_info.banner[0]) {
275*0a6a1f1dSLionel Sambuc 		for (n = 0; bootcfg_info.banner[n]
276*0a6a1f1dSLionel Sambuc 		    && n < BOOTCFG_MAXBANNER; n++)
277*0a6a1f1dSLionel Sambuc 			printf("%s\n", bootcfg_info.banner[n]);
27858a2b000SEvgeniy Ivanov 	} else {
27958a2b000SEvgeniy Ivanov #endif /* !SMALL */
280*0a6a1f1dSLionel Sambuc #if !defined(__minix)
28158a2b000SEvgeniy Ivanov 		printf("\n"
28258a2b000SEvgeniy Ivanov 		       ">> %s, Revision %s (from NetBSD %s)\n"
28358a2b000SEvgeniy Ivanov 		       ">> Memory: %d/%d k\n",
28458a2b000SEvgeniy Ivanov 		       bootprog_name, bootprog_rev, bootprog_kernrev,
28558a2b000SEvgeniy Ivanov 		       getbasemem(), getextmem());
28660223321SEvgeniy Ivanov #else
28760223321SEvgeniy Ivanov 		printf("\n"
28860223321SEvgeniy Ivanov 			"--- Welcome to MINIX 3. This is the boot monitor. ---\n"
28960223321SEvgeniy Ivanov 			"Memory: %d/%d k\n",
29060223321SEvgeniy Ivanov 			getbasemem(), getextmem());
291*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
29258a2b000SEvgeniy Ivanov 
29358a2b000SEvgeniy Ivanov #ifndef SMALL
29458a2b000SEvgeniy Ivanov 	}
29558a2b000SEvgeniy Ivanov #endif /* !SMALL */
29658a2b000SEvgeniy Ivanov }
29758a2b000SEvgeniy Ivanov 
29858a2b000SEvgeniy Ivanov /*
29958a2b000SEvgeniy Ivanov  * Called from the initial entry point boot_start in biosboot.S
30058a2b000SEvgeniy Ivanov  *
30158a2b000SEvgeniy Ivanov  * biosdev: BIOS drive number the system booted from
30258a2b000SEvgeniy Ivanov  * biossector: Sector number of the NetBSD partition
30358a2b000SEvgeniy Ivanov  */
30458a2b000SEvgeniy Ivanov void
boot2(int biosdev,uint64_t biossector)30558a2b000SEvgeniy Ivanov boot2(int biosdev, uint64_t biossector)
30658a2b000SEvgeniy Ivanov {
30758a2b000SEvgeniy Ivanov 	extern char twiddle_toggle;
30858a2b000SEvgeniy Ivanov 	int currname;
30958a2b000SEvgeniy Ivanov 	char c;
31058a2b000SEvgeniy Ivanov 
31158a2b000SEvgeniy Ivanov 	twiddle_toggle = 1;	/* no twiddling until we're ready */
31258a2b000SEvgeniy Ivanov 
31358a2b000SEvgeniy Ivanov 	initio(boot_params.bp_consdev);
31458a2b000SEvgeniy Ivanov 
31558a2b000SEvgeniy Ivanov #ifdef SUPPORT_PS2
31658a2b000SEvgeniy Ivanov 	biosmca();
31758a2b000SEvgeniy Ivanov #endif
31858a2b000SEvgeniy Ivanov 	gateA20();
31958a2b000SEvgeniy Ivanov 
32058a2b000SEvgeniy Ivanov 	boot_modules_enabled = !(boot_params.bp_flags
32158a2b000SEvgeniy Ivanov 				 & X86_BP_FLAGS_NOMODULES);
32258a2b000SEvgeniy Ivanov 	if (boot_params.bp_flags & X86_BP_FLAGS_RESET_VIDEO)
32358a2b000SEvgeniy Ivanov 		biosvideomode();
32458a2b000SEvgeniy Ivanov 
32558a2b000SEvgeniy Ivanov 	vbe_init();
32658a2b000SEvgeniy Ivanov 
32758a2b000SEvgeniy Ivanov 	/* need to remember these */
32858a2b000SEvgeniy Ivanov 	boot_biosdev = biosdev;
32958a2b000SEvgeniy Ivanov 	boot_biossector = biossector;
33058a2b000SEvgeniy Ivanov 
33158a2b000SEvgeniy Ivanov 	/* try to set default device to what BIOS tells us */
33258a2b000SEvgeniy Ivanov 	bios2dev(biosdev, biossector, &default_devname, &default_unit,
33358a2b000SEvgeniy Ivanov 		 &default_partition);
33458a2b000SEvgeniy Ivanov 
33558a2b000SEvgeniy Ivanov 	/* if the user types "boot" without filename */
33658a2b000SEvgeniy Ivanov 	default_filename = DEFFILENAME;
33758a2b000SEvgeniy Ivanov 
33858a2b000SEvgeniy Ivanov #ifndef SMALL
33958a2b000SEvgeniy Ivanov 	if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) {
340*0a6a1f1dSLionel Sambuc 		parsebootconf(BOOTCFG_FILENAME);
34158a2b000SEvgeniy Ivanov 	} else {
342*0a6a1f1dSLionel Sambuc 		bootcfg_info.timeout = boot_params.bp_timeout;
34358a2b000SEvgeniy Ivanov 	}
34458a2b000SEvgeniy Ivanov 
34558a2b000SEvgeniy Ivanov 
34658a2b000SEvgeniy Ivanov 	/*
34758a2b000SEvgeniy Ivanov 	 * If console set in boot.cfg, switch to it.
34858a2b000SEvgeniy Ivanov 	 * This will print the banner, so we don't need to explicitly do it
34958a2b000SEvgeniy Ivanov 	 */
350*0a6a1f1dSLionel Sambuc 	if (bootcfg_info.consdev)
351*0a6a1f1dSLionel Sambuc 		command_consdev(bootcfg_info.consdev);
35258a2b000SEvgeniy Ivanov 	else
35358a2b000SEvgeniy Ivanov 		print_banner();
35458a2b000SEvgeniy Ivanov 
35558a2b000SEvgeniy Ivanov 	/* Display the menu, if applicable */
35658a2b000SEvgeniy Ivanov 	twiddle_toggle = 0;
357*0a6a1f1dSLionel Sambuc 	if (bootcfg_info.nummenu > 0) {
35858a2b000SEvgeniy Ivanov 		/* Does not return */
35958a2b000SEvgeniy Ivanov 		doboottypemenu();
36058a2b000SEvgeniy Ivanov 	}
36158a2b000SEvgeniy Ivanov 
36258a2b000SEvgeniy Ivanov #else
36358a2b000SEvgeniy Ivanov 	twiddle_toggle = 0;
36458a2b000SEvgeniy Ivanov 	print_banner();
36558a2b000SEvgeniy Ivanov #endif
36658a2b000SEvgeniy Ivanov 
36758a2b000SEvgeniy Ivanov 	printf("Press return to boot now, any other key for boot menu\n");
36858a2b000SEvgeniy Ivanov 	for (currname = 0; currname < NUMNAMES; currname++) {
36958a2b000SEvgeniy Ivanov 		printf("booting %s - starting in ",
37058a2b000SEvgeniy Ivanov 		       sprint_bootsel(names[currname][0]));
37158a2b000SEvgeniy Ivanov 
37258a2b000SEvgeniy Ivanov #ifdef SMALL
37358a2b000SEvgeniy Ivanov 		c = awaitkey(boot_params.bp_timeout, 1);
37458a2b000SEvgeniy Ivanov #else
375*0a6a1f1dSLionel Sambuc 		c = awaitkey((bootcfg_info.timeout < 0) ? 0
376*0a6a1f1dSLionel Sambuc 		    : bootcfg_info.timeout, 1);
37758a2b000SEvgeniy Ivanov #endif
37858a2b000SEvgeniy Ivanov 		if ((c != '\r') && (c != '\n') && (c != '\0')) {
37958a2b000SEvgeniy Ivanov 		    if ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0) {
38058a2b000SEvgeniy Ivanov 			/* do NOT ask for password */
38158a2b000SEvgeniy Ivanov 			bootmenu(); /* does not return */
38258a2b000SEvgeniy Ivanov 		    } else {
38358a2b000SEvgeniy Ivanov 			/* DO ask for password */
38458a2b000SEvgeniy Ivanov 			if (check_password((char *)boot_params.bp_password)) {
38558a2b000SEvgeniy Ivanov 			    /* password ok */
38658a2b000SEvgeniy Ivanov 			    printf("type \"?\" or \"help\" for help.\n");
38758a2b000SEvgeniy Ivanov 			    bootmenu(); /* does not return */
38858a2b000SEvgeniy Ivanov 			} else {
38958a2b000SEvgeniy Ivanov 			    /* bad password */
39058a2b000SEvgeniy Ivanov 			    printf("Wrong password.\n");
39158a2b000SEvgeniy Ivanov 			    currname = 0;
39258a2b000SEvgeniy Ivanov 			    continue;
39358a2b000SEvgeniy Ivanov 			}
39458a2b000SEvgeniy Ivanov 		    }
39558a2b000SEvgeniy Ivanov 		}
39658a2b000SEvgeniy Ivanov 
39758a2b000SEvgeniy Ivanov 		/*
39858a2b000SEvgeniy Ivanov 		 * try pairs of names[] entries, foo and foo.gz
39958a2b000SEvgeniy Ivanov 		 */
40058a2b000SEvgeniy Ivanov 		/* don't print "booting..." again */
401*0a6a1f1dSLionel Sambuc 		bootit(names[currname][0], 0);
40258a2b000SEvgeniy Ivanov 		/* since it failed, try compressed bootfile. */
403*0a6a1f1dSLionel Sambuc 		bootit(names[currname][1], AB_VERBOSE);
40458a2b000SEvgeniy Ivanov 	}
40558a2b000SEvgeniy Ivanov 
40658a2b000SEvgeniy Ivanov 	bootmenu();	/* does not return */
40758a2b000SEvgeniy Ivanov }
40858a2b000SEvgeniy Ivanov 
40958a2b000SEvgeniy Ivanov /* ARGSUSED */
41058a2b000SEvgeniy Ivanov void
command_help(char * arg)41158a2b000SEvgeniy Ivanov command_help(char *arg)
41258a2b000SEvgeniy Ivanov {
41358a2b000SEvgeniy Ivanov 
41458a2b000SEvgeniy Ivanov 	printf("commands are:\n"
41558a2b000SEvgeniy Ivanov 	       "boot [xdNx:][filename] [-12acdqsvxz]\n"
41658a2b000SEvgeniy Ivanov 	       "     (ex. \"hd0a:netbsd.old -s\"\n"
417*0a6a1f1dSLionel Sambuc #if LIBSA_ENABLE_LS_OP
41858a2b000SEvgeniy Ivanov 	       "ls [path]\n"
419*0a6a1f1dSLionel Sambuc #endif
42058a2b000SEvgeniy Ivanov 	       "dev xd[N[x]]:\n"
42158a2b000SEvgeniy Ivanov 	       "consdev {pc|com[0123]|com[0123]kbd|auto}\n"
42258a2b000SEvgeniy Ivanov 	       "vesa {modenum|on|off|enabled|disabled|list}\n"
42384d9c625SLionel Sambuc #ifndef SMALL
42484d9c625SLionel Sambuc 	       "menu (reenters boot menu, if defined in boot.cfg)\n"
42584d9c625SLionel Sambuc #endif
42658a2b000SEvgeniy Ivanov 	       "modules {on|off|enabled|disabled}\n"
42758a2b000SEvgeniy Ivanov 	       "load {path_to_module}\n"
428*0a6a1f1dSLionel Sambuc #if defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP
42960223321SEvgeniy Ivanov 	       "load_mods {path_to_modules}, pattern might be used\n"
430*0a6a1f1dSLionel Sambuc #endif /*defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP */
43158a2b000SEvgeniy Ivanov 	       "multiboot [xdNx:][filename] [<args>]\n"
432*0a6a1f1dSLionel Sambuc 	       "splash {path_to_image_file}\n"
43358a2b000SEvgeniy Ivanov 	       "userconf {command}\n"
43458a2b000SEvgeniy Ivanov 	       "rndseed {path_to_rndseed_file}\n"
43558a2b000SEvgeniy Ivanov 	       "help|?\n"
43658a2b000SEvgeniy Ivanov 	       "quit\n");
43758a2b000SEvgeniy Ivanov }
43858a2b000SEvgeniy Ivanov 
439*0a6a1f1dSLionel Sambuc #if LIBSA_ENABLE_LS_OP
44058a2b000SEvgeniy Ivanov void
command_ls(char * arg)44158a2b000SEvgeniy Ivanov command_ls(char *arg)
44258a2b000SEvgeniy Ivanov {
44358a2b000SEvgeniy Ivanov 	const char *save = default_filename;
44458a2b000SEvgeniy Ivanov 
44558a2b000SEvgeniy Ivanov 	default_filename = "/";
446f14fb602SLionel Sambuc 	ls(arg);
44760223321SEvgeniy Ivanov 	default_filename = save;
44860223321SEvgeniy Ivanov }
449*0a6a1f1dSLionel Sambuc #endif
45060223321SEvgeniy Ivanov 
451*0a6a1f1dSLionel Sambuc #if defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP
45260223321SEvgeniy Ivanov void
command_load_mods(char * arg)45360223321SEvgeniy Ivanov command_load_mods(char *arg)
45460223321SEvgeniy Ivanov {
45560223321SEvgeniy Ivanov 	const char *save = default_filename;
45660223321SEvgeniy Ivanov 
45760223321SEvgeniy Ivanov 	default_filename = "/";
458*0a6a1f1dSLionel Sambuc 	load_mods(arg, module_add);
45958a2b000SEvgeniy Ivanov 	default_filename = save;
46058a2b000SEvgeniy Ivanov }
461*0a6a1f1dSLionel Sambuc #endif /* defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP */
46258a2b000SEvgeniy Ivanov 
46358a2b000SEvgeniy Ivanov /* ARGSUSED */
46458a2b000SEvgeniy Ivanov void
command_quit(char * arg)46558a2b000SEvgeniy Ivanov command_quit(char *arg)
46658a2b000SEvgeniy Ivanov {
46758a2b000SEvgeniy Ivanov 
46858a2b000SEvgeniy Ivanov 	printf("Exiting...\n");
46958a2b000SEvgeniy Ivanov 	delay(1000000);
47058a2b000SEvgeniy Ivanov 	reboot();
47158a2b000SEvgeniy Ivanov 	/* Note: we shouldn't get to this point! */
47258a2b000SEvgeniy Ivanov 	panic("Could not reboot!");
47358a2b000SEvgeniy Ivanov }
47458a2b000SEvgeniy Ivanov 
47558a2b000SEvgeniy Ivanov void
command_boot(char * arg)47658a2b000SEvgeniy Ivanov command_boot(char *arg)
47758a2b000SEvgeniy Ivanov {
47858a2b000SEvgeniy Ivanov 	char *filename;
479*0a6a1f1dSLionel Sambuc 	int howto;
48058a2b000SEvgeniy Ivanov 
481f14fb602SLionel Sambuc 	if (!parseboot(arg, &filename, &howto))
482f14fb602SLionel Sambuc 		return;
483f14fb602SLionel Sambuc 
484f14fb602SLionel Sambuc 	if (filename != NULL) {
485*0a6a1f1dSLionel Sambuc 		bootit(filename, howto);
486f14fb602SLionel Sambuc 	} else {
487f14fb602SLionel Sambuc 		int i;
48884d9c625SLionel Sambuc 
48984d9c625SLionel Sambuc #ifndef SMALL
490*0a6a1f1dSLionel Sambuc 		if (howto == 0)
49184d9c625SLionel Sambuc 			bootdefault();
49284d9c625SLionel Sambuc #endif
493f14fb602SLionel Sambuc 		for (i = 0; i < NUMNAMES; i++) {
494*0a6a1f1dSLionel Sambuc 			bootit(names[i][0], howto);
495*0a6a1f1dSLionel Sambuc 			bootit(names[i][1], howto);
496f14fb602SLionel Sambuc 		}
497f14fb602SLionel Sambuc 	}
49858a2b000SEvgeniy Ivanov }
49958a2b000SEvgeniy Ivanov 
50058a2b000SEvgeniy Ivanov void
command_dev(char * arg)50158a2b000SEvgeniy Ivanov command_dev(char *arg)
50258a2b000SEvgeniy Ivanov {
50358a2b000SEvgeniy Ivanov 	static char savedevname[MAXDEVNAME + 1];
50458a2b000SEvgeniy Ivanov 	char *fsname, *devname;
50558a2b000SEvgeniy Ivanov 	const char *file; /* dummy */
50658a2b000SEvgeniy Ivanov 
50758a2b000SEvgeniy Ivanov 	if (*arg == '\0') {
50858a2b000SEvgeniy Ivanov 		biosdisk_probe();
50958a2b000SEvgeniy Ivanov 		printf("default %s%d%c\n", default_devname, default_unit,
51058a2b000SEvgeniy Ivanov 		       'a' + default_partition);
51158a2b000SEvgeniy Ivanov 		return;
51258a2b000SEvgeniy Ivanov 	}
51358a2b000SEvgeniy Ivanov 
51458a2b000SEvgeniy Ivanov 	if (strchr(arg, ':') == NULL ||
51558a2b000SEvgeniy Ivanov 	    parsebootfile(arg, &fsname, &devname, &default_unit,
51658a2b000SEvgeniy Ivanov 			  &default_partition, &file)) {
51758a2b000SEvgeniy Ivanov 		command_help(NULL);
51858a2b000SEvgeniy Ivanov 		return;
51958a2b000SEvgeniy Ivanov 	}
52058a2b000SEvgeniy Ivanov 
52158a2b000SEvgeniy Ivanov 	/* put to own static storage */
52258a2b000SEvgeniy Ivanov 	strncpy(savedevname, devname, MAXDEVNAME + 1);
52358a2b000SEvgeniy Ivanov 	default_devname = savedevname;
52458a2b000SEvgeniy Ivanov }
52558a2b000SEvgeniy Ivanov 
52658a2b000SEvgeniy Ivanov static const struct cons_devs {
52758a2b000SEvgeniy Ivanov 	const char	*name;
52858a2b000SEvgeniy Ivanov 	u_int		tag;
52958a2b000SEvgeniy Ivanov } cons_devs[] = {
53058a2b000SEvgeniy Ivanov 	{ "pc",		CONSDEV_PC },
53158a2b000SEvgeniy Ivanov 	{ "com0",	CONSDEV_COM0 },
53258a2b000SEvgeniy Ivanov 	{ "com1",	CONSDEV_COM1 },
53358a2b000SEvgeniy Ivanov 	{ "com2",	CONSDEV_COM2 },
53458a2b000SEvgeniy Ivanov 	{ "com3",	CONSDEV_COM3 },
53558a2b000SEvgeniy Ivanov 	{ "com0kbd",	CONSDEV_COM0KBD },
53658a2b000SEvgeniy Ivanov 	{ "com1kbd",	CONSDEV_COM1KBD },
53758a2b000SEvgeniy Ivanov 	{ "com2kbd",	CONSDEV_COM2KBD },
53858a2b000SEvgeniy Ivanov 	{ "com3kbd",	CONSDEV_COM3KBD },
53958a2b000SEvgeniy Ivanov 	{ "auto",	CONSDEV_AUTO },
54058a2b000SEvgeniy Ivanov 	{ NULL,		0 }
54158a2b000SEvgeniy Ivanov };
54258a2b000SEvgeniy Ivanov 
54358a2b000SEvgeniy Ivanov void
command_consdev(char * arg)54458a2b000SEvgeniy Ivanov command_consdev(char *arg)
54558a2b000SEvgeniy Ivanov {
54658a2b000SEvgeniy Ivanov 	const struct cons_devs *cdp;
54758a2b000SEvgeniy Ivanov 
54858a2b000SEvgeniy Ivanov 	for (cdp = cons_devs; cdp->name; cdp++) {
54958a2b000SEvgeniy Ivanov 		if (strcmp(arg, cdp->name) == 0) {
55058a2b000SEvgeniy Ivanov 			initio(cdp->tag);
55158a2b000SEvgeniy Ivanov 			print_banner();
55258a2b000SEvgeniy Ivanov 			return;
55358a2b000SEvgeniy Ivanov 		}
55458a2b000SEvgeniy Ivanov 	}
55558a2b000SEvgeniy Ivanov 	printf("invalid console device.\n");
55658a2b000SEvgeniy Ivanov }
55758a2b000SEvgeniy Ivanov 
55884d9c625SLionel Sambuc #ifndef SMALL
55984d9c625SLionel Sambuc /* ARGSUSED */
56084d9c625SLionel Sambuc void
command_menu(char * arg)56184d9c625SLionel Sambuc command_menu(char *arg)
56284d9c625SLionel Sambuc {
56384d9c625SLionel Sambuc 
564*0a6a1f1dSLionel Sambuc 	if (bootcfg_info.nummenu > 0) {
56584d9c625SLionel Sambuc 		/* Does not return */
56684d9c625SLionel Sambuc 		doboottypemenu();
56784d9c625SLionel Sambuc 	} else {
56884d9c625SLionel Sambuc 		printf("No menu defined in boot.cfg\n");
56984d9c625SLionel Sambuc 	}
57084d9c625SLionel Sambuc }
57184d9c625SLionel Sambuc #endif /* !SMALL */
57284d9c625SLionel Sambuc 
57358a2b000SEvgeniy Ivanov void
command_modules(char * arg)57458a2b000SEvgeniy Ivanov command_modules(char *arg)
57558a2b000SEvgeniy Ivanov {
57658a2b000SEvgeniy Ivanov 
57758a2b000SEvgeniy Ivanov 	if (strcmp(arg, "enabled") == 0 ||
57858a2b000SEvgeniy Ivanov 	    strcmp(arg, "on") == 0)
57958a2b000SEvgeniy Ivanov 		boot_modules_enabled = true;
58058a2b000SEvgeniy Ivanov 	else if (strcmp(arg, "disabled") == 0 ||
58158a2b000SEvgeniy Ivanov 	    strcmp(arg, "off") == 0)
58258a2b000SEvgeniy Ivanov 		boot_modules_enabled = false;
58358a2b000SEvgeniy Ivanov 	else
58458a2b000SEvgeniy Ivanov 		printf("invalid flag, must be 'enabled' or 'disabled'.\n");
58558a2b000SEvgeniy Ivanov }
58658a2b000SEvgeniy Ivanov 
58758a2b000SEvgeniy Ivanov void
command_multiboot(char * arg)58858a2b000SEvgeniy Ivanov command_multiboot(char *arg)
58958a2b000SEvgeniy Ivanov {
59058a2b000SEvgeniy Ivanov 	char *filename;
59158a2b000SEvgeniy Ivanov 
59258a2b000SEvgeniy Ivanov 	filename = arg;
59358a2b000SEvgeniy Ivanov 	if (exec_multiboot(filename, gettrailer(arg)) < 0)
59458a2b000SEvgeniy Ivanov 		printf("multiboot: %s: %s\n", sprint_bootsel(filename),
59558a2b000SEvgeniy Ivanov 		       strerror(errno));
59658a2b000SEvgeniy Ivanov 	else
59758a2b000SEvgeniy Ivanov 		printf("boot returned\n");
59858a2b000SEvgeniy Ivanov }
59958a2b000SEvgeniy Ivanov 
600