loadbsd.c revision 1.26.8.2 1 /* $NetBSD: loadbsd.c,v 1.26.8.2 2002/08/13 02:17:47 nathanw 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