1/* $NetBSD: loadbsd.c,v 1.38 2023/05/14 16:13:05 phx 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 34#include <exec/memory.h> 35#include <exec/execbase.h> 36#include <exec/resident.h> 37#include <graphics/gfxbase.h> 38#include <libraries/expansion.h> 39#include <libraries/expansionbase.h> 40#include <libraries/configregs.h> 41#include <libraries/configvars.h> 42#include <proto/expansion.h> 43#include <proto/graphics.h> 44#include <proto/exec.h> 45#include <proto/dos.h> 46 47/* Get definitions for boothowto */ 48#include "sys/reboot.h" 49#include "inttypes.h" 50#include "loadfile.h" 51 52#undef AOUT_LDPGSZ 53#define AOUT_LDPGSZ 8192 54 55#undef sleep 56#define sleep(n) if (!t_flag) (void)Delay(50*n) 57 58/* 59 * Version history: 60 * 1.x Kernel startup interface version check. 61 * 2.0 Added symbol table end address and symbol table support. 62 * 2.1 03/23/94 - Round up end of fastram segment. 63 * Check fastram segment size for minimum of 2M. 64 * Use largest segment of highest priority if -p option. 65 * Print out fastram size in KB if not a multiple of MB. 66 * 2.2 03/24/94 - Zero out all unused registers. 67 * Started version history comment. 68 * 2.3 04/26/94 - Added -D option to enter debugger on boot. 69 * 2.4 04/30/94 - Cpuid includes base machine type. 70 * Also check if CPU is capable of running NetBSD. 71 * 2.5 05/17/94 - Add check for "A3000 bonus". 72 * 2.6 06/05/94 - Added -c option to override machine type. 73 * 2.7 06/15/94 - Pass E clock frequency. 74 * 2.8 06/22/94 - Fix supervisor stack usage. 75 * 2.9 06/26/94 - Use PAL flag for E clock freq on pre 2.0 WB 76 * Added AGA enable parameter 77 * 2.10 12/22/94 - Use FindResident() & OpenResource() for machine 78 * type detection. 79 * Add -n flag & option for non-contiguous memory. 80 * 01/28/95 - Corrected -n on usage & help messages. 81 * 2.11 03/12/95 - Check kernel size against chip memory size. 82 * 2.12 11/11/95 - Add -I option to inhibit synchronous transfer 83 * 11/12/95 - New kernel startup interface version - to 84 * support loading kernel image to fastmem rather than chipmem. 85 * 2.13 04/15/96 - Direct load to fastmem. 86 * Add -Z flag to force chipmem load. 87 * Moved test mode exit to later - kernel image is created 88 * and startup interface version checked in test mode. 89 * Add -s flag for compatibility to bootblock loader. 90 * 05/02/96 - Add a maximum startup interface version level 91 * to allow future kernel compatibility. 92 * 2.14 06/26/96 is - Add first version of kludges needed to 93 * boot on DraCos. This can probably be done a bit more cleanly 94 * using TTRs, but it works for now. 95 * 2.15 07/28/96 is - Add first version of kludges needed to 96 * get FusionForty kickrom'd memory back. Hope this doesn't 97 * break anything else. 98 * 2.16 07/08/00 - Added bootverbose support. 99 * 01/15/03 - Plugged resource leaks. 100 * Fixed printf() statements. 101 * Ansified. 102 * 3.0 01/16/03 - ELF support through loadfile() interface. 103 * 3.1 07/10/11 - Added a serial console flag 104 * 11/18/15 - (gnikl) Added detection of A600. 105 * Fix handling of multiple -n options. 106 * 3.2 09/02/22 - Make it compile with modern AmigaOS gcc ports. 107 * 3.3 01/04/22 - Loading the kernel to the highest priority memory 108 * segment is the default now. New option -l to revert to the 109 * previous behaviour of largest segment. 110 * New option -M to define a minimum size for the memory segment. 111 */ 112static const char _version[] = "$VER: LoadBSD 3.3 (01.04.2023)"; 113 114/* 115 * Kernel startup interface version 116 * 1: first version of loadbsd 117 * 2: needs esym location passed in a4 118 * 3: load kernel image into fastmem rather than chipmem 119 * MAX: highest version with backward compatibility. 120 */ 121#define KERNEL_STARTUP_VERSION 3 122#define KERNEL_STARTUP_VERSION_MAX 9 123 124#define DRACOREVISION (*(UBYTE *)0x02000009) 125#define DRACOMMUMARGIN 0x200000 126 127#define MAXMEMSEG 16 128struct boot_memlist { 129 u_int m_nseg; /* num_mem; */ 130 struct boot_memseg { 131 u_int ms_start; 132 u_int ms_size; 133 u_short ms_attrib; 134 short ms_pri; 135 } m_seg[MAXMEMSEG]; 136}; 137struct boot_memlist memlist; 138struct boot_memlist *kmemlist; 139 140void err(int eval, const char *, ...); 141int getopt(int, char * const [], const char *); 142void get_mem_config (void **, u_long *, u_long *); 143void get_cpuid (void); 144void get_eclock (void); 145void get_AGA (void); 146void usage (void); 147void verbose_usage (void); 148extern void startit (void *, u_long, u_long, void *, u_long, u_long, int, void *, 149 int, int, u_long, u_long, int); 150extern u_long startit_sz; 151 152extern char *optarg; 153extern int optind; 154 155struct ExpansionBase *ExpansionBase = NULL; 156struct GfxBase *GfxBase = NULL; 157 158u_int minmemsz = 2 * 1024 * 1024; 159int p_flag = 1; 160int k_flag; 161int t_flag; 162int reqmemsz; 163int S_flag; 164u_long I_flag; 165int Z_flag; 166u_long cpuid; 167long eclock_freq; 168long amiga_flags; 169char *program_name; 170u_char *kp; 171u_long kpsz; 172 173 174void 175exit_func(void) 176{ 177 if (kp) 178 FreeMem(kp, kpsz); 179 if (ExpansionBase) 180 CloseLibrary((struct Library *)ExpansionBase); 181 if (GfxBase) 182 CloseLibrary((struct Library *)GfxBase); 183} 184 185int 186main(int argc, char **argv) 187{ 188 struct ConfigDev *cd, *kcd; 189 u_long fmemsz, cmemsz, ksize, marks[MARK_MAX]; 190 int boothowto, ncd, i, mem_ix, ch; 191 u_short kvers; 192 int *nkcd; 193 u_char *fmem; 194 char *esym; 195 void (*start_it) (void *, u_long, u_long, void *, u_long, u_long, 196 int, void *, int, int, u_long, u_long, int) = startit; 197 char *kernel_name; 198 199 atexit(exit_func); 200 201 program_name = argv[0]; 202 boothowto = RB_SINGLE; 203 204 if (argc < 2) 205 usage(); 206 207 if ((GfxBase = (void *)OpenLibrary(GRAPHICSNAME, 0)) == NULL) 208 err(20, "can't open graphics library"); 209 if ((ExpansionBase=(void *)OpenLibrary(EXPANSIONNAME, 0)) == NULL) 210 err(20, "can't open expansion library"); 211 212 while ((ch = getopt(argc, argv, "aAbCc:DhI:klm:M:n:qptsSvVZ")) != -1) { 213 switch (ch) { 214 case 'k': 215 k_flag = 1; 216 break; 217 case 'a': 218 boothowto &= ~(RB_SINGLE); 219 boothowto |= RB_AUTOBOOT; 220 break; 221 case 'b': 222 boothowto |= RB_ASKNAME; 223 break; 224 case 'p': 225 p_flag = 1; 226 break; 227 case 'l': 228 p_flag = 0; 229 break; 230 case 't': 231 t_flag = 1; 232 break; 233 case 'm': 234 reqmemsz = atoi(optarg) * 1024; 235 break; 236 case 'M': 237 minmemsz = atoi(optarg) * 1024 * 1024; 238 break; 239 case 's': 240 boothowto &= ~(RB_AUTOBOOT); 241 boothowto |= RB_SINGLE; 242 break; 243 case 'q': 244 boothowto |= AB_QUIET; 245 break; 246 case 'v': 247 boothowto |= AB_VERBOSE; 248 break; 249 case 'V': 250 fprintf(stderr,"%s\n",_version + 6); 251 break; 252 case 'S': 253 S_flag = 1; 254 break; 255 case 'D': 256 boothowto |= RB_KDB; 257 break; 258 case 'c': 259 cpuid = atoi(optarg) << 16; 260 break; 261 case 'A': 262 amiga_flags |= 1; 263 break; 264 case 'n': 265 i = atoi(optarg); 266 if (i >= 0 && i <= 3) { 267 amiga_flags &= ~(3 << 1); 268 amiga_flags |= i << 1; 269 } 270 else 271 err(20, "-n option must be 0, 1, 2, or 3"); 272 break; 273 case 'C': 274 amiga_flags |= (1 << 3); 275 break; 276 case 'I': 277 I_flag = strtoul(optarg, NULL, 16); 278 break; 279 case 'Z': 280 Z_flag = 1; 281 break; 282 case 'h': 283 verbose_usage(); 284 default: 285 usage(); 286 } 287 } 288 argc -= optind; 289 argv += optind; 290 291 if (argc != 1) 292 usage(); 293 294 kernel_name = argv[0]; 295 296 for (cd = 0, ncd = 0; cd = FindConfigDev(cd, -1, -1); ncd++) 297 ; 298 get_cpuid(); 299 get_mem_config((void **)&fmem, &fmemsz, &cmemsz); 300 get_eclock(); 301 get_AGA(); 302 303/* 304 * XXX Call loadfile with COUNT* options to get size 305 * XXX Allocate memory for kernel + additional data 306 * XXX Call loadfile with LOAD* options to load text/data/symbols 307 */ 308 marks[MARK_START] = 0; 309 if (loadfile(kernel_name, marks, 310 COUNT_TEXT|COUNT_TEXTA|COUNT_DATA|COUNT_BSS| 311 (S_flag ? (COUNT_SYM|COUNT_HDR) : 0)) == -1) { 312 err(20, "unable to parse kernel image"); 313 } 314 ksize = ((marks[MARK_END] + 3) & ~3) 315 + sizeof(*nkcd) + ncd * sizeof(*cd) 316 + sizeof(*nkcd) + memlist.m_nseg * sizeof(struct boot_memseg); 317 318 if (t_flag) { 319 for (i = 0; i < memlist.m_nseg; ++i) { 320 printf("mem segment %d: start=%08x size=%08x" 321 " attribute=%04x pri=%d\n", 322 i + 1, 323 memlist.m_seg[i].ms_start, 324 memlist.m_seg[i].ms_size, 325 memlist.m_seg[i].ms_attrib, 326 memlist.m_seg[i].ms_pri); 327 } 328 printf("kernel size: %lu\n", ksize); 329 } 330 331 kpsz = ksize + 256 + startit_sz; 332 kp = (u_char *)AllocMem(kpsz, MEMF_FAST|MEMF_REVERSE); 333 if (kp == NULL) 334 err(20, "failed alloc %d", ksize); 335 336 marks[MARK_START] = (u_long)kp; 337 if (loadfile(kernel_name, marks, 338 LOAD_TEXT|LOAD_TEXTA|LOAD_DATA|LOAD_BSS| 339 (S_flag ? (LOAD_SYM|LOAD_HDR) : 0)) == -1) { 340 err(20, "unable to load kernel image"); 341 } 342 marks[MARK_END] = (marks[MARK_END] + 3) & ~3; 343 344 if (k_flag) { 345 fmem += 4 * 1024 * 1024; 346 fmemsz -= 4 * 1024 * 1024; 347 } 348 if (reqmemsz && reqmemsz <= fmemsz) 349 fmemsz = reqmemsz; 350 351 if (boothowto & RB_AUTOBOOT) 352 printf("Autobooting..."); 353 if (boothowto & RB_ASKNAME) 354 printf("Askboot..."); 355 356 printf("Using %lu%c FASTMEM at 0x%lx, %luM CHIPMEM\n", 357 (fmemsz & 0xfffff) ? fmemsz >> 10 : fmemsz >> 20, 358 (fmemsz & 0xfffff) ? 'K' : 'M', (u_long)fmem, cmemsz >> 20); 359 360 kvers = *(u_short *)(marks[MARK_ENTRY] - 2); 361 if (kvers == 0x4e73) kvers = 0; 362 if (kvers > KERNEL_STARTUP_VERSION_MAX) 363 err(20, "newer loadbsd required: %d\n", kvers); 364 if (kvers > KERNEL_STARTUP_VERSION) { 365 printf("****************************************************\n" 366 "*** Notice: this kernel has features which require\n" 367 "*** a newer version of loadbsd. To allow the use of\n" 368 "*** any newer features or capabilities, you should\n" 369 "*** update to a newer version of loadbsd\n" 370 "****************************************************\n"); 371 sleep(3); /* even more time to see that message */ 372 } 373 374 /* 375 * give them a chance to read the information... 376 */ 377 sleep(2); 378 379 nkcd = (int *)marks[MARK_END]; 380 esym = 0; 381 /* 382 * If symbols loaded and kernel can handle them, set esym to end. 383 */ 384 if (marks[MARK_SYM] != marks[MARK_START]) { 385 if (kvers > 1) { 386 esym = (void *)(marks[MARK_END] - marks[MARK_START]); 387 } 388 else { 389 /* 390 * suppress symbols 391 */ 392 nkcd = (int *)marks[MARK_SYM]; 393 } 394 } 395 396 *nkcd = ncd; 397 kcd = (struct ConfigDev *)(nkcd + 1); 398 while((cd = FindConfigDev(cd, -1, -1))) { 399 u_char *ba = kcd->cd_BoardAddr; 400 401 memcpy(kcd, cd, sizeof(*kcd)); 402 if (((cpuid >> 24) == 0x7d) && ((u_long)ba < 0x1000000)) { 403 if (t_flag) 404 printf("Transformed Z2 device from %08lx ", (u_long)ba); 405 ba += 0x3000000; 406 kcd->cd_BoardAddr = ba; 407 if (t_flag) 408 printf("to %08lx\n", (u_long)ba); 409 } 410 ++kcd; 411 } 412 413 kmemlist = (struct boot_memlist *)kcd; 414 kmemlist->m_nseg = memlist.m_nseg; 415 for (mem_ix = 0; mem_ix < memlist.m_nseg; mem_ix++) 416 kmemlist->m_seg[mem_ix] = memlist.m_seg[mem_ix]; 417 418 if (kvers > 2 && Z_flag == 0) { 419 /* 420 * Kernel supports direct load to fastmem, and the -Z 421 * option was not specified. Copy startup code to end 422 * of kernel image and set start_it. 423 */ 424 if (ksize >= fmemsz) { 425 printf("Kernel size %lu exceeds best Fast Memory segment of %lu\n", 426 ksize, fmemsz); 427 err(20, "Insufficient Fast Memory for kernel"); 428 } 429 if (kp < fmem) { 430 printf("Kernel at %08lx, Fastmem used at %08lx\n", 431 (u_long)kp, (u_long)fmem); 432 err(20, "Can't copy upwards yet.\nDefragment your memory and try again OR try the -p OR try the -Z options."); 433 } 434 start_it = (void (*)())(kp + ksize + 256); 435 memcpy((void *)start_it, (void *)startit, startit_sz); 436 CacheClearU(); 437 printf("*** Loading from %08lx to Fastmem %08lx ***\n", 438 (u_long)kp, (u_long)fmem); 439 sleep(2); 440 } else { 441 /* 442 * Either the kernel doesn't support loading directly to 443 * fastmem or the -Z flag was given. Verify kernel image 444 * fits into chipmem. 445 */ 446 if (ksize >= cmemsz) { 447 printf("Kernel size %lu exceeds Chip Memory of %lu\n", 448 ksize, cmemsz); 449 err(20, "Insufficient Chip Memory for kernel"); 450 } 451 Z_flag = 1; 452 printf("*** Loading from %08lx to Chipmem ***\n", (u_long)kp); 453 } 454 455 /* 456 * if test option set, done 457 */ 458 if (t_flag) { 459 exit(0); 460 } 461 462 /* 463 * XXX AGA startup - may need more 464 */ 465 LoadView(NULL); /* Don't do this if AGA active? */ 466 start_it(kp, ksize, marks[MARK_ENTRY] - marks[MARK_START], fmem, fmemsz, cmemsz, 467 boothowto, esym, cpuid, eclock_freq, amiga_flags, I_flag, Z_flag == 0); 468 /*NOTREACHED*/ 469} 470 471void 472get_mem_config(void **fmem, u_long *fmemsz, u_long *cmemsz) 473{ 474 struct MemHeader *mh, *nmh; 475 u_int nmem, eseg, segsz, seg, nseg, nsegsz; 476 char mempri; 477 478 nmem = 0; 479 mempri = -128; 480 *fmemsz = 0; 481 *cmemsz = 0; 482 *fmem = NULL; 483 484 /* 485 * walk through the exec memory list 486 */ 487 Forbid(); 488 for (mh = (void *) SysBase->MemList.lh_Head; 489 nmh = (void *) mh->mh_Node.ln_Succ; mh = nmh) { 490 491 nseg = (u_int)mh->mh_Lower; 492 nsegsz = (u_int)mh->mh_Upper - nseg; 493 494 segsz = nsegsz; 495 seg = (u_int)CachePreDMA((APTR)nseg, (LONG *)&segsz, 0L); 496 nsegsz -= segsz, nseg += segsz; 497 for (;segsz; 498 segsz = nsegsz, 499 seg = (u_int)CachePreDMA((APTR)nseg, (LONG *)&segsz, DMA_Continue), 500 nsegsz -= segsz, nseg += segsz, ++nmem) { 501 502 if (t_flag) 503 printf("Translated %08x sz %08x to %08x sz %08x\n", 504 nseg - segsz, nsegsz + segsz, seg, segsz); 505 506 eseg = seg + segsz; 507 508 if ((cpuid >> 24) == 0x7D) { 509 /* DraCo MMU table kludge */ 510 511 segsz = ((segsz -1) | 0xfffff) + 1; 512 seg = eseg - segsz; 513 514 /* 515 * Only use first SIMM to boot; we know it is VA==PA. 516 * Enter into table and continue. Yes, 517 * this is ugly. 518 */ 519 if (seg != 0x40000000) { 520 memlist.m_seg[nmem].ms_attrib = mh->mh_Attributes; 521 memlist.m_seg[nmem].ms_pri = mh->mh_Node.ln_Pri; 522 memlist.m_seg[nmem].ms_size = segsz; 523 memlist.m_seg[nmem].ms_start = seg; 524 ++nmem; 525 continue; 526 } 527 528 memlist.m_seg[nmem].ms_attrib = mh->mh_Attributes; 529 memlist.m_seg[nmem].ms_pri = mh->mh_Node.ln_Pri; 530 memlist.m_seg[nmem].ms_size = DRACOMMUMARGIN; 531 memlist.m_seg[nmem].ms_start = seg; 532 533 ++nmem; 534 seg += DRACOMMUMARGIN; 535 segsz -= DRACOMMUMARGIN; 536 } 537 538 memlist.m_seg[nmem].ms_attrib = mh->mh_Attributes; 539 memlist.m_seg[nmem].ms_pri = mh->mh_Node.ln_Pri; 540 memlist.m_seg[nmem].ms_size = segsz; 541 memlist.m_seg[nmem].ms_start = seg; 542 543 if ((mh->mh_Attributes & (MEMF_CHIP|MEMF_FAST)) == MEMF_CHIP) { 544 /* 545 * there should hardly be more than one entry for 546 * chip mem, but handle it the same nevertheless 547 * cmem always starts at 0, so include vector area 548 */ 549 memlist.m_seg[nmem].ms_start = seg = 0; 550 /* 551 * round to multiple of 512K 552 */ 553 segsz = (segsz + 512 * 1024 - 1) & -(512 * 1024); 554 memlist.m_seg[nmem].ms_size = segsz; 555 if (segsz > *cmemsz) 556 *cmemsz = segsz; 557 continue; 558 } 559 /* 560 * some heuristics.. 561 */ 562 seg &= -AOUT_LDPGSZ; 563 eseg = (eseg + AOUT_LDPGSZ - 1) & -AOUT_LDPGSZ; 564 565 /* 566 * get the mem back stolen by incore kickstart on 567 * A3000 with V36 bootrom. 568 */ 569 if (eseg == 0x07f80000) 570 eseg = 0x08000000; 571 572 /* 573 * or by zkick on a A2000. 574 */ 575 if (seg == 0x280000 && 576 strcmp(mh->mh_Node.ln_Name, "zkick memory") == 0) 577 seg = 0x200000; 578 /* 579 * or by Fusion Forty fastrom 580 */ 581 if ((seg & ~(1024*1024-1)) == 0x11000000) { 582 /* 583 * XXX we should test the name. 584 * Unfortunately, the memory is just called 585 * "32 bit memory" which isn't very specific. 586 */ 587 seg = 0x11000000; 588 } 589 590 segsz = eseg - seg; 591 memlist.m_seg[nmem].ms_start = seg; 592 memlist.m_seg[nmem].ms_size = segsz; 593 /* 594 * If this segment is smaller than minmemsz (default: 2M), 595 * don't use it to load the kernel 596 */ 597 if (segsz < minmemsz) 598 continue; 599 /* 600 * if p_flag is set, select memory by priority 601 * instead of size 602 */ 603 if ((!p_flag && segsz > *fmemsz) || (p_flag && 604 mempri <= mh->mh_Node.ln_Pri && segsz > *fmemsz)) { 605 *fmemsz = segsz; 606 *fmem = (void *)seg; 607 mempri = mh->mh_Node.ln_Pri; 608 } 609 610 } 611 } 612 memlist.m_nseg = nmem; 613 Permit(); 614} 615 616/* 617 * Try to determine the machine ID by searching the resident module list 618 * for modules only present on specific machines. (Thanks, Bill!) 619 */ 620void 621get_cpuid(void) 622{ 623 cpuid |= SysBase->AttnFlags; /* get FPU and CPU flags */ 624 if ((cpuid & AFB_68020) == 0) 625 err(20, "CPU not supported"); 626 if (cpuid & 0xffff0000) { 627 if ((cpuid >> 24) == 0x7D) 628 return; 629 630 switch (cpuid >> 16) { 631 case 500: 632 case 600: 633 case 1000: 634 case 1200: 635 case 2000: 636 case 3000: 637 case 4000: 638 return; 639 default: 640 printf("machine Amiga %lu is not recognized\n", 641 cpuid >> 16); 642 exit(1); 643 } 644 } 645 if (FindResident("A4000 Bonus") || FindResident("A4000 bonus") 646 || FindResident("A1000 Bonus")) 647 cpuid |= 4000 << 16; 648 else if (FindResident("A3000 Bonus") || FindResident("A3000 bonus")) 649 cpuid |= 3000 << 16; 650 else if (OpenResource("card.resource")) { 651 UBYTE alicerev = *((UBYTE *)0xdff004) & 0x6f; 652 if (alicerev == 0x22 || alicerev == 0x23) 653 cpuid |= 1200 << 16; /* AGA + PCMCIA = A1200 */ 654 else 655 cpuid |= 600 << 16; /* noAGA + PCMCIA = A600 */ 656 } else if (OpenResource("draco.resource")) { 657 cpuid |= (32000 | DRACOREVISION) << 16; 658 } 659 /* 660 * Nothing found, it's probably an A2000 or A500 661 */ 662 if ((cpuid >> 16) == 0) 663 cpuid |= 2000 << 16; 664} 665 666void 667get_eclock(void) 668{ 669 /* Fix for 1.3 startups? */ 670 if (SysBase->LibNode.lib_Version > 36) 671 eclock_freq = SysBase->ex_EClockFrequency; 672 else 673 eclock_freq = (GfxBase->DisplayFlags & PAL) ? 674 709379 : 715909; 675} 676 677void 678get_AGA(void) 679{ 680 /* 681 * Determine if an AGA mode is active 682 */ 683} 684 685void 686usage(void) 687{ 688 fprintf(stderr, "usage: %s [-abhklpstACDSVZ] [-c machine] [-m size] [-M size] [-n mode] [-I sync-inhibit] kernel\n", 689 program_name); 690 exit(1); 691} 692 693void 694verbose_usage(void) 695{ 696 fprintf(stderr, "\n\ 697NAME\n\ 698\t%s - loads NetBSD from amiga dos.\n\ 699SYNOPSIS\n\ 700\t%s [-abhklpstACDSVZ] [-c machine] [-m size] [-M size] [-n mode] [-I sync-inhibit] kernel\n\ 701OPTIONS\n\ 702\t-a Boot up to multiuser mode.\n\ 703\t-A Use AGA display mode, if available.\n\ 704\t-b Ask for which root device.\n\ 705\t It is possible to have multiple roots and choose between them.\n\ 706\t-c Set machine type. [e.g 3000; use 32000+N for DraCo rev. N]\n\ 707\t-C Use Serial Console.\n\ 708\t-D Enter debugger\n\ 709\t-h This help message.\n\ 710\t-I Inhibit sync negotiation. Option value is bit-encoded targets.\n\ 711\t-k Reserve the first 4M of fast mem [Some one else\n\ 712\t is going to have to answer what that it is used for].\n\ 713\t-l Use the largest memory segment for loading the kernel.\n\ 714\t-m Tweak amount of available memory, for finding minimum amount\n\ 715\t of memory required to run. Sets fastmem size to specified\n\ 716\t size in Kbytes.\n\ 717\t-M Request a minimum size in Mbytes for the kernel's memory\n\ 718\t segment. Defaults to 2M.\n\ 719\t-n Enable multiple non-contiguous memory: value = 0 (disabled),\n\ 720\t 1 (two segments), 2 (all avail segments), 3 (same as 2?).\n\ 721\t-p Use highest priority fastmem segment for loading the kernel.\n\ 722\t This is the default.\n\ 723\t-q Boot up in quiet mode.\n\ 724\t-s Boot up in singleuser mode (default).\n\ 725\t-S Include kernel symbol table.\n\ 726\t-t This is a *test* option. It prints out the memory\n\ 727\t list information being passed to the kernel and also\n\ 728\t exits without actually starting NetBSD.\n\ 729\t-v Boot up in verbose mode.\n\ 730\t-V Version of loadbsd program.\n\ 731\t-Z Force kernel load to chipmem.\n\ 732HISTORY\n\ 733\tThis version supports Kernel version 720 +\n", 734 program_name, program_name); 735 exit(1); 736} 737 738static void 739_Vdomessage(int doerrno, const char *fmt, va_list args) 740{ 741 fprintf(stderr, "%s: ", program_name); 742 if (fmt) { 743 vfprintf(stderr, fmt, args); 744 fprintf(stderr, ": "); 745 } 746 if (doerrno) { 747 fprintf(stderr, "%s", strerror(errno)); 748 } 749 fprintf(stderr, "\n"); 750} 751 752void 753err(int eval, const char *fmt, ...) 754{ 755 va_list ap; 756 va_start(ap, fmt); 757 _Vdomessage(1, fmt, ap); 758 va_end(ap); 759 exit(eval); 760} 761 762void 763warn(const char *fmt, ...) 764{ 765 va_list ap; 766 va_start(ap, fmt); 767 _Vdomessage(1, fmt, ap); 768 va_end(ap); 769} 770