loadbsd.c revision 1.5 1 1.1 mw #include <sys/types.h>
2 1.1 mw #include <a.out.h>
3 1.1 mw #include <stdio.h>
4 1.1 mw
5 1.1 mw #include <exec/types.h>
6 1.1 mw #include <exec/execbase.h>
7 1.1 mw #include <exec/memory.h>
8 1.1 mw #include <libraries/configregs.h>
9 1.1 mw #include <libraries/expansionbase.h>
10 1.5 mw #include <graphics/gfxbase.h>
11 1.1 mw
12 1.1 mw #include <inline/exec.h>
13 1.1 mw #include <inline/expansion.h>
14 1.5 mw #include <inline/graphics.h>
15 1.1 mw
16 1.3 mw /* Get definitions for boothowto */
17 1.3 mw #include "reboot.h"
18 1.3 mw
19 1.1 mw struct ExpansionBase *ExpansionBase;
20 1.5 mw struct GfxBase *GfxBase;
21 1.1 mw
22 1.1 mw #undef __LDPGSZ
23 1.1 mw #define __LDPGSZ 8192
24 1.1 mw
25 1.5 mw #define MAX_MEM_SEG 16
26 1.5 mw
27 1.5 mw struct MEM_LIST {
28 1.5 mw u_long num_mem;
29 1.5 mw struct MEM_SEG {
30 1.5 mw u_long mem_start;
31 1.5 mw u_long mem_size;
32 1.5 mw u_short mem_attrib;
33 1.5 mw short mem_prio;
34 1.5 mw } mem_seg[MAX_MEM_SEG];
35 1.5 mw } mem_list, *kmem_list;
36 1.5 mw
37 1.5 mw int k_opt;
38 1.5 mw int a_opt;
39 1.5 mw int b_opt;
40 1.5 mw int p_opt;
41 1.5 mw int t_opt;
42 1.5 mw
43 1.5 mw extern char *optarg;
44 1.5 mw extern int optind;
45 1.5 mw
46 1.1 mw void get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size);
47 1.1 mw
48 1.1 mw int
49 1.1 mw main (int argc, char *argv[])
50 1.1 mw {
51 1.1 mw struct exec e;
52 1.1 mw int fd;
53 1.3 mw int boothowto = RB_SINGLE;
54 1.1 mw
55 1.1 mw if (argc >= 2)
56 1.1 mw {
57 1.1 mw if ((fd = open (argv[1], 0)) >= 0)
58 1.1 mw {
59 1.1 mw if (read (fd, &e, sizeof (e)) == sizeof (e))
60 1.1 mw {
61 1.1 mw if (e.a_magic == NMAGIC)
62 1.1 mw {
63 1.1 mw u_char *kernel;
64 1.1 mw int text_size;
65 1.1 mw struct ConfigDev *cd;
66 1.1 mw int num_cd;
67 1.5 mw void *fastmem_start;
68 1.5 mw u_long fastmem_size, chipmem_size;
69 1.5 mw int i;
70 1.1 mw
71 1.5 mw GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", 0);
72 1.5 mw if (! GfxBase) /* not supposed to fail... */
73 1.5 mw abort();
74 1.1 mw ExpansionBase= (struct ExpansionBase *) OpenLibrary ("expansion.library", 0);
75 1.1 mw if (! ExpansionBase) /* not supposed to fail... */
76 1.1 mw abort();
77 1.5 mw optind = 2;
78 1.5 mw while ((i = getopt (argc, argv, "kabpt")) != EOF)
79 1.5 mw switch (i) {
80 1.5 mw case 'k':
81 1.5 mw k_opt = 1;
82 1.5 mw break;
83 1.5 mw case 'a':
84 1.5 mw a_opt = 1;
85 1.5 mw break;
86 1.5 mw case 'b':
87 1.5 mw b_opt = 1;
88 1.5 mw break;
89 1.5 mw case 'p':
90 1.5 mw p_opt = 1;
91 1.5 mw break;
92 1.5 mw case 't':
93 1.5 mw t_opt = 1;
94 1.5 mw break;
95 1.5 mw }
96 1.5 mw
97 1.1 mw for (cd = 0, num_cd = 0; cd = FindConfigDev (cd, -1, -1); num_cd++) ;
98 1.5 mw get_mem_config (&fastmem_start, &fastmem_size, &chipmem_size);
99 1.1 mw
100 1.1 mw text_size = (e.a_text + __LDPGSZ - 1) & (-__LDPGSZ);
101 1.1 mw kernel = (u_char *) malloc (text_size + e.a_data + e.a_bss
102 1.5 mw + num_cd*sizeof(*cd) + 4
103 1.5 mw + mem_list.num_mem*sizeof(struct MEM_SEG) + 4);
104 1.5 mw
105 1.5 mw if (t_opt)
106 1.5 mw for (i = 0; i < mem_list.num_mem; ++i) {
107 1.5 mw printf ("mem segment %d: start=%08lx size=%08lx attribute=%04lx pri=%d\n",
108 1.5 mw i + 1, mem_list.mem_seg[i].mem_start,
109 1.5 mw mem_list.mem_seg[i].mem_size,
110 1.5 mw mem_list.mem_seg[i].mem_attrib,
111 1.5 mw mem_list.mem_seg[i].mem_prio);
112 1.5 mw }
113 1.1 mw
114 1.1 mw if (kernel)
115 1.1 mw {
116 1.1 mw if (read (fd, kernel, e.a_text) == e.a_text
117 1.1 mw && read (fd, kernel + text_size, e.a_data) == e.a_data)
118 1.1 mw {
119 1.1 mw int *knum_cd;
120 1.1 mw struct ConfigDev *kcd;
121 1.5 mw int mem_ix;
122 1.1 mw
123 1.5 mw if (k_opt)
124 1.1 mw {
125 1.1 mw fastmem_start += 4*1024*1024;
126 1.1 mw fastmem_size -= 4*1024*1024;
127 1.1 mw }
128 1.1 mw
129 1.5 mw if (a_opt)
130 1.3 mw {
131 1.3 mw printf("Autobooting...");
132 1.3 mw boothowto = RB_AUTOBOOT;
133 1.3 mw }
134 1.5 mw
135 1.5 mw if (b_opt)
136 1.5 mw {
137 1.5 mw printf("Askboot...");
138 1.5 mw boothowto |= RB_ASKNAME;
139 1.5 mw }
140 1.3 mw
141 1.1 mw printf ("Using %dM FASTMEM at 0x%x, %dM CHIPMEM\n",
142 1.1 mw fastmem_size>>20, fastmem_start, chipmem_size>>20);
143 1.5 mw if (t_opt)
144 1.5 mw exit (0);
145 1.1 mw /* give them a chance to read the information... */
146 1.1 mw sleep(2);
147 1.1 mw
148 1.1 mw bzero (kernel + text_size + e.a_data, e.a_bss);
149 1.1 mw knum_cd = (int *) (kernel + text_size + e.a_data + e.a_bss);
150 1.1 mw *knum_cd = num_cd;
151 1.5 mw cd = 0;
152 1.5 mw for (kcd = (struct ConfigDev *) (knum_cd+1);
153 1.5 mw cd = FindConfigDev (cd, -1, -1);
154 1.5 mw *kcd++ = *cd) ;
155 1.5 mw kmem_list = (struct MEM_LIST *)kcd;
156 1.5 mw kmem_list->num_mem = mem_list.num_mem;
157 1.5 mw for (mem_ix = 0; mem_ix < mem_list.num_mem; mem_ix++)
158 1.5 mw kmem_list->mem_seg[mem_ix] = mem_list.mem_seg[mem_ix];
159 1.5 mw /* AGA startup - probably needs more */
160 1.5 mw LoadView (NULL);
161 1.1 mw startit (kernel,
162 1.5 mw text_size + e.a_data + e.a_bss + num_cd*sizeof(*cd) + 4
163 1.5 mw + mem_list.num_mem*sizeof(struct MEM_SEG) + 4,
164 1.1 mw e.a_entry, fastmem_start,
165 1.3 mw fastmem_size, chipmem_size,
166 1.3 mw boothowto );
167 1.1 mw }
168 1.1 mw else
169 1.1 mw fprintf (stderr, "Executable corrupt!\n");
170 1.1 mw }
171 1.1 mw else
172 1.1 mw fprintf (stderr, "Out of memory! (%d)\n", text_size + e.a_data + e.a_bss
173 1.5 mw + num_cd*sizeof(*cd) + 4
174 1.5 mw + mem_list.num_mem*sizeof(struct MEM_SEG) + 4);
175 1.1 mw }
176 1.1 mw else
177 1.1 mw fprintf (stderr, "Unsupported executable: %o\n", e.a_magic);
178 1.1 mw }
179 1.1 mw else
180 1.1 mw fprintf (stderr, "Can't read header of %s\n", argv[1]);
181 1.1 mw
182 1.1 mw close (fd);
183 1.1 mw }
184 1.1 mw else
185 1.1 mw perror ("open");
186 1.1 mw }
187 1.1 mw else
188 1.5 mw fprintf (stderr, "%s some-vmunix [-a] [-b] [-k] [-p] [-t]\n", argv[0]);
189 1.1 mw }
190 1.1 mw
191 1.1 mw
192 1.1 mw void
193 1.1 mw get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size)
194 1.1 mw {
195 1.1 mw extern struct ExecBase *SysBase;
196 1.1 mw struct MemHeader *mh, *nmh;
197 1.5 mw int num_mem = 0;
198 1.5 mw u_int seg_size;
199 1.5 mw u_int seg_start;
200 1.5 mw u_int seg_end;
201 1.1 mw
202 1.1 mw *fastmem_size = 0;
203 1.1 mw *chipmem_size = 0;
204 1.1 mw
205 1.1 mw /* walk thru the exec memory list */
206 1.1 mw Forbid ();
207 1.1 mw for (mh = (struct MemHeader *) SysBase->MemList.lh_Head;
208 1.1 mw nmh = (struct MemHeader *) mh->mh_Node.ln_Succ;
209 1.5 mw mh = nmh, num_mem++)
210 1.1 mw {
211 1.5 mw mem_list.mem_seg[num_mem].mem_attrib = mh->mh_Attributes;
212 1.5 mw mem_list.mem_seg[num_mem].mem_prio = mh->mh_Node.ln_Pri;
213 1.5 mw seg_start = (u_int)mh->mh_Lower;
214 1.5 mw seg_end = (u_int)mh->mh_Upper;
215 1.5 mw seg_size = seg_end - seg_start;
216 1.5 mw mem_list.mem_seg[num_mem].mem_size = seg_size;
217 1.5 mw mem_list.mem_seg[num_mem].mem_start = seg_start;
218 1.5 mw
219 1.1 mw if (mh->mh_Attributes & MEMF_CHIP)
220 1.1 mw {
221 1.1 mw /* there should hardly be more than one entry for chip mem, but
222 1.1 mw handle it the same nevertheless */
223 1.5 mw /* chipmem always starts at 0, so include vector area */
224 1.5 mw if (seg_start < 0x500)
225 1.5 mw mem_list.mem_seg[num_mem].mem_start = seg_start = 0;
226 1.5 mw /* round to multiple of 512K */
227 1.5 mw seg_size = (seg_size + 512*1024 - 1) & -(512*1024);
228 1.5 mw mem_list.mem_seg[num_mem].mem_size = seg_size;
229 1.5 mw if (seg_size > *chipmem_size)
230 1.1 mw {
231 1.5 mw *chipmem_size = seg_size;
232 1.1 mw }
233 1.1 mw }
234 1.1 mw else
235 1.1 mw {
236 1.5 mw /* some heuristics.. */
237 1.5 mw seg_start &= -__LDPGSZ;
238 1.5 mw /* get the mem back stolen by incore kickstart on A3000 with
239 1.5 mw V36 bootrom. */
240 1.5 mw if (seg_end == 0x07f80000)
241 1.5 mw seg_end = 0x08000000;
242 1.5 mw
243 1.5 mw /* or by zkick on a A2000. */
244 1.5 mw if (seg_start == 0x280000
245 1.5 mw && strcmp (mh->mh_Node.ln_Name, "zkick memory") == 0)
246 1.5 mw seg_start = 0x200000;
247 1.5 mw
248 1.5 mw seg_size = seg_end - seg_start;
249 1.5 mw mem_list.mem_seg[num_mem].mem_start = seg_start;
250 1.5 mw mem_list.mem_seg[num_mem].mem_size = seg_size;
251 1.5 mw /* if p_opt is set, select memory by priority instead of size */
252 1.5 mw if (seg_size > *fastmem_size)
253 1.1 mw {
254 1.5 mw *fastmem_size = seg_size;
255 1.5 mw *fastmem_start = (void *)seg_start;
256 1.1 mw }
257 1.1 mw }
258 1.1 mw }
259 1.5 mw mem_list.num_mem = num_mem;
260 1.1 mw Permit();
261 1.1 mw }
262 1.1 mw
263 1.1 mw
264 1.1 mw
265 1.1 mw
266 1.1 mw asm ("
267 1.1 mw .set ABSEXECBASE,4
268 1.1 mw
269 1.1 mw .text
270 1.1 mw .globl _startit
271 1.1 mw
272 1.1 mw _startit:
273 1.1 mw movel sp,a3
274 1.1 mw movel 4:w,a6
275 1.1 mw lea pc@(start_super-.+2),a5
276 1.1 mw jmp a6@(-0x1e) | supervisor-call
277 1.1 mw
278 1.1 mw start_super:
279 1.1 mw movew #0x2700,sr
280 1.1 mw
281 1.1 mw | the BSD kernel wants values into the following registers:
282 1.1 mw | a0: fastmem-start
283 1.1 mw | d0: fastmem-size
284 1.1 mw | d1: chipmem-size
285 1.5 mw | d5: AttnFlags (cpuid)
286 1.3 mw | d7: boothowto
287 1.1 mw
288 1.1 mw movel a3@(4),a1 | loaded kernel
289 1.1 mw movel a3@(8),d2 | length of loaded kernel
290 1.1 mw movel a3@(12),a2 | entry point
291 1.1 mw movel a3@(16),a0 | fastmem-start
292 1.1 mw movel a3@(20),d0 | fastmem-size
293 1.1 mw movel a3@(24),d1 | chipmem-size
294 1.5 mw movel #0,d5
295 1.5 mw movew (ABSEXECBASE)@(0x128),d5 | SysBase->AttnFlags
296 1.3 mw movel a3@(28),d7 | boothowto
297 1.1 mw subl a4,a4 | target, load to 0
298 1.1 mw
299 1.5 mw btst #3,(ABSEXECBASE)@(0x129) | AFB_68040,SysBase->AttnFlags
300 1.5 mw beq not040
301 1.5 mw
302 1.5 mw | Turn off 68040 MMU
303 1.5 mw
304 1.5 mw .word 0x4e7b,0xc003 | movec a4,tc
305 1.5 mw .word 0x4e7b,0xc806 | movec a4,urp
306 1.5 mw .word 0x4e7b,0xc807 | movec a4,srp
307 1.5 mw .word 0x4e7b,0xc004 | movec a4,itt0
308 1.5 mw .word 0x4e7b,0xc005 | movec a4,itt1
309 1.5 mw .word 0x4e7b,0xc006 | movec a4,dtt0
310 1.5 mw .word 0x4e7b,0xc007 | movec a4,dtt1
311 1.5 mw bra nott
312 1.5 mw
313 1.5 mw not040:
314 1.1 mw lea pc@(zero-.+2),a3
315 1.1 mw pmove a3@,tc | Turn off MMU
316 1.1 mw lea pc@(nullrp-.+2),a3
317 1.1 mw pmove a3@,crp | Turn off MMU some more
318 1.1 mw pmove a3@,srp | Really, really, turn off MMU
319 1.1 mw
320 1.1 mw | Turn off 68030 TT registers
321 1.1 mw
322 1.1 mw btst #2,(ABSEXECBASE)@(0x129) | AFB_68030,SysBase->AttnFlags
323 1.1 mw beq nott | Skip TT registers if not 68030
324 1.1 mw lea pc@(zero-.+2),a3
325 1.1 mw .word 0xf013,0x0800 | pmove a3@,tt0 (gas only knows about 68851 ops..)
326 1.1 mw .word 0xf013,0x0c00 | pmove a3@,tt1 (gas only knows about 68851 ops..)
327 1.1 mw
328 1.1 mw nott:
329 1.1 mw
330 1.1 mw movew #(1<<9),0xdff096 | disable DMA
331 1.1 mw
332 1.1 mw L0:
333 1.1 mw moveb a1@+,a4@+
334 1.1 mw subl #1,d2
335 1.1 mw bcc L0
336 1.1 mw
337 1.1 mw
338 1.1 mw jmp a2@
339 1.1 mw
340 1.1 mw
341 1.1 mw | A do-nothing MMU root pointer (includes the following long as well)
342 1.1 mw
343 1.1 mw nullrp: .long 0x7fff0001
344 1.1 mw zero: .long 0
345 1.1 mw
346 1.1 mw
347 1.1 mw ");
348 1.1 mw
349