loadbsd.c revision 1.10 1 /* $NetBSD: loadbsd.c,v 1.10 1996/01/07 22:06:15 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 <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.10 $";
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:")) != EOF) {
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 default:
280 fatal(-1, "Unknown CPU-type");
281 }
282 }
283 if (jar[0] == 0x42504658) { /* BPFX */
284 unsigned long *p;
285
286 p = (unsigned long*)jar[1];
287
288 kparam.ttmem_start = p[1];
289 kparam.ttmem_size = p[2];
290 }
291 jar = &jar[2];
292 } while (jar[-2]);
293 }
294 if (!(kparam.bootflags & ATARI_ANYCPU))
295 fatal(-1, "Cannot determine CPU-type");
296
297 (void)Super(stck);
298
299 if (d_flag) {
300 eprintf("Machine info:\r\n");
301 eprintf("ST-RAM size\t: %10d bytes\r\n",kparam.stmem_size);
302 eprintf("TT-RAM size\t: %10d bytes\r\n",kparam.ttmem_size);
303 eprintf("TT-RAM start\t: 0x%08x\r\n", kparam.ttmem_start);
304 eprintf("Cpu-type\t: 0x%08x\r\n", kparam.bootflags);
305 }
306 }
307
308 void
309 help()
310 {
311 eprintf("\r
312 NetBSD loader for the Atari-TT\r
313 \r
314 Usage: %s [-abdhstVD] [-S <stram-size>] [-T <ttram-size>] [kernel]\r
315 \r
316 Description of options:\r
317 \r
318 \t-a Boot up to multi-user mode.\r
319 \t-b Ask for root device to use.\r
320 \t-d Enter kernel debugger.\r
321 \t-D printout debug information while loading\r
322 \t-h What your getting right now.\r
323 \t-o Write output to both <output file> and stdout.\r
324 \t-s Use only ST-compatible RAM\r
325 \t-S Set amount of ST-compatible RAM\r
326 \t-T Set amount of TT-compatible RAM\r
327 \t-t Test the loader. It will do everything except executing the\r
328 \t loaded kernel.\r
329 \t-V Print loader version.\r
330 \t-w Wait for a keypress before exiting.\r
331 ", Progname);
332 xexit(0);
333 }
334
335 void
336 usage()
337 {
338 eprintf("Usage: %s [-abdhstVD] [-S <stram-size>] "
339 "[-T <ttram-size>] [kernel]\r\n", Progname);
340 xexit(1);
341 }
342
343 void
344 start_kernel()
345 {
346 long stck;
347
348 stck = Super(0);
349 bsd_startup(&kparam);
350 /* NOT REACHED */
351
352 (void)Super(stck);
353 }
354