1 /* $NetBSD: loadbsd.c,v 1.38 2023/05/14 16:13:05 phx Exp $ */
2
3 /*
4 * Copyright (c) 1994 Michael L. Hitch
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <errno.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdarg.h>
33
34 #include <exec/memory.h>
35 #include <exec/execbase.h>
36 #include <exec/resident.h>
37 #include <graphics/gfxbase.h>
38 #include <libraries/expansion.h>
39 #include <libraries/expansionbase.h>
40 #include <libraries/configregs.h>
41 #include <libraries/configvars.h>
42 #include <proto/expansion.h>
43 #include <proto/graphics.h>
44 #include <proto/exec.h>
45 #include <proto/dos.h>
46
47 /* Get definitions for boothowto */
48 #include "sys/reboot.h"
49 #include "inttypes.h"
50 #include "loadfile.h"
51
52 #undef AOUT_LDPGSZ
53 #define AOUT_LDPGSZ 8192
54
55 #undef sleep
56 #define sleep(n) if (!t_flag) (void)Delay(50*n)
57
58 /*
59 * Version history:
60 * 1.x Kernel startup interface version check.
61 * 2.0 Added symbol table end address and symbol table support.
62 * 2.1 03/23/94 - Round up end of fastram segment.
63 * Check fastram segment size for minimum of 2M.
64 * Use largest segment of highest priority if -p option.
65 * Print out fastram size in KB if not a multiple of MB.
66 * 2.2 03/24/94 - Zero out all unused registers.
67 * Started version history comment.
68 * 2.3 04/26/94 - Added -D option to enter debugger on boot.
69 * 2.4 04/30/94 - Cpuid includes base machine type.
70 * Also check if CPU is capable of running NetBSD.
71 * 2.5 05/17/94 - Add check for "A3000 bonus".
72 * 2.6 06/05/94 - Added -c option to override machine type.
73 * 2.7 06/15/94 - Pass E clock frequency.
74 * 2.8 06/22/94 - Fix supervisor stack usage.
75 * 2.9 06/26/94 - Use PAL flag for E clock freq on pre 2.0 WB
76 * Added AGA enable parameter
77 * 2.10 12/22/94 - Use FindResident() & OpenResource() for machine
78 * type detection.
79 * Add -n flag & option for non-contiguous memory.
80 * 01/28/95 - Corrected -n on usage & help messages.
81 * 2.11 03/12/95 - Check kernel size against chip memory size.
82 * 2.12 11/11/95 - Add -I option to inhibit synchronous transfer
83 * 11/12/95 - New kernel startup interface version - to
84 * support loading kernel image to fastmem rather than chipmem.
85 * 2.13 04/15/96 - Direct load to fastmem.
86 * Add -Z flag to force chipmem load.
87 * Moved test mode exit to later - kernel image is created
88 * and startup interface version checked in test mode.
89 * Add -s flag for compatibility to bootblock loader.
90 * 05/02/96 - Add a maximum startup interface version level
91 * to allow future kernel compatibility.
92 * 2.14 06/26/96 is - Add first version of kludges needed to
93 * boot on DraCos. This can probably be done a bit more cleanly
94 * using TTRs, but it works for now.
95 * 2.15 07/28/96 is - Add first version of kludges needed to
96 * get FusionForty kickrom'd memory back. Hope this doesn't
97 * break anything else.
98 * 2.16 07/08/00 - Added bootverbose support.
99 * 01/15/03 - Plugged resource leaks.
100 * Fixed printf() statements.
101 * Ansified.
102 * 3.0 01/16/03 - ELF support through loadfile() interface.
103 * 3.1 07/10/11 - Added a serial console flag
104 * 11/18/15 - (gnikl) Added detection of A600.
105 * Fix handling of multiple -n options.
106 * 3.2 09/02/22 - Make it compile with modern AmigaOS gcc ports.
107 * 3.3 01/04/22 - Loading the kernel to the highest priority memory
108 * segment is the default now. New option -l to revert to the
109 * previous behaviour of largest segment.
110 * New option -M to define a minimum size for the memory segment.
111 */
112 static const char _version[] = "$VER: LoadBSD 3.3 (01.04.2023)";
113
114 /*
115 * Kernel startup interface version
116 * 1: first version of loadbsd
117 * 2: needs esym location passed in a4
118 * 3: load kernel image into fastmem rather than chipmem
119 * MAX: highest version with backward compatibility.
120 */
121 #define KERNEL_STARTUP_VERSION 3
122 #define KERNEL_STARTUP_VERSION_MAX 9
123
124 #define DRACOREVISION (*(UBYTE *)0x02000009)
125 #define DRACOMMUMARGIN 0x200000
126
127 #define MAXMEMSEG 16
128 struct boot_memlist {
129 u_int m_nseg; /* num_mem; */
130 struct boot_memseg {
131 u_int ms_start;
132 u_int ms_size;
133 u_short ms_attrib;
134 short ms_pri;
135 } m_seg[MAXMEMSEG];
136 };
137 struct boot_memlist memlist;
138 struct boot_memlist *kmemlist;
139
140 void err(int eval, const char *, ...);
141 int getopt(int, char * const [], const char *);
142 void get_mem_config (void **, u_long *, u_long *);
143 void get_cpuid (void);
144 void get_eclock (void);
145 void get_AGA (void);
146 void usage (void);
147 void verbose_usage (void);
148 extern void startit (void *, u_long, u_long, void *, u_long, u_long, int, void *,
149 int, int, u_long, u_long, int);
150 extern u_long startit_sz;
151
152 extern char *optarg;
153 extern int optind;
154
155 struct ExpansionBase *ExpansionBase = NULL;
156 struct GfxBase *GfxBase = NULL;
157
158 u_int minmemsz = 2 * 1024 * 1024;
159 int p_flag = 1;
160 int k_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 u_char *kp;
171 u_long kpsz;
172
173
174 void
exit_func(void)175 exit_func(void)
176 {
177 if (kp)
178 FreeMem(kp, kpsz);
179 if (ExpansionBase)
180 CloseLibrary((struct Library *)ExpansionBase);
181 if (GfxBase)
182 CloseLibrary((struct Library *)GfxBase);
183 }
184
185 int
main(int argc,char ** argv)186 main(int argc, char **argv)
187 {
188 struct ConfigDev *cd, *kcd;
189 u_long fmemsz, cmemsz, ksize, marks[MARK_MAX];
190 int boothowto, ncd, i, mem_ix, ch;
191 u_short kvers;
192 int *nkcd;
193 u_char *fmem;
194 char *esym;
195 void (*start_it) (void *, u_long, u_long, void *, u_long, u_long,
196 int, void *, int, int, u_long, u_long, int) = startit;
197 char *kernel_name;
198
199 atexit(exit_func);
200
201 program_name = argv[0];
202 boothowto = RB_SINGLE;
203
204 if (argc < 2)
205 usage();
206
207 if ((GfxBase = (void *)OpenLibrary(GRAPHICSNAME, 0)) == NULL)
208 err(20, "can't open graphics library");
209 if ((ExpansionBase=(void *)OpenLibrary(EXPANSIONNAME, 0)) == NULL)
210 err(20, "can't open expansion library");
211
212 while ((ch = getopt(argc, argv, "aAbCc:DhI:klm:M:n:qptsSvVZ")) != -1) {
213 switch (ch) {
214 case 'k':
215 k_flag = 1;
216 break;
217 case 'a':
218 boothowto &= ~(RB_SINGLE);
219 boothowto |= RB_AUTOBOOT;
220 break;
221 case 'b':
222 boothowto |= RB_ASKNAME;
223 break;
224 case 'p':
225 p_flag = 1;
226 break;
227 case 'l':
228 p_flag = 0;
229 break;
230 case 't':
231 t_flag = 1;
232 break;
233 case 'm':
234 reqmemsz = atoi(optarg) * 1024;
235 break;
236 case 'M':
237 minmemsz = atoi(optarg) * 1024 * 1024;
238 break;
239 case 's':
240 boothowto &= ~(RB_AUTOBOOT);
241 boothowto |= RB_SINGLE;
242 break;
243 case 'q':
244 boothowto |= AB_QUIET;
245 break;
246 case 'v':
247 boothowto |= AB_VERBOSE;
248 break;
249 case 'V':
250 fprintf(stderr,"%s\n",_version + 6);
251 break;
252 case 'S':
253 S_flag = 1;
254 break;
255 case 'D':
256 boothowto |= RB_KDB;
257 break;
258 case 'c':
259 cpuid = atoi(optarg) << 16;
260 break;
261 case 'A':
262 amiga_flags |= 1;
263 break;
264 case 'n':
265 i = atoi(optarg);
266 if (i >= 0 && i <= 3) {
267 amiga_flags &= ~(3 << 1);
268 amiga_flags |= i << 1;
269 }
270 else
271 err(20, "-n option must be 0, 1, 2, or 3");
272 break;
273 case 'C':
274 amiga_flags |= (1 << 3);
275 break;
276 case 'I':
277 I_flag = strtoul(optarg, NULL, 16);
278 break;
279 case 'Z':
280 Z_flag = 1;
281 break;
282 case 'h':
283 verbose_usage();
284 default:
285 usage();
286 }
287 }
288 argc -= optind;
289 argv += optind;
290
291 if (argc != 1)
292 usage();
293
294 kernel_name = argv[0];
295
296 for (cd = 0, ncd = 0; cd = FindConfigDev(cd, -1, -1); ncd++)
297 ;
298 get_cpuid();
299 get_mem_config((void **)&fmem, &fmemsz, &cmemsz);
300 get_eclock();
301 get_AGA();
302
303 /*
304 * XXX Call loadfile with COUNT* options to get size
305 * XXX Allocate memory for kernel + additional data
306 * XXX Call loadfile with LOAD* options to load text/data/symbols
307 */
308 marks[MARK_START] = 0;
309 if (loadfile(kernel_name, marks,
310 COUNT_TEXT|COUNT_TEXTA|COUNT_DATA|COUNT_BSS|
311 (S_flag ? (COUNT_SYM|COUNT_HDR) : 0)) == -1) {
312 err(20, "unable to parse kernel image");
313 }
314 ksize = ((marks[MARK_END] + 3) & ~3)
315 + sizeof(*nkcd) + ncd * sizeof(*cd)
316 + sizeof(*nkcd) + memlist.m_nseg * sizeof(struct boot_memseg);
317
318 if (t_flag) {
319 for (i = 0; i < memlist.m_nseg; ++i) {
320 printf("mem segment %d: start=%08x size=%08x"
321 " attribute=%04x pri=%d\n",
322 i + 1,
323 memlist.m_seg[i].ms_start,
324 memlist.m_seg[i].ms_size,
325 memlist.m_seg[i].ms_attrib,
326 memlist.m_seg[i].ms_pri);
327 }
328 printf("kernel size: %lu\n", ksize);
329 }
330
331 kpsz = ksize + 256 + startit_sz;
332 kp = (u_char *)AllocMem(kpsz, MEMF_FAST|MEMF_REVERSE);
333 if (kp == NULL)
334 err(20, "failed alloc %d", ksize);
335
336 marks[MARK_START] = (u_long)kp;
337 if (loadfile(kernel_name, marks,
338 LOAD_TEXT|LOAD_TEXTA|LOAD_DATA|LOAD_BSS|
339 (S_flag ? (LOAD_SYM|LOAD_HDR) : 0)) == -1) {
340 err(20, "unable to load kernel image");
341 }
342 marks[MARK_END] = (marks[MARK_END] + 3) & ~3;
343
344 if (k_flag) {
345 fmem += 4 * 1024 * 1024;
346 fmemsz -= 4 * 1024 * 1024;
347 }
348 if (reqmemsz && reqmemsz <= fmemsz)
349 fmemsz = reqmemsz;
350
351 if (boothowto & RB_AUTOBOOT)
352 printf("Autobooting...");
353 if (boothowto & RB_ASKNAME)
354 printf("Askboot...");
355
356 printf("Using %lu%c FASTMEM at 0x%lx, %luM CHIPMEM\n",
357 (fmemsz & 0xfffff) ? fmemsz >> 10 : fmemsz >> 20,
358 (fmemsz & 0xfffff) ? 'K' : 'M', (u_long)fmem, cmemsz >> 20);
359
360 kvers = *(u_short *)(marks[MARK_ENTRY] - 2);
361 if (kvers == 0x4e73) kvers = 0;
362 if (kvers > KERNEL_STARTUP_VERSION_MAX)
363 err(20, "newer loadbsd required: %d\n", kvers);
364 if (kvers > KERNEL_STARTUP_VERSION) {
365 printf("****************************************************\n"
366 "*** Notice: this kernel has features which require\n"
367 "*** a newer version of loadbsd. To allow the use of\n"
368 "*** any newer features or capabilities, you should\n"
369 "*** update to a newer version of loadbsd\n"
370 "****************************************************\n");
371 sleep(3); /* even more time to see that message */
372 }
373
374 /*
375 * give them a chance to read the information...
376 */
377 sleep(2);
378
379 nkcd = (int *)marks[MARK_END];
380 esym = 0;
381 /*
382 * If symbols loaded and kernel can handle them, set esym to end.
383 */
384 if (marks[MARK_SYM] != marks[MARK_START]) {
385 if (kvers > 1) {
386 esym = (void *)(marks[MARK_END] - marks[MARK_START]);
387 }
388 else {
389 /*
390 * suppress symbols
391 */
392 nkcd = (int *)marks[MARK_SYM];
393 }
394 }
395
396 *nkcd = ncd;
397 kcd = (struct ConfigDev *)(nkcd + 1);
398 while((cd = FindConfigDev(cd, -1, -1))) {
399 u_char *ba = kcd->cd_BoardAddr;
400
401 memcpy(kcd, cd, sizeof(*kcd));
402 if (((cpuid >> 24) == 0x7d) && ((u_long)ba < 0x1000000)) {
403 if (t_flag)
404 printf("Transformed Z2 device from %08lx ", (u_long)ba);
405 ba += 0x3000000;
406 kcd->cd_BoardAddr = ba;
407 if (t_flag)
408 printf("to %08lx\n", (u_long)ba);
409 }
410 ++kcd;
411 }
412
413 kmemlist = (struct boot_memlist *)kcd;
414 kmemlist->m_nseg = memlist.m_nseg;
415 for (mem_ix = 0; mem_ix < memlist.m_nseg; mem_ix++)
416 kmemlist->m_seg[mem_ix] = memlist.m_seg[mem_ix];
417
418 if (kvers > 2 && Z_flag == 0) {
419 /*
420 * Kernel supports direct load to fastmem, and the -Z
421 * option was not specified. Copy startup code to end
422 * of kernel image and set start_it.
423 */
424 if (ksize >= fmemsz) {
425 printf("Kernel size %lu exceeds best Fast Memory segment of %lu\n",
426 ksize, fmemsz);
427 err(20, "Insufficient Fast Memory for kernel");
428 }
429 if (kp < fmem) {
430 printf("Kernel at %08lx, Fastmem used at %08lx\n",
431 (u_long)kp, (u_long)fmem);
432 err(20, "Can't copy upwards yet.\nDefragment your memory and try again OR try the -p OR try the -Z options.");
433 }
434 start_it = (void (*)())(kp + ksize + 256);
435 memcpy((void *)start_it, (void *)startit, startit_sz);
436 CacheClearU();
437 printf("*** Loading from %08lx to Fastmem %08lx ***\n",
438 (u_long)kp, (u_long)fmem);
439 sleep(2);
440 } else {
441 /*
442 * Either the kernel doesn't support loading directly to
443 * fastmem or the -Z flag was given. Verify kernel image
444 * fits into chipmem.
445 */
446 if (ksize >= cmemsz) {
447 printf("Kernel size %lu exceeds Chip Memory of %lu\n",
448 ksize, cmemsz);
449 err(20, "Insufficient Chip Memory for kernel");
450 }
451 Z_flag = 1;
452 printf("*** Loading from %08lx to Chipmem ***\n", (u_long)kp);
453 }
454
455 /*
456 * if test option set, done
457 */
458 if (t_flag) {
459 exit(0);
460 }
461
462 /*
463 * XXX AGA startup - may need more
464 */
465 LoadView(NULL); /* Don't do this if AGA active? */
466 start_it(kp, ksize, marks[MARK_ENTRY] - marks[MARK_START], fmem, fmemsz, cmemsz,
467 boothowto, esym, cpuid, eclock_freq, amiga_flags, I_flag, Z_flag == 0);
468 /*NOTREACHED*/
469 }
470
471 void
get_mem_config(void ** fmem,u_long * fmemsz,u_long * cmemsz)472 get_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 */
620 void
get_cpuid(void)621 get_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
666 void
get_eclock(void)667 get_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
677 void
get_AGA(void)678 get_AGA(void)
679 {
680 /*
681 * Determine if an AGA mode is active
682 */
683 }
684
685 void
usage(void)686 usage(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
693 void
verbose_usage(void)694 verbose_usage(void)
695 {
696 fprintf(stderr, "\n\
697 NAME\n\
698 \t%s - loads NetBSD from amiga dos.\n\
699 SYNOPSIS\n\
700 \t%s [-abhklpstACDSVZ] [-c machine] [-m size] [-M size] [-n mode] [-I sync-inhibit] kernel\n\
701 OPTIONS\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\
732 HISTORY\n\
733 \tThis version supports Kernel version 720 +\n",
734 program_name, program_name);
735 exit(1);
736 }
737
738 static void
_Vdomessage(int doerrno,const char * fmt,va_list args)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
752 void
err(int eval,const char * fmt,...)753 err(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
762 void
warn(const char * fmt,...)763 warn(const char *fmt, ...)
764 {
765 va_list ap;
766 va_start(ap, fmt);
767 _Vdomessage(1, fmt, ap);
768 va_end(ap);
769 }
770