xref: /netbsd-src/sys/arch/atari/stand/tostools/loadbsd/loadbsd.c (revision 4458e4600157ae2bb26ee802d50d1323e732c500)
1 /*	$NetBSD: loadbsd.c,v 1.2 1995/03/28 06:26:50 leo Exp $	*/
2 
3 /*
4  * Copyright (c) 1995 L. Weppelman
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Leo Weppelman.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * NetBSD loader for the Atari-TT.
35  */
36 
37 #include <stdio.h>
38 #include <a_out.h>
39 #include <fcntl.h>
40 #include <osbind.h>
41 #include <stdarg.h>
42 #include "loader.h"
43 
44 char	*Progname;		/* How are we called		*/
45 int	t_flag = 0;		/* Just test, do not execute	*/
46 
47 char version[] = "$VER: LoadBSD 1.0 (11/01/95)";
48 
49 /*
50  * Default name of kernel to boot, large enough to patch
51  */
52 char		kname[80] = "n:/netbsd";
53 
54 static struct {
55 	u_char	*kp;		/* 00: Kernel load address		*/
56 	long	ksize;		/* 04: Size of loaded kernel		*/
57 	u_long	entry;		/* 08: Kernel entry point		*/
58 	long	stmem_size;	/* 12: Size of st-ram			*/
59 	long	ttmem_size;	/* 16: Size of tt-ram			*/
60 	long	cputype;	/* 20: Type of cpu			*/
61 	long	boothowto;	/* 24: How to boot			*/
62 	long	ttmem_start;	/* 28: Start of tt-ram			*/
63 	long	esym_loc;	/* 32: End of symbol table		*/
64 } kparam;
65 
66 void get_sys_info(void);
67 void error(char *fmt, ...);
68 void help(void);
69 void usage(void);
70 void start_kernel(void);
71 
72 int main(argc, argv)
73 int	argc;
74 char	**argv;
75 {
76 	/*
77 	 * Option parsing
78 	 */
79 	extern	int	optind;
80 	extern	char	*optarg;
81 	int		ch;
82 	int		fd;
83 	long		textsz, stringsz;
84 	struct exec	ehdr;
85 
86 	Progname = argv[0];
87 
88 	kparam.boothowto = RB_SINGLE;
89 
90 	while ((ch = getopt(argc, argv, "abdhtv")) != EOF) {
91 		switch(ch) {
92 		case 'a':
93 			kparam.boothowto &= ~(RB_SINGLE);
94 			kparam.boothowto |= RB_AUTOBOOT;
95 			break;
96 		case 'b':
97 			kparam.boothowto |= RB_ASKNAME;
98 			break;
99 		case 'd':
100 			kparam.boothowto |= RB_KDB;
101 			break;
102 		case 't':
103 			t_flag = 1;
104 			break;
105 		case 'v':
106 			fprintf(stderr,"%s\n", version);
107 			break;
108 		case 'h':
109 			help();
110 		default:
111 			usage();
112 		}
113 	}
114 	argc -= optind;
115 	argv += optind;
116 	if(argc == 1)
117 		strcpy(kname, argv[0]);
118 
119 	/*
120 	 * Get system info to pass to NetBSD
121 	 */
122 	get_sys_info();
123 
124 	/*
125 	 * Find the kernel to boot and read it's exec-header
126 	 */
127 	if((fd = open(kname, O_RDONLY)) < 0)
128 		error("Cannot open kernel '%s'", kname);
129 	if(read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
130 		error("Cannot read exec-header of '%s'", kname);
131 	if((ehdr.a_magic & 0xffff) != NMAGIC) /* XXX */
132 		error("Not an NMAGIC file '%s'", kname);
133 
134 	/*
135 	 * Extract various sizes from the kernel executable
136 	 */
137 	textsz          = (ehdr.a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1);
138 	kparam.esym_loc = 0;
139 	kparam.ksize    = textsz + ehdr.a_data + ehdr.a_bss;
140 	kparam.entry    = ehdr.a_entry;
141 
142 	if(ehdr.a_syms) {
143 	  if(lseek(fd,ehdr.a_text+ehdr.a_data+ehdr.a_syms+sizeof(ehdr), 0) <= 0)
144 		error("Cannot seek to string table in '%s'", kname);
145 	  if(read(fd, &stringsz, sizeof(long)) != sizeof(long))
146 		error("Cannot read string-table size");
147 	  if(lseek(fd, sizeof(ehdr), 0) <= 0)
148 		error("Cannot seek back to text start");
149 	  kparam.ksize += ehdr.a_syms + sizeof(long) + stringsz;
150 	}
151 
152 	if((kparam.kp = (u_char *)malloc(kparam.ksize)) == NULL)
153 		error("Cannot malloc kernel image space");
154 
155 	/*
156 	 * Read text & data, clear bss
157 	 */
158 	if((read(fd, kparam.kp, ehdr.a_text) != ehdr.a_text)
159 	    || (read(fd, kparam.kp + textsz, ehdr.a_data) != ehdr.a_data))
160 		error("Unable to read kernel image\n");
161 	memset(kparam.kp + textsz + ehdr.a_data, 0, ehdr.a_bss);
162 
163 	/*
164 	 * Read symbol and string table
165 	 */
166 	if(ehdr.a_syms) {
167 		long	*p;
168 
169 		p = (long *)(kparam.kp + textsz + ehdr.a_data + ehdr.a_bss);
170 		*p++ = ehdr.a_syms;
171 		if(read(fd, (char *)p, ehdr.a_syms) != ehdr.a_syms)
172 			error("Cannot read symbol table\n");
173 		p = (long *)((char *)p + ehdr.a_syms);
174 		if(read(fd, (char *)p, stringsz) != stringsz)
175 			error("Cannot read string table\n");
176 		kparam.esym_loc = (long)((char *)p-(char *)kparam.kp +stringsz);
177 	}
178 
179 	if(!t_flag)
180 		start_kernel();
181 		/* NOT REACHED */
182 
183 	fprintf(stderr, "Kernel '%s' was loaded OK\n", kname);
184 	exit(0);
185 }
186 
187 /*
188  * Extract memory and cpu/fpu info from system.
189  */
190 void get_sys_info()
191 {
192 	long	stck;
193 	long	*jar;
194 
195 	kparam.cputype = 0;
196 
197 	stck = Super(0);
198 
199 	kparam.ttmem_start = TTRAM_BASE;
200 	kparam.ttmem_size  = *ADDR_RAMTOP - TTRAM_BASE;
201 	kparam.stmem_size  = *ADDR_PHYSTOP;
202 
203 	/*
204 	 * Scan cookiejar for cpu/fpu types
205 	 */
206 	jar = *ADDR_P_COOKIE;
207 	if(jar != NULL) {
208 		do {
209 			if(jar[0] == 0x5f435055) { /* _CPU	*/
210 				switch(jar[1]) {
211 					case 0:
212 						kparam.cputype |= ATARI_68000;
213 						break;
214 					case 10:
215 						kparam.cputype |= ATARI_68010;
216 						break;
217 					case 20:
218 						kparam.cputype |= ATARI_68020;
219 						break;
220 					case 30:
221 						kparam.cputype |= ATARI_68030;
222 						break;
223 					case 40:
224 						kparam.cputype |= ATARI_68040;
225 						break;
226 					default:
227 						error("Unknown CPU-type");
228 				}
229 			}
230 			if(jar[0] == 0x5f465055) { /* _FPU	*/
231 				switch(jar[1]) {
232 					case 0x10000:
233 					case 0x20000:
234 						kparam.cputype |= ATARI_68881;
235 						break;
236 					case 0x30000:
237 						kparam.cputype |= ATARI_68882;
238 						break;
239 					case 0x40000:
240 						kparam.cputype |= ATARI_FPU40;
241 						break;
242 					default:
243 						error("Unknown FPU-type");
244 				}
245 			}
246 			jar = &jar[2];
247 		} while(jar[-2]);
248 	}
249 	if(!(kparam.cputype & ATARI_ANYCPU))
250 		error("Cannot determine CPU-type");
251 	if(!(kparam.cputype & ATARI_ANYFPU))
252 		error("Cannot determine FPU-type");
253 
254 	Super(stck);
255 }
256 
257 void error(char *fmt, ...)
258 {
259 	va_list	ap;
260 
261 	va_start(ap, fmt);
262 
263 	fprintf(stderr, "%s: ", Progname);
264 	vfprintf(stderr, fmt, ap);
265 	fprintf(stderr, "\n");
266 	exit(1);
267 	/*NOTREACHED*/
268 }
269 
270 void help()
271 {
272 	fprintf(stderr, "
273 NetBSD loader for the Atari-TT
274 
275 Usage: %s [-abdhtv] [kernel]
276 
277 Description of options:
278 
279 \t-a  Boot up to multi-user mode.
280 \t-b  Ask for root device to use.
281 \t-d  Enter kernel debugger.
282 \t-h  What your getting right now.
283 \t-t  Test the loader. It will do everything except executing the
284 \t    loaded kernel.
285 \t-v  Print loader version.
286 ", Progname);
287 	exit(1);
288 }
289 
290 void usage()
291 {
292 	fprintf(stderr, "Usage: %s [-abdhtv] [kernel]", Progname);
293 	exit(1);
294 }
295 
296 void start_kernel()
297 {
298 	long	stck;
299 
300 	stck = Super(0);
301 	startit();
302 	/* NOT REACHED */
303 
304 	Super(stck);
305 }
306 
307 asm("
308 	.text
309 	.globl	_startit
310 
311 _startit:
312 	move.w	#0x2700,sr
313 
314 	| the BSD kernel wants values into the following registers:
315 	| d0:  ttmem-size
316 	| d1:  stmem-size
317 	| d2:  cputype
318 	| d3:  boothowto
319 	| d4:  length of loaded kernel
320 	| a0:  start of loaded kernel
321 	| a1:  end of symbols (esym)
322 	| All other registers zeroed for possible future requirements.
323 
324 	lea	_kparam, a3		| a3 points to parameter block
325 	lea	_startit,sp		| make sure we have a good stack ***
326 	move.l	(a3),a0			| loaded kernel
327 	move.l	8(a3),-(sp)		| push entry point		***
328 	move.l	a0,d0			| offset of loaded kernel
329 	add.l	d0,(sp)			| add offset
330 	move.l	12(a3),d1		| stmem-size
331 	move.l	16(a3),d0		| ttmem-size
332 	move.l	20(a3),d2		| cputype
333 	move.l	24(a3),d3		| boothowto
334 	move.l	4(a3),d4		| length of loaded kernel
335 	move.l	28(a3),d5		| start of fastram
336 	move.l	32(a3),a1		| end of symbols
337 	sub.l	a5,a5			| target, load to 0
338 	btst	#4, d2			| Is this an 68040?
339 	beq	not040
340 
341 	| Turn off 68040 MMU
342 	.word 0x4e7b,0xd003		| movec a5,tc
343 	.word 0x4e7b,0xd806		| movec a5,urp
344 	.word 0x4e7b,0xd807		| movec a5,srp
345 	.word 0x4e7b,0xd004		| movec a5,itt0
346 	.word 0x4e7b,0xd005		| movec a5,itt1
347 	.word 0x4e7b,0xd006		| movec a5,dtt0
348 	.word 0x4e7b,0xd007		| movec a5,dtt1
349 	bra	nott
350 
351 not040:
352 	lea	zero,a3
353 	pmove	(a3),tcr		| Turn off MMU
354 	lea	nullrp,a3
355 	pmove	(a3),crp		| Turn off MMU some more
356 	pmove	(a3),srp		| Really, really, turn off MMU
357 
358 	| Turn off 68030 TT registers
359 	btst	#3, d2			| Is this an 68030?
360 	beq.b	nott
361 	lea	zero,a3
362 	pmove	(a3),tt0
363 	pmove	(a3),tt1
364 
365 nott:
366 	moveq.l	#0,d6			|  would have known contents)
367 	moveq.l	#0,d7
368 	movea.l	d6,a2
369 	movea.l	d6,a3
370 	movea.l	d6,a4
371 	movea.l	d6,a5
372 	movea.l	d6,a6
373 	rts				| enter kernel at address on stack ***
374 
375 
376 | A do-nothing MMU root pointer (includes the following long as well)
377 
378 nullrp:	.long	0x80000202
379 zero:	.long	0
380 svsp:	.long   0
381 
382 
383 ");
384