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