main.c revision 150751
113044Sasami/*-
213044Sasami * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
313044Sasami * All rights reserved.
413044Sasami *
513044Sasami * Redistribution and use in source and binary forms, with or without
613044Sasami * modification, are permitted provided that the following conditions
713044Sasami * are met:
813044Sasami * 1. Redistributions of source code must retain the above copyright
913044Sasami *    notice, this list of conditions and the following disclaimer.
1013044Sasami * 2. Redistributions in binary form must reproduce the above copyright
1113044Sasami *    notice, this list of conditions and the following disclaimer in the
1213044Sasami *    documentation and/or other materials provided with the distribution.
1313044Sasami *
1413044Sasami * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1513044Sasami * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1613044Sasami * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1713044Sasami * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1813044Sasami * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1913044Sasami * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2013044Sasami * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2113044Sasami * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2213044Sasami * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2313044Sasami * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2413044Sasami * SUCH DAMAGE.
2513044Sasami */
2613044Sasami
2713044Sasami#include <sys/cdefs.h>
2813044Sasami__FBSDID("$FreeBSD: head/sys/boot/pc98/loader/main.c 150751 2005-09-30 13:24:14Z nyan $");
2913044Sasami
3013044Sasami/*
3113044Sasami * MD bootstrap main() and assorted miscellaneous
3213044Sasami * commands.
3313044Sasami */
3413044Sasami
3536628Scharnier#include <stand.h>
3636628Scharnier#include <string.h>
3750476Speter#include <machine/bootinfo.h>
3836628Scharnier#include <sys/reboot.h>
3936628Scharnier
4013044Sasami#include "bootstrap.h"
4148568Sbillf#include "libi386/libi386.h"
4213044Sasami#include "btxv86.h"
4313044Sasami
4445329Speter#define	KARGS_FLAGS_CD		0x1
4513044Sasami#define	KARGS_FLAGS_PXE		0x2
4613044Sasami
4713044Sasami/* Arguments passed in from the boot1/boot2 loader */
4813044Sasamistatic struct
4913044Sasami{
5013044Sasami    u_int32_t	howto;
5169793Sobrien    u_int32_t	bootdev;
5213044Sasami    u_int32_t	bootflags;
5313044Sasami    u_int32_t	pxeinfo;
5413044Sasami    u_int32_t	res2;
5513044Sasami    u_int32_t	bootinfo;
5613044Sasami} *kargs;
5739228Sgibbs
5813052Sasamistatic u_int32_t	initial_howto;
5913044Sasamistatic u_int32_t	initial_bootdev;
6013044Sasamistatic struct bootinfo	*initial_bootinfo;
6113044Sasami
6213044Sasamistruct arch_switch	archsw;		/* MI/MD interface boundary */
6313044Sasami
6413044Sasamistatic void		extract_currdev(void);
6513044Sasamistatic int		isa_inb(int port);
6613044Sasamistatic void		isa_outb(int port, int value);
6713044Sasamivoid			exit(int code);
6813044Sasami
6913044Sasami/* from vers.c */
7013044Sasamiextern	char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
7113044Sasami
7213044Sasami/* XXX debugging */
7313044Sasamiextern char end[];
7413044Sasami
7513762Sasamiint
7613762Sasamimain(void)
7713044Sasami{
7813044Sasami    int			i;
7913044Sasami
8013044Sasami    /* Pick up arguments */
8113044Sasami    kargs = (void *)__args;
8213044Sasami    initial_howto = kargs->howto;
8313044Sasami    initial_bootdev = kargs->bootdev;
8413044Sasami    initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL;
8513044Sasami
8613044Sasami    /*
8713044Sasami     * Initialise the heap as early as possible.  Once this is done, malloc() is usable.
8813044Sasami     */
8913044Sasami    bios_getmem();
9013044Sasami
9113044Sasami    setheap((void *)end, (void *)bios_basemem);
9213044Sasami
9313044Sasami    /*
9413044Sasami     * XXX Chicken-and-egg problem; we want to have console output early, but some
9513044Sasami     * console attributes may depend on reading from eg. the boot device, which we
9613044Sasami     * can't do yet.
9713044Sasami     *
9813044Sasami     * We can use printf() etc. once this is done.
9913044Sasami     * If the previous boot stage has requested a serial console, prefer that.
10013044Sasami     */
10113044Sasami    bi_setboothowto(initial_howto);
10213044Sasami    if (initial_howto & RB_MULTIPLE) {
10313044Sasami	if (initial_howto & RB_SERIAL)
10413044Sasami	    setenv("console", "comconsole vidconsole", 1);
10513044Sasami	else
10613044Sasami	    setenv("console", "vidconsole comconsole", 1);
10713044Sasami    } else if (initial_howto & RB_SERIAL)
10813044Sasami	setenv("console", "comconsole", 1);
10913044Sasami    else if (initial_howto & RB_MUTE)
11013044Sasami	setenv("console", "nullconsole", 1);
11113044Sasami    cons_probe();
11213044Sasami
11313044Sasami    /*
11413044Sasami     * Initialise the block cache
11513044Sasami     */
11613044Sasami    bcache_init(32, 512);	/* 16k cache XXX tune this */
11713044Sasami
11813044Sasami    /*
11913044Sasami     * Special handling for PXE and CD booting.
12013044Sasami     */
12113044Sasami    if (kargs->bootinfo == 0) {
12213044Sasami	/*
12313044Sasami	 * We only want the PXE disk to try to init itself in the below
12413044Sasami	 * walk through devsw if we actually booted off of PXE.
12513044Sasami	 */
12613044Sasami	if (kargs->bootflags & KARGS_FLAGS_PXE)
12713044Sasami	    pxe_enable(kargs->pxeinfo ? PTOV(kargs->pxeinfo) : NULL);
12813044Sasami	else if (kargs->bootflags & KARGS_FLAGS_CD)
12913044Sasami	    bc_add(initial_bootdev);
13013044Sasami    }
13113044Sasami
13213044Sasami    /*
13313044Sasami     * March through the device switch probing for things.
13413044Sasami     */
13513044Sasami    for (i = 0; devsw[i] != NULL; i++)
13613044Sasami	if (devsw[i]->dv_init != NULL)
13713044Sasami	    (devsw[i]->dv_init)();
13813044Sasami    printf("BIOS %dkB/%dkB available memory\n", bios_basemem / 1024, bios_extmem / 1024);
13913044Sasami    if (initial_bootinfo != NULL) {
14013044Sasami	initial_bootinfo->bi_basemem = bios_basemem / 1024;
14113044Sasami	initial_bootinfo->bi_extmem = bios_extmem / 1024;
14213044Sasami    }
14313044Sasami
14413044Sasami    printf("\n");
14513044Sasami    printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
14613044Sasami    printf("(%s, %s)\n", bootprog_maker, bootprog_date);
14713044Sasami
14813044Sasami    extract_currdev();				/* set $currdev and $loaddev */
14913044Sasami    setenv("LINES", "24", 1);			/* optional */
15013044Sasami
15113044Sasami    archsw.arch_autoload = i386_autoload;
15213044Sasami    archsw.arch_getdev = i386_getdev;
15313044Sasami    archsw.arch_copyin = i386_copyin;
15413044Sasami    archsw.arch_copyout = i386_copyout;
15513044Sasami    archsw.arch_readin = i386_readin;
15613044Sasami    archsw.arch_isainb = isa_inb;
15713044Sasami    archsw.arch_isaoutb = isa_outb;
15813044Sasami
15913044Sasami    interact();			/* doesn't return */
16013044Sasami
16113044Sasami    /* if we ever get here, it is an error */
16213044Sasami    return (1);
16313044Sasami}
16413044Sasami
16532116Simp/*
16632116Simp * Set the 'current device' by (if possible) recovering the boot device as
16732116Simp * supplied by the initial bootstrap.
16832116Simp *
16932116Simp * XXX should be extended for netbooting.
17032116Simp */
17132116Simpstatic void
17232116Simpextract_currdev(void)
17332116Simp{
17445329Speter    struct i386_devdesc	new_currdev;
17545329Speter    int			major, biosdev = -1;
17645329Speter
17745329Speter    /* Assume we are booting from a BIOS disk by default */
17845329Speter    new_currdev.d_dev = &biosdisk;
17945329Speter
18013044Sasami    /* new-style boot loaders such as pxeldr and cdldr */
18113044Sasami    if (kargs->bootinfo == 0) {
18213044Sasami        if ((kargs->bootflags & KARGS_FLAGS_CD) != 0) {
18313044Sasami	    /* we are booting from a CD with cdboot */
18413044Sasami	    new_currdev.d_dev = &bioscd;
18513044Sasami	    new_currdev.d_kind.bioscd.unit = bc_bios2unit(initial_bootdev);
18613044Sasami	} else if ((kargs->bootflags & KARGS_FLAGS_PXE) != 0) {
18713044Sasami	    /* we are booting from pxeldr */
18813044Sasami	    new_currdev.d_dev = &pxedisk;
18913044Sasami	    new_currdev.d_kind.netif.unit = 0;
19013044Sasami	} else {
19113044Sasami	    /* we don't know what our boot device is */
19213044Sasami	    new_currdev.d_kind.biosdisk.slice = -1;
19313044Sasami	    new_currdev.d_kind.biosdisk.partition = 0;
19413044Sasami	    biosdev = -1;
19513044Sasami	}
19636628Scharnier    } else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) {
19713044Sasami	/* The passed-in boot device is bad */
19813044Sasami	new_currdev.d_kind.biosdisk.slice = -1;
19913044Sasami	new_currdev.d_kind.biosdisk.partition = 0;
20013044Sasami	biosdev = -1;
20113044Sasami    } else {
20213044Sasami	new_currdev.d_kind.biosdisk.slice = (B_ADAPTOR(initial_bootdev) << 4) +
20313044Sasami					     B_CONTROLLER(initial_bootdev) - 1;
20413044Sasami	new_currdev.d_kind.biosdisk.partition = B_PARTITION(initial_bootdev);
20513044Sasami	biosdev = initial_bootinfo->bi_bios_dev;
20613044Sasami	major = B_TYPE(initial_bootdev);
20751690Sbillf
20813044Sasami	/*
20913044Sasami	 * If we are booted by an old bootstrap, we have to guess at the BIOS
21013044Sasami	 * unit number.  We will loose if there is more than one disk type
21113044Sasami	 * and we are not booting from the lowest-numbered disk type
21213044Sasami	 * (ie. SCSI when IDE also exists).
21313044Sasami	 */
21413044Sasami	if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2)) {	/* biosdev doesn't match major */
21513044Sasami	    if (B_TYPE(initial_bootdev) == 6)
21613044Sasami		biosdev = 0x30 + B_UNIT(initial_bootdev);
21713044Sasami	    else
21813044Sasami		biosdev = (major << 3) + 0x80 + B_UNIT(initial_bootdev);
21913044Sasami	}
22013044Sasami    }
22113044Sasami    new_currdev.d_type = new_currdev.d_dev->dv_type;
22213044Sasami
22313044Sasami    /*
22413044Sasami     * If we are booting off of a BIOS disk and we didn't succeed in determining
22513044Sasami     * which one we booted off of, just use disk0: as a reasonable default.
22613044Sasami     */
22713044Sasami    if ((new_currdev.d_type == biosdisk.dv_type) &&
22813044Sasami	((new_currdev.d_kind.biosdisk.unit = bd_bios2unit(biosdev)) == -1)) {
22913044Sasami	printf("Can't work out which disk we are booting from.\n"
23013044Sasami	       "Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev);
23113044Sasami	new_currdev.d_kind.biosdisk.unit = 0;
23248568Sbillf    }
23313044Sasami    env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev),
23413044Sasami	       i386_setcurrdev, env_nounset);
23513044Sasami    env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset,
23613044Sasami	       env_nounset);
23713044Sasami}
23813044Sasami
23913044SasamiCOMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
24013044Sasami
24113044Sasamistatic int
24213044Sasamicommand_reboot(int argc, char *argv[])
24348568Sbillf{
24413044Sasami    int i;
24513044Sasami
24613044Sasami    for (i = 0; devsw[i] != NULL; ++i)
24713044Sasami	if (devsw[i]->dv_cleanup != NULL)
24813044Sasami	    (devsw[i]->dv_cleanup)();
24913044Sasami
25013044Sasami    printf("Rebooting...\n");
25113044Sasami    delay(1000000);
25213044Sasami    __exit(0);
25313044Sasami}
25413044Sasami
25513044Sasami/* provide this for panic, as it's not in the startup code */
25613044Sasamivoid
25713044Sasamiexit(int code)
25813044Sasami{
25913044Sasami    __exit(code);
26013044Sasami}
26113044Sasami
26213044SasamiCOMMAND_SET(heap, "heap", "show heap usage", command_heap);
26313044Sasami
26413044Sasamistatic int
26513044Sasamicommand_heap(int argc, char *argv[])
26613044Sasami{
26713044Sasami    mallocstats();
26813044Sasami    printf("heap base at %p, top at %p\n", end, sbrk(0));
26913044Sasami    return(CMD_OK);
27013044Sasami}
27113044Sasami
27213044Sasami/* ISA bus access functions for PnP, derived from <machine/cpufunc.h> */
27313044Sasamistatic int
27413044Sasamiisa_inb(int port)
27513044Sasami{
27613044Sasami    u_char	data;
27713044Sasami
27813044Sasami    if (__builtin_constant_p(port) &&
27913044Sasami	(((port) & 0xffff) < 0x100) &&
28013044Sasami	((port) < 0x10000)) {
28113044Sasami	__asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
28213044Sasami    } else {
28313044Sasami	__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
28413044Sasami    }
28513044Sasami    return(data);
28613044Sasami}
28713044Sasami
28813044Sasamistatic void
28913044Sasamiisa_outb(int port, int value)
29013044Sasami{
29113044Sasami    u_char	al = value;
29213044Sasami
29313044Sasami    if (__builtin_constant_p(port) &&
29413044Sasami	(((port) & 0xffff) < 0x100) &&
29513044Sasami	((port) < 0x10000)) {
29613044Sasami	__asm __volatile("outb %0,%1" : : "a" (al), "id" ((u_short)(port)));
29713044Sasami    } else {
29813044Sasami        __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
29913044Sasami    }
30013044Sasami}
30113044Sasami
30213044Sasami