loadbsd.c revision 1.6.2.1 1 1.1 itohy /*
2 1.1 itohy * Load and boot NetBSD kernel on Human68k
3 1.1 itohy *
4 1.1 itohy * written by Yasha (ITOH Yasufumi)
5 1.1 itohy * public domain
6 1.1 itohy *
7 1.1 itohy * loadbsd [-hvV] [-abDs] [-r root_device] netbsd
8 1.1 itohy *
9 1.1 itohy * loadbsd options:
10 1.1 itohy * -h help
11 1.1 itohy * -V print version and exit
12 1.1 itohy *
13 1.1 itohy * kernel options:
14 1.1 itohy * -a auto boot, opposite of -s
15 1.1 itohy * -s single user boot (default)
16 1.1 itohy * -D enter kernel debugger
17 1.1 itohy * -b ask root device
18 1.1 itohy * -r specify root device
19 1.6 jdolecek * -q quiet boot
20 1.6 jdolecek * -v verbose boot (also turn on verbosity of loadbsd)
21 1.1 itohy *
22 1.6.2.1 nathanw * $NetBSD: loadbsd.c,v 1.6.2.1 2001/06/21 19:58:32 nathanw Exp $
23 1.1 itohy */
24 1.1 itohy
25 1.1 itohy #include <sys/cdefs.h>
26 1.1 itohy
27 1.6.2.1 nathanw __RCSID("$NetBSD: loadbsd.c,v 1.6.2.1 2001/06/21 19:58:32 nathanw Exp $");
28 1.6.2.1 nathanw #define VERSION "$Revision: 1.6.2.1 $ $Date: 2001/06/21 19:58:32 $"
29 1.1 itohy
30 1.1 itohy #include <sys/types.h> /* ntohl */
31 1.1 itohy #include <sys/reboot.h>
32 1.1 itohy #include <sys/param.h> /* ALIGN, ALIGNBYTES */
33 1.1 itohy #include <a.out.h>
34 1.1 itohy #include <string.h>
35 1.1 itohy #include <machine/bootinfo.h>
36 1.1 itohy
37 1.1 itohy #include <dos.h>
38 1.1 itohy #include <iocs.h>
39 1.1 itohy #include "../common/xprintf.h"
40 1.1 itohy #include "trampoline.h"
41 1.1 itohy
42 1.1 itohy #define DEFAULT_ROOTDEVNAME "sd@0,0:a"
43 1.1 itohy
44 1.1 itohy #define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
45 1.1 itohy
46 1.1 itohy #define GETDECIMAL(var, str) \
47 1.1 itohy do { var *= 10; var += *str++ - '0'; } while (ISDIGIT(*str))
48 1.1 itohy
49 1.1 itohy static const char *lookupif __P((const char *name,
50 1.1 itohy unsigned *pif, unsigned *punit));
51 1.1 itohy static void get_current_scsi_interface __P((unsigned *pif, unsigned *punit));
52 1.1 itohy static int bootdev __P((const char *devstr));
53 1.1 itohy static struct tramparg *read_kernel __P((const char *fn));
54 1.1 itohy static int chkmpu __P((void));
55 1.1 itohy static __dead void usage __P((int status, const char *msg))
56 1.1 itohy __attribute__((noreturn));
57 1.1 itohy
58 1.1 itohy int main __P((int argc, char *argv[]));
59 1.1 itohy
60 1.1 itohy int opt_v;
61 1.1 itohy int opt_N;
62 1.1 itohy
63 1.1 itohy const struct hatbl {
64 1.1 itohy char name[4];
65 1.1 itohy unsigned short id;
66 1.1 itohy } hatable[] = {
67 1.1 itohy X68K_BOOT_SCSIIF_LIST
68 1.1 itohy };
69 1.1 itohy
70 1.1 itohy /*
71 1.1 itohy * parse interface name
72 1.3 itohy * return the next position
73 1.1 itohy */
74 1.1 itohy static const char *
75 1.1 itohy lookupif(name, pif, punit)
76 1.1 itohy const char *name;
77 1.1 itohy unsigned *pif, *punit;
78 1.1 itohy {
79 1.1 itohy unsigned u, unit;
80 1.1 itohy const char *p;
81 1.1 itohy
82 1.1 itohy for (u = 0; u < sizeof hatable / sizeof hatable[0]; u++) {
83 1.1 itohy const char *n;
84 1.1 itohy
85 1.1 itohy for (n = hatable[u].name, p = name; *n && *n == *p; n++, p++)
86 1.1 itohy ;
87 1.1 itohy if (!*n)
88 1.1 itohy goto found;
89 1.1 itohy }
90 1.1 itohy /* not found */
91 1.1 itohy return (char *) 0;
92 1.1 itohy
93 1.1 itohy found:
94 1.1 itohy if (*p == '@')
95 1.1 itohy p++;
96 1.1 itohy
97 1.1 itohy /* get unit # */
98 1.1 itohy if (!ISDIGIT(*p))
99 1.1 itohy return (char *) 0;
100 1.1 itohy
101 1.1 itohy unit = 0;
102 1.1 itohy GETDECIMAL(unit, p);
103 1.1 itohy
104 1.1 itohy *pif = hatable[u].id;
105 1.1 itohy *punit = unit;
106 1.1 itohy
107 1.1 itohy return p;
108 1.1 itohy }
109 1.1 itohy
110 1.1 itohy /*
111 1.1 itohy * if the SCSI interface is not specified, use the current one
112 1.1 itohy */
113 1.1 itohy static void
114 1.1 itohy get_current_scsi_interface(pif, punit)
115 1.1 itohy unsigned *pif, *punit;
116 1.1 itohy {
117 1.1 itohy unsigned binf;
118 1.1 itohy char *bootrom;
119 1.1 itohy int bus_err_buf;
120 1.1 itohy
121 1.1 itohy binf = (unsigned) IOCS_BOOTINF();
122 1.1 itohy if (binf < 0x00fc0000)
123 1.1 itohy return; /* not booted from SCSI */
124 1.1 itohy
125 1.1 itohy bootrom = (char *) (binf & 0x00ffffe0);
126 1.1 itohy if (IOCS_B_LPEEK(bootrom + 0x24) == 0x53435349 && /* 'SCSI' */
127 1.1 itohy IOCS_B_WPEEK(bootrom + 0x28) == 0x494E) { /* 'IN' */
128 1.1 itohy /* spc0 */
129 1.1 itohy *pif = X68K_BOOT_SCSIIF_SPC;
130 1.1 itohy *punit = 0;
131 1.1 itohy } else if (DOS_BUS_ERR(&bus_err_buf, (void *)EXSPC_BDID, 1)) {
132 1.1 itohy /* mha0 */
133 1.1 itohy *pif = X68K_BOOT_SCSIIF_MHA;
134 1.1 itohy *punit = 0;
135 1.1 itohy } else {
136 1.1 itohy /* spc1 */
137 1.1 itohy *pif = X68K_BOOT_SCSIIF_SPC;
138 1.1 itohy *punit = 1;
139 1.1 itohy }
140 1.1 itohy }
141 1.1 itohy
142 1.1 itohy /*
143 1.1 itohy * parse device name
144 1.1 itohy *
145 1.1 itohy * [/<controller>@<unit>/]<device>@<unit>[,<lun>][:<partition>]
146 1.1 itohy *
147 1.1 itohy * <unit> must be target SCSI ID if <device> is a SCSI device
148 1.1 itohy *
149 1.1 itohy * full form:
150 1.1 itohy * /spc@0/sd@1,2:e
151 1.1 itohy *
152 1.1 itohy * partial form:
153 1.3 itohy * /mha@0/sd@1 = /mha@0/sd@1,0:a
154 1.1 itohy * sd@1:e = /current_device/sd@1,0e
155 1.1 itohy * sd@1,2:e = /current_device/sd@1,2:e
156 1.1 itohy */
157 1.1 itohy
158 1.1 itohy const struct devtbl {
159 1.1 itohy char name[3];
160 1.1 itohy u_char major;
161 1.1 itohy } devtable[] = {
162 1.4 minoura X68K_BOOT_DEV_LIST,
163 1.4 minoura X68K_BOOT_NETIF_LIST
164 1.1 itohy };
165 1.1 itohy
166 1.1 itohy static int
167 1.1 itohy bootdev(devstr)
168 1.1 itohy const char *devstr;
169 1.1 itohy {
170 1.1 itohy unsigned u;
171 1.1 itohy unsigned major, unit, lun, partition;
172 1.1 itohy int dev;
173 1.1 itohy const char *s = devstr;
174 1.1 itohy unsigned interface = 0, unit_if = 0;
175 1.1 itohy
176 1.1 itohy if (*s == '/') {
177 1.1 itohy /*
178 1.1 itohy * /<interface>/<device>"
179 1.1 itohy * "/spc@1/sd@2,3:e"
180 1.1 itohy */
181 1.1 itohy while (*++s == '/') /* skip slashes */
182 1.1 itohy ;
183 1.1 itohy if (!strchr(s, '/'))
184 1.1 itohy xerrx(1, "%s: bad format", devstr);
185 1.1 itohy
186 1.1 itohy if (!(s = lookupif(s, &interface, &unit_if)))
187 1.1 itohy xerrx(1, "%s: unknown interface", devstr);
188 1.1 itohy
189 1.1 itohy while (*s == '/') /* skip slashes */
190 1.1 itohy s++;
191 1.1 itohy } else {
192 1.1 itohy /* make lint happy */
193 1.1 itohy interface = 0;
194 1.1 itohy unit_if = 0;
195 1.1 itohy }
196 1.1 itohy
197 1.1 itohy /* allow r at the top */
198 1.1 itohy if (*s == 'r')
199 1.1 itohy s++;
200 1.1 itohy
201 1.1 itohy for (u = 0; u < sizeof devtable / sizeof devtable[0]; u++)
202 1.1 itohy if (s[0] == devtable[u].name[0] && s[1] == devtable[u].name[1])
203 1.1 itohy goto found;
204 1.1 itohy
205 1.1 itohy /* not found */
206 1.1 itohy xerrx(1, "%s: unknown device", devstr);
207 1.1 itohy
208 1.1 itohy found: major = devtable[u].major;
209 1.1 itohy
210 1.1 itohy /*
211 1.1 itohy * <type>@unit[,lun][:part]
212 1.1 itohy * "sd@1,3:a"
213 1.1 itohy */
214 1.1 itohy
215 1.1 itohy /* get device unit # */
216 1.1 itohy s += 2;
217 1.1 itohy if (*s == '@')
218 1.1 itohy s++;
219 1.1 itohy if (!*s)
220 1.1 itohy xerrx(1, "%s: missing unit number", devstr);
221 1.1 itohy if (!ISDIGIT(*s))
222 1.1 itohy xerrx(1, "%s: wrong device", devstr);
223 1.1 itohy
224 1.1 itohy unit = 0;
225 1.1 itohy GETDECIMAL(unit, s);
226 1.1 itohy
227 1.1 itohy lun = 0;
228 1.1 itohy if (*s == ',') {
229 1.1 itohy s++;
230 1.1 itohy if (!ISDIGIT(*s))
231 1.1 itohy xerrx(1, "%s: wrong device", devstr);
232 1.1 itohy GETDECIMAL(lun, s);
233 1.1 itohy }
234 1.1 itohy
235 1.1 itohy /* get device partition */
236 1.1 itohy if (*s == ':')
237 1.1 itohy s++;
238 1.1 itohy if (!*s)
239 1.1 itohy partition = 0; /* no partition letter -- assuming 'a' */
240 1.1 itohy else if (!s[1])
241 1.1 itohy partition = *s - 'a';
242 1.1 itohy else
243 1.1 itohy xerrx(1, "%s: wrong partition letter", devstr);
244 1.1 itohy
245 1.1 itohy /*
246 1.1 itohy * sanity check
247 1.1 itohy */
248 1.1 itohy if (unit_if >= 16)
249 1.1 itohy xerrx(1, "%s: interface unit # too large", devstr);
250 1.1 itohy if (unit >= 16)
251 1.1 itohy xerrx(1, "%s: device unit # too large", devstr);
252 1.1 itohy if (lun >= 8)
253 1.1 itohy xerrx(1, "%s: SCSI LUN >= 8 is not supported yet", devstr);
254 1.1 itohy if (partition >= 16)
255 1.1 itohy xerrx(1, "%s: unsupported partition", devstr);
256 1.1 itohy
257 1.1 itohy /*
258 1.1 itohy * encode device to be passed to kernel
259 1.1 itohy */
260 1.1 itohy if (X68K_BOOT_DEV_IS_SCSI(major)) {
261 1.1 itohy /*
262 1.1 itohy * encode SCSI device
263 1.1 itohy */
264 1.1 itohy if (interface == 0)
265 1.1 itohy get_current_scsi_interface(&interface, &unit_if);
266 1.1 itohy
267 1.1 itohy dev = X68K_MAKESCSIBOOTDEV(major, interface, unit_if,
268 1.1 itohy unit, lun, partition);
269 1.1 itohy } else {
270 1.1 itohy /* encode non-SCSI device */
271 1.1 itohy dev = X68K_MAKEBOOTDEV(major, unit, partition);
272 1.1 itohy }
273 1.1 itohy
274 1.1 itohy if (opt_v)
275 1.1 itohy xwarnx("%s: major %u, if %u, un_if %u, unit %u, lun %u, partition %u; bootdev 0x%x",
276 1.1 itohy devstr, major, interface, unit_if, unit, lun, partition, dev);
277 1.1 itohy
278 1.1 itohy return dev;
279 1.1 itohy }
280 1.1 itohy
281 1.1 itohy /*
282 1.1 itohy * read kernel and create trampoline
283 1.1 itohy *
284 1.1 itohy * |----------------------| <- allocated buf addr
285 1.1 itohy * | kernel image |
286 1.1 itohy * ~ (header is excluded) ~
287 1.1 itohy * | |
288 1.1 itohy * |----------------------| <- return value (entry addr of trampoline)
289 1.1 itohy * | struct tramparg |
290 1.1 itohy * | (trampoline args) |
291 1.1 itohy * |----------------------|
292 1.1 itohy * | trampoline code |
293 1.1 itohy * | (in assembly) |
294 1.1 itohy * |----------------------|
295 1.1 itohy */
296 1.1 itohy static struct tramparg *
297 1.1 itohy read_kernel(fn)
298 1.1 itohy const char *fn;
299 1.1 itohy {
300 1.1 itohy int fd;
301 1.1 itohy union dos_fcb *fcb;
302 1.1 itohy size_t filesize, nread;
303 1.1 itohy void *buf;
304 1.1 itohy struct exec hdr;
305 1.1 itohy int i;
306 1.1 itohy struct tramparg *arg;
307 1.1 itohy size_t size_tramp = end_trampoline - trampoline;
308 1.1 itohy
309 1.1 itohy if ((fd = DOS_OPEN(fn, 0x20)) < 0) /* RO, share READ */
310 1.1 itohy xerr(1, "%s: open", fn);
311 1.1 itohy
312 1.1 itohy if ((int)(fcb = DOS_GET_FCB_ADR(fd)) < 0)
313 1.1 itohy xerr(1, "%s: get_fcb_adr", fn);
314 1.1 itohy
315 1.1 itohy /*
316 1.1 itohy * XXX FCB is in supervisor area
317 1.1 itohy */
318 1.1 itohy /*if (fcb->blk.mode != 0)*/
319 1.1 itohy if (IOCS_B_BPEEK((char *)fcb + 1) & 0x80)
320 1.1 itohy xerrx(1, "%s: Not a regular file", fn);
321 1.1 itohy
322 1.1 itohy /*filesize = fcb->blk.size;*/
323 1.1 itohy filesize = IOCS_B_LPEEK(&fcb->blk.size);
324 1.1 itohy
325 1.1 itohy /*
326 1.1 itohy * read a.out header
327 1.1 itohy */
328 1.1 itohy if ((nread = DOS_READ(fd, (void *) &hdr, sizeof hdr)) != sizeof hdr) {
329 1.1 itohy if ((int)nread < 0)
330 1.1 itohy xerr(1, "%s: read header", fn);
331 1.1 itohy else
332 1.1 itohy xerrx(1, "%s: Not an a.out", fn);
333 1.1 itohy }
334 1.1 itohy /*
335 1.1 itohy * check header
336 1.1 itohy */
337 1.1 itohy if (N_GETMAGIC(hdr) != NMAGIC)
338 1.1 itohy xerrx(1, "%s: Bad magic number", fn);
339 1.1 itohy if ((i = N_GETMID(hdr)) != MID_M68K)
340 1.1 itohy xerrx(1, "%s: Wrong architecture (mid %d)", fn, i);
341 1.1 itohy
342 1.1 itohy if (opt_v)
343 1.1 itohy xwarnx("%s: %u bytes; text %u, data %u, bss %u, sym %u",
344 1.1 itohy fn, filesize, hdr.a_text, hdr.a_data,
345 1.1 itohy hdr.a_bss, hdr.a_syms);
346 1.1 itohy
347 1.1 itohy /*
348 1.1 itohy * then, read entire body
349 1.1 itohy */
350 1.1 itohy if ((int)(buf = DOS_MALLOC(filesize + ALIGNBYTES - sizeof hdr
351 1.1 itohy + sizeof(struct tramparg)
352 1.1 itohy + size_tramp + SIZE_TMPSTACK)) < 0)
353 1.1 itohy xerr(1, "read_kernel");
354 1.1 itohy
355 1.1 itohy if ((nread = DOS_READ(fd, buf, filesize - sizeof hdr))
356 1.1 itohy != filesize - sizeof hdr) {
357 1.1 itohy if ((int)nread < 0)
358 1.1 itohy xerr(1, "%s: read", fn);
359 1.1 itohy else
360 1.1 itohy xerrx(1, "%s: short read", fn);
361 1.1 itohy }
362 1.1 itohy
363 1.1 itohy if (DOS_CLOSE(fd) < 0)
364 1.1 itohy xerr(1, "%s: close", fn);
365 1.1 itohy
366 1.1 itohy /*
367 1.1 itohy * create argument for trampoline code
368 1.1 itohy */
369 1.1 itohy arg = (struct tramparg *) ALIGN(buf + nread);
370 1.1 itohy
371 1.1 itohy if (opt_v)
372 1.1 itohy xwarnx("trampoline arg at %p", arg);
373 1.1 itohy
374 1.2 minoura arg->bsr_inst = TRAMP_BSR + sizeof(struct tramparg) - 2;
375 1.1 itohy arg->tmp_stack = (char *) arg + sizeof(struct tramparg)
376 1.1 itohy + size_tramp + SIZE_TMPSTACK;
377 1.1 itohy arg->mpu_type = IOCS_MPU_STAT() & 0xff;
378 1.1 itohy arg->xk.image_top = buf;
379 1.1 itohy arg->xk.load_addr = 0x00000000; /* XXX should not be a fixed addr */
380 1.1 itohy arg->xk.text_size = hdr.a_text;
381 1.1 itohy arg->xk.data_size = hdr.a_data;
382 1.1 itohy arg->xk.bss_size = hdr.a_bss;
383 1.1 itohy arg->xk.symbol_size = hdr.a_syms;
384 1.1 itohy arg->xk.d5 = IOCS_BOOTINF(); /* unused for now */
385 1.1 itohy #if 0
386 1.1 itohy /* filled afterwards */
387 1.1 itohy arg->xk.rootdev =
388 1.1 itohy arg->xk.boothowto =
389 1.1 itohy #endif
390 1.1 itohy arg->xk.entry_addr = hdr.a_entry;
391 1.1 itohy
392 1.1 itohy if (opt_v)
393 1.1 itohy xwarnx("args: mpu %d, image %p, load 0x%x, entry 0x%x",
394 1.1 itohy arg->mpu_type, arg->xk.image_top, arg->xk.load_addr,
395 1.1 itohy arg->xk.entry_addr);
396 1.1 itohy
397 1.1 itohy /*
398 1.1 itohy * copy trampoline code
399 1.1 itohy */
400 1.1 itohy if (opt_v)
401 1.1 itohy xwarnx("trampoline code at %p (%u bytes)",
402 1.1 itohy (char *) arg + sizeof(struct tramparg), size_tramp);
403 1.1 itohy
404 1.1 itohy memcpy((char *) arg + sizeof(struct tramparg), trampoline, size_tramp);
405 1.1 itohy
406 1.1 itohy return arg;
407 1.1 itohy }
408 1.1 itohy
409 1.1 itohy /*
410 1.1 itohy * MC68000/010 -> return zero
411 1.1 itohy * MC68020 and later -> return nonzero
412 1.1 itohy */
413 1.1 itohy static int
414 1.1 itohy chkmpu()
415 1.1 itohy {
416 1.6.2.1 nathanw register int ret asm("%d0");
417 1.1 itohy
418 1.6.2.1 nathanw asm("| %0 <- this must be %%d0\n\
419 1.6.2.1 nathanw moveq #1,%%d0\n\
420 1.6.2.1 nathanw .long 0x103B02FF | foo: moveb %%pc@((foo+1)-foo-2:B,d0:W:2),%%d0\n\
421 1.1 itohy | ^ ^\n\
422 1.6.2.1 nathanw | %%d0.b = 0x02 (68000/010)\n\
423 1.1 itohy | = 0xff (68020 and later)\n\
424 1.1 itohy bmis 1f\n\
425 1.6.2.1 nathanw moveq #0,%%d0 | 68000/010\n\
426 1.1 itohy 1:" : "=d" (ret));
427 1.1 itohy
428 1.1 itohy return ret;
429 1.1 itohy }
430 1.1 itohy
431 1.1 itohy static __dead void
432 1.1 itohy usage(status, msg)
433 1.1 itohy int status;
434 1.1 itohy const char *msg;
435 1.1 itohy {
436 1.1 itohy extern const char *const __progname;
437 1.1 itohy
438 1.1 itohy if (msg)
439 1.1 itohy xwarnx("%s", msg);
440 1.1 itohy
441 1.1 itohy xerrprintf("\
442 1.1 itohy %s [-hvV] [-abDs] [-r root_device] netbsd\n\
443 1.1 itohy \n\
444 1.1 itohy loadbsd options:\n\
445 1.1 itohy \t-h help\n\
446 1.1 itohy \t-v verbose\n\
447 1.1 itohy \t-V print version and exit\n\
448 1.1 itohy \n\
449 1.1 itohy kernel options:\n\
450 1.1 itohy \t-a auto boot, opposite of -s\n\
451 1.1 itohy \t-s single user boot (default)\n\
452 1.1 itohy \t-D enter kernel debugger\n\
453 1.1 itohy \t-b ask root device\n\
454 1.1 itohy \t-r specify root device (default %s)\n\
455 1.1 itohy \t format: [/interface/]device@unit[,lun][:partition]\n\
456 1.1 itohy \t interface: one of spc@0, spc@1, mha@0\n\
457 1.1 itohy \t (current boot interface if omitted)\n\
458 1.4 minoura \t device: one of fd, sd, cd, md, ne\n\
459 1.1 itohy \t unit: device unit number (SCSI ID for SCSI device)\n\
460 1.1 itohy \t lun: SCSI LUN # (0 if omitted)\n\
461 1.1 itohy \t partition: partition letter ('a' if omitted)\n\
462 1.1 itohy ", __progname, DEFAULT_ROOTDEVNAME);
463 1.1 itohy
464 1.1 itohy DOS_EXIT2(status);
465 1.1 itohy }
466 1.1 itohy
467 1.1 itohy int
468 1.1 itohy main(argc, argv)
469 1.1 itohy int argc;
470 1.1 itohy char *argv[];
471 1.1 itohy {
472 1.1 itohy char *rootdevname = 0;
473 1.1 itohy int rootdev;
474 1.1 itohy u_long boothowto = RB_SINGLE;
475 1.1 itohy const char *kernel;
476 1.1 itohy char *p, **flg, **arg;
477 1.1 itohy struct tramparg *tramp;
478 1.1 itohy struct dos_dregs regs; /* unused... */
479 1.1 itohy int i;
480 1.1 itohy
481 1.1 itohy /* parse options */
482 1.1 itohy for (arg = flg = argv + 1; (p = *flg) && *p == '-'; ) {
483 1.1 itohy int c;
484 1.1 itohy
485 1.1 itohy while ((c = *++p))
486 1.1 itohy switch (c) {
487 1.1 itohy case 'h':
488 1.1 itohy usage(0, (char *) 0);
489 1.1 itohy /* NOTREACHED */
490 1.1 itohy break;
491 1.1 itohy case 'N': /* don't actually execute kernel */
492 1.1 itohy opt_N = 1;
493 1.1 itohy break;
494 1.1 itohy case 'v':
495 1.1 itohy opt_v = 1;
496 1.6 jdolecek boothowto |= AB_VERBOSE; /* XXX */
497 1.1 itohy break;
498 1.1 itohy case 'V':
499 1.1 itohy xprintf("loadbsd %s\n", VERSION);
500 1.1 itohy return 0;
501 1.1 itohy
502 1.1 itohy /*
503 1.1 itohy * kernel boot flags
504 1.1 itohy */
505 1.1 itohy case 'r':
506 1.1 itohy if (rootdevname)
507 1.1 itohy usage(1, "multiple -r flags");
508 1.1 itohy else if (!*++arg)
509 1.1 itohy usage(1, "-r requires device name");
510 1.1 itohy else
511 1.1 itohy rootdevname = *arg;
512 1.1 itohy break;
513 1.1 itohy case 'b':
514 1.1 itohy boothowto |= RB_ASKNAME;
515 1.1 itohy break;
516 1.1 itohy case 'a':
517 1.1 itohy boothowto &= ~RB_SINGLE;
518 1.1 itohy break;
519 1.1 itohy case 's':
520 1.1 itohy boothowto |= RB_SINGLE;
521 1.1 itohy break;
522 1.1 itohy case 'D':
523 1.1 itohy boothowto |= RB_KDB;
524 1.6 jdolecek break;
525 1.6 jdolecek case 'q':
526 1.6 jdolecek boothowto |= AB_QUIET;
527 1.1 itohy break;
528 1.1 itohy
529 1.1 itohy default:
530 1.1 itohy usage(1, (char *) 0);
531 1.1 itohy /* NOTREACHED */
532 1.1 itohy break;
533 1.1 itohy }
534 1.1 itohy flg = ++arg;
535 1.1 itohy }
536 1.1 itohy
537 1.1 itohy /* check MPU */
538 1.1 itohy if (chkmpu() == 0)
539 1.1 itohy xerrx(1, "Can't boot NetBSD on 68000/010");
540 1.1 itohy
541 1.1 itohy argc -= arg - argv;
542 1.1 itohy argv = arg;
543 1.1 itohy
544 1.1 itohy if (argc != 1)
545 1.1 itohy usage(1, (char *) 0);
546 1.1 itohy
547 1.1 itohy kernel = *argv;
548 1.1 itohy
549 1.1 itohy rootdev = bootdev(rootdevname ? rootdevname : DEFAULT_ROOTDEVNAME);
550 1.1 itohy
551 1.1 itohy if (opt_v)
552 1.1 itohy xwarnx("boothowto 0x%x", boothowto);
553 1.1 itohy
554 1.1 itohy tramp = read_kernel(kernel);
555 1.1 itohy
556 1.1 itohy tramp->xk.rootdev = rootdev;
557 1.1 itohy tramp->xk.boothowto = boothowto;
558 1.1 itohy
559 1.1 itohy /*
560 1.3 itohy * we never return, and make sure the disk cache
561 1.1 itohy * be flushed (if write-back cache is enabled)
562 1.1 itohy */
563 1.1 itohy if (opt_v)
564 1.1 itohy xwarnx("flush disk cache...");
565 1.1 itohy
566 1.1 itohy i = DOS_FFLUSH_SET(1); /* enable fflush */
567 1.1 itohy DOS_FFLUSH(); /* then, issue fflush */
568 1.1 itohy (void) DOS_FFLUSH_SET(i); /* restore old mode just in case */
569 1.1 itohy
570 1.1 itohy /*
571 1.1 itohy * the program assumes the MPU caches off
572 1.1 itohy */
573 1.1 itohy if (opt_v)
574 1.1 itohy xwarnx("flush and disable MPU caches...");
575 1.1 itohy
576 1.1 itohy IOCS_CACHE_MD(-1); /* flush */
577 1.1 itohy if (!opt_N)
578 1.1 itohy IOCS_CACHE_MD(0); /* disable both caches */
579 1.1 itohy
580 1.1 itohy if (opt_v)
581 1.1 itohy xwarnx("Jumping to the kernel. Good Luck!");
582 1.1 itohy
583 1.1 itohy if (opt_N)
584 1.1 itohy xerrx(0, "But don't actually do it.");
585 1.1 itohy
586 1.1 itohy DOS_SUPER_JSR((void (*) __P((void))) tramp, ®s, ®s);
587 1.1 itohy
588 1.1 itohy /* NOTREACHED */
589 1.1 itohy
590 1.1 itohy xwarnx("??? return from kernel");
591 1.1 itohy
592 1.1 itohy return 1;
593 1.1 itohy }
594