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