xref: /dragonfly/stand/boot/pc32/loader/main.c (revision 479ab7f0)
1*479ab7f0SSascha Wildner /*
2*479ab7f0SSascha Wildner  * Copyright (c) 2003,2004 The DragonFly Project.  All rights reserved.
3*479ab7f0SSascha Wildner  *
4*479ab7f0SSascha Wildner  * This code is derived from software contributed to The DragonFly Project
5*479ab7f0SSascha Wildner  * by Matthew Dillon <dillon@backplane.com>
6*479ab7f0SSascha Wildner  *
7*479ab7f0SSascha Wildner  * Redistribution and use in source and binary forms, with or without
8*479ab7f0SSascha Wildner  * modification, are permitted provided that the following conditions
9*479ab7f0SSascha Wildner  * are met:
10*479ab7f0SSascha Wildner  *
11*479ab7f0SSascha Wildner  * 1. Redistributions of source code must retain the above copyright
12*479ab7f0SSascha Wildner  *    notice, this list of conditions and the following disclaimer.
13*479ab7f0SSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
14*479ab7f0SSascha Wildner  *    notice, this list of conditions and the following disclaimer in
15*479ab7f0SSascha Wildner  *    the documentation and/or other materials provided with the
16*479ab7f0SSascha Wildner  *    distribution.
17*479ab7f0SSascha Wildner  * 3. Neither the name of The DragonFly Project nor the names of its
18*479ab7f0SSascha Wildner  *    contributors may be used to endorse or promote products derived
19*479ab7f0SSascha Wildner  *    from this software without specific, prior written permission.
20*479ab7f0SSascha Wildner  *
21*479ab7f0SSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*479ab7f0SSascha Wildner  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*479ab7f0SSascha Wildner  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24*479ab7f0SSascha Wildner  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25*479ab7f0SSascha Wildner  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26*479ab7f0SSascha Wildner  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27*479ab7f0SSascha Wildner  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28*479ab7f0SSascha Wildner  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29*479ab7f0SSascha Wildner  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30*479ab7f0SSascha Wildner  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31*479ab7f0SSascha Wildner  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*479ab7f0SSascha Wildner  * SUCH DAMAGE.
33*479ab7f0SSascha Wildner  *
34*479ab7f0SSascha Wildner  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
35*479ab7f0SSascha Wildner  * All rights reserved.
36*479ab7f0SSascha Wildner  *
37*479ab7f0SSascha Wildner  * Redistribution and use in source and binary forms, with or without
38*479ab7f0SSascha Wildner  * modification, are permitted provided that the following conditions
39*479ab7f0SSascha Wildner  * are met:
40*479ab7f0SSascha Wildner  * 1. Redistributions of source code must retain the above copyright
41*479ab7f0SSascha Wildner  *    notice, this list of conditions and the following disclaimer.
42*479ab7f0SSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
43*479ab7f0SSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
44*479ab7f0SSascha Wildner  *    documentation and/or other materials provided with the distribution.
45*479ab7f0SSascha Wildner  *
46*479ab7f0SSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
47*479ab7f0SSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48*479ab7f0SSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49*479ab7f0SSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
50*479ab7f0SSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51*479ab7f0SSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52*479ab7f0SSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53*479ab7f0SSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54*479ab7f0SSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55*479ab7f0SSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56*479ab7f0SSascha Wildner  * SUCH DAMAGE.
57*479ab7f0SSascha Wildner  *
58*479ab7f0SSascha Wildner  * $FreeBSD: src/sys/boot/i386/loader/main.c,v 1.28 2003/08/25 23:28:32 obrien Exp $
59*479ab7f0SSascha Wildner  */
60*479ab7f0SSascha Wildner 
61*479ab7f0SSascha Wildner /*
62*479ab7f0SSascha Wildner  * MD bootstrap main() and assorted miscellaneous
63*479ab7f0SSascha Wildner  * commands.
64*479ab7f0SSascha Wildner  */
65*479ab7f0SSascha Wildner 
66*479ab7f0SSascha Wildner #include <stand.h>
67*479ab7f0SSascha Wildner #include <string.h>
68*479ab7f0SSascha Wildner #include <machine/bootinfo.h>
69*479ab7f0SSascha Wildner #include <machine/psl.h>
70*479ab7f0SSascha Wildner #include <sys/reboot.h>
71*479ab7f0SSascha Wildner 
72*479ab7f0SSascha Wildner #include "bootstrap.h"
73*479ab7f0SSascha Wildner #include "libi386/libi386.h"
74*479ab7f0SSascha Wildner #include "libi386/smbios.h"
75*479ab7f0SSascha Wildner #include "btxv86.h"
76*479ab7f0SSascha Wildner 
77*479ab7f0SSascha Wildner #define	KARGS_FLAGS_CD		0x1
78*479ab7f0SSascha Wildner #define	KARGS_FLAGS_PXE		0x2
79*479ab7f0SSascha Wildner 
80*479ab7f0SSascha Wildner /* Arguments passed in from the boot1/boot2 loader */
81*479ab7f0SSascha Wildner static struct
82*479ab7f0SSascha Wildner {
83*479ab7f0SSascha Wildner     u_int32_t	howto;
84*479ab7f0SSascha Wildner     u_int32_t	bootdev;
85*479ab7f0SSascha Wildner     u_int32_t	bootflags;
86*479ab7f0SSascha Wildner     u_int32_t	pxeinfo;
87*479ab7f0SSascha Wildner     u_int32_t	res2;
88*479ab7f0SSascha Wildner     u_int32_t	bootinfo;
89*479ab7f0SSascha Wildner } *kargs;
90*479ab7f0SSascha Wildner 
91*479ab7f0SSascha Wildner static u_int32_t	initial_howto;
92*479ab7f0SSascha Wildner static u_int32_t	initial_bootdev;
93*479ab7f0SSascha Wildner static struct bootinfo	*initial_bootinfo;
94*479ab7f0SSascha Wildner 
95*479ab7f0SSascha Wildner struct arch_switch	archsw;		/* MI/MD interface boundary */
96*479ab7f0SSascha Wildner 
97*479ab7f0SSascha Wildner static void		extract_currdev(void);
98*479ab7f0SSascha Wildner static int		isa_inb(int port);
99*479ab7f0SSascha Wildner static void		isa_outb(int port, int value);
100*479ab7f0SSascha Wildner void			exit(int code);
101*479ab7f0SSascha Wildner 
102*479ab7f0SSascha Wildner /* from vers.c */
103*479ab7f0SSascha Wildner extern	char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
104*479ab7f0SSascha Wildner 
105*479ab7f0SSascha Wildner /* XXX debugging */
106*479ab7f0SSascha Wildner extern char _end[];
107*479ab7f0SSascha Wildner 
108*479ab7f0SSascha Wildner #define COMCONSOLE_DEBUG
109*479ab7f0SSascha Wildner #ifdef COMCONSOLE_DEBUG
110*479ab7f0SSascha Wildner 
111*479ab7f0SSascha Wildner static void
WDEBUG_INIT(void)112*479ab7f0SSascha Wildner WDEBUG_INIT(void)
113*479ab7f0SSascha Wildner {
114*479ab7f0SSascha Wildner     isa_outb(0x3f8+3, 0x83);	/* DLAB + 8N1 */
115*479ab7f0SSascha Wildner     isa_outb(0x3f8+0, (115200 / 115200) & 0xFF);
116*479ab7f0SSascha Wildner     isa_outb(0x3f8+1, (115200 / 115200) >> 8);
117*479ab7f0SSascha Wildner     isa_outb(0x3f8+3, 0x03);	/* 8N1 */
118*479ab7f0SSascha Wildner     isa_outb(0x3f8+4, 0x03);	/* RTS+DTR */
119*479ab7f0SSascha Wildner     isa_outb(0x3f8+2, 0x01);	/* FIFO_ENABLE */
120*479ab7f0SSascha Wildner }
121*479ab7f0SSascha Wildner 
122*479ab7f0SSascha Wildner static void
WDEBUG(char c)123*479ab7f0SSascha Wildner WDEBUG(char c)
124*479ab7f0SSascha Wildner {
125*479ab7f0SSascha Wildner     isa_outb(0x3f8, c);
126*479ab7f0SSascha Wildner }
127*479ab7f0SSascha Wildner 
128*479ab7f0SSascha Wildner #else
129*479ab7f0SSascha Wildner 
130*479ab7f0SSascha Wildner #define WDEBUG(x)
131*479ab7f0SSascha Wildner #define WDEBUG_INIT()
132*479ab7f0SSascha Wildner 
133*479ab7f0SSascha Wildner #endif
134*479ab7f0SSascha Wildner 
135*479ab7f0SSascha Wildner int
main(void)136*479ab7f0SSascha Wildner main(void)
137*479ab7f0SSascha Wildner {
138*479ab7f0SSascha Wildner     char *memend;
139*479ab7f0SSascha Wildner     int i;
140*479ab7f0SSascha Wildner 
141*479ab7f0SSascha Wildner     WDEBUG_INIT();
142*479ab7f0SSascha Wildner     WDEBUG('X');
143*479ab7f0SSascha Wildner 
144*479ab7f0SSascha Wildner     /* Pick up arguments */
145*479ab7f0SSascha Wildner     kargs = (void *)__args;
146*479ab7f0SSascha Wildner     initial_howto = kargs->howto;
147*479ab7f0SSascha Wildner     initial_bootdev = kargs->bootdev;
148*479ab7f0SSascha Wildner     initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL;
149*479ab7f0SSascha Wildner 
150*479ab7f0SSascha Wildner #ifdef COMCONSOLE_DEBUG
151*479ab7f0SSascha Wildner     printf("args at %p initial_howto = %08x bootdev = %08x bootinfo = %p\n",
152*479ab7f0SSascha Wildner 	kargs, initial_howto, initial_bootdev, initial_bootinfo);
153*479ab7f0SSascha Wildner #endif
154*479ab7f0SSascha Wildner 
155*479ab7f0SSascha Wildner     /* Initialize the v86 register set to a known-good state. */
156*479ab7f0SSascha Wildner     bzero(&v86, sizeof(v86));
157*479ab7f0SSascha Wildner     v86.efl = PSL_RESERVED_DEFAULT | PSL_I;
158*479ab7f0SSascha Wildner 
159*479ab7f0SSascha Wildner 
160*479ab7f0SSascha Wildner     /*
161*479ab7f0SSascha Wildner      * Initialize the heap as early as possible.  Once this is done,
162*479ab7f0SSascha Wildner      * malloc() is usable.
163*479ab7f0SSascha Wildner      *
164*479ab7f0SSascha Wildner      * Don't include our stack in the heap.  If the stack is in low
165*479ab7f0SSascha Wildner      * user memory use {end,bios_basemem}.  If the stack is in high
166*479ab7f0SSascha Wildner      * user memory but not extended memory then don't let the heap
167*479ab7f0SSascha Wildner      * overlap the stack.  If the stack is in extended memory limit
168*479ab7f0SSascha Wildner      * the heap to bios_basemem.
169*479ab7f0SSascha Wildner      *
170*479ab7f0SSascha Wildner      * Be sure to use the virtual bios_basemem address rather then
171*479ab7f0SSascha Wildner      * the physical bios_basemem address or we may overwrite BIOS
172*479ab7f0SSascha Wildner      * data.
173*479ab7f0SSascha Wildner      */
174*479ab7f0SSascha Wildner     bios_getmem();
175*479ab7f0SSascha Wildner     memend = (char *)&memend - 0x8000;	/* space for stack (16K) */
176*479ab7f0SSascha Wildner     memend = (char *)((uintptr_t)memend & ~(uintptr_t)(0x1000 - 1));
177*479ab7f0SSascha Wildner 
178*479ab7f0SSascha Wildner     /*
179*479ab7f0SSascha Wildner      * Steal the heap from high memory.  bios_basemem no longer has
180*479ab7f0SSascha Wildner      * enough space, last failure was the gunzip code for initrd.img
181*479ab7f0SSascha Wildner      * needing > ~32KB of temporary buffer space and we ran out.  again.
182*479ab7f0SSascha Wildner      *
183*479ab7f0SSascha Wildner      * High memory reserves at least ~1MB for the loader.
184*479ab7f0SSascha Wildner      */
185*479ab7f0SSascha Wildner #if 0
186*479ab7f0SSascha Wildner     if (memend < (char *)_end) {
187*479ab7f0SSascha Wildner 	setheap((void *)_end, PTOV(bios_basemem));
188*479ab7f0SSascha Wildner     } else {
189*479ab7f0SSascha Wildner 	if (memend > (char *)PTOV(bios_basemem))
190*479ab7f0SSascha Wildner 	    memend = (char *)PTOV(bios_basemem);
191*479ab7f0SSascha Wildner 	setheap((void *)_end, memend);
192*479ab7f0SSascha Wildner     }
193*479ab7f0SSascha Wildner #endif
194*479ab7f0SSascha Wildner     setheap((void *)heapbase, (void *)memtop);
195*479ab7f0SSascha Wildner 
196*479ab7f0SSascha Wildner     /*
197*479ab7f0SSascha Wildner      * XXX Chicken-and-egg problem; we want to have console output early,
198*479ab7f0SSascha Wildner      * but some console attributes may depend on reading from eg. the boot
199*479ab7f0SSascha Wildner      * device, which we can't do yet.
200*479ab7f0SSascha Wildner      *
201*479ab7f0SSascha Wildner      * We can use printf() etc. once this is done.   The previous boot stage
202*479ab7f0SSascha Wildner      * might have requested a video or serial preference, in which case we
203*479ab7f0SSascha Wildner      * set it.  If neither is specified or both are specified we leave the
204*479ab7f0SSascha Wildner      * console environment variable alone, defaulting to dual boot.
205*479ab7f0SSascha Wildner      */
206*479ab7f0SSascha Wildner     if (initial_howto & RB_MUTE) {
207*479ab7f0SSascha Wildner 	setenv("console", "nullconsole", 1);
208*479ab7f0SSascha Wildner     } else if ((initial_howto & (RB_VIDEO|RB_SERIAL)) != (RB_VIDEO|RB_SERIAL)) {
209*479ab7f0SSascha Wildner 	if (initial_howto & RB_VIDEO)
210*479ab7f0SSascha Wildner 	    setenv("console", "vidconsole", 1);
211*479ab7f0SSascha Wildner 	if (initial_howto & RB_SERIAL)
212*479ab7f0SSascha Wildner 	    setenv("console", "comconsole", 1);
213*479ab7f0SSascha Wildner     }
214*479ab7f0SSascha Wildner     cons_probe();
215*479ab7f0SSascha Wildner 
216*479ab7f0SSascha Wildner     /*
217*479ab7f0SSascha Wildner      * Initialise the block cache
218*479ab7f0SSascha Wildner      */
219*479ab7f0SSascha Wildner     bcache_init(32, 512);	/* 16k cache XXX tune this */
220*479ab7f0SSascha Wildner 
221*479ab7f0SSascha Wildner     /*
222*479ab7f0SSascha Wildner      * Special handling for PXE and CD booting.
223*479ab7f0SSascha Wildner      */
224*479ab7f0SSascha Wildner     if (kargs->bootinfo == 0) {
225*479ab7f0SSascha Wildner 	/*
226*479ab7f0SSascha Wildner 	 * We only want the PXE disk to try to init itself in the below
227*479ab7f0SSascha Wildner 	 * walk through devsw if we actually booted off of PXE.
228*479ab7f0SSascha Wildner 	 */
229*479ab7f0SSascha Wildner 	if (kargs->bootflags & KARGS_FLAGS_PXE)
230*479ab7f0SSascha Wildner 	    pxe_enable(kargs->pxeinfo ? PTOV(kargs->pxeinfo) : NULL);
231*479ab7f0SSascha Wildner 	else if (kargs->bootflags & KARGS_FLAGS_CD)
232*479ab7f0SSascha Wildner 	    bc_add(initial_bootdev);
233*479ab7f0SSascha Wildner     }
234*479ab7f0SSascha Wildner 
235*479ab7f0SSascha Wildner     /*
236*479ab7f0SSascha Wildner      * March through the device switch probing for things.
237*479ab7f0SSascha Wildner      */
238*479ab7f0SSascha Wildner     for (i = 0; devsw[i] != NULL; i++) {
239*479ab7f0SSascha Wildner 	WDEBUG('M' + i);
240*479ab7f0SSascha Wildner 	if (devsw[i]->dv_init != NULL)
241*479ab7f0SSascha Wildner 	    (devsw[i]->dv_init)();
242*479ab7f0SSascha Wildner 	WDEBUG('M' + i);
243*479ab7f0SSascha Wildner     }
244*479ab7f0SSascha Wildner     printf("BIOS %dkB/%dkB available memory\n",
245*479ab7f0SSascha Wildner 	    bios_basemem / 1024, bios_extmem / 1024);
246*479ab7f0SSascha Wildner     if (initial_bootinfo != NULL) {
247*479ab7f0SSascha Wildner 	initial_bootinfo->bi_basemem = bios_basemem / 1024;
248*479ab7f0SSascha Wildner 	initial_bootinfo->bi_extmem = bios_extmem / 1024;
249*479ab7f0SSascha Wildner     }
250*479ab7f0SSascha Wildner 
251*479ab7f0SSascha Wildner     /* detect ACPI for future reference */
252*479ab7f0SSascha Wildner     biosacpi_detect();
253*479ab7f0SSascha Wildner 
254*479ab7f0SSascha Wildner     /* detect SMBIOS for future reference */
255*479ab7f0SSascha Wildner     smbios_detect(NULL);
256*479ab7f0SSascha Wildner 
257*479ab7f0SSascha Wildner     /* enable EHCI */
258*479ab7f0SSascha Wildner     setenv("ehci_load", "YES", 1);
259*479ab7f0SSascha Wildner 
260*479ab7f0SSascha Wildner     /* enable XHCI */
261*479ab7f0SSascha Wildner     setenv("xhci_load", "YES", 1);
262*479ab7f0SSascha Wildner 
263*479ab7f0SSascha Wildner     printf("\n");
264*479ab7f0SSascha Wildner     printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
265*479ab7f0SSascha Wildner     printf("(%s, %s)\n", bootprog_maker, bootprog_date);
266*479ab7f0SSascha Wildner 
267*479ab7f0SSascha Wildner     extract_currdev();				/* set $currdev and $loaddev */
268*479ab7f0SSascha Wildner     setenv("LINES", "24", 1);			/* optional */
269*479ab7f0SSascha Wildner 
270*479ab7f0SSascha Wildner     bios_getsmap();
271*479ab7f0SSascha Wildner 
272*479ab7f0SSascha Wildner     archsw.arch_autoload = i386_autoload;
273*479ab7f0SSascha Wildner     archsw.arch_getdev = i386_getdev;
274*479ab7f0SSascha Wildner     archsw.arch_copyin = i386_copyin;
275*479ab7f0SSascha Wildner     archsw.arch_copyout = i386_copyout;
276*479ab7f0SSascha Wildner     archsw.arch_readin = i386_readin;
277*479ab7f0SSascha Wildner     archsw.arch_isainb = isa_inb;
278*479ab7f0SSascha Wildner     archsw.arch_isaoutb = isa_outb;
279*479ab7f0SSascha Wildner 
280*479ab7f0SSascha Wildner     interact();			/* doesn't return */
281*479ab7f0SSascha Wildner 
282*479ab7f0SSascha Wildner     /* if we ever get here, it is an error */
283*479ab7f0SSascha Wildner     return (1);
284*479ab7f0SSascha Wildner }
285*479ab7f0SSascha Wildner 
286*479ab7f0SSascha Wildner /*
287*479ab7f0SSascha Wildner  * Set the 'current device' by (if possible) recovering the boot device as
288*479ab7f0SSascha Wildner  * supplied by the initial bootstrap.
289*479ab7f0SSascha Wildner  *
290*479ab7f0SSascha Wildner  * XXX should be extended for netbooting.
291*479ab7f0SSascha Wildner  */
292*479ab7f0SSascha Wildner static void
extract_currdev(void)293*479ab7f0SSascha Wildner extract_currdev(void)
294*479ab7f0SSascha Wildner {
295*479ab7f0SSascha Wildner     struct i386_devdesc	new_currdev;
296*479ab7f0SSascha Wildner     int			biosdev = -1;
297*479ab7f0SSascha Wildner 
298*479ab7f0SSascha Wildner     /* Assume we are booting from a BIOS disk by default */
299*479ab7f0SSascha Wildner     new_currdev.d_dev = &biosdisk;
300*479ab7f0SSascha Wildner 
301*479ab7f0SSascha Wildner     /* new-style boot loaders such as pxeldr and cdldr */
302*479ab7f0SSascha Wildner     if (kargs->bootinfo == 0) {
303*479ab7f0SSascha Wildner         if ((kargs->bootflags & KARGS_FLAGS_CD) != 0) {
304*479ab7f0SSascha Wildner 	    /* we are booting from a CD with cdboot */
305*479ab7f0SSascha Wildner 	    new_currdev.d_dev = &bioscd;
306*479ab7f0SSascha Wildner 	    new_currdev.d_kind.bioscd.unit = bc_bios2unit(initial_bootdev);
307*479ab7f0SSascha Wildner 	} else if ((kargs->bootflags & KARGS_FLAGS_PXE) != 0) {
308*479ab7f0SSascha Wildner 	    /* we are booting from pxeldr */
309*479ab7f0SSascha Wildner 	    new_currdev.d_dev = &pxedisk;
310*479ab7f0SSascha Wildner 	    new_currdev.d_kind.netif.unit = 0;
311*479ab7f0SSascha Wildner 	} else {
312*479ab7f0SSascha Wildner 	    /* we don't know what our boot device is */
313*479ab7f0SSascha Wildner 	    new_currdev.d_kind.biosdisk.slice = -1;
314*479ab7f0SSascha Wildner 	    new_currdev.d_kind.biosdisk.partition = 0;
315*479ab7f0SSascha Wildner 	    biosdev = -1;
316*479ab7f0SSascha Wildner 	}
317*479ab7f0SSascha Wildner     } else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) {
318*479ab7f0SSascha Wildner 	/* The passed-in boot device is bad */
319*479ab7f0SSascha Wildner 	new_currdev.d_kind.biosdisk.slice = -1;
320*479ab7f0SSascha Wildner 	new_currdev.d_kind.biosdisk.partition = 0;
321*479ab7f0SSascha Wildner 	biosdev = -1;
322*479ab7f0SSascha Wildner     } else {
323*479ab7f0SSascha Wildner 	new_currdev.d_kind.biosdisk.slice = B_SLICE(initial_bootdev) - 1;
324*479ab7f0SSascha Wildner 	new_currdev.d_kind.biosdisk.partition = B_PARTITION(initial_bootdev);
325*479ab7f0SSascha Wildner 	biosdev = initial_bootinfo->bi_bios_dev;
326*479ab7f0SSascha Wildner 
327*479ab7f0SSascha Wildner 	/*
328*479ab7f0SSascha Wildner 	 * If we are booted by an old bootstrap, we have to guess at the BIOS
329*479ab7f0SSascha Wildner 	 * unit number.  We will loose if there is more than one disk type
330*479ab7f0SSascha Wildner 	 * and we are not booting from the lowest-numbered disk type
331*479ab7f0SSascha Wildner 	 * (ie. SCSI when IDE also exists).
332*479ab7f0SSascha Wildner 	 */
333*479ab7f0SSascha Wildner 	if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2))	/* biosdev doesn't match major */
334*479ab7f0SSascha Wildner 	    biosdev = 0x80 + B_UNIT(initial_bootdev);		/* assume harddisk */
335*479ab7f0SSascha Wildner     }
336*479ab7f0SSascha Wildner     new_currdev.d_type = new_currdev.d_dev->dv_type;
337*479ab7f0SSascha Wildner 
338*479ab7f0SSascha Wildner     /*
339*479ab7f0SSascha Wildner      * If we are booting off of a BIOS disk and we didn't succeed in determining
340*479ab7f0SSascha Wildner      * which one we booted off of, just use disk0: as a reasonable default.
341*479ab7f0SSascha Wildner      */
342*479ab7f0SSascha Wildner     if ((new_currdev.d_type == biosdisk.dv_type) &&
343*479ab7f0SSascha Wildner 	((new_currdev.d_kind.biosdisk.unit = bd_bios2unit(biosdev)) == -1)) {
344*479ab7f0SSascha Wildner 	printf("Can't work out which disk we are booting from.\n"
345*479ab7f0SSascha Wildner 	       "Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev);
346*479ab7f0SSascha Wildner 	new_currdev.d_kind.biosdisk.unit = 0;
347*479ab7f0SSascha Wildner     }
348*479ab7f0SSascha Wildner     env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev),
349*479ab7f0SSascha Wildner 	       i386_setcurrdev, env_nounset);
350*479ab7f0SSascha Wildner     env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset,
351*479ab7f0SSascha Wildner 	       env_nounset);
352*479ab7f0SSascha Wildner }
353*479ab7f0SSascha Wildner 
354*479ab7f0SSascha Wildner COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
355*479ab7f0SSascha Wildner 
356*479ab7f0SSascha Wildner static int
command_reboot(int argc,char * argv[])357*479ab7f0SSascha Wildner command_reboot(int argc, char *argv[])
358*479ab7f0SSascha Wildner {
359*479ab7f0SSascha Wildner     int i;
360*479ab7f0SSascha Wildner 
361*479ab7f0SSascha Wildner     for (i = 0; devsw[i] != NULL; ++i)
362*479ab7f0SSascha Wildner 	if (devsw[i]->dv_cleanup != NULL)
363*479ab7f0SSascha Wildner 	    (devsw[i]->dv_cleanup)();
364*479ab7f0SSascha Wildner 
365*479ab7f0SSascha Wildner     printf("Rebooting...\n");
366*479ab7f0SSascha Wildner     delay(1000000);
367*479ab7f0SSascha Wildner     __exit(0);
368*479ab7f0SSascha Wildner }
369*479ab7f0SSascha Wildner 
370*479ab7f0SSascha Wildner /* provide this for panic, as it's not in the startup code */
371*479ab7f0SSascha Wildner void
exit(int code)372*479ab7f0SSascha Wildner exit(int code)
373*479ab7f0SSascha Wildner {
374*479ab7f0SSascha Wildner     __exit(code);
375*479ab7f0SSascha Wildner }
376*479ab7f0SSascha Wildner 
377*479ab7f0SSascha Wildner COMMAND_SET(heap, "heap", "show heap usage", command_heap);
378*479ab7f0SSascha Wildner 
379*479ab7f0SSascha Wildner static int
command_heap(int argc,char * argv[])380*479ab7f0SSascha Wildner command_heap(int argc, char *argv[])
381*479ab7f0SSascha Wildner {
382*479ab7f0SSascha Wildner     char *base;
383*479ab7f0SSascha Wildner     size_t bytes;
384*479ab7f0SSascha Wildner 
385*479ab7f0SSascha Wildner     mallocstats();
386*479ab7f0SSascha Wildner     base = getheap(&bytes);
387*479ab7f0SSascha Wildner     printf("heap %p-%p (%d)\n", base, base + bytes, (int)bytes);
388*479ab7f0SSascha Wildner     printf("stack at %p\n", &argc);
389*479ab7f0SSascha Wildner     return(CMD_OK);
390*479ab7f0SSascha Wildner }
391*479ab7f0SSascha Wildner 
392*479ab7f0SSascha Wildner /* ISA bus access functions for PnP, derived from <machine/cpufunc.h> */
393*479ab7f0SSascha Wildner static int
isa_inb(int port)394*479ab7f0SSascha Wildner isa_inb(int port)
395*479ab7f0SSascha Wildner {
396*479ab7f0SSascha Wildner     u_char	data;
397*479ab7f0SSascha Wildner 
398*479ab7f0SSascha Wildner     if (__builtin_constant_p(port) &&
399*479ab7f0SSascha Wildner 	(((port) & 0xffff) < 0x100) &&
400*479ab7f0SSascha Wildner 	((port) < 0x10000)) {
401*479ab7f0SSascha Wildner 	__asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
402*479ab7f0SSascha Wildner     } else {
403*479ab7f0SSascha Wildner 	__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
404*479ab7f0SSascha Wildner     }
405*479ab7f0SSascha Wildner     return(data);
406*479ab7f0SSascha Wildner }
407*479ab7f0SSascha Wildner 
408*479ab7f0SSascha Wildner static void
isa_outb(int port,int value)409*479ab7f0SSascha Wildner isa_outb(int port, int value)
410*479ab7f0SSascha Wildner {
411*479ab7f0SSascha Wildner     u_char	al = value;
412*479ab7f0SSascha Wildner 
413*479ab7f0SSascha Wildner     if (__builtin_constant_p(port) &&
414*479ab7f0SSascha Wildner 	(((port) & 0xffff) < 0x100) &&
415*479ab7f0SSascha Wildner 	((port) < 0x10000)) {
416*479ab7f0SSascha Wildner 	__asm __volatile("outb %0,%1" : : "a" (al), "id" ((u_short)(port)));
417*479ab7f0SSascha Wildner     } else {
418*479ab7f0SSascha Wildner         __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
419*479ab7f0SSascha Wildner     }
420*479ab7f0SSascha Wildner }
421*479ab7f0SSascha Wildner 
422