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