1/* $NetBSD: loadbsd.c,v 1.34 2009/10/21 23:53:38 snj Exp $ */ 2 3/* 4 * Copyright (c) 1994 Michael L. Hitch 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include <errno.h> 29#include <stdio.h> 30#include <stdlib.h> 31#include <string.h> 32#include <stdarg.h> 33#include <err.h> 34 35#include <exec/memory.h> 36#include <exec/execbase.h> 37#include <exec/resident.h> 38#include <graphics/gfxbase.h> 39#include <libraries/expansion.h> 40#include <libraries/expansionbase.h> 41#include <libraries/configregs.h> 42#include <libraries/configvars.h> 43#include <proto/expansion.h> 44#include <proto/graphics.h> 45#include <proto/exec.h> 46#include <proto/dos.h> 47 48/* Get definitions for boothowto */ 49#include "sys/reboot.h" 50#include "inttypes.h" 51#include "loadfile.h" 52 53#undef AOUT_LDPGSZ 54#define AOUT_LDPGSZ 8192 55 56#undef sleep 57#define sleep(n) if (!t_flag) (void)Delay(50*n) 58 59/* 60 * Version history: 61 * 1.x Kernel startup interface version check. 62 * 2.0 Added symbol table end address and symbol table support. 63 * 2.1 03/23/94 - Round up end of fastram segment. 64 * Check fastram segment size for minimum of 2M. 65 * Use largest segment of highest priority if -p option. 66 * Print out fastram size in KB if not a multiple of MB. 67 * 2.2 03/24/94 - Zero out all unused registers. 68 * Started version history comment. 69 * 2.3 04/26/94 - Added -D option to enter debugger on boot. 70 * 2.4 04/30/94 - Cpuid includes base machine type. 71 * Also check if CPU is capable of running NetBSD. 72 * 2.5 05/17/94 - Add check for "A3000 bonus". 73 * 2.6 06/05/94 - Added -c option to override machine type. 74 * 2.7 06/15/94 - Pass E clock frequency. 75 * 2.8 06/22/94 - Fix supervisor stack usage. 76 * 2.9 06/26/94 - Use PAL flag for E clock freq on pre 2.0 WB 77 * Added AGA enable parameter 78 * 2.10 12/22/94 - Use FindResident() & OpenResource() for machine 79 * type detection. 80 * Add -n flag & option for non-contiguous memory. 81 * 01/28/95 - Corrected -n on usage & help messages. 82 * 2.11 03/12/95 - Check kernel size against chip memory size. 83 * 2.12 11/11/95 - Add -I option to inhibit synchronous transfer 84 * 11/12/95 - New kernel startup interface version - to 85 * support loading kernel image to fastmem rather than chipmem. 86 * 2.13 04/15/96 - Direct load to fastmem. 87 * Add -Z flag to force chipmem load. 88 * Moved test mode exit to later - kernel image is created 89 * and startup interface version checked in test mode. 90 * Add -s flag for compatibility to bootblock loader. 91 * 05/02/96 - Add a maximum startup interface version level 92 * to allow future kernel compatibility. 93 * 2.14 06/26/96 is - Add first version of kludges needed to 94 * boot on DraCos. This can probably be done a bit more cleanly 95 * using TTRs, but it works for now. 96 * 2.15 07/28/96 is - Add first version of kludges needed to 97 * get FusionForty kickrom'd memory back. Hope this doesn't 98 * break anything else. 99 * 2.16 07/08/00 - Added bootverbose support. 100 * 01/15/03 - Plugged resource leaks. 101 * Fixed printf() statements. 102 * Ansified. 103 * 3.0 01/16/03 - ELF support through loadfile() interface. 104 */ 105static const char _version[] = "$VER: LoadBSD 3.0 (16.1.2003)"; 106 107/* 108 * Kernel startup interface version 109 * 1: first version of loadbsd 110 * 2: needs esym location passed in a4 111 * 3: load kernel image into fastmem rather than chipmem 112 * MAX: highest version with backward compatibility. 113 */ 114#define KERNEL_STARTUP_VERSION 3 115#define KERNEL_STARTUP_VERSION_MAX 9 116 117#define DRACOREVISION (*(UBYTE *)0x02000009) 118#define DRACOMMUMARGIN 0x200000 119 120#define MAXMEMSEG 16 121struct boot_memlist { 122 u_int m_nseg; /* num_mem; */ 123 struct boot_memseg { 124 u_int ms_start; 125 u_int ms_size; 126 u_short ms_attrib; 127 short ms_pri; 128 } m_seg[MAXMEMSEG]; 129}; 130struct boot_memlist memlist; 131struct boot_memlist *kmemlist; 132 133void get_mem_config (void **, u_long *, u_long *); 134void get_cpuid (void); 135void get_eclock (void); 136void get_AGA (void); 137void usage (void); 138void verbose_usage (void); 139void startit (void *, u_long, u_long, void *, u_long, u_long, int, void *, 140 int, int, u_long, u_long, int); 141extern u_long startit_sz; 142 143extern char *optarg; 144extern int optind; 145 146struct ExpansionBase *ExpansionBase = NULL; 147struct GfxBase *GfxBase = NULL; 148 149int k_flag; 150int p_flag; 151int t_flag; 152int reqmemsz; 153int S_flag; 154u_long I_flag; 155int Z_flag; 156u_long cpuid; 157long eclock_freq; 158long amiga_flags; 159char *program_name; 160u_char *kp; 161u_long kpsz; 162 163void 164exit_func(void) 165{ 166 if (kp) 167 FreeMem(kp, kpsz); 168 if (ExpansionBase) 169 CloseLibrary((struct Library *)ExpansionBase); 170 if (GfxBase) 171 CloseLibrary((struct Library *)GfxBase); 172} 173 174int 175main(int argc, char **argv) 176{ 177 struct ConfigDev *cd, *kcd; 178 u_long fmemsz, cmemsz, ksize, marks[MARK_MAX]; 179 int boothowto, ncd, i, mem_ix, ch; 180 u_short kvers; 181 int *nkcd; 182 void *fmem; 183 char *esym; 184 void (*start_it) (void *, u_long, u_long, void *, u_long, u_long, 185 int, void *, int, int, u_long, u_long, int) = startit; 186 char *kernel_name; 187 188 atexit(exit_func); 189 190 program_name = argv[0]; 191 boothowto = RB_SINGLE; 192 193 if (argc < 2) 194 usage(); 195 196 if ((GfxBase = (void *)OpenLibrary(GRAPHICSNAME, 0)) == NULL) 197 err(20, "can't open graphics library"); 198 if ((ExpansionBase=(void *)OpenLibrary(EXPANSIONNAME, 0)) == NULL) 199 err(20, "can't open expansion library"); 200 201 while ((ch = getopt(argc, argv, "aAbCc:DhI:km:n:qptsSvVZ")) != -1) { 202 switch (ch) { 203 case 'k': 204 k_flag = 1; 205 break; 206 case 'a': 207 boothowto &= ~(RB_SINGLE); 208 boothowto |= RB_AUTOBOOT; 209 break; 210 case 'b': 211 boothowto |= RB_ASKNAME; 212 break; 213 case 'p': 214 p_flag = 1; 215 break; 216 case 't': 217 t_flag = 1; 218 break; 219 case 'm': 220 reqmemsz = atoi(optarg) * 1024; 221 break; 222 case 's': 223 boothowto &= ~(RB_AUTOBOOT); 224 boothowto |= RB_SINGLE; 225 break; 226 case 'q': 227 boothowto |= AB_QUIET; 228 break; 229 case 'v': 230 boothowto |= AB_VERBOSE; 231 break; 232 case 'V': 233 fprintf(stderr,"%s\n",_version + 6); 234 break; 235 case 'S': 236 S_flag = 1; 237 break; 238 case 'D': 239 boothowto |= RB_KDB; 240 break; 241 case 'c': 242 cpuid = atoi(optarg) << 16; 243 break; 244 case 'A': 245 amiga_flags |= 1; 246 break; 247 case 'n': 248 i = atoi(optarg); 249 if (i >= 0 && i <= 3) 250 amiga_flags |= i << 1; 251 else 252 err(20, "-n option must be 0, 1, 2, or 3"); 253 break; 254 case 'C': 255 amiga_flags |= (1 << 3); 256 break; 257 case 'I': 258 I_flag = strtoul(optarg, NULL, 16); 259 break; 260 case 'Z': 261 Z_flag = 1; 262 break; 263 case 'h': 264 verbose_usage(); 265 default: 266 usage(); 267 } 268 } 269 argc -= optind; 270 argv += optind; 271 272 if (argc != 1) 273 usage(); 274 275 kernel_name = argv[0]; 276 277 for (cd = 0, ncd = 0; cd = FindConfigDev(cd, -1, -1); ncd++) 278 ; 279 get_cpuid(); 280 get_mem_config(&fmem, &fmemsz, &cmemsz); 281 get_eclock(); 282 get_AGA(); 283 284/* 285 * XXX Call loadfile with COUNT* options to get size 286 * XXX Allocate memory for kernel + additional data 287 * XXX Call loadfile with LOAD* options to load text/data/symbols 288 */ 289 marks[MARK_START] = 0; 290 if (loadfile(kernel_name, marks, 291 COUNT_TEXT|COUNT_TEXTA|COUNT_DATA|COUNT_BSS| 292 (S_flag ? (COUNT_SYM|COUNT_HDR) : 0)) == -1) { 293 err(20, "unable to parse kernel image"); 294 } 295 ksize = ((marks[MARK_END] + 3) & ~3) 296 + sizeof(*nkcd) + ncd * sizeof(*cd) 297 + sizeof(*nkcd) + memlist.m_nseg * sizeof(struct boot_memseg); 298 299 if (t_flag) { 300 for (i = 0; i < memlist.m_nseg; ++i) { 301 printf("mem segment %d: start=%08lx size=%08lx" 302 " attribute=%04lx pri=%d\n", 303 i + 1, 304 memlist.m_seg[i].ms_start, 305 memlist.m_seg[i].ms_size, 306 memlist.m_seg[i].ms_attrib, 307 memlist.m_seg[i].ms_pri); 308 } 309 printf("kernel size: %ld\n", ksize); 310 } 311 312 kpsz = ksize + 256 + startit_sz; 313 kp = (u_char *)AllocMem(kpsz, MEMF_FAST|MEMF_REVERSE); 314 if (kp == NULL) 315 err(20, "failed alloc %d", ksize); 316 317 marks[MARK_START] = (u_long)kp; 318 if (loadfile(kernel_name, marks, 319 LOAD_TEXT|LOAD_TEXTA|LOAD_DATA|LOAD_BSS| 320 (S_flag ? (LOAD_SYM|LOAD_HDR) : 0)) == -1) { 321 err(20, "unable to load kernel image"); 322 } 323 marks[MARK_END] = (marks[MARK_END] + 3) & ~3; 324 325 if (k_flag) { 326 fmem += 4 * 1024 * 1024; 327 fmemsz -= 4 * 1024 * 1024; 328 } 329 if (reqmemsz && reqmemsz <= fmemsz) 330 fmemsz = reqmemsz; 331 332 if (boothowto & RB_AUTOBOOT) 333 printf("Autobooting..."); 334 if (boothowto & RB_ASKNAME) 335 printf("Askboot..."); 336 337 printf("Using %ld%c FASTMEM at 0x%lx, %ldM CHIPMEM\n", 338 (fmemsz & 0xfffff) ? fmemsz >> 10 : fmemsz >> 20, 339 (fmemsz & 0xfffff) ? 'K' : 'M', (u_long)fmem, cmemsz >> 20); 340 341 kvers = *(u_short *)(marks[MARK_ENTRY] - 2); 342 if (kvers == 0x4e73) kvers = 0; 343 if (kvers > KERNEL_STARTUP_VERSION_MAX) 344 err(20, "newer loadbsd required: %d\n", kvers); 345 if (kvers > KERNEL_STARTUP_VERSION) { 346 printf("****************************************************\n" 347 "*** Notice: this kernel has features which require\n" 348 "*** a newer version of loadbsd. To allow the use of\n" 349 "*** any newer features or capabilities, you should\n" 350 "*** update to a newer version of loadbsd\n" 351 "****************************************************\n"); 352 sleep(3); /* even more time to see that message */ 353 } 354 355 /* 356 * give them a chance to read the information... 357 */ 358 sleep(2); 359 360 nkcd = (int *)marks[MARK_END]; 361 esym = 0; 362 /* 363 * If symbols loaded and kernel can handle them, set esym to end. 364 */ 365 if (marks[MARK_SYM] != marks[MARK_START]) { 366 if (kvers > 1) { 367 esym = (void *)(marks[MARK_END] - marks[MARK_START]); 368 } 369 else { 370 /* 371 * suppress symbols 372 */ 373 nkcd = (int *)marks[MARK_SYM]; 374 } 375 } 376 377 *nkcd = ncd; 378 kcd = (struct ConfigDev *)(nkcd + 1); 379 while((cd = FindConfigDev(cd, -1, -1))) { 380 memcpy(kcd, cd, sizeof(*kcd)); 381 if (((cpuid >> 24) == 0x7d) && 382 ((u_long)kcd->cd_BoardAddr < 0x1000000)) { 383 if (t_flag) 384 printf("Transformed Z2 device from %08lx ", (u_long)kcd->cd_BoardAddr); 385 kcd->cd_BoardAddr += 0x3000000; 386 if (t_flag) 387 printf("to %08lx\n", (u_long)kcd->cd_BoardAddr); 388 } 389 ++kcd; 390 } 391 392 kmemlist = (struct boot_memlist *)kcd; 393 kmemlist->m_nseg = memlist.m_nseg; 394 for (mem_ix = 0; mem_ix < memlist.m_nseg; mem_ix++) 395 kmemlist->m_seg[mem_ix] = memlist.m_seg[mem_ix]; 396 397 if (kvers > 2 && Z_flag == 0) { 398 /* 399 * Kernel supports direct load to fastmem, and the -Z 400 * option was not specified. Copy startup code to end 401 * of kernel image and set start_it. 402 */ 403 if ((void *)kp < fmem) { 404 printf("Kernel at %08lx, Fastmem used at %08lx\n", 405 (u_long)kp, (u_long)fmem); 406 err(20, "Can't copy upwards yet.\nDefragment your memory and try again OR try the -p OR try the -Z options."); 407 } 408 start_it = (void (*)())kp + ksize + 256; 409 memcpy(start_it, startit, startit_sz); 410 CacheClearU(); 411 printf("*** Loading from %08lx to Fastmem %08lx ***\n", 412 (u_long)kp, (u_long)fmem); 413 sleep(2); 414 } else { 415 /* 416 * Either the kernel doesn't suppport loading directly to 417 * fastmem or the -Z flag was given. Verify kernel image 418 * fits into chipmem. 419 */ 420 if (ksize >= cmemsz) { 421 printf("Kernel size %ld exceeds Chip Memory of %ld\n", 422 ksize, cmemsz); 423 err(20, "Insufficient Chip Memory for kernel"); 424 } 425 Z_flag = 1; 426 printf("*** Loading from %08lx to Chipmem ***\n", (u_long)kp); 427 } 428 429 /* 430 * if test option set, done 431 */ 432 if (t_flag) { 433 exit(0); 434 } 435 436 /* 437 * XXX AGA startup - may need more 438 */ 439 LoadView(NULL); /* Don't do this if AGA active? */ 440 start_it(kp, ksize, marks[MARK_ENTRY] - marks[MARK_START], fmem, fmemsz, cmemsz, 441 boothowto, esym, cpuid, eclock_freq, amiga_flags, I_flag, Z_flag == 0); 442 /*NOTREACHED*/ 443} 444 445void 446get_mem_config(void **fmem, u_long *fmemsz, u_long *cmemsz) 447{ 448 struct MemHeader *mh, *nmh; 449 u_int nmem, eseg, segsz, seg, nseg, nsegsz; 450 char mempri; 451 452 nmem = 0; 453 mempri = -128; 454 *fmemsz = 0; 455 *cmemsz = 0; 456 457 /* 458 * walk thru the exec memory list 459 */ 460 Forbid(); 461 for (mh = (void *) SysBase->MemList.lh_Head; 462 nmh = (void *) mh->mh_Node.ln_Succ; mh = nmh) { 463 464 nseg = (u_int)mh->mh_Lower; 465 nsegsz = (u_int)mh->mh_Upper - nseg; 466 467 segsz = nsegsz; 468 seg = (u_int)CachePreDMA((APTR)nseg, (LONG *)&segsz, 0L); 469 nsegsz -= segsz, nseg += segsz; 470 for (;segsz; 471 segsz = nsegsz, 472 seg = (u_int)CachePreDMA((APTR)nseg, (LONG *)&segsz, DMA_Continue), 473 nsegsz -= segsz, nseg += segsz, ++nmem) { 474 475 if (t_flag) 476 printf("Translated %08x sz %08x to %08x sz %08x\n", 477 nseg - segsz, nsegsz + segsz, seg, segsz); 478 479 eseg = seg + segsz; 480 481 if ((cpuid >> 24) == 0x7D) { 482 /* DraCo MMU table kludge */ 483 484 segsz = ((segsz -1) | 0xfffff) + 1; 485 seg = eseg - segsz; 486 487 /* 488 * Only use first SIMM to boot; we know it is VA==PA. 489 * Enter into table and continue. Yes, 490 * this is ugly. 491 */ 492 if (seg != 0x40000000) { 493 memlist.m_seg[nmem].ms_attrib = mh->mh_Attributes; 494 memlist.m_seg[nmem].ms_pri = mh->mh_Node.ln_Pri; 495 memlist.m_seg[nmem].ms_size = segsz; 496 memlist.m_seg[nmem].ms_start = seg; 497 ++nmem; 498 continue; 499 } 500 501 memlist.m_seg[nmem].ms_attrib = mh->mh_Attributes; 502 memlist.m_seg[nmem].ms_pri = mh->mh_Node.ln_Pri; 503 memlist.m_seg[nmem].ms_size = DRACOMMUMARGIN; 504 memlist.m_seg[nmem].ms_start = seg; 505 506 ++nmem; 507 seg += DRACOMMUMARGIN; 508 segsz -= DRACOMMUMARGIN; 509 } 510 511 memlist.m_seg[nmem].ms_attrib = mh->mh_Attributes; 512 memlist.m_seg[nmem].ms_pri = mh->mh_Node.ln_Pri; 513 memlist.m_seg[nmem].ms_size = segsz; 514 memlist.m_seg[nmem].ms_start = seg; 515 516 if ((mh->mh_Attributes & (MEMF_CHIP|MEMF_FAST)) == MEMF_CHIP) { 517 /* 518 * there should hardly be more than one entry for 519 * chip mem, but handle it the same nevertheless 520 * cmem always starts at 0, so include vector area 521 */ 522 memlist.m_seg[nmem].ms_start = seg = 0; 523 /* 524 * round to multiple of 512K 525 */ 526 segsz = (segsz + 512 * 1024 - 1) & -(512 * 1024); 527 memlist.m_seg[nmem].ms_size = segsz; 528 if (segsz > *cmemsz) 529 *cmemsz = segsz; 530 continue; 531 } 532 /* 533 * some heuristics.. 534 */ 535 seg &= -AOUT_LDPGSZ; 536 eseg = (eseg + AOUT_LDPGSZ - 1) & -AOUT_LDPGSZ; 537 538 /* 539 * get the mem back stolen by incore kickstart on 540 * A3000 with V36 bootrom. 541 */ 542 if (eseg == 0x07f80000) 543 eseg = 0x08000000; 544 545 /* 546 * or by zkick on a A2000. 547 */ 548 if (seg == 0x280000 && 549 strcmp(mh->mh_Node.ln_Name, "zkick memory") == 0) 550 seg = 0x200000; 551 /* 552 * or by Fusion Forty fastrom 553 */ 554 if ((seg & ~(1024*1024-1)) == 0x11000000) { 555 /* 556 * XXX we should test the name. 557 * Unfortunately, the memory is just called 558 * "32 bit memory" which isn't very specific. 559 */ 560 seg = 0x11000000; 561 } 562 563 segsz = eseg - seg; 564 memlist.m_seg[nmem].ms_start = seg; 565 memlist.m_seg[nmem].ms_size = segsz; 566 /* 567 * If this segment is smaller than 2M, 568 * don't use it to load the kernel 569 */ 570 if (segsz < 2 * 1024 * 1024) 571 continue; 572 /* 573 * if p_flag is set, select memory by priority 574 * instead of size 575 */ 576 if ((!p_flag && segsz > *fmemsz) || (p_flag && 577 mempri <= mh->mh_Node.ln_Pri && segsz > *fmemsz)) { 578 *fmemsz = segsz; 579 *fmem = (void *)seg; 580 mempri = mh->mh_Node.ln_Pri; 581 } 582 583 } 584 } 585 memlist.m_nseg = nmem; 586 Permit(); 587} 588 589/* 590 * Try to determine the machine ID by searching the resident module list 591 * for modules only present on specific machines. (Thanks, Bill!) 592 */ 593void 594get_cpuid(void) 595{ 596 cpuid |= SysBase->AttnFlags; /* get FPU and CPU flags */ 597 if ((cpuid & AFB_68020) == 0) 598 err(20, "CPU not supported"); 599 if (cpuid & 0xffff0000) { 600 if ((cpuid >> 24) == 0x7D) 601 return; 602 603 switch (cpuid >> 16) { 604 case 500: 605 case 600: 606 case 1000: 607 case 1200: 608 case 2000: 609 case 3000: 610 case 4000: 611 return; 612 default: 613 printf("machine Amiga %ld is not recognized\n", 614 cpuid >> 16); 615 exit(1); 616 } 617 } 618 if (FindResident("A4000 Bonus") || FindResident("A4000 bonus") 619 || FindResident("A1000 Bonus")) 620 cpuid |= 4000 << 16; 621 else if (FindResident("A3000 Bonus") || FindResident("A3000 bonus")) 622 cpuid |= 3000 << 16; 623 else if (OpenResource("card.resource")) { 624 /* Test for AGA? */ 625 cpuid |= 1200 << 16; 626 } else if (OpenResource("draco.resource")) { 627 cpuid |= (32000 | DRACOREVISION) << 16; 628 } 629 /* 630 * Nothing found, it's probably an A2000 or A500 631 */ 632 if ((cpuid >> 16) == 0) 633 cpuid |= 2000 << 16; 634} 635 636void 637get_eclock(void) 638{ 639 /* Fix for 1.3 startups? */ 640 if (SysBase->LibNode.lib_Version > 36) 641 eclock_freq = SysBase->ex_EClockFrequency; 642 else 643 eclock_freq = (GfxBase->DisplayFlags & PAL) ? 644 709379 : 715909; 645} 646 647void 648get_AGA(void) 649{ 650 /* 651 * Determine if an AGA mode is active 652 */ 653} 654 655__asm(" 656 .text 657 658_startit: 659 movel sp,a3 660 movel 4:w,a6 661 lea pc@(start_super),a5 662 jmp a6@(-0x1e) | supervisor-call 663 664start_super: 665 movew #0x2700,sr 666 667 | the BSD kernel wants values into the following registers: 668 | a0: fastmem-start 669 | d0: fastmem-size 670 | d1: chipmem-size 671 | d3: Amiga specific flags 672 | d4: E clock frequency 673 | d5: AttnFlags (cpuid) 674 | d7: boothowto 675 | a4: esym location 676 | a2: Inhibit sync flags 677 | All other registers zeroed for possible future requirements. 678 679 lea pc@(_startit),sp | make sure we have a good stack *** 680 681 movel a3@(4),a1 | loaded kernel 682 movel a3@(8),d2 | length of loaded kernel 683| movel a3@(12),sp | entry point in stack pointer 684 movel a3@(12),a6 | push entry point *** 685 movel a3@(16),a0 | fastmem-start 686 movel a3@(20),d0 | fastmem-size 687 movel a3@(24),d1 | chipmem-size 688 movel a3@(28),d7 | boothowto 689 movel a3@(32),a4 | esym 690 movel a3@(36),d5 | cpuid 691 movel a3@(40),d4 | E clock frequency 692 movel a3@(44),d3 | Amiga flags 693 movel a3@(48),a2 | Inhibit sync flags 694 movel a3@(52),d6 | Load to fastmem flag 695 subl a5,a5 | target, load to 0 696 697 cmpb #0x7D,a3@(36) | is it DraCo? 698 beq nott | yes, switch off MMU later 699 700 | no, it is an Amiga: 701 702| movew #0xf00,0xdff180 |red 703| moveb #0,0x200003c8 704| moveb #63,0x200003c9 705| moveb #0,0x200003c9 706| moveb #0,0x200003c9 707 708 movew #(1<<9),0xdff096 | disable DMA on Amigas. 709 710| ------ mmu off start ----- 711 712 btst #3,d5 | AFB_68040,SysBase->AttnFlags 713 beq not040 714 715| Turn off 68040/060 MMU 716 717 subl a3,a3 718 .word 0x4e7b,0xb003 | movec a3,tc 719 .word 0x4e7b,0xb806 | movec a3,urp 720 .word 0x4e7b,0xb807 | movec a3,srp 721 .word 0x4e7b,0xb004 | movec a3,itt0 722 .word 0x4e7b,0xb005 | movec a3,itt1 723 .word 0x4e7b,0xb006 | movec a3,dtt0 724 .word 0x4e7b,0xb007 | movec a3,dtt1 725 bra nott 726 727not040: 728 lea pc@(zero),a3 729 pmove a3@,tc | Turn off MMU 730 lea pc@(nullrp),a3 731 pmove a3@,crp | Turn off MMU some more 732 pmove a3@,srp | Really, really, turn off MMU 733 734| Turn off 68030 TT registers 735 736 btst #2,d5 | AFB_68030,SysBase->AttnFlags 737 beq nott | Skip TT registers if not 68030 738 lea pc@(zero),a3 739 .word 0xf013,0x0800 | pmove a3@,tt0 (gas only knows about 68851 ops..) 740 .word 0xf013,0x0c00 | pmove a3@,tt1 (gas only knows about 68851 ops..) 741 742nott: 743| ---- mmu off end ---- 744| movew #0xf60,0xdff180 | orange 745| moveb #0,0x200003c8 746| moveb #63,0x200003c9 747| moveb #24,0x200003c9 748| moveb #0,0x200003c9 749 750| ---- copy kernel start ---- 751 752 tstl d6 | Can we load to fastmem? 753 beq L0 | No, leave destination at 0 754 movl a0,a5 | Move to start of fastmem chunk 755 addl a0,a6 | relocate kernel entry point 756L0: 757 movl a1@+,a5@+ 758 subl #4,d2 759 bcc L0 760 761 lea pc@(ckend),a1 762 movl a5,sp@- 763 movl #_startit_end - ckend,d2 764L2: 765 movl a1@+,a5@+ 766 subl #4,d2 767 bcc L2 768 769 btst #3,d5 770 jeq L1 771 .word 0xf4f8 772L1: 773 movql #0,d2 | switch off cache to ensure we use 774 movec d2,cacr | valid kernel data 775 776| movew #0xFF0,0xdff180 | yellow 777| moveb #0,0x200003c8 778| moveb #63,0x200003c9 779| moveb #0,0x200003c9 780| moveb #0,0x200003c9 781 rts 782 783| ---- copy kernel end ---- 784 785ckend: 786| movew #0x0ff,0xdff180 | petrol 787| moveb #0,0x200003c8 788| moveb #0,0x200003c9 789| moveb #63,0x200003c9 790| moveb #63,0x200003c9 791 792 movl d5,d2 793 roll #8,d2 794 cmpb #0x7D,d2 795 jne noDraCo 796 797| DraCo: switch off MMU now: 798 799 subl a3,a3 800 .word 0x4e7b,0xb003 | movec a3,tc 801 .word 0x4e7b,0xb806 | movec a3,urp 802 .word 0x4e7b,0xb807 | movec a3,srp 803 .word 0x4e7b,0xb004 | movec a3,itt0 804 .word 0x4e7b,0xb005 | movec a3,itt1 805 .word 0x4e7b,0xb006 | movec a3,dtt0 806 .word 0x4e7b,0xb007 | movec a3,dtt1 807 808noDraCo: 809 moveq #0,d2 | zero out unused registers 810 moveq #0,d6 | (might make future compatibility 811 movel d6,a1 | would have known contents) 812 movel d6,a3 813 movel d6,a5 814 movel a6,sp | entry point into stack pointer 815 movel d6,a6 816 817| movew #0x0F0,0xdff180 | green 818| moveb #0,0x200003c8 819| moveb #0,0x200003c9 820| moveb #63,0x200003c9 821| moveb #0,0x200003c9 822 823 jmp sp@ | jump to kernel entry point 824 825| A do-nothing MMU root pointer (includes the following long as well) 826 827nullrp: .long 0x7fff0001 828zero: .long 0 829 830_startit_end: 831 832 .data 833_startit_sz: .long _startit_end-_startit 834 835 .text 836"); 837 838void 839usage(void) 840{ 841 fprintf(stderr, "usage: %s [-abhkpstACDSVZ] [-c machine] [-m mem] [-n mode] [-I sync-inhibit] kernel\n", 842 program_name); 843 exit(1); 844} 845 846void 847verbose_usage(void) 848{ 849 fprintf(stderr, " 850NAME 851\t%s - loads NetBSD from amiga dos. 852SYNOPSIS 853\t%s [-abhkpstADSVZ] [-c machine] [-m mem] [-n flags] [-I sync-inhibit] kernel 854OPTIONS 855\t-a Boot up to multiuser mode. 856\t-A Use AGA display mode, if available. 857\t-b Ask for which root device. 858\t Its possible to have multiple roots and choose between them. 859\t-c Set machine type. [e.g 3000; use 32000+N for DraCo rev. N] 860\t-C Use Serial Console. 861\t-D Enter debugger 862\t-h This help message. 863\t-I Inhibit sync negotiation. Option value is bit-encoded targets. 864\t-k Reserve the first 4M of fast mem [Some one else 865\t is going to have to answer what that it is used for]. 866\t-m Tweak amount of available memory, for finding minimum amount 867\t of memory required to run. Sets fastmem size to specified 868\t size in Kbytes. 869\t-n Enable multiple non-contiguous memory: value = 0 (disabled), 870\t 1 (two segments), 2 (all avail segments), 3 (same as 2?). 871\t-p Use highest priority fastmem segement instead of the largest 872\t segment. The higher priority segment is usually faster 873\t (i.e. 32 bit memory), but some people have smaller amounts 874\t of 32 bit memory. 875\t-q Boot up in quiet mode. 876\t-s Boot up in singleuser mode (default). 877\t-S Include kernel symbol table. 878\t-t This is a *test* option. It prints out the memory 879\t list information being passed to the kernel and also 880\t exits without actually starting NetBSD. 881\t-v Boot up in verbose mode. 882\t-V Version of loadbsd program. 883\t-Z Force kernel load to chipmem. 884HISTORY 885\tThis version supports Kernel version 720 +\n", 886 program_name, program_name); 887 exit(1); 888} 889 890static void 891_Vdomessage(int doerrno, const char *fmt, va_list args) 892{ 893 fprintf(stderr, "%s: ", program_name); 894 if (fmt) { 895 vfprintf(stderr, fmt, args); 896 fprintf(stderr, ": "); 897 } 898 if (doerrno && errno < sys_nerr) { 899 fprintf(stderr, "%s", strerror(errno)); 900 } 901 fprintf(stderr, "\n"); 902} 903 904void 905err(int eval, const char *fmt, ...) 906{ 907 va_list ap; 908 va_start(ap, fmt); 909 _Vdomessage(1, fmt, ap); 910 va_end(ap); 911 exit(eval); 912} 913 914#if 0 915void 916errx(int eval, const char *fmt, ...) 917{ 918 va_list ap; 919 va_start(ap, fmt); 920 _Vdomessage(0, fmt, ap); 921 va_end(ap); 922 exit(eval); 923} 924#endif 925 926void 927warn(const char *fmt, ...) 928{ 929 va_list ap; 930 va_start(ap, fmt); 931 _Vdomessage(1, fmt, ap); 932 va_end(ap); 933} 934 935#if 0 936void 937warnx(const char *fmt, ...) 938{ 939 va_list ap; 940 va_start(ap, fmt); 941 _Vdomessage(0, fmt, ap); 942 va_end(ap); 943} 944#endif 945