Deleted Added
full compact
1/*-
2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/boot/pc98/loader/main.c 59167 2000-04-12 11:17:08Z kato $
26 * $FreeBSD: head/sys/boot/pc98/loader/main.c 59535 2000-04-23 09:33:31Z nyan $
27 */
28
29/*
30 * MD bootstrap main() and assorted miscellaneous
31 * commands.
32 */
33
34#include <stand.h>
35#include <string.h>
36#include <machine/bootinfo.h>
37#include <sys/reboot.h>
38
39#include "bootstrap.h"
40#include "libi386/libi386.h"
41#include "btxv86.h"
42
43#define KARGS_FLAGS_CD 0x1
44#define KARGS_FLAGS_PXE 0x2
45
46/* Arguments passed in from the boot1/boot2 loader */
47static struct
48{
49 u_int32_t howto;
50 u_int32_t bootdev;
51 u_int32_t bootflags;
52 u_int32_t pxeinfo;
53 u_int32_t res2;
54 u_int32_t bootinfo;
55} *kargs;
56
57static u_int32_t initial_howto;
58static u_int32_t initial_bootdev;
59static struct bootinfo *initial_bootinfo;
60
61struct arch_switch archsw; /* MI/MD interface boundary */
62
63static void extract_currdev(void);
64static int isa_inb(int port);
65static void isa_outb(int port, int value);
66
67/* from vers.c */
68extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
69
70/* XXX debugging */
71extern char end[];
72
73/* XXX - I dont know why we have to do this, but it helps. */
74#if defined(LOADER_NFS_SUPPORT) || defined(LOADER_TFTP_SUPPORT)
75char Heap[200*1024];
76#endif
77
78void
79main(void)
80{
81 int i;
82
83 /* Pick up arguments */
84 kargs = (void *)__args;
85 initial_howto = kargs->howto;
86 initial_bootdev = kargs->bootdev;
87 initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL;
88
89 /*
90 * Initialise the heap as early as possible. Once this is done, malloc() is usable.
91 */
92 bios_getmem();
93
94 /* XXX - I dont know why we have to do this, but it helps PXE. */
95#if defined(LOADER_NFS_SUPPORT) || defined(LOADER_TFTP_SUPPORT)
96 setheap(Heap, Heap+sizeof(Heap));
97#else
98 setheap((void *)end, (void *)bios_basemem);
99#endif
100
101 /*
102 * XXX Chicken-and-egg problem; we want to have console output early, but some
103 * console attributes may depend on reading from eg. the boot device, which we
104 * can't do yet.
105 *
106 * We can use printf() etc. once this is done.
107 * If the previous boot stage has requested a serial console, prefer that.
108 */
109 if (initial_howto & RB_SERIAL)
110 setenv("console", "comconsole", 1);
111 cons_probe();
112
113 /*
114 * Initialise the block cache
115 */
116 bcache_init(32, 512); /* 16k cache XXX tune this */
117
118 /*
119 * We only want the PXE disk to try to init itself in the below walk through
120 * devsw if we actually booted off of PXE.
121 */
122 if((kargs->bootinfo == NULL) &&
123 ((kargs->bootflags & KARGS_FLAGS_PXE) != 0)) {
124 pxe_enable(kargs->pxeinfo ? PTOV(kargs->pxeinfo) : NULL);
125 }
126
127 /*
128 * March through the device switch probing for things.
129 */
130 for (i = 0; devsw[i] != NULL; i++)
131 if (devsw[i]->dv_init != NULL)
132 (devsw[i]->dv_init)();
133 printf("BIOS %dkB/%dkB available memory\n", bios_basemem / 1024, bios_extmem / 1024);
134
135 printf("\n");
136 printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
137 printf("(%s, %s)\n", bootprog_maker, bootprog_date);
138
139 extract_currdev(); /* set $currdev and $loaddev */
140 setenv("LINES", "24", 1); /* optional */
141
142 archsw.arch_autoload = i386_autoload;
143 archsw.arch_getdev = i386_getdev;
144 archsw.arch_copyin = i386_copyin;
145 archsw.arch_copyout = i386_copyout;
146 archsw.arch_readin = i386_readin;
147 archsw.arch_isainb = isa_inb;
148 archsw.arch_isaoutb = isa_outb;
149
150 interact(); /* doesn't return */
151}
152
153/*
154 * Set the 'current device' by (if possible) recovering the boot device as
155 * supplied by the initial bootstrap.
156 *
157 * XXX should be extended for netbooting.
158 */
159static void
160extract_currdev(void)
161{
162 struct i386_devdesc currdev;
163 int major, biosdev;
164
165 /* Assume we are booting from a BIOS disk by default */
166 currdev.d_dev = &biosdisk;
167 currdev.d_type = currdev.d_dev->dv_type;
168
169 /* new-style boot loaders such as pxeldr and cdldr */
170 if (kargs->bootinfo == NULL) {
171 if ((kargs->bootflags & KARGS_FLAGS_CD) != 0) {
172 /* we are booting from a CD with cdldr */
173 currdev.d_kind.biosdisk.slice = -1;
174 currdev.d_kind.biosdisk.partition = 0;
175 biosdev = initial_bootdev;
176 } else if ((kargs->bootflags & KARGS_FLAGS_PXE) != 0) {
177 /* we are booting from pxeldr */
178 currdev.d_dev = &pxedisk;
179 currdev.d_type = currdev.d_dev->dv_type;
180 currdev.d_kind.netif.unit = 0;
181 } else {
182 /* we don't know what our boot device is */
183 currdev.d_kind.biosdisk.slice = -1;
184 currdev.d_kind.biosdisk.partition = 0;
185 biosdev = -1;
186 }
187 } else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) {
188 /* The passed-in boot device is bad */
189 currdev.d_kind.biosdisk.slice = -1;
190 currdev.d_kind.biosdisk.partition = 0;
191 biosdev = -1;
192 } else {
193 currdev.d_kind.biosdisk.slice = (B_ADAPTOR(initial_bootdev) << 4) +
194 B_CONTROLLER(initial_bootdev) - 1;
195 currdev.d_kind.biosdisk.partition = B_PARTITION(initial_bootdev);
196 biosdev = initial_bootinfo->bi_bios_dev;
197 major = B_TYPE(initial_bootdev);
198
199 /*
200 * If we are booted by an old bootstrap, we have to guess at the BIOS
201 * unit number. We will loose if there is more than one disk type
202 * and we are not booting from the lowest-numbered disk type
203 * (ie. SCSI when IDE also exists).
204 */
205#ifdef PC98
206 if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2)) { /* biosdev doesn't match major */
207 if (B_TYPE(initial_bootdev) == 6)
208 biosdev = 0x30 + B_UNIT(initial_bootdev);
209 else
210 biosdev = (major << 3) + 0x80 + B_UNIT(initial_bootdev);
211 }
212#else
213 if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2)) /* biosdev doesn't match major */
214 biosdev = 0x80 + B_UNIT(initial_bootdev); /* assume harddisk */
215#endif
216 }
217
218 /*
219 * If we are booting off of a BIOS disk and we didn't succeed in determining
220 * which one we booted off of, just use disk0: as a reasonable default.
221 */
222 if ((currdev.d_type == devsw[0]->dv_type) &&
223 ((currdev.d_kind.biosdisk.unit = bd_bios2unit(biosdev)) == -1)) {
224 printf("Can't work out which disk we are booting from.\n"
225 "Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev);
226 currdev.d_kind.biosdisk.unit = 0;
227 }
228 env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&currdev), i386_setcurrdev, env_nounset);
229 env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&currdev), env_noset, env_nounset);
230}
231
232COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
233
234static int
235command_reboot(int argc, char *argv[])
236{
237 int i;
238
239 for (i = 0; devsw[i] != NULL; ++i)
240 if (devsw[i]->dv_cleanup != NULL)
241 (devsw[i]->dv_cleanup)();
242
243 printf("Rebooting...\n");
244 delay(1000000);
245 __exit(0);
246}
247
248/* provide this for panic, as it's not in the startup code */
249void
250exit(int code)
251{
252 __exit(code);
253}
254
255COMMAND_SET(heap, "heap", "show heap usage", command_heap);
256
257static int
258command_heap(int argc, char *argv[])
259{
260 mallocstats();
261 printf("heap base at %p, top at %p\n", end, sbrk(0));
262 return(CMD_OK);
263}
264
265/* ISA bus access functions for PnP, derived from <machine/cpufunc.h> */
266static int
267isa_inb(int port)
268{
269 u_char data;
270
271 if (__builtin_constant_p(port) &&
272 (((port) & 0xffff) < 0x100) &&
273 ((port) < 0x10000)) {
274 __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
275 } else {
276 __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
277 }
278 return(data);
279}
280
281static void
282isa_outb(int port, int value)
283{
284 u_char al = value;
285
286 if (__builtin_constant_p(port) &&
287 (((port) & 0xffff) < 0x100) &&
288 ((port) < 0x10000)) {
289 __asm __volatile("outb %0,%1" : : "a" (al), "id" ((u_short)(port)));
290 } else {
291 __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
292 }
293}
294