Home | History | Annotate | Line # | Download | only in loadbsd
loadbsd.c revision 1.26.4.2
      1 /*	$NetBSD: loadbsd.c,v 1.26.4.2 2002/09/06 08:31:57 jdolecek 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
     71 void err __P((int, const char *, ...));
     72 void errx __P((int, const char *, ...));
     73 void warn __P((const char *, ...));
     74 void 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  */
    119 static 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
    135 struct 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 };
    144 struct boot_memlist memlist;
    145 struct boot_memlist *kmemlist;
    146 
    147 
    148 void get_mem_config __P((void **, u_long *, u_long *));
    149 void get_cpuid __P((void));
    150 void get_eclock __P((void));
    151 void get_AGA __P((void));
    152 void usage __P((void));
    153 void verbose_usage __P((void));
    154 void Version __P((void));
    155 void startit __P((void *, u_long, u_long, void *, u_long, u_long, int, void *,
    156 		int, int, u_long, u_long, int));
    157 void startit_end __P((void));
    158 
    159 extern struct ExecBase *SysBase;
    160 extern char *optarg;
    161 extern int optind;
    162 
    163 int k_flag;
    164 int p_flag;
    165 int t_flag;
    166 int reqmemsz;
    167 int S_flag;
    168 u_long I_flag;
    169 int Z_flag;
    170 u_long cpuid;
    171 long eclock_freq;
    172 long amiga_flags;
    173 char *program_name;
    174 char *kname;
    175 struct ExpansionBase *ExpansionBase;
    176 struct GfxBase *GfxBase;
    177 u_char *kp;
    178 int ksize;
    179 
    180 int
    181 main(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", 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");
    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 
    453 void
    454 get_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  */
    605 void
    606 get_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 
    650 void
    651 get_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 
    661 void
    662 get_AGA()
    663 {
    664 	/*
    665 	 * Determine if an AGA mode is active
    666 	 */
    667 }
    668 
    669 
    670 asm("
    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 
    682 start_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 
    745 not040:
    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 
    760 nott:
    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
    774 L0:
    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
    782 L2:
    783 	movl	a1@+,a5@+
    784 	subl	#4,d2
    785 	bcc	L2
    786 
    787 	btst	#3,d5
    788 	jeq	L1
    789 	.word	0xf4f8
    790 L1:	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 
    802 ckend:
    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 
    825 noDraCo:
    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 
    845 nullrp:	.long	0x7fff0001
    846 zero:	.long	0
    847 
    848 _startit_end:
    849 
    850 ");
    851 
    852 void
    853 usage()
    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 
    861 void
    862 verbose_usage()
    863 {
    864 	fprintf(stderr, "
    865 NAME
    866 \t%s - loads NetBSD from amiga dos.
    867 SYNOPSIS
    868 \t%s [-abhkpstADSVZ] [-c machine] [-m mem] [-n flags] [-I sync-inhibit] kernel
    869 OPTIONS
    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.
    898 HISTORY
    899 \tThis version supports Kernel version 720 +\n",
    900       program_name, program_name);
    901       exit(1);
    902 }
    903 
    904 
    905 void
    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 
    935 void
    936 err(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 
    944 void
    945 errx(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 
    953 void
    954 warn(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 
    962 void
    963 warnx(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 
    972 u_int
    973 sleep(u_int n)
    974 {
    975 	(void)TimeDelay(0L, n, 0L);
    976 }
    977 
    978 
    979