main.c revision 59167
185556Siwasaki/*-
285556Siwasaki * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
385556Siwasaki * All rights reserved.
485556Siwasaki *
585556Siwasaki * Redistribution and use in source and binary forms, with or without
685556Siwasaki * modification, are permitted provided that the following conditions
785556Siwasaki * are met:
885556Siwasaki * 1. Redistributions of source code must retain the above copyright
985556Siwasaki *    notice, this list of conditions and the following disclaimer.
1085556Siwasaki * 2. Redistributions in binary form must reproduce the above copyright
1185556Siwasaki *    notice, this list of conditions and the following disclaimer in the
1285556Siwasaki *    documentation and/or other materials provided with the distribution.
1385556Siwasaki *
1485556Siwasaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1585556Siwasaki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1685556Siwasaki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1785556Siwasaki * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1885556Siwasaki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1985556Siwasaki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2085556Siwasaki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2185556Siwasaki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2285556Siwasaki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2385556Siwasaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2485556Siwasaki * SUCH DAMAGE.
2585556Siwasaki *
2685556Siwasaki * $FreeBSD: head/sys/boot/pc98/loader/main.c 59167 2000-04-12 11:17:08Z kato $
27115681Sobrien */
28115681Sobrien
29115681Sobrien/*
3085556Siwasaki * MD bootstrap main() and assorted miscellaneous
3185556Siwasaki * commands.
32168191Sjhb */
3385556Siwasaki
3485556Siwasaki#include <stand.h>
35215097Sjkim#include <string.h>
36170976Snjl#include <machine/bootinfo.h>
37170976Snjl#include <sys/reboot.h>
3885556Siwasaki
3985556Siwasaki#include "bootstrap.h"
40193530Sjkim#include "libi386/libi386.h"
41193530Sjkim#include "btxv86.h"
4285556Siwasaki
4385556Siwasaki#define	KARGS_FLAGS_CD		0x1
4485556Siwasaki#define	KARGS_FLAGS_PXE		0x2
45215072Sjkim
46177157Sjhb/* Arguments passed in from the boot1/boot2 loader */
4785556Siwasakistatic struct
4885556Siwasaki{
4985556Siwasaki    u_int32_t	howto;
5085556Siwasaki    u_int32_t	bootdev;
51215072Sjkim    u_int32_t	bootflags;
5285556Siwasaki    u_int32_t	pxeinfo;
53132619Snjl    u_int32_t	res2;
54170976Snjl    u_int32_t	bootinfo;
5585556Siwasaki} *kargs;
56170976Snjl
5785556Siwasakistatic u_int32_t	initial_howto;
58170976Snjlstatic u_int32_t	initial_bootdev;
59170976Snjlstatic struct bootinfo	*initial_bootinfo;
60170976Snjl
61170976Snjlstruct arch_switch	archsw;		/* MI/MD interface boundary */
62170976Snjl
63170976Snjlstatic void		extract_currdev(void);
64170976Snjlstatic int		isa_inb(int port);
65170976Snjlstatic void		isa_outb(int port, int value);
66197134Srwatson
67197134Srwatson/* from vers.c */
68197134Srwatsonextern	char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
69197134Srwatson
70197134Srwatson/* XXX debugging */
71170976Snjlextern char end[];
7285556Siwasaki
73126080Sphk/* XXX - I dont know why we have to do this, but it helps. */
74179726Sed#if defined(LOADER_NFS_SUPPORT) || defined(LOADER_TFTP_SUPPORT)
75111815Sphkchar	Heap[200*1024];
76111815Sphk#endif
77111815Sphk
78111815Sphkvoid
79111815Sphkmain(void)
80111815Sphk{
81170976Snjl    int			i;
8285556Siwasaki
8385556Siwasaki    /* Pick up arguments */
8485556Siwasaki    kargs = (void *)__args;
8585556Siwasaki    initial_howto = kargs->howto;
8685556Siwasaki    initial_bootdev = kargs->bootdev;
8785556Siwasaki    initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL;
8885556Siwasaki
89131218Simp    /*
9085556Siwasaki     * Initialise the heap as early as possible.  Once this is done, malloc() is usable.
9185556Siwasaki     */
92119530Snjl    bios_getmem();
9385556Siwasaki
94119530Snjl    /* XXX - I dont know why we have to do this, but it helps PXE. */
9585556Siwasaki#if defined(LOADER_NFS_SUPPORT) || defined(LOADER_TFTP_SUPPORT)
9685556Siwasaki    setheap(Heap, Heap+sizeof(Heap));
97119530Snjl#else
9885556Siwasaki    setheap((void *)end, (void *)bios_basemem);
99119530Snjl#endif
10085556Siwasaki
101119530Snjl    /*
102120156Siwasaki     * XXX Chicken-and-egg problem; we want to have console output early, but some
103131218Simp     * console attributes may depend on reading from eg. the boot device, which we
104128975Snjl     * can't do yet.
105120156Siwasaki     *
106128975Snjl     * We can use printf() etc. once this is done.
107120156Siwasaki     * If the previous boot stage has requested a serial console, prefer that.
108120156Siwasaki     */
109120156Siwasaki    if (initial_howto & RB_SERIAL)
11085556Siwasaki	setenv("console", "comconsole", 1);
11185556Siwasaki    cons_probe();
11285556Siwasaki
11385556Siwasaki    /*
11485556Siwasaki     * Initialise the block cache
11585556Siwasaki     */
11685556Siwasaki    bcache_init(32, 512);	/* 16k cache XXX tune this */
11785556Siwasaki
11885556Siwasaki    /*
11985556Siwasaki     * We only want the PXE disk to try to init itself in the below walk through
120128975Snjl     * devsw if we actually booted off of PXE.
12185556Siwasaki     */
122128975Snjl    if((kargs->bootinfo == NULL) &&
123119530Snjl       ((kargs->bootflags & KARGS_FLAGS_PXE) != 0)) {
12485556Siwasaki      pxe_enable(kargs->pxeinfo ? PTOV(kargs->pxeinfo) : NULL);
125119530Snjl    }
12685556Siwasaki
12785556Siwasaki    /*
128119530Snjl     * March through the device switch probing for things.
12985556Siwasaki     */
130119530Snjl    for (i = 0; devsw[i] != NULL; i++)
13185556Siwasaki	if (devsw[i]->dv_init != NULL)
13285556Siwasaki	    (devsw[i]->dv_init)();
13385556Siwasaki    printf("BIOS %dkB/%dkB available memory\n", bios_basemem / 1024, bios_extmem / 1024);
13485556Siwasaki
13585556Siwasaki    printf("\n");
13685556Siwasaki    printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
13785556Siwasaki    printf("(%s, %s)\n", bootprog_maker, bootprog_date);
13885556Siwasaki
13985556Siwasaki    extract_currdev();				/* set $currdev and $loaddev */
14085556Siwasaki    setenv("LINES", "24", 1);			/* optional */
14185556Siwasaki
14285556Siwasaki    archsw.arch_autoload = i386_autoload;
14385556Siwasaki    archsw.arch_getdev = i386_getdev;
14485556Siwasaki    archsw.arch_copyin = i386_copyin;
145132619Snjl    archsw.arch_copyout = i386_copyout;
146131218Simp    archsw.arch_readin = i386_readin;
14785556Siwasaki    archsw.arch_isainb = isa_inb;
148119530Snjl    archsw.arch_isaoutb = isa_outb;
149131218Simp
150119530Snjl    interact();			/* doesn't return */
15185556Siwasaki}
15285556Siwasaki
153148352Snjl/*
154131218Simp * Set the 'current device' by (if possible) recovering the boot device as
155131218Simp * supplied by the initial bootstrap.
156131218Simp *
157131218Simp * XXX should be extended for netbooting.
15885556Siwasaki */
15985556Siwasakistatic void
16085556Siwasakiextract_currdev(void)
16185556Siwasaki{
16285556Siwasaki    struct i386_devdesc	currdev;
16385556Siwasaki    int			major, biosdev;
16485556Siwasaki
16585556Siwasaki    /* Assume we are booting from a BIOS disk by default */
16685556Siwasaki    currdev.d_dev = &biosdisk;
16785556Siwasaki    currdev.d_type = currdev.d_dev->dv_type;
16885556Siwasaki
16985556Siwasaki    /* new-style boot loaders such as pxeldr and cdldr */
17085556Siwasaki    if (kargs->bootinfo == NULL) {
171148352Snjl        if ((kargs->bootflags & KARGS_FLAGS_CD) != 0) {
172148352Snjl	    /* we are booting from a CD with cdldr */
17385556Siwasaki	    currdev.d_kind.biosdisk.slice = -1;
17485556Siwasaki	    currdev.d_kind.biosdisk.partition = 0;
17585556Siwasaki	    biosdev = initial_bootdev;
176128975Snjl	} else if ((kargs->bootflags & KARGS_FLAGS_PXE) != 0) {
17785556Siwasaki	    /* we are booting from pxeldr */
17885556Siwasaki	    currdev.d_dev = &pxedisk;
179119530Snjl	    currdev.d_type = currdev.d_dev->dv_type;
180148352Snjl	    currdev.d_kind.netif.unit = 0;
181148352Snjl	} else {
182148352Snjl	    /* we don't know what our boot device is */
183148352Snjl	    currdev.d_kind.biosdisk.slice = -1;
184148352Snjl	    currdev.d_kind.biosdisk.partition = 0;
185148352Snjl	    biosdev = -1;
186148352Snjl	}
187148352Snjl    } else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) {
188148352Snjl	/* The passed-in boot device is bad */
189148352Snjl	currdev.d_kind.biosdisk.slice = -1;
19085556Siwasaki	currdev.d_kind.biosdisk.partition = 0;
19185556Siwasaki	biosdev = -1;
19285556Siwasaki    } else {
19385556Siwasaki	currdev.d_kind.biosdisk.slice = (B_ADAPTOR(initial_bootdev) << 4) +
19485556Siwasaki					 B_CONTROLLER(initial_bootdev) - 1;
19585556Siwasaki	currdev.d_kind.biosdisk.partition = B_PARTITION(initial_bootdev);
19685556Siwasaki	biosdev = initial_bootinfo->bi_bios_dev;
197119530Snjl	major = B_TYPE(initial_bootdev);
198131218Simp
199119530Snjl	/*
20085556Siwasaki	 * If we are booted by an old bootstrap, we have to guess at the BIOS
20185556Siwasaki	 * unit number.  We will loose if there is more than one disk type
20285556Siwasaki	 * and we are not booting from the lowest-numbered disk type
20385556Siwasaki	 * (ie. SCSI when IDE also exists).
20485556Siwasaki	 */
205170976Snjl#ifdef PC98
206170976Snjl	if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2)) {	/* biosdev doesn't match major */
207170976Snjl	    if (B_TYPE(initial_bootdev) == 6)
208170976Snjl		biosdev = 0x30 + B_UNIT(initial_bootdev);
209170976Snjl	    else
210170976Snjl		biosdev = (major << 3) + 0x80 + B_UNIT(initial_bootdev);
211170976Snjl	}
212170976Snjl#else
213170976Snjl	if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2))	/* biosdev doesn't match major */
214170976Snjl	    biosdev = 0x80 + B_UNIT(initial_bootdev);		/* assume harddisk */
215170976Snjl#endif
216170976Snjl    }
217170976Snjl
218170976Snjl    /*
219170976Snjl     * If we are booting off of a BIOS disk and we didn't succeed in determining
220170976Snjl     * which one we booted off of, just use disk0: as a reasonable default.
221170976Snjl     */
222170976Snjl    if ((currdev.d_type == devsw[0]->dv_type) &&
223170976Snjl	((currdev.d_kind.biosdisk.unit = bd_bios2unit(biosdev)) == -1)) {
224170976Snjl	printf("Can't work out which disk we are booting from.\n"
225183381Sed	       "Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev);
226170976Snjl	currdev.d_kind.biosdisk.unit = 0;
227170976Snjl    }
228183381Sed    env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&currdev), i386_setcurrdev, env_nounset);
229170976Snjl    env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&currdev), env_noset, env_nounset);
230170976Snjl}
231170976Snjl
232170976SnjlCOMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
233170976Snjl
234170976Snjlstatic int
235170976Snjlcommand_reboot(int argc, char *argv[])
236170976Snjl{
237170976Snjl
238170976Snjl    printf("Rebooting...\n");
239170976Snjl    delay(1000000);
240170976Snjl    __exit(0);
241170976Snjl}
242170976Snjl
243170976Snjl/* provide this for panic, as it's not in the startup code */
244170976Snjlvoid
245170976Snjlexit(int code)
246170976Snjl{
247170976Snjl    __exit(code);
248170976Snjl}
249193951Skib
250170976SnjlCOMMAND_SET(heap, "heap", "show heap usage", command_heap);
251170976Snjl
252170976Snjlstatic int
253170976Snjlcommand_heap(int argc, char *argv[])
254170976Snjl{
255170976Snjl    mallocstats();
256170976Snjl    printf("heap base at %p, top at %p\n", end, sbrk(0));
257170976Snjl    return(CMD_OK);
258170976Snjl}
259170976Snjl
260170976Snjl/* ISA bus access functions for PnP, derived from <machine/cpufunc.h> */
261170976Snjlstatic int
262170976Snjlisa_inb(int port)
263170976Snjl{
264170976Snjl    u_char	data;
265170976Snjl
26685556Siwasaki    if (__builtin_constant_p(port) &&
267192442Simp	(((port) & 0xffff) < 0x100) &&
26885556Siwasaki	((port) < 0x10000)) {
269170976Snjl	__asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
270170976Snjl    } else {
271170976Snjl	__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
272170976Snjl    }
273170976Snjl    return(data);
274170976Snjl}
275170976Snjl
276170976Snjlstatic void
277170976Snjlisa_outb(int port, int value)
278170976Snjl{
279170976Snjl    u_char	al = value;
28085556Siwasaki
28185556Siwasaki    if (__builtin_constant_p(port) &&
28285556Siwasaki	(((port) & 0xffff) < 0x100) &&
28385556Siwasaki	((port) < 0x10000)) {
284192442Simp	__asm __volatile("outb %0,%1" : : "a" (al), "id" ((u_short)(port)));
28585556Siwasaki    } else {
286170976Snjl        __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
287170976Snjl    }
288170976Snjl}
289170976Snjl
290170976Snjl