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