xref: /netbsd-src/sys/arch/atari/stand/tostools/loadbsd/loadbsd.c (revision 2a399c6883d870daece976daec6ffa7bb7f934ce)
1 /*	$NetBSD: loadbsd.c,v 1.13 1997/11/01 06:49:22 lukem 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 <a_out.h>
38 #include <fcntl.h>
39 #include <stdio.h>
40 #include <osbind.h>
41 #include <stdarg.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 #include "libtos.h"
46 #include "loader.h"
47 
48 char	*Progname;		/* How are we called		*/
49 int	d_flag  = 0;		/* Output debugging output?	*/
50 int	h_flag  = 0;		/* show help			*/
51 int	s_flag  = 0;		/* St-ram only			*/
52 int	t_flag  = 0;		/* Just test, do not execute	*/
53 int	v_flag  = 0;		/* show version			*/
54 
55 const char version[] = "$Revision: 1.13 $";
56 
57 /*
58  * Default name of kernel to boot, large enough to patch
59  */
60 char	kname[80] = "n:/netbsd";
61 
62 static struct kparamb kparam;
63 
64 void help  PROTO((void));
65 void usage PROTO((void));
66 void get_sys_info PROTO((void));
67 void start_kernel PROTO((void));
68 
69 int
70 main(argc, argv)
71 int	argc;
72 char	**argv;
73 {
74 	/*
75 	 * Option parsing
76 	 */
77 	extern	int	optind;
78 	extern	char	*optarg;
79 	int		ch;
80 	int		fd;
81 	long		textsz, stringsz;
82 	struct exec	ehdr;
83 
84 	init_toslib(argv[0]);
85 	Progname = argv[0];
86 
87 	kparam.boothowto = RB_SINGLE;
88 
89 	while ((ch = getopt(argc, argv, "abdhstVwDo:S:T:")) != -1) {
90 		switch (ch) {
91 		case 'a':
92 			kparam.boothowto &= ~(RB_SINGLE);
93 			kparam.boothowto |= RB_AUTOBOOT;
94 			break;
95 		case 'b':
96 			kparam.boothowto |= RB_ASKNAME;
97 			break;
98 		case 'd':
99 			kparam.boothowto |= RB_KDB;
100 			break;
101 		case 'D':
102 			d_flag = 1;
103 			break;
104 		case 'h':
105 			h_flag = 1;
106 			break;
107 		case 'o':
108 			redirect_output(optarg);
109 			break;
110 		case 's':
111 			s_flag = 1;
112 			break;
113 		case 'S':
114 			kparam.stmem_size = atoi(optarg);
115 			break;
116 		case 't':
117 			t_flag = 1;
118 			break;
119 		case 'T':
120 			kparam.ttmem_size = atoi(optarg);
121 			break;
122 		case 'V':
123 			v_flag = 1;
124 			break;
125 		case 'w':
126 			set_wait_for_key();
127 			break;
128 		default:
129 			usage();
130 		}
131 	}
132 	argc -= optind;
133 	argv += optind;
134 	if (argc == 1)
135 		strcpy(kname, argv[0]);
136 
137 	if (h_flag)
138 		help();
139 	if (v_flag)
140 		eprintf("%s\r\n", version);
141 
142 	/*
143 	 * Get system info to pass to NetBSD
144 	 */
145 	get_sys_info();
146 
147 	/*
148 	 * Find the kernel to boot and read it's exec-header
149 	 */
150 	if ((fd = open(kname, O_RDONLY)) < 0)
151 		fatal(-1, "Cannot open kernel '%s'", kname);
152 	if (read(fd, (char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr))
153 		fatal(-1, "Cannot read exec-header of '%s'", kname);
154 	if (N_MAGIC(ehdr) != NMAGIC)
155 		fatal(-1, "Not an NMAGIC file '%s'", kname);
156 
157 	/*
158 	 * Extract various sizes from the kernel executable
159 	 */
160 	textsz          = (ehdr.a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1);
161 	kparam.esym_loc = 0;
162 	kparam.ksize    = textsz + ehdr.a_data + ehdr.a_bss;
163 	kparam.entry    = ehdr.a_entry;
164 
165 	if (ehdr.a_syms) {
166 	  if (lseek(fd,ehdr.a_text+ehdr.a_data+ehdr.a_syms+sizeof(ehdr),0) <= 0)
167 		fatal(-1, "Cannot seek to string table in '%s'", kname);
168 	  if (read(fd, (char *)&stringsz, sizeof(long)) != sizeof(long))
169 		fatal(-1, "Cannot read string-table size");
170 	  if (lseek(fd, sizeof(ehdr), 0) <= 0)
171 		fatal(-1, "Cannot seek back to text start");
172 	  kparam.ksize += ehdr.a_syms + sizeof(long) + stringsz;
173 	}
174 
175 	if ((kparam.kp = (u_char *)malloc(kparam.ksize)) == NULL)
176 		fatal(-1, "Cannot malloc kernel image space");
177 
178 	/*
179 	 * Read text & data, clear bss
180 	 */
181 	if ((read(fd, (char *)kparam.kp, ehdr.a_text) != ehdr.a_text)
182 	    || (read(fd,(char *)(kparam.kp+textsz),ehdr.a_data) != ehdr.a_data))
183 		fatal(-1, "Unable to read kernel image\n");
184 	memset(kparam.kp + textsz + ehdr.a_data, 0, ehdr.a_bss);
185 
186 	/*
187 	 * Read symbol and string table
188 	 */
189 	if (ehdr.a_syms) {
190 		long	*p;
191 
192 		p = (long *)(kparam.kp + textsz + ehdr.a_data + ehdr.a_bss);
193 		*p++ = ehdr.a_syms;
194 		if (read(fd, (char *)p, ehdr.a_syms) != ehdr.a_syms)
195 			fatal(-1, "Cannot read symbol table\n");
196 		p = (long *)((char *)p + ehdr.a_syms);
197 		if (read(fd, (char *)p, stringsz) != stringsz)
198 			fatal(-1, "Cannot read string table\n");
199 		kparam.esym_loc = (long)((char *)p-(char *)kparam.kp +stringsz);
200 	}
201 
202 	if (d_flag) {
203 	    eprintf("\r\nKernel info:\r\n");
204 	    eprintf("Kernel loadaddr\t: 0x%08x\r\n", kparam.kp);
205 	    eprintf("Kernel size\t: %10d bytes\r\n", kparam.ksize);
206 	    eprintf("Kernel entry\t: 0x%08x\r\n", kparam.entry);
207 	    eprintf("Kernel esym\t: 0x%08x\r\n", kparam.esym_loc);
208 	}
209 
210 	if (!t_flag)
211 		start_kernel();
212 		/* NOT REACHED */
213 
214 	eprintf("Kernel '%s' was loaded OK\r\n", kname);
215 	xexit(0);
216 }
217 
218 /*
219  * Extract memory and cpu/fpu info from system.
220  */
221 void
222 get_sys_info()
223 {
224 	long	stck;
225 	long	*jar;
226 	OSH	*oshdr;
227 
228 	kparam.bootflags = 0;
229 
230 	stck = Super(0);
231 
232 	/*
233 	 * Some GEMDOS versions use a different year-base in the RTC.
234 	 */
235 	oshdr = *ADDR_OSHEAD;
236 	oshdr = oshdr->os_beg;
237 	if ((oshdr->os_version > 0x0300) && (oshdr->os_version < 0x0306))
238 		kparam.bootflags |= ATARI_CLKBROKEN;
239 
240 	if (kparam.stmem_size <= 0)
241 		kparam.stmem_size  = *ADDR_PHYSTOP;
242 
243 	if (kparam.ttmem_size)
244 		kparam.ttmem_start  = TTRAM_BASE;
245 	else {
246 		if (!s_flag && (*ADDR_CHKRAMTOP == RAM_TOP_MAGIC)) {
247 			kparam.ttmem_size  = *ADDR_RAMTOP;
248 			if (kparam.ttmem_size > TTRAM_BASE) {
249 				kparam.ttmem_size  -= TTRAM_BASE;
250 				kparam.ttmem_start  = TTRAM_BASE;
251 			}
252 			else kparam.ttmem_size = 0;
253 		}
254 	}
255 
256 	/*
257 	 * Scan cookiejar for cpu types
258 	 */
259 	jar = *ADDR_P_COOKIE;
260 	if (jar != NULL) {
261 		do {
262 			if (jar[0] == 0x5f435055) { /* _CPU	*/
263 				switch (jar[1]) {
264 					case 0:
265 						kparam.bootflags |= ATARI_68000;
266 						break;
267 					case 10:
268 						kparam.bootflags |= ATARI_68010;
269 						break;
270 					case 20:
271 						kparam.bootflags |= ATARI_68020;
272 						break;
273 					case 30:
274 						kparam.bootflags |= ATARI_68030;
275 						break;
276 					case 40:
277 						kparam.bootflags |= ATARI_68040;
278 						break;
279 					case 60:
280 						kparam.bootflags |= ATARI_68060;
281 						break;
282 					default:
283 						fatal(-1, "Unknown CPU-type");
284 				}
285 			}
286 			if (jar[0] == 0x42504658) { /* BPFX	*/
287 				unsigned long	*p;
288 
289 				p = (unsigned long*)jar[1];
290 
291 				kparam.ttmem_start = p[1];
292 				kparam.ttmem_size  = p[2];
293 			}
294 			jar = &jar[2];
295 		} while (jar[-2]);
296 	}
297 	if (!(kparam.bootflags & ATARI_ANYCPU))
298 		fatal(-1, "Cannot determine CPU-type");
299 
300 	(void)Super(stck);
301 
302 	if (d_flag) {
303 	    eprintf("Machine info:\r\n");
304 	    eprintf("ST-RAM size\t: %10d bytes\r\n",kparam.stmem_size);
305 	    eprintf("TT-RAM size\t: %10d bytes\r\n",kparam.ttmem_size);
306 	    eprintf("TT-RAM start\t: 0x%08x\r\n", kparam.ttmem_start);
307 	    eprintf("Cpu-type\t: 0x%08x\r\n", kparam.bootflags);
308 	}
309 }
310 
311 void
312 help()
313 {
314 	eprintf("\r
315 NetBSD loader for the Atari-TT\r
316 \r
317 Usage: %s [-abdhstVD] [-S <stram-size>] [-T <ttram-size>] [kernel]\r
318 \r
319 Description of options:\r
320 \r
321 \t-a  Boot up to multi-user mode.\r
322 \t-b  Ask for root device to use.\r
323 \t-d  Enter kernel debugger.\r
324 \t-D  printout debug information while loading\r
325 \t-h  What you're getting right now.\r
326 \t-o  Write output to both <output file> and stdout.\r
327 \t-s  Use only ST-compatible RAM\r
328 \t-S  Set amount of ST-compatible RAM\r
329 \t-T  Set amount of TT-compatible RAM\r
330 \t-t  Test the loader. It will do everything except executing the\r
331 \t    loaded kernel.\r
332 \t-V  Print loader version.\r
333 \t-w  Wait for a keypress before exiting.\r
334 ", Progname);
335 	xexit(0);
336 }
337 
338 void
339 usage()
340 {
341 	eprintf("Usage: %s [-abdhstVD] [-S <stram-size>] "
342 		"[-T <ttram-size>] [kernel]\r\n", Progname);
343 	xexit(1);
344 }
345 
346 void
347 start_kernel()
348 {
349 	long	stck;
350 
351 	stck = Super(0);
352 	bsd_startup(&kparam);
353 	/* NOT REACHED */
354 
355 	(void)Super(stck);
356 }
357