xref: /netbsd-src/sys/arch/amiga/stand/loadbsd/loadbsd.c (revision cda4f8f6ee55684e8d311b86c99ea59191e6b74f)
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 
14 struct ExpansionBase *ExpansionBase;
15 
16 #undef __LDPGSZ
17 #define __LDPGSZ 8192
18 
19 void get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size);
20 
21 int
22 main (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 
107 void
108 get_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 
161 asm ("
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 
173 start_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 
203 nott:
204 
205 	movew	#(1<<9),0xdff096	| disable DMA
206 
207 L0:
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 
218 nullrp:	.long	0x7fff0001
219 zero:	.long	0
220 
221 
222 ");
223 
224