loadbsd.c revision 1.7 1 1.7 chopps /*
2 1.7 chopps * $Id: loadbsd.c,v 1.7 1994/02/11 07:03:01 chopps Exp $
3 1.7 chopps */
4 1.7 chopps
5 1.1 mw #include <sys/types.h>
6 1.1 mw #include <a.out.h>
7 1.1 mw #include <stdio.h>
8 1.1 mw
9 1.1 mw #include <exec/types.h>
10 1.1 mw #include <exec/execbase.h>
11 1.1 mw #include <exec/memory.h>
12 1.1 mw #include <libraries/configregs.h>
13 1.1 mw #include <libraries/expansionbase.h>
14 1.5 mw #include <graphics/gfxbase.h>
15 1.1 mw
16 1.1 mw #include <inline/exec.h>
17 1.1 mw #include <inline/expansion.h>
18 1.5 mw #include <inline/graphics.h>
19 1.1 mw
20 1.3 mw /* Get definitions for boothowto */
21 1.3 mw #include "reboot.h"
22 1.3 mw
23 1.6 chopps static char usage[] =
24 1.6 chopps "
25 1.6 chopps NAME
26 1.6 chopps \t%s - loads NetBSD from amiga dos.
27 1.6 chopps SYNOPSIS
28 1.6 chopps \t%s some-vmunix [-a] [-b] [-k] [-m memory] [-p] [-t] [-V]
29 1.6 chopps OPTIONS
30 1.6 chopps \t-a Boot up to multiuser mode.
31 1.6 chopps \t-b Ask for which root device.
32 1.6 chopps \t Its possible to have multiple roots and choose between them.
33 1.6 chopps \t-k Reserve the first 4M of fast mem [Some one else
34 1.6 chopps \t is going to have to answer what that it is used for].
35 1.6 chopps \t-m Tweak amount of available memory, for finding minimum amount
36 1.6 chopps \t of memory required to run. Sets fastmem size to specified
37 1.6 chopps \t size in Kbytes.
38 1.6 chopps \t-p Use highest priority fastmem segement instead of the largest
39 1.6 chopps \t segment. The higher priority segment is usually faster
40 1.6 chopps \t (i.e. 32 bit memory), but some people have smaller amounts
41 1.6 chopps \t of 32 bit memory.
42 1.6 chopps \t-t This is a *test* option. It prints out the memory
43 1.6 chopps \t list information being passed to the kernel and also
44 1.6 chopps \t exits without actually starting NetBSD.
45 1.6 chopps \t-V Version of loadbsd program.
46 1.6 chopps HISTORY
47 1.6 chopps This version supports Kernel version 720 +
48 1.6 chopps ";
49 1.6 chopps
50 1.1 mw struct ExpansionBase *ExpansionBase;
51 1.5 mw struct GfxBase *GfxBase;
52 1.1 mw
53 1.1 mw #undef __LDPGSZ
54 1.1 mw #define __LDPGSZ 8192
55 1.1 mw
56 1.5 mw #define MAX_MEM_SEG 16
57 1.5 mw
58 1.6 chopps /*
59 1.6 chopps * Kernel parameter passing version
60 1.6 chopps */
61 1.6 chopps #define KERNEL_PARAMETER_VERSION 1
62 1.6 chopps
63 1.5 mw struct MEM_LIST {
64 1.5 mw u_long num_mem;
65 1.5 mw struct MEM_SEG {
66 1.5 mw u_long mem_start;
67 1.5 mw u_long mem_size;
68 1.5 mw u_short mem_attrib;
69 1.5 mw short mem_prio;
70 1.5 mw } mem_seg[MAX_MEM_SEG];
71 1.5 mw } mem_list, *kmem_list;
72 1.5 mw
73 1.5 mw int k_opt;
74 1.5 mw int a_opt;
75 1.5 mw int b_opt;
76 1.5 mw int p_opt;
77 1.5 mw int t_opt;
78 1.6 chopps int m_opt;
79 1.5 mw
80 1.5 mw extern char *optarg;
81 1.5 mw extern int optind;
82 1.5 mw
83 1.1 mw void get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size);
84 1.6 chopps void Usage (char *program_name);
85 1.6 chopps void Version (void);
86 1.6 chopps
87 1.6 chopps static const char _version[] = "$VER: LoadBSD 1.744 (28.1.94)";
88 1.1 mw
89 1.1 mw int
90 1.1 mw main (int argc, char *argv[])
91 1.1 mw {
92 1.1 mw struct exec e;
93 1.1 mw int fd;
94 1.3 mw int boothowto = RB_SINGLE;
95 1.1 mw
96 1.1 mw if (argc >= 2)
97 1.1 mw {
98 1.1 mw if ((fd = open (argv[1], 0)) >= 0)
99 1.1 mw {
100 1.1 mw if (read (fd, &e, sizeof (e)) == sizeof (e))
101 1.1 mw {
102 1.1 mw if (e.a_magic == NMAGIC)
103 1.1 mw {
104 1.1 mw u_char *kernel;
105 1.1 mw int text_size;
106 1.1 mw struct ConfigDev *cd;
107 1.1 mw int num_cd;
108 1.5 mw void *fastmem_start;
109 1.5 mw u_long fastmem_size, chipmem_size;
110 1.5 mw int i;
111 1.6 chopps u_short *kern_vers;
112 1.1 mw
113 1.5 mw GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", 0);
114 1.5 mw if (! GfxBase) /* not supposed to fail... */
115 1.5 mw abort();
116 1.1 mw ExpansionBase= (struct ExpansionBase *) OpenLibrary ("expansion.library", 0);
117 1.1 mw if (! ExpansionBase) /* not supposed to fail... */
118 1.1 mw abort();
119 1.5 mw optind = 2;
120 1.6 chopps while ((i = getopt (argc, argv, "kabptVm:")) != EOF)
121 1.5 mw switch (i) {
122 1.5 mw case 'k':
123 1.5 mw k_opt = 1;
124 1.5 mw break;
125 1.5 mw case 'a':
126 1.5 mw a_opt = 1;
127 1.5 mw break;
128 1.5 mw case 'b':
129 1.5 mw b_opt = 1;
130 1.5 mw break;
131 1.5 mw case 'p':
132 1.5 mw p_opt = 1;
133 1.5 mw break;
134 1.5 mw case 't':
135 1.5 mw t_opt = 1;
136 1.5 mw break;
137 1.6 chopps case 'm':
138 1.6 chopps m_opt = atoi (optarg) * 1024;
139 1.6 chopps break;
140 1.6 chopps case 'V':
141 1.6 chopps Version();
142 1.6 chopps break;
143 1.6 chopps default:
144 1.6 chopps Usage(argv[0]);
145 1.6 chopps fprintf(stderr,"Unrecognized option \n");
146 1.6 chopps exit(-1);
147 1.5 mw }
148 1.5 mw
149 1.1 mw for (cd = 0, num_cd = 0; cd = FindConfigDev (cd, -1, -1); num_cd++) ;
150 1.5 mw get_mem_config (&fastmem_start, &fastmem_size, &chipmem_size);
151 1.1 mw
152 1.1 mw text_size = (e.a_text + __LDPGSZ - 1) & (-__LDPGSZ);
153 1.1 mw kernel = (u_char *) malloc (text_size + e.a_data + e.a_bss
154 1.5 mw + num_cd*sizeof(*cd) + 4
155 1.5 mw + mem_list.num_mem*sizeof(struct MEM_SEG) + 4);
156 1.5 mw
157 1.5 mw if (t_opt)
158 1.5 mw for (i = 0; i < mem_list.num_mem; ++i) {
159 1.5 mw printf ("mem segment %d: start=%08lx size=%08lx attribute=%04lx pri=%d\n",
160 1.5 mw i + 1, mem_list.mem_seg[i].mem_start,
161 1.5 mw mem_list.mem_seg[i].mem_size,
162 1.5 mw mem_list.mem_seg[i].mem_attrib,
163 1.5 mw mem_list.mem_seg[i].mem_prio);
164 1.5 mw }
165 1.1 mw
166 1.1 mw if (kernel)
167 1.1 mw {
168 1.1 mw if (read (fd, kernel, e.a_text) == e.a_text
169 1.1 mw && read (fd, kernel + text_size, e.a_data) == e.a_data)
170 1.1 mw {
171 1.1 mw int *knum_cd;
172 1.1 mw struct ConfigDev *kcd;
173 1.5 mw int mem_ix;
174 1.1 mw
175 1.5 mw if (k_opt)
176 1.1 mw {
177 1.1 mw fastmem_start += 4*1024*1024;
178 1.1 mw fastmem_size -= 4*1024*1024;
179 1.1 mw }
180 1.6 chopps
181 1.6 chopps if (m_opt && m_opt <= fastmem_size)
182 1.6 chopps {
183 1.6 chopps fastmem_size = m_opt;
184 1.6 chopps }
185 1.1 mw
186 1.5 mw if (a_opt)
187 1.3 mw {
188 1.3 mw printf("Autobooting...");
189 1.3 mw boothowto = RB_AUTOBOOT;
190 1.3 mw }
191 1.5 mw
192 1.5 mw if (b_opt)
193 1.5 mw {
194 1.5 mw printf("Askboot...");
195 1.5 mw boothowto |= RB_ASKNAME;
196 1.5 mw }
197 1.3 mw
198 1.1 mw printf ("Using %dM FASTMEM at 0x%x, %dM CHIPMEM\n",
199 1.1 mw fastmem_size>>20, fastmem_start, chipmem_size>>20);
200 1.6 chopps kern_vers = (u_short *) (kernel + e.a_entry - 2);
201 1.6 chopps if (*kern_vers > KERNEL_PARAMETER_VERSION &&
202 1.6 chopps *kern_vers != 0x4e73)
203 1.6 chopps {
204 1.6 chopps printf ("This kernel requires a newer version of loadbsd: %d\n", *kern_vers);
205 1.6 chopps exit (0);
206 1.6 chopps }
207 1.6 chopps if (t_opt) /* if test option */
208 1.6 chopps exit (0); /* don't start kernel */
209 1.1 mw /* give them a chance to read the information... */
210 1.1 mw sleep(2);
211 1.1 mw
212 1.1 mw bzero (kernel + text_size + e.a_data, e.a_bss);
213 1.1 mw knum_cd = (int *) (kernel + text_size + e.a_data + e.a_bss);
214 1.1 mw *knum_cd = num_cd;
215 1.5 mw for (kcd = (struct ConfigDev *) (knum_cd+1);
216 1.5 mw cd = FindConfigDev (cd, -1, -1);
217 1.6 chopps *kcd++ = *cd)
218 1.6 chopps ;
219 1.5 mw kmem_list = (struct MEM_LIST *)kcd;
220 1.5 mw kmem_list->num_mem = mem_list.num_mem;
221 1.5 mw for (mem_ix = 0; mem_ix < mem_list.num_mem; mem_ix++)
222 1.5 mw kmem_list->mem_seg[mem_ix] = mem_list.mem_seg[mem_ix];
223 1.5 mw /* AGA startup - probably needs more */
224 1.5 mw LoadView (NULL);
225 1.1 mw startit (kernel,
226 1.5 mw text_size + e.a_data + e.a_bss + num_cd*sizeof(*cd) + 4
227 1.5 mw + mem_list.num_mem*sizeof(struct MEM_SEG) + 4,
228 1.1 mw e.a_entry, fastmem_start,
229 1.3 mw fastmem_size, chipmem_size,
230 1.3 mw boothowto );
231 1.1 mw }
232 1.1 mw else
233 1.1 mw fprintf (stderr, "Executable corrupt!\n");
234 1.1 mw }
235 1.1 mw else
236 1.1 mw fprintf (stderr, "Out of memory! (%d)\n", text_size + e.a_data + e.a_bss
237 1.5 mw + num_cd*sizeof(*cd) + 4
238 1.5 mw + mem_list.num_mem*sizeof(struct MEM_SEG) + 4);
239 1.1 mw }
240 1.1 mw else
241 1.1 mw fprintf (stderr, "Unsupported executable: %o\n", e.a_magic);
242 1.1 mw }
243 1.1 mw else
244 1.1 mw fprintf (stderr, "Can't read header of %s\n", argv[1]);
245 1.1 mw
246 1.1 mw close (fd);
247 1.1 mw }
248 1.1 mw else
249 1.1 mw perror ("open");
250 1.1 mw }
251 1.1 mw else
252 1.6 chopps Usage(argv[0]);
253 1.6 chopps Version();
254 1.6 chopps }/* main() */
255 1.1 mw
256 1.1 mw void
257 1.1 mw get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size)
258 1.1 mw {
259 1.1 mw extern struct ExecBase *SysBase;
260 1.1 mw struct MemHeader *mh, *nmh;
261 1.5 mw int num_mem = 0;
262 1.5 mw u_int seg_size;
263 1.5 mw u_int seg_start;
264 1.5 mw u_int seg_end;
265 1.1 mw
266 1.1 mw *fastmem_size = 0;
267 1.1 mw *chipmem_size = 0;
268 1.1 mw
269 1.1 mw /* walk thru the exec memory list */
270 1.1 mw Forbid ();
271 1.1 mw for (mh = (struct MemHeader *) SysBase->MemList.lh_Head;
272 1.1 mw nmh = (struct MemHeader *) mh->mh_Node.ln_Succ;
273 1.5 mw mh = nmh, num_mem++)
274 1.1 mw {
275 1.5 mw mem_list.mem_seg[num_mem].mem_attrib = mh->mh_Attributes;
276 1.5 mw mem_list.mem_seg[num_mem].mem_prio = mh->mh_Node.ln_Pri;
277 1.5 mw seg_start = (u_int)mh->mh_Lower;
278 1.5 mw seg_end = (u_int)mh->mh_Upper;
279 1.5 mw seg_size = seg_end - seg_start;
280 1.5 mw mem_list.mem_seg[num_mem].mem_size = seg_size;
281 1.5 mw mem_list.mem_seg[num_mem].mem_start = seg_start;
282 1.5 mw
283 1.1 mw if (mh->mh_Attributes & MEMF_CHIP)
284 1.1 mw {
285 1.1 mw /* there should hardly be more than one entry for chip mem, but
286 1.1 mw handle it the same nevertheless */
287 1.5 mw /* chipmem always starts at 0, so include vector area */
288 1.6 chopps mem_list.mem_seg[num_mem].mem_start = seg_start = 0;
289 1.5 mw /* round to multiple of 512K */
290 1.5 mw seg_size = (seg_size + 512*1024 - 1) & -(512*1024);
291 1.5 mw mem_list.mem_seg[num_mem].mem_size = seg_size;
292 1.5 mw if (seg_size > *chipmem_size)
293 1.1 mw {
294 1.5 mw *chipmem_size = seg_size;
295 1.1 mw }
296 1.1 mw }
297 1.1 mw else
298 1.1 mw {
299 1.5 mw /* some heuristics.. */
300 1.5 mw seg_start &= -__LDPGSZ;
301 1.5 mw /* get the mem back stolen by incore kickstart on A3000 with
302 1.5 mw V36 bootrom. */
303 1.5 mw if (seg_end == 0x07f80000)
304 1.5 mw seg_end = 0x08000000;
305 1.5 mw
306 1.5 mw /* or by zkick on a A2000. */
307 1.5 mw if (seg_start == 0x280000
308 1.5 mw && strcmp (mh->mh_Node.ln_Name, "zkick memory") == 0)
309 1.5 mw seg_start = 0x200000;
310 1.5 mw
311 1.5 mw seg_size = seg_end - seg_start;
312 1.5 mw mem_list.mem_seg[num_mem].mem_start = seg_start;
313 1.5 mw mem_list.mem_seg[num_mem].mem_size = seg_size;
314 1.5 mw /* if p_opt is set, select memory by priority instead of size */
315 1.6 chopps if ((!p_opt && seg_size > *fastmem_size) ||
316 1.6 chopps (p_opt && *fastmem_size == 0))
317 1.1 mw {
318 1.5 mw *fastmem_size = seg_size;
319 1.5 mw *fastmem_start = (void *)seg_start;
320 1.1 mw }
321 1.1 mw }
322 1.1 mw }
323 1.5 mw mem_list.num_mem = num_mem;
324 1.1 mw Permit();
325 1.1 mw }
326 1.1 mw
327 1.1 mw
328 1.1 mw
329 1.1 mw
330 1.1 mw asm ("
331 1.1 mw .set ABSEXECBASE,4
332 1.1 mw
333 1.1 mw .text
334 1.1 mw .globl _startit
335 1.1 mw
336 1.1 mw _startit:
337 1.1 mw movel sp,a3
338 1.1 mw movel 4:w,a6
339 1.1 mw lea pc@(start_super-.+2),a5
340 1.1 mw jmp a6@(-0x1e) | supervisor-call
341 1.1 mw
342 1.1 mw start_super:
343 1.1 mw movew #0x2700,sr
344 1.1 mw
345 1.1 mw | the BSD kernel wants values into the following registers:
346 1.1 mw | a0: fastmem-start
347 1.1 mw | d0: fastmem-size
348 1.1 mw | d1: chipmem-size
349 1.5 mw | d5: AttnFlags (cpuid)
350 1.3 mw | d7: boothowto
351 1.1 mw
352 1.1 mw movel a3@(4),a1 | loaded kernel
353 1.1 mw movel a3@(8),d2 | length of loaded kernel
354 1.1 mw movel a3@(12),a2 | entry point
355 1.1 mw movel a3@(16),a0 | fastmem-start
356 1.1 mw movel a3@(20),d0 | fastmem-size
357 1.1 mw movel a3@(24),d1 | chipmem-size
358 1.5 mw movel #0,d5
359 1.5 mw movew (ABSEXECBASE)@(0x128),d5 | SysBase->AttnFlags
360 1.3 mw movel a3@(28),d7 | boothowto
361 1.1 mw subl a4,a4 | target, load to 0
362 1.1 mw
363 1.5 mw btst #3,(ABSEXECBASE)@(0x129) | AFB_68040,SysBase->AttnFlags
364 1.5 mw beq not040
365 1.5 mw
366 1.5 mw | Turn off 68040 MMU
367 1.5 mw
368 1.5 mw .word 0x4e7b,0xc003 | movec a4,tc
369 1.5 mw .word 0x4e7b,0xc806 | movec a4,urp
370 1.5 mw .word 0x4e7b,0xc807 | movec a4,srp
371 1.5 mw .word 0x4e7b,0xc004 | movec a4,itt0
372 1.5 mw .word 0x4e7b,0xc005 | movec a4,itt1
373 1.5 mw .word 0x4e7b,0xc006 | movec a4,dtt0
374 1.5 mw .word 0x4e7b,0xc007 | movec a4,dtt1
375 1.5 mw bra nott
376 1.5 mw
377 1.5 mw not040:
378 1.1 mw lea pc@(zero-.+2),a3
379 1.1 mw pmove a3@,tc | Turn off MMU
380 1.1 mw lea pc@(nullrp-.+2),a3
381 1.1 mw pmove a3@,crp | Turn off MMU some more
382 1.1 mw pmove a3@,srp | Really, really, turn off MMU
383 1.1 mw
384 1.1 mw | Turn off 68030 TT registers
385 1.1 mw
386 1.1 mw btst #2,(ABSEXECBASE)@(0x129) | AFB_68030,SysBase->AttnFlags
387 1.1 mw beq nott | Skip TT registers if not 68030
388 1.1 mw lea pc@(zero-.+2),a3
389 1.1 mw .word 0xf013,0x0800 | pmove a3@,tt0 (gas only knows about 68851 ops..)
390 1.1 mw .word 0xf013,0x0c00 | pmove a3@,tt1 (gas only knows about 68851 ops..)
391 1.1 mw
392 1.1 mw nott:
393 1.1 mw
394 1.1 mw movew #(1<<9),0xdff096 | disable DMA
395 1.1 mw
396 1.1 mw L0:
397 1.1 mw moveb a1@+,a4@+
398 1.1 mw subl #1,d2
399 1.1 mw bcc L0
400 1.1 mw
401 1.1 mw
402 1.1 mw jmp a2@
403 1.1 mw
404 1.1 mw
405 1.1 mw | A do-nothing MMU root pointer (includes the following long as well)
406 1.1 mw
407 1.1 mw nullrp: .long 0x7fff0001
408 1.1 mw zero: .long 0
409 1.1 mw
410 1.1 mw
411 1.1 mw ");
412 1.1 mw
413 1.6 chopps void Usage(char *program_name)
414 1.6 chopps {
415 1.6 chopps fprintf(stderr,usage,program_name,program_name);
416 1.6 chopps }
417 1.6 chopps
418 1.6 chopps void Version()
419 1.6 chopps {
420 1.6 chopps fprintf(stderr,"%s\n",_version + 6);
421 1.6 chopps }
422