Home | History | Annotate | Line # | Download | only in loadbsd
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