167754Smsmith/* $NetBSD: loadbsd.c,v 1.38 2023/05/14 16:13:05 phx Exp $ */ 267754Smsmith 367754Smsmith/* 467754Smsmith * Copyright (c) 1994 Michael L. Hitch 567754Smsmith * All rights reserved. 667754Smsmith * 7217365Sjkim * Redistribution and use in source and binary forms, with or without 8217365Sjkim * modification, are permitted provided that the following conditions 970243Smsmith * are met: 1067754Smsmith * 1. Redistributions of source code must retain the above copyright 11217365Sjkim * notice, this list of conditions and the following disclaimer. 12217365Sjkim * 2. Redistributions in binary form must reproduce the above copyright 13217365Sjkim * notice, this list of conditions and the following disclaimer in the 14217365Sjkim * documentation and/or other materials provided with the distribution. 15217365Sjkim * 16217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17217365Sjkim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18217365Sjkim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19217365Sjkim * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20217365Sjkim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21217365Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22217365Sjkim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23217365Sjkim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24217365Sjkim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2567754Smsmith * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26217365Sjkim */ 27217365Sjkim 28217365Sjkim#include <errno.h> 2967754Smsmith#include <stdio.h> 30217365Sjkim#include <stdlib.h> 31217365Sjkim#include <string.h> 32217365Sjkim#include <stdarg.h> 33217365Sjkim 34217365Sjkim#include <exec/memory.h> 35217365Sjkim#include <exec/execbase.h> 36217365Sjkim#include <exec/resident.h> 37217365Sjkim#include <graphics/gfxbase.h> 38217365Sjkim#include <libraries/expansion.h> 39217365Sjkim#include <libraries/expansionbase.h> 40217365Sjkim#include <libraries/configregs.h> 41217365Sjkim#include <libraries/configvars.h> 42217365Sjkim#include <proto/expansion.h> 4367754Smsmith#include <proto/graphics.h> 4467754Smsmith#include <proto/exec.h> 4567754Smsmith#include <proto/dos.h> 4667754Smsmith 4767754Smsmith/* Get definitions for boothowto */ 4867754Smsmith#include "sys/reboot.h" 4967754Smsmith#include "inttypes.h" 50117521Snjl#include "loadfile.h" 5167754Smsmith 5267754Smsmith#undef AOUT_LDPGSZ 5367754Smsmith#define AOUT_LDPGSZ 8192 5467754Smsmith 55102550Siwasaki#undef sleep 5691116Smsmith#define sleep(n) if (!t_flag) (void)Delay(50*n) 5791116Smsmith 5887031Smsmith/* 5967754Smsmith * Version history: 6067754Smsmith * 1.x Kernel startup interface version check. 6187031Smsmith * 2.0 Added symbol table end address and symbol table support. 6267754Smsmith * 2.1 03/23/94 - Round up end of fastram segment. 6367754Smsmith * Check fastram segment size for minimum of 2M. 6467754Smsmith * Use largest segment of highest priority if -p option. 65129684Snjl * Print out fastram size in KB if not a multiple of MB. 66129684Snjl * 2.2 03/24/94 - Zero out all unused registers. 67129684Snjl * Started version history comment. 68138287Smarks * 2.3 04/26/94 - Added -D option to enter debugger on boot. 69129684Snjl * 2.4 04/30/94 - Cpuid includes base machine type. 70129684Snjl * Also check if CPU is capable of running NetBSD. 71129684Snjl * 2.5 05/17/94 - Add check for "A3000 bonus". 72129684Snjl * 2.6 06/05/94 - Added -c option to override machine type. 73129684Snjl * 2.7 06/15/94 - Pass E clock frequency. 74129684Snjl * 2.8 06/22/94 - Fix supervisor stack usage. 75117521Snjl * 2.9 06/26/94 - Use PAL flag for E clock freq on pre 2.0 WB 76117521Snjl * Added AGA enable parameter 77151937Sjkim * 2.10 12/22/94 - Use FindResident() & OpenResource() for machine 78117521Snjl * type detection. 79151937Sjkim * Add -n flag & option for non-contiguous memory. 80151937Sjkim * 01/28/95 - Corrected -n on usage & help messages. 81167802Sjkim * 2.11 03/12/95 - Check kernel size against chip memory size. 82117521Snjl * 2.12 11/11/95 - Add -I option to inhibit synchronous transfer 83117521Snjl * 11/12/95 - New kernel startup interface version - to 84167802Sjkim * support loading kernel image to fastmem rather than chipmem. 85117521Snjl * 2.13 04/15/96 - Direct load to fastmem. 86117521Snjl * Add -Z flag to force chipmem load. 87117521Snjl * Moved test mode exit to later - kernel image is created 88117521Snjl * and startup interface version checked in test mode. 89117521Snjl * Add -s flag for compatibility to bootblock loader. 9067754Smsmith * 05/02/96 - Add a maximum startup interface version level 9167754Smsmith * to allow future kernel compatibility. 9267754Smsmith * 2.14 06/26/96 is - Add first version of kludges needed to 9367754Smsmith * boot on DraCos. This can probably be done a bit more cleanly 9467754Smsmith * using TTRs, but it works for now. 9567754Smsmith * 2.15 07/28/96 is - Add first version of kludges needed to 9685756Smsmith * get FusionForty kickrom'd memory back. Hope this doesn't 9767754Smsmith * break anything else. 98151937Sjkim * 2.16 07/08/00 - Added bootverbose support. 9985756Smsmith * 01/15/03 - Plugged resource leaks. 10067754Smsmith * Fixed printf() statements. 10167754Smsmith * Ansified. 102114237Snjl * 3.0 01/16/03 - ELF support through loadfile() interface. 10367754Smsmith * 3.1 07/10/11 - Added a serial console flag 104167802Sjkim * 11/18/15 - (gnikl) Added detection of A600. 10567754Smsmith * Fix handling of multiple -n options. 106167802Sjkim * 3.2 09/02/22 - Make it compile with modern AmigaOS gcc ports. 10767754Smsmith * 3.3 01/04/22 - Loading the kernel to the highest priority memory 108199337Sjkim * segment is the default now. New option -l to revert to the 10967754Smsmith * previous behaviour of largest segment. 110199337Sjkim * New option -M to define a minimum size for the memory segment. 11167754Smsmith */ 112167802Sjkimstatic const char _version[] = "$VER: LoadBSD 3.3 (01.04.2023)"; 11367754Smsmith 114167802Sjkim/* 115167802Sjkim * Kernel startup interface version 116167802Sjkim * 1: first version of loadbsd 117167802Sjkim * 2: needs esym location passed in a4 118167802Sjkim * 3: load kernel image into fastmem rather than chipmem 119167802Sjkim * MAX: highest version with backward compatibility. 120193267Sjkim */ 121167802Sjkim#define KERNEL_STARTUP_VERSION 3 122193267Sjkim#define KERNEL_STARTUP_VERSION_MAX 9 123193267Sjkim 124209746Sjkim#define DRACOREVISION (*(UBYTE *)0x02000009) 125193267Sjkim#define DRACOMMUMARGIN 0x200000 126228110Sjkim 127209746Sjkim#define MAXMEMSEG 16 128209746Sjkimstruct boot_memlist { 12991116Smsmith u_int m_nseg; /* num_mem; */ 13091116Smsmith struct boot_memseg { 13167754Smsmith u_int ms_start; 13267754Smsmith u_int ms_size; 13367754Smsmith u_short ms_attrib; 13467754Smsmith short ms_pri; 135151937Sjkim } m_seg[MAXMEMSEG]; 136151937Sjkim}; 137114237Snjlstruct boot_memlist memlist; 138114237Snjlstruct boot_memlist *kmemlist; 13967754Smsmith 140114237Snjlvoid err(int eval, const char *, ...); 141114237Snjlint getopt(int, char * const [], const char *); 14267754Smsmithvoid get_mem_config (void **, u_long *, u_long *); 14367754Smsmithvoid get_cpuid (void); 144114237Snjlvoid get_eclock (void); 14567754Smsmithvoid get_AGA (void); 146114237Snjlvoid usage (void); 147114237Snjlvoid verbose_usage (void); 14867754Smsmithextern void startit (void *, u_long, u_long, void *, u_long, u_long, int, void *, 149167802Sjkim int, int, u_long, u_long, int); 150167802Sjkimextern u_long startit_sz; 151167802Sjkim 152167802Sjkimextern char *optarg; 153167802Sjkimextern int optind; 154167802Sjkim 155167802Sjkimstruct ExpansionBase *ExpansionBase = NULL; 156167802Sjkimstruct GfxBase *GfxBase = NULL; 157167802Sjkim 158167802Sjkimu_int minmemsz = 2 * 1024 * 1024; 159167802Sjkimint p_flag = 1; 16067754Smsmithint k_flag; 16167754Smsmithint t_flag; 162131440Smarksint reqmemsz; 163131440Smarksint S_flag; 164131440Smarksu_long I_flag; 165131440Smarksint Z_flag; 166131440Smarksu_long cpuid; 167114237Snjllong eclock_freq; 16867754Smsmithlong amiga_flags; 16987031Smsmithchar *program_name; 17087031Smsmithu_char *kp; 17199679Siwasakiu_long kpsz; 17287031Smsmith 17377424Smsmith 17467754Smsmithvoid 17599679Siwasakiexit_func(void) 17677424Smsmith{ 177100966Siwasaki if (kp) 178100966Siwasaki FreeMem(kp, kpsz); 179167802Sjkim if (ExpansionBase) 180100966Siwasaki CloseLibrary((struct Library *)ExpansionBase); 18191116Smsmith if (GfxBase) 18277424Smsmith CloseLibrary((struct Library *)GfxBase); 18399679Siwasaki} 18499679Siwasaki 18591116Smsmithint 186228110Sjkimmain(int argc, char **argv) 18791116Smsmith{ 188107325Siwasaki struct ConfigDev *cd, *kcd; 189228110Sjkim u_long fmemsz, cmemsz, ksize, marks[MARK_MAX]; 190197104Sjkim int boothowto, ncd, i, mem_ix, ch; 191107325Siwasaki u_short kvers; 192197104Sjkim int *nkcd; 193107325Siwasaki u_char *fmem; 194197104Sjkim char *esym; 195197104Sjkim void (*start_it) (void *, u_long, u_long, void *, u_long, u_long, 196197104Sjkim int, void *, int, int, u_long, u_long, int) = startit; 197197104Sjkim char *kernel_name; 19891116Smsmith 19991116Smsmith atexit(exit_func); 20091116Smsmith 20191116Smsmith program_name = argv[0]; 20291116Smsmith boothowto = RB_SINGLE; 20391116Smsmith 204222544Sjkim if (argc < 2) 205222544Sjkim usage(); 20691116Smsmith 20799679Siwasaki if ((GfxBase = (void *)OpenLibrary(GRAPHICSNAME, 0)) == NULL) 20899679Siwasaki err(20, "can't open graphics library"); 20991116Smsmith if ((ExpansionBase=(void *)OpenLibrary(EXPANSIONNAME, 0)) == NULL) 21091116Smsmith err(20, "can't open expansion library"); 21167754Smsmith 21267754Smsmith 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