loadbsd.c revision 1.13 1 1.7 chopps /*
2 1.12 chopps * Copyright (c) 1994 Michael L. Hitch
3 1.12 chopps * All rights reserved.
4 1.12 chopps *
5 1.12 chopps * Redistribution and use in source and binary forms, with or without
6 1.12 chopps * modification, are permitted provided that the following conditions
7 1.12 chopps * are met:
8 1.12 chopps * 1. Redistributions of source code must retain the above copyright
9 1.12 chopps * notice, this list of conditions and the following disclaimer.
10 1.12 chopps * 2. Redistributions in binary form must reproduce the above copyright
11 1.12 chopps * notice, this list of conditions and the following disclaimer in the
12 1.12 chopps * documentation and/or other materials provided with the distribution.
13 1.12 chopps * 3. All advertising materials mentioning features or use of this software
14 1.12 chopps * must display the following acknowledgement:
15 1.12 chopps * This product includes software developed by Michael L. Hitch.
16 1.12 chopps * 4. The name of the author may not be used to endorse or promote products
17 1.12 chopps * derived from this software without specific prior written permission
18 1.12 chopps *
19 1.12 chopps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 1.12 chopps * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 1.12 chopps * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 1.12 chopps * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 1.12 chopps * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 1.12 chopps * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 1.12 chopps * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 1.12 chopps * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 1.12 chopps * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 1.12 chopps * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 1.12 chopps *
30 1.12 chopps * $Id: loadbsd.c,v 1.13 1994/06/23 05:28:04 chopps Exp $
31 1.7 chopps */
32 1.7 chopps
33 1.1 mw #include <sys/types.h>
34 1.1 mw #include <a.out.h>
35 1.1 mw #include <stdio.h>
36 1.8 chopps #include <unistd.h>
37 1.12 chopps #include <errno.h>
38 1.12 chopps #include <stdarg.h>
39 1.12 chopps #include <signal.h>
40 1.12 chopps #ifdef __NetBSD__
41 1.12 chopps #include <err.h>
42 1.12 chopps #endif
43 1.1 mw #include <exec/types.h>
44 1.1 mw #include <exec/execbase.h>
45 1.1 mw #include <exec/memory.h>
46 1.10 chopps #include <exec/resident.h>
47 1.12 chopps #include <graphics/gfxbase.h>
48 1.1 mw #include <libraries/configregs.h>
49 1.12 chopps #include <libraries/configvars.h>
50 1.12 chopps #include <libraries/expansion.h>
51 1.1 mw #include <libraries/expansionbase.h>
52 1.1 mw
53 1.1 mw #include <inline/exec.h>
54 1.1 mw #include <inline/expansion.h>
55 1.5 mw #include <inline/graphics.h>
56 1.1 mw
57 1.3 mw /* Get definitions for boothowto */
58 1.3 mw #include "reboot.h"
59 1.3 mw
60 1.1 mw #undef __LDPGSZ
61 1.1 mw #define __LDPGSZ 8192
62 1.1 mw
63 1.12 chopps #ifndef __NetBSD__
64 1.12 chopps #ifndef __P
65 1.12 chopps #ifdef __STDC__
66 1.12 chopps #define __P(x) x
67 1.12 chopps #else
68 1.12 chopps #define __P(x)
69 1.12 chopps #endif
70 1.12 chopps #endif
71 1.12 chopps void err __P((int, const char *, ...));
72 1.12 chopps void errx __P((int, const char *, ...));
73 1.12 chopps void warn __P((const char *, ...));
74 1.12 chopps void warnx __P((const char *, ...));
75 1.12 chopps #endif
76 1.6 chopps
77 1.9 chopps /*
78 1.9 chopps * Version history:
79 1.10 chopps * 1.x Kernel parameter passing version check.
80 1.10 chopps * 2.0 Added symbol table end address and symbol table support.
81 1.10 chopps * 2.1 03/23/94 - Round up end of fastram segment.
82 1.10 chopps * Check fastram segment size for minimum of 2M.
83 1.10 chopps * Use largest segment of highest priority if -p option.
84 1.10 chopps * Print out fastram size in KB if not a multiple of MB.
85 1.10 chopps * 2.2 03/24/94 - Zero out all unused registers.
86 1.10 chopps * Started version history comment.
87 1.10 chopps * 2.3 04/26/94 - Added -D option to enter debugger on boot.
88 1.10 chopps * 2.4 04/30/94 - Cpuid includes base machine type.
89 1.10 chopps * Also check if CPU is capable of running NetBSD.
90 1.11 chopps * 2.5 05/17/94 - Add check for "A3000 bonus".
91 1.11 chopps * 2.6 06/05/94 - Added -c option to override machine type.
92 1.12 chopps * 2.7 06/15/94 - Pass E clock frequency.
93 1.13 chopps * 2.8 06/22/94 - Fix supervisor stack usage.
94 1.9 chopps */
95 1.13 chopps static const char _version[] = "$VER: LoadBSD 2.8 (22.6.94)";
96 1.9 chopps
97 1.12 chopps /*
98 1.12 chopps * Kernel parameter passing version
99 1.12 chopps * 1: first version of loadbsd
100 1.12 chopps * 2: needs esym location passed in a4
101 1.12 chopps */
102 1.12 chopps #define KERNEL_PARAMETER_VERSION 2
103 1.10 chopps
104 1.12 chopps #define MAXMEMSEG 16
105 1.12 chopps struct boot_memlist {
106 1.12 chopps u_int m_nseg; /* num_mem; */
107 1.12 chopps struct boot_memseg {
108 1.12 chopps u_int ms_start;
109 1.12 chopps u_int ms_size;
110 1.12 chopps u_short ms_attrib;
111 1.12 chopps short ms_pri;
112 1.12 chopps } m_seg[MAXMEMSEG];
113 1.12 chopps };
114 1.12 chopps struct boot_memlist memlist;
115 1.12 chopps struct boot_memlist *kmemlist;
116 1.12 chopps
117 1.12 chopps
118 1.12 chopps void get_mem_config __P((void **, u_long *, u_long *));
119 1.12 chopps void get_cpuid __P((void));
120 1.12 chopps void get_eclock __P((void));
121 1.12 chopps void usage __P((void));
122 1.12 chopps void verbose_usage __P((void));
123 1.12 chopps void Version __P((void));
124 1.5 mw
125 1.12 chopps extern struct ExecBase *SysBase;
126 1.5 mw extern char *optarg;
127 1.5 mw extern int optind;
128 1.5 mw
129 1.12 chopps int k_flag;
130 1.12 chopps int p_flag;
131 1.12 chopps int t_flag;
132 1.12 chopps int reqmemsz;
133 1.12 chopps int S_flag;
134 1.12 chopps u_long cpuid;
135 1.12 chopps long eclock_freq;
136 1.12 chopps char *program_name;
137 1.12 chopps char *kname;
138 1.12 chopps struct ExpansionBase *ExpansionBase;
139 1.12 chopps struct GfxBase *GfxBase;
140 1.6 chopps
141 1.1 mw
142 1.10 chopps int
143 1.12 chopps main(argc, argv)
144 1.12 chopps int argc;
145 1.12 chopps char **argv;
146 1.1 mw {
147 1.12 chopps struct exec e;
148 1.12 chopps struct ConfigDev *cd, *kcd;
149 1.12 chopps u_long fmemsz, cmemsz;
150 1.12 chopps int fd, boothowto, ksize, textsz, stringsz, ncd, i, mem_ix, ch;
151 1.12 chopps u_short *kvers;
152 1.12 chopps int *nkcd;
153 1.12 chopps u_char *kp;
154 1.12 chopps void *fmem;
155 1.12 chopps char *esym;
156 1.12 chopps
157 1.12 chopps program_name = argv[0];
158 1.12 chopps boothowto = RB_SINGLE;
159 1.12 chopps
160 1.12 chopps if (argc < 2)
161 1.12 chopps usage();
162 1.12 chopps if ((GfxBase = (void *)OpenLibrary(GRAPHICSNAME, 0)) == NULL)
163 1.12 chopps err(20, "can't open graphics library");
164 1.12 chopps if ((ExpansionBase=(void *)OpenLibrary(EXPANSIONNAME, 0)) == NULL)
165 1.12 chopps err(20, "can't open expansion library");
166 1.12 chopps
167 1.12 chopps while ((ch = getopt(argc, argv, "abc:Dkm:ptSV")) != EOF) {
168 1.12 chopps switch (ch) {
169 1.12 chopps case 'k':
170 1.12 chopps k_flag = 1;
171 1.12 chopps break;
172 1.12 chopps case 'a':
173 1.12 chopps boothowto &= ~(RB_SINGLE);
174 1.12 chopps boothowto |= RB_AUTOBOOT;
175 1.12 chopps break;
176 1.12 chopps case 'b':
177 1.12 chopps boothowto |= RB_ASKNAME;
178 1.12 chopps break;
179 1.12 chopps case 'p':
180 1.12 chopps p_flag = 1;
181 1.12 chopps break;
182 1.12 chopps case 't':
183 1.12 chopps t_flag = 1;
184 1.12 chopps break;
185 1.12 chopps case 'm':
186 1.12 chopps reqmemsz = atoi(optarg) * 1024;
187 1.12 chopps break;
188 1.12 chopps case 'V':
189 1.12 chopps fprintf(stderr,"%s\n",_version + 6);
190 1.12 chopps break;
191 1.12 chopps case 'S':
192 1.12 chopps S_flag = 1;
193 1.12 chopps break;
194 1.12 chopps case 'D':
195 1.12 chopps boothowto |= RB_KDB;
196 1.12 chopps break;
197 1.12 chopps case 'c':
198 1.12 chopps cpuid = atoi(optarg) << 16;
199 1.12 chopps break;
200 1.12 chopps case 'h':
201 1.12 chopps verbose_usage();
202 1.12 chopps default:
203 1.12 chopps usage();
204 1.12 chopps }
205 1.12 chopps }
206 1.12 chopps argc -= optind;
207 1.12 chopps argv += optind;
208 1.12 chopps
209 1.12 chopps if (argc != 1)
210 1.12 chopps usage();
211 1.12 chopps kname = argv[0];
212 1.12 chopps
213 1.12 chopps if ((fd = open(kname, 0)) < 0)
214 1.12 chopps err(20, "open");
215 1.12 chopps if (read(fd, &e, sizeof(e)) != sizeof(e))
216 1.12 chopps err(20, "reading exec");
217 1.12 chopps if (e.a_magic != NMAGIC)
218 1.12 chopps err(20, "unknown binary");
219 1.12 chopps
220 1.12 chopps for (cd = 0, ncd = 0; cd = FindConfigDev(cd, -1, -1); ncd++)
221 1.12 chopps ;
222 1.12 chopps get_mem_config(&fmem, &fmemsz, &cmemsz);
223 1.12 chopps get_cpuid();
224 1.12 chopps get_eclock();
225 1.12 chopps
226 1.12 chopps textsz = (e.a_text + __LDPGSZ - 1) & (-__LDPGSZ);
227 1.12 chopps esym = NULL;
228 1.12 chopps ksize = textsz + e.a_data + e.a_bss + ncd * sizeof(*cd)
229 1.12 chopps + 4 + memlist.m_nseg * sizeof(struct boot_memseg) + 4;
230 1.12 chopps
231 1.12 chopps /*
232 1.12 chopps * get symbol table size & string size
233 1.12 chopps * (should check kernel version to see if it will handle it)
234 1.12 chopps */
235 1.12 chopps if (S_flag && e.a_syms) {
236 1.12 chopps if (lseek(fd, e.a_text + e.a_data + e.a_syms, SEEK_CUR) <= 0
237 1.12 chopps || read(fd, &stringsz, 4) != 4
238 1.12 chopps || lseek(fd, sizeof(e), SEEK_SET) < 0)
239 1.12 chopps err(20, "lseek for symbols");
240 1.12 chopps ksize += e.a_syms + 4 + stringsz;
241 1.12 chopps }
242 1.12 chopps
243 1.12 chopps kp = (u_char *)malloc(ksize);
244 1.12 chopps if (t_flag) {
245 1.12 chopps for (i = 0; i < memlist.m_nseg; ++i) {
246 1.12 chopps printf("mem segment %d: start=%08lx size=%08lx"
247 1.12 chopps " attribute=%04lx pri=%d\n",
248 1.12 chopps i + 1, memlist.m_seg[i].ms_start,
249 1.12 chopps memlist.m_seg[i].ms_size,
250 1.12 chopps memlist.m_seg[i].ms_attrib,
251 1.12 chopps memlist.m_seg[i].ms_pri);
252 1.10 chopps }
253 1.12 chopps }
254 1.12 chopps if (kp == NULL)
255 1.12 chopps err(20, "failed malloc %d\n", ksize);
256 1.12 chopps
257 1.12 chopps if (read(fd, kp, e.a_text) != e.a_text
258 1.12 chopps || read(fd, kp + textsz, e.a_data) != e.a_data)
259 1.12 chopps err(20, "unable to read kernel image\n");
260 1.12 chopps
261 1.12 chopps if (k_flag) {
262 1.12 chopps fmem += 4 * 1024 * 1024;
263 1.12 chopps fmemsz -= 4 * 1024 * 1024;
264 1.12 chopps }
265 1.1 mw
266 1.12 chopps if (reqmemsz && reqmemsz <= fmemsz)
267 1.12 chopps fmemsz = reqmemsz;
268 1.12 chopps if (boothowto & RB_AUTOBOOT)
269 1.12 chopps printf("Autobooting...");
270 1.12 chopps if (boothowto & RB_ASKNAME)
271 1.12 chopps printf("Askboot...");
272 1.12 chopps
273 1.12 chopps printf("Using %d%c FASTMEM at 0x%x, %dM CHIPMEM\n",
274 1.12 chopps (fmemsz & 0xfffff) ? fmemsz >> 10 : fmemsz >> 20,
275 1.12 chopps (fmemsz & 0xfffff) ? 'K' : 'M', fmem, cmemsz >> 20);
276 1.12 chopps kvers = (u_short *)(kp + e.a_entry - 2);
277 1.12 chopps if (*kvers > KERNEL_PARAMETER_VERSION && *kvers != 0x4e73)
278 1.12 chopps err(20, "newer loadbsd required: %d\n", *kvers);
279 1.12 chopps if ((cpuid & AFB_68020) == 0)
280 1.12 chopps err(20, "cpu not supported");
281 1.12 chopps /*
282 1.12 chopps * give them a chance to read the information...
283 1.12 chopps */
284 1.12 chopps sleep(2);
285 1.12 chopps
286 1.12 chopps bzero(kp + textsz + e.a_data, e.a_bss);
287 1.12 chopps /*
288 1.12 chopps * If symbols wanted (and kernel can handle them),
289 1.12 chopps * load symbol table & strings and set esym to end.
290 1.12 chopps */
291 1.12 chopps nkcd = (int *)(kp + textsz + e.a_data + e.a_bss);
292 1.12 chopps if (*kvers != 0x4e73 && *kvers > 1 && S_flag && e.a_syms) {
293 1.12 chopps *nkcd++ = e.a_syms;
294 1.12 chopps read(fd, (char *)nkcd, e.a_syms);
295 1.12 chopps nkcd = (int *)((char *)nkcd + e.a_syms);
296 1.12 chopps read(fd, (char *)nkcd, stringsz);
297 1.12 chopps nkcd = (int*)((char *)nkcd + stringsz);
298 1.12 chopps esym = (char *)(textsz + e.a_data + e.a_bss
299 1.12 chopps + e.a_syms + 4 + stringsz);
300 1.10 chopps }
301 1.12 chopps *nkcd = ncd;
302 1.12 chopps
303 1.12 chopps kcd = (struct ConfigDev *)(nkcd + 1);
304 1.12 chopps while(cd = FindConfigDev(cd, -1, -1))
305 1.12 chopps *kcd++ = *cd;
306 1.12 chopps
307 1.12 chopps kmemlist = (struct boot_memlist *)kcd;
308 1.12 chopps kmemlist->m_nseg = memlist.m_nseg;
309 1.12 chopps for (mem_ix = 0; mem_ix < memlist.m_nseg; mem_ix++)
310 1.12 chopps kmemlist->m_seg[mem_ix] = memlist.m_seg[mem_ix];
311 1.12 chopps /*
312 1.12 chopps * if test option set, done
313 1.12 chopps */
314 1.12 chopps if (t_flag)
315 1.12 chopps exit(0);
316 1.12 chopps
317 1.12 chopps /*
318 1.12 chopps * XXX AGA startup - may need more
319 1.12 chopps */
320 1.12 chopps LoadView(NULL);
321 1.12 chopps startit(kp, ksize, e.a_entry, fmem, fmemsz, cmemsz, boothowto, esym,
322 1.12 chopps cpuid, eclock_freq);
323 1.12 chopps /*NOTREACHED*/
324 1.12 chopps }
325 1.1 mw
326 1.1 mw void
327 1.12 chopps get_mem_config(fmem, fmemsz, cmemsz)
328 1.12 chopps void **fmem;
329 1.12 chopps u_long *fmemsz, *cmemsz;
330 1.1 mw {
331 1.12 chopps struct MemHeader *mh, *nmh;
332 1.12 chopps u_int segsz, seg, eseg, nmem;
333 1.12 chopps char mempri;
334 1.12 chopps
335 1.12 chopps nmem = 0;
336 1.12 chopps mempri = -128;
337 1.12 chopps *fmemsz = 0;
338 1.12 chopps *cmemsz = 0;
339 1.12 chopps
340 1.12 chopps /*
341 1.12 chopps * walk thru the exec memory list
342 1.12 chopps */
343 1.12 chopps Forbid();
344 1.12 chopps for (mh = (void *) SysBase->MemList.lh_Head;
345 1.12 chopps nmh = (void *) mh->mh_Node.ln_Succ; mh = nmh, nmem++) {
346 1.12 chopps memlist.m_seg[nmem].ms_attrib = mh->mh_Attributes;
347 1.12 chopps memlist.m_seg[nmem].ms_pri = mh->mh_Node.ln_Pri;
348 1.12 chopps seg = (u_int)mh->mh_Lower;
349 1.12 chopps eseg = (u_int)mh->mh_Upper;
350 1.12 chopps segsz = eseg - seg;
351 1.12 chopps memlist.m_seg[nmem].ms_size = segsz;
352 1.12 chopps memlist.m_seg[nmem].ms_start = seg;
353 1.12 chopps
354 1.12 chopps if (mh->mh_Attributes & MEMF_CHIP) {
355 1.12 chopps /*
356 1.12 chopps * there should hardly be more than one entry for
357 1.12 chopps * chip mem, but handle it the same nevertheless
358 1.12 chopps * cmem always starts at 0, so include vector area
359 1.12 chopps */
360 1.12 chopps memlist.m_seg[nmem].ms_start = seg = 0;
361 1.12 chopps /*
362 1.12 chopps * round to multiple of 512K
363 1.12 chopps */
364 1.12 chopps segsz = (segsz + 512 * 1024 - 1) & -(512 * 1024);
365 1.12 chopps memlist.m_seg[nmem].ms_size = segsz;
366 1.12 chopps if (segsz > *cmemsz)
367 1.12 chopps *cmemsz = segsz;
368 1.12 chopps continue;
369 1.12 chopps }
370 1.12 chopps /*
371 1.12 chopps * some heuristics..
372 1.12 chopps */
373 1.12 chopps seg &= -__LDPGSZ;
374 1.12 chopps eseg = (eseg + __LDPGSZ - 1) & -__LDPGSZ;
375 1.12 chopps
376 1.12 chopps /*
377 1.12 chopps * get the mem back stolen by incore kickstart on
378 1.12 chopps * A3000 with V36 bootrom.
379 1.12 chopps */
380 1.12 chopps if (eseg == 0x07f80000)
381 1.12 chopps eseg = 0x08000000;
382 1.12 chopps
383 1.12 chopps /*
384 1.12 chopps * or by zkick on a A2000.
385 1.12 chopps */
386 1.12 chopps if (seg == 0x280000 &&
387 1.12 chopps strcmp(mh->mh_Node.ln_Name, "zkick memory") == 0)
388 1.12 chopps seg = 0x200000;
389 1.12 chopps
390 1.12 chopps segsz = eseg - seg;
391 1.12 chopps memlist.m_seg[nmem].ms_start = seg;
392 1.12 chopps memlist.m_seg[nmem].ms_size = segsz;
393 1.12 chopps /*
394 1.12 chopps * If this segment is smaller than 2M,
395 1.12 chopps * don't use it to load the kernel
396 1.12 chopps */
397 1.12 chopps if (segsz < 2 * 1024 * 1024)
398 1.12 chopps continue;
399 1.12 chopps /*
400 1.12 chopps * if p_flag is set, select memory by priority
401 1.12 chopps * instead of size
402 1.12 chopps */
403 1.12 chopps if ((!p_flag && segsz > *fmemsz) || (p_flag &&
404 1.12 chopps mempri <= mh->mh_Node.ln_Pri && segsz > *fmemsz)) {
405 1.12 chopps *fmemsz = segsz;
406 1.12 chopps *fmem = (void *)seg;
407 1.12 chopps mempri = mh->mh_Node.ln_Pri;
408 1.12 chopps }
409 1.1 mw }
410 1.12 chopps memlist.m_nseg = nmem;
411 1.12 chopps Permit();
412 1.1 mw }
413 1.1 mw
414 1.10 chopps /*
415 1.10 chopps * Try to determine the machine ID by searching the resident module list
416 1.10 chopps * for modules only present on specific machines. (Thanks, Bill!)
417 1.10 chopps */
418 1.10 chopps void
419 1.12 chopps get_cpuid()
420 1.10 chopps {
421 1.10 chopps u_long *rl;
422 1.10 chopps struct Resident *rm;
423 1.10 chopps
424 1.11 chopps cpuid |= SysBase->AttnFlags; /* get FPU and CPU flags */
425 1.11 chopps if (cpuid & 0xffff0000) {
426 1.11 chopps switch (cpuid >> 16) {
427 1.11 chopps case 500:
428 1.11 chopps case 600:
429 1.11 chopps case 1000:
430 1.11 chopps case 1200:
431 1.11 chopps case 2000:
432 1.11 chopps case 3000:
433 1.11 chopps case 4000:
434 1.11 chopps return;
435 1.11 chopps default:
436 1.12 chopps printf("machine Amiga %d is not recognized\n",
437 1.11 chopps cpuid >> 16);
438 1.12 chopps exit(1);
439 1.11 chopps }
440 1.11 chopps }
441 1.12 chopps rl = (u_long *)SysBase->ResModules;
442 1.10 chopps if (rl == NULL)
443 1.10 chopps return;
444 1.10 chopps
445 1.10 chopps while (*rl) {
446 1.10 chopps rm = (struct Resident *) *rl;
447 1.12 chopps if (strcmp(rm->rt_Name, "A4000 Bonus") == 0 ||
448 1.12 chopps strcmp(rm->rt_Name, "A1000 Bonus") == 0) {
449 1.10 chopps cpuid |= 4000 << 16;
450 1.10 chopps break;
451 1.10 chopps }
452 1.12 chopps if (strcmp(rm->rt_Name, "A3000 bonus") == 0 ||
453 1.12 chopps strcmp(rm->rt_Name, "A3000 Bonus") == 0) {
454 1.10 chopps cpuid |= 3000 << 16;
455 1.10 chopps break;
456 1.10 chopps }
457 1.12 chopps if (strcmp(rm->rt_Name, "card.resource") == 0) {
458 1.10 chopps cpuid |= 1200 << 16; /* or A600 :-) */
459 1.10 chopps break;
460 1.10 chopps }
461 1.10 chopps ++rl;
462 1.10 chopps }
463 1.12 chopps /*
464 1.12 chopps * Nothing found, it's probably an A2000 or A500
465 1.12 chopps */
466 1.12 chopps if (*rl == 0)
467 1.10 chopps cpuid |= 2000 << 16;
468 1.10 chopps }
469 1.1 mw
470 1.12 chopps void
471 1.12 chopps get_eclock()
472 1.12 chopps {
473 1.12 chopps /* Fix for 1.3 startups? */
474 1.12 chopps eclock_freq = SysBase->ex_EClockFrequency;
475 1.12 chopps }
476 1.12 chopps
477 1.1 mw
478 1.12 chopps asm("
479 1.1 mw .set ABSEXECBASE,4
480 1.1 mw
481 1.1 mw .text
482 1.1 mw .globl _startit
483 1.1 mw
484 1.1 mw _startit:
485 1.1 mw movel sp,a3
486 1.1 mw movel 4:w,a6
487 1.1 mw lea pc@(start_super-.+2),a5
488 1.1 mw jmp a6@(-0x1e) | supervisor-call
489 1.1 mw
490 1.1 mw start_super:
491 1.1 mw movew #0x2700,sr
492 1.1 mw
493 1.1 mw | the BSD kernel wants values into the following registers:
494 1.1 mw | a0: fastmem-start
495 1.1 mw | d0: fastmem-size
496 1.1 mw | d1: chipmem-size
497 1.12 chopps | d4: E clock frequency
498 1.5 mw | d5: AttnFlags (cpuid)
499 1.3 mw | d7: boothowto
500 1.8 chopps | a4: esym location
501 1.10 chopps | All other registers zeroed for possible future requirements.
502 1.1 mw
503 1.1 mw movel a3@(4),a1 | loaded kernel
504 1.1 mw movel a3@(8),d2 | length of loaded kernel
505 1.13 chopps movel a3@(12),sp | entry point in stack pointer
506 1.1 mw movel a3@(16),a0 | fastmem-start
507 1.1 mw movel a3@(20),d0 | fastmem-size
508 1.1 mw movel a3@(24),d1 | chipmem-size
509 1.3 mw movel a3@(28),d7 | boothowto
510 1.8 chopps movel a3@(32),a4 | esym
511 1.10 chopps movel a3@(36),d5 | cpuid
512 1.12 chopps movel a3@(40),d4 | E clock frequency
513 1.8 chopps subl a5,a5 | target, load to 0
514 1.1 mw
515 1.5 mw btst #3,(ABSEXECBASE)@(0x129) | AFB_68040,SysBase->AttnFlags
516 1.5 mw beq not040
517 1.5 mw
518 1.5 mw | Turn off 68040 MMU
519 1.5 mw
520 1.8 chopps .word 0x4e7b,0xd003 | movec a5,tc
521 1.8 chopps .word 0x4e7b,0xd806 | movec a5,urp
522 1.8 chopps .word 0x4e7b,0xd807 | movec a5,srp
523 1.8 chopps .word 0x4e7b,0xd004 | movec a5,itt0
524 1.8 chopps .word 0x4e7b,0xd005 | movec a5,itt1
525 1.8 chopps .word 0x4e7b,0xd006 | movec a5,dtt0
526 1.8 chopps .word 0x4e7b,0xd007 | movec a5,dtt1
527 1.5 mw bra nott
528 1.5 mw
529 1.5 mw not040:
530 1.1 mw lea pc@(zero-.+2),a3
531 1.1 mw pmove a3@,tc | Turn off MMU
532 1.1 mw lea pc@(nullrp-.+2),a3
533 1.1 mw pmove a3@,crp | Turn off MMU some more
534 1.1 mw pmove a3@,srp | Really, really, turn off MMU
535 1.1 mw
536 1.1 mw | Turn off 68030 TT registers
537 1.1 mw
538 1.1 mw btst #2,(ABSEXECBASE)@(0x129) | AFB_68030,SysBase->AttnFlags
539 1.1 mw beq nott | Skip TT registers if not 68030
540 1.1 mw lea pc@(zero-.+2),a3
541 1.1 mw .word 0xf013,0x0800 | pmove a3@,tt0 (gas only knows about 68851 ops..)
542 1.1 mw .word 0xf013,0x0c00 | pmove a3@,tt1 (gas only knows about 68851 ops..)
543 1.1 mw
544 1.1 mw nott:
545 1.1 mw
546 1.1 mw movew #(1<<9),0xdff096 | disable DMA
547 1.1 mw
548 1.1 mw L0:
549 1.8 chopps moveb a1@+,a5@+
550 1.1 mw subl #1,d2
551 1.1 mw bcc L0
552 1.1 mw
553 1.1 mw
554 1.9 chopps moveq #0,d2 | zero out unused registers
555 1.9 chopps moveq #0,d3 | (might make future compatibility
556 1.9 chopps moveq #0,d6 | would have known contents)
557 1.9 chopps movel d6,a1
558 1.9 chopps movel d6,a2
559 1.9 chopps movel d6,a3
560 1.9 chopps movel d6,a5
561 1.9 chopps movel d6,a6
562 1.13 chopps jmp sp@ | jump to kernel entry point
563 1.1 mw
564 1.1 mw
565 1.1 mw | A do-nothing MMU root pointer (includes the following long as well)
566 1.1 mw
567 1.1 mw nullrp: .long 0x7fff0001
568 1.1 mw zero: .long 0
569 1.1 mw
570 1.1 mw
571 1.1 mw ");
572 1.1 mw
573 1.12 chopps void
574 1.12 chopps usage()
575 1.6 chopps {
576 1.12 chopps fprintf(stderr, "usage: %s [-abkptDSV] [-c machine] [-m mem] kernel\n",
577 1.12 chopps program_name);
578 1.12 chopps exit(1);
579 1.6 chopps }
580 1.6 chopps
581 1.12 chopps
582 1.12 chopps void
583 1.12 chopps verbose_usage()
584 1.12 chopps {
585 1.12 chopps fprintf(stderr, "
586 1.12 chopps NAME
587 1.12 chopps \t%s - loads NetBSD from amiga dos.
588 1.12 chopps SYNOPSIS
589 1.12 chopps \t%s [-abkptDSV] [-c machine] [-m mem] kernel
590 1.12 chopps OPTIONS
591 1.12 chopps \t-a Boot up to multiuser mode.
592 1.12 chopps \t-b Ask for which root device.
593 1.12 chopps \t Its possible to have multiple roots and choose between them.
594 1.12 chopps \t-c Set machine type. [e.g 3000]
595 1.12 chopps \t-k Reserve the first 4M of fast mem [Some one else
596 1.12 chopps \t is going to have to answer what that it is used for].
597 1.12 chopps \t-m Tweak amount of available memory, for finding minimum amount
598 1.12 chopps \t of memory required to run. Sets fastmem size to specified
599 1.12 chopps \t size in Kbytes.
600 1.12 chopps \t-p Use highest priority fastmem segement instead of the largest
601 1.12 chopps \t segment. The higher priority segment is usually faster
602 1.12 chopps \t (i.e. 32 bit memory), but some people have smaller amounts
603 1.12 chopps \t of 32 bit memory.
604 1.12 chopps \t-t This is a *test* option. It prints out the memory
605 1.12 chopps \t list information being passed to the kernel and also
606 1.12 chopps \t exits without actually starting NetBSD.
607 1.12 chopps \t-S Include kernel symbol table.
608 1.12 chopps \t-D Enter debugger
609 1.12 chopps \t-V Version of loadbsd program.
610 1.12 chopps HISTORY
611 1.12 chopps \tThis version supports Kernel version 720 +\n",
612 1.12 chopps program_name, program_name);
613 1.12 chopps exit(1);
614 1.12 chopps }
615 1.12 chopps
616 1.12 chopps
617 1.12 chopps void
618 1.12 chopps _Vdomessage(doexit, eval, doerrno, fmt, args)
619 1.12 chopps int doexit, doerrno, eval;
620 1.12 chopps const char *fmt;
621 1.12 chopps va_list args;
622 1.12 chopps {
623 1.12 chopps fprintf(stderr, "%s: ", program_name);
624 1.12 chopps if (fmt) {
625 1.12 chopps vfprintf(stderr, fmt, args);
626 1.12 chopps fprintf(stderr, ": ");
627 1.12 chopps }
628 1.12 chopps if (doerrno && errno < sys_nerr) {
629 1.12 chopps fprintf(stderr, "%s", strerror(errno));
630 1.12 chopps if (errno == EINTR || errno == 0) {
631 1.12 chopps int sigs;
632 1.12 chopps sigpending((sigset_t *)&sigs);
633 1.12 chopps printf("%x\n", sigs);
634 1.12 chopps }
635 1.12 chopps }
636 1.12 chopps fprintf(stderr, "\n");
637 1.12 chopps if (doexit)
638 1.12 chopps exit(eval);
639 1.12 chopps }
640 1.12 chopps
641 1.12 chopps void
642 1.12 chopps err(int eval, const char *fmt, ...)
643 1.12 chopps {
644 1.12 chopps va_list ap;
645 1.12 chopps va_start(ap, fmt);
646 1.12 chopps _Vdomessage(1, eval, 1, fmt, ap);
647 1.12 chopps /*NOTREACHED*/
648 1.12 chopps }
649 1.12 chopps
650 1.12 chopps void
651 1.12 chopps errx(int eval, const char *fmt, ...)
652 1.12 chopps {
653 1.12 chopps va_list ap;
654 1.12 chopps va_start(ap, fmt);
655 1.12 chopps _Vdomessage(1, eval, 0, fmt, ap);
656 1.12 chopps /*NOTREACHED*/
657 1.12 chopps }
658 1.12 chopps
659 1.12 chopps void
660 1.12 chopps warn(const char *fmt, ...)
661 1.12 chopps {
662 1.12 chopps va_list ap;
663 1.12 chopps va_start(ap, fmt);
664 1.12 chopps _Vdomessage(0, 0, 1, fmt, ap);
665 1.12 chopps va_end(ap);
666 1.12 chopps }
667 1.12 chopps
668 1.12 chopps void
669 1.12 chopps warnx(const char *fmt, ...)
670 1.6 chopps {
671 1.12 chopps va_list ap;
672 1.12 chopps va_start(ap, fmt);
673 1.12 chopps _Vdomessage(0, 0, 0, fmt, ap);
674 1.12 chopps va_end(ap);
675 1.6 chopps }
676