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