loadbsd.c revision 1.1
1#include <sys/types.h>
2#include <a.out.h>
3#include <stdio.h>
4
5#include <exec/types.h>
6#include <exec/execbase.h>
7#include <exec/memory.h>
8#include <libraries/configregs.h>
9#include <libraries/expansionbase.h>
10
11#include <inline/exec.h>
12#include <inline/expansion.h>
13
14struct ExpansionBase *ExpansionBase;
15
16#undef __LDPGSZ
17#define __LDPGSZ 8192
18
19void get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size);
20
21int
22main (int argc, char *argv[])
23{
24  struct exec e;
25  int fd;
26
27  if (argc >= 2)
28    {
29      if ((fd = open (argv[1], 0)) >= 0)
30        {
31          if (read (fd, &e, sizeof (e)) == sizeof (e))
32            {
33              if (e.a_magic == NMAGIC)
34                {
35                  u_char *kernel;
36		  int text_size;
37		  struct ConfigDev *cd;
38		  int num_cd;
39
40		  ExpansionBase= (struct ExpansionBase *) OpenLibrary ("expansion.library", 0);
41		  if (! ExpansionBase)	/* not supposed to fail... */
42		    abort();
43		  for (cd = 0, num_cd = 0; cd = FindConfigDev (cd, -1, -1); num_cd++) ;
44
45		  text_size = (e.a_text + __LDPGSZ - 1) & (-__LDPGSZ);
46		  kernel = (u_char *) malloc (text_size + e.a_data + e.a_bss
47				              + num_cd*sizeof(*cd) + 4);
48
49                  if (kernel)
50                    {
51		      if (read (fd, kernel, e.a_text) == e.a_text
52			  && read (fd, kernel + text_size, e.a_data) == e.a_data)
53			{
54			  int *knum_cd;
55			  struct ConfigDev *kcd;
56			  void *fastmem_start;
57			  u_long fastmem_size, chipmem_size;
58
59			  get_mem_config (&fastmem_start, &fastmem_size, &chipmem_size);
60
61			  if (argc == 3 && !strcmp (argv[2], "-k"))
62			    {
63			      fastmem_start += 4*1024*1024;
64			      fastmem_size  -= 4*1024*1024;
65			    }
66
67			  printf ("Using %dM FASTMEM at 0x%x, %dM CHIPMEM\n",
68				  fastmem_size>>20, fastmem_start, chipmem_size>>20);
69			  /* give them a chance to read the information... */
70			  sleep(2);
71
72			  bzero (kernel + text_size + e.a_data, e.a_bss);
73			  knum_cd = (int *) (kernel + text_size + e.a_data + e.a_bss);
74			  *knum_cd = num_cd;
75			  if (num_cd)
76			    for (kcd = (struct ConfigDev *) (knum_cd+1);
77			         cd = FindConfigDev (cd, -1, -1);
78			         *kcd++ = *cd) ;
79			  startit (kernel,
80				   text_size + e.a_data + e.a_bss + num_cd*sizeof(*cd) + 4,
81				   e.a_entry, fastmem_start,
82				   fastmem_size, chipmem_size);
83			}
84		      else
85			fprintf (stderr, "Executable corrupt!\n");
86                    }
87                  else
88		    fprintf (stderr, "Out of memory! (%d)\n", text_size + e.a_data + e.a_bss
89				   + num_cd*sizeof(*cd) + 4);
90                }
91	      else
92	        fprintf (stderr, "Unsupported executable: %o\n", e.a_magic);
93            }
94          else
95	    fprintf (stderr, "Can't read header of %s\n", argv[1]);
96
97	  close (fd);
98        }
99      else
100	perror ("open");
101    }
102  else
103    fprintf (stderr, "%0 some-vmunix\n", argv[0]);
104}
105
106
107void
108get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size)
109{
110  extern struct ExecBase *SysBase;
111  struct MemHeader *mh, *nmh;
112
113  *fastmem_size = 0;
114  *chipmem_size = 0;
115
116  /* walk thru the exec memory list */
117  Forbid ();
118  for (mh  = (struct MemHeader *) SysBase->MemList.lh_Head;
119       nmh = (struct MemHeader *) mh->mh_Node.ln_Succ;
120       mh  = nmh)
121    {
122      if (mh->mh_Attributes & MEMF_CHIP)
123        {
124	  /* there should hardly be more than one entry for chip mem, but
125	     handle it the same nevertheless */
126	  if ((u_int)mh->mh_Upper - (u_int)mh->mh_Lower > *chipmem_size)
127	    {
128	      *chipmem_size = (u_int)mh->mh_Upper - (u_int)mh->mh_Lower;
129	      /* round to multiple of 512K */
130	      *chipmem_size = (*chipmem_size + 512*1024 - 1) & -(512*1024);
131
132	      /* chipmem always starts at 0, so don't remember start
133	         address */
134	    }
135        }
136      else
137	{
138	  if ((u_int)mh->mh_Upper - (u_int)mh->mh_Lower > *fastmem_size)
139	    {
140	      u_int start = (u_int) mh->mh_Lower;
141	      u_int end = (u_int) mh->mh_Upper;
142
143	      /* some heuristics.. */
144	      start &= -__LDPGSZ;
145	      /* get the mem back stolen by incore kickstart on A3000 with
146	         V36 bootrom. */
147	      if (end == 0x07f80000)
148	        end = 0x08000000;
149
150	      *fastmem_size = end - start;
151	      *fastmem_start = (void *)start;
152	    }
153	}
154    }
155  Permit();
156}
157
158
159
160
161asm ("
162	.set	ABSEXECBASE,4
163
164	.text
165	.globl	_startit
166
167_startit:
168	movel	sp,a3
169	movel	4:w,a6
170	lea	pc@(start_super-.+2),a5
171	jmp	a6@(-0x1e)		| supervisor-call
172
173start_super:
174	movew	#0x2700,sr
175
176	| the BSD kernel wants values into the following registers:
177	| a0:  fastmem-start
178	| d0:  fastmem-size
179	| d1:  chipmem-size
180
181	movel	a3@(4),a1		| loaded kernel
182	movel	a3@(8),d2		| length of loaded kernel
183	movel	a3@(12),a2		| entry point
184	movel	a3@(16),a0		| fastmem-start
185	movel	a3@(20),d0		| fastmem-size
186	movel	a3@(24),d1		| chipmem-size
187	subl	a4,a4			| target, load to 0
188
189	lea	pc@(zero-.+2),a3
190	pmove	a3@,tc			| Turn off MMU
191	lea	pc@(nullrp-.+2),a3
192	pmove	a3@,crp			| Turn off MMU some more
193	pmove	a3@,srp			| Really, really, turn off MMU
194
195| Turn off 68030 TT registers
196
197	btst	#2,(ABSEXECBASE)@(0x129) | AFB_68030,SysBase->AttnFlags
198	beq	nott			| Skip TT registers if not 68030
199	lea	pc@(zero-.+2),a3
200	.word 0xf013,0x0800		| pmove a3@,tt0 (gas only knows about 68851 ops..)
201	.word 0xf013,0x0c00		| pmove a3@,tt1 (gas only knows about 68851 ops..)
202
203nott:
204
205	movew	#(1<<9),0xdff096	| disable DMA
206
207L0:
208	moveb	a1@+,a4@+
209	subl	#1,d2
210	bcc	L0
211
212
213	jmp	a2@
214
215
216| A do-nothing MMU root pointer (includes the following long as well)
217
218nullrp:	.long	0x7fff0001
219zero:	.long	0
220
221
222");
223
224