Home | History | Annotate | Line # | Download | only in loadbsd
loadbsd.c revision 1.14
      1  1.14    leo /*	$NetBSD: loadbsd.c,v 1.14 1999/05/27 09:08:25 leo Exp $	*/
      2   1.1    leo 
      3   1.1    leo /*
      4   1.1    leo  * Copyright (c) 1995 L. Weppelman
      5   1.1    leo  * All rights reserved.
      6   1.1    leo  *
      7   1.1    leo  * Redistribution and use in source and binary forms, with or without
      8   1.1    leo  * modification, are permitted provided that the following conditions
      9   1.1    leo  * are met:
     10   1.1    leo  * 1. Redistributions of source code must retain the above copyright
     11   1.1    leo  *    notice, this list of conditions and the following disclaimer.
     12   1.1    leo  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1    leo  *    notice, this list of conditions and the following disclaimer in the
     14   1.1    leo  *    documentation and/or other materials provided with the distribution.
     15   1.1    leo  * 3. All advertising materials mentioning features or use of this software
     16   1.1    leo  *    must display the following acknowledgement:
     17   1.1    leo  *      This product includes software developed by Leo Weppelman.
     18   1.1    leo  * 4. The name of the author may not be used to endorse or promote products
     19   1.1    leo  *    derived from this software without specific prior written permission
     20   1.1    leo  *
     21   1.1    leo  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22   1.1    leo  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23   1.1    leo  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24   1.1    leo  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25   1.1    leo  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26   1.1    leo  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27   1.1    leo  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28   1.1    leo  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29   1.1    leo  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30   1.1    leo  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31   1.1    leo  */
     32   1.1    leo 
     33   1.1    leo /*
     34   1.1    leo  * NetBSD loader for the Atari-TT.
     35   1.1    leo  */
     36   1.1    leo 
     37   1.1    leo #include <a_out.h>
     38   1.1    leo #include <fcntl.h>
     39  1.10    leo #include <stdio.h>
     40   1.1    leo #include <osbind.h>
     41   1.1    leo #include <stdarg.h>
     42  1.10    leo #include <stdlib.h>
     43  1.10    leo #include <string.h>
     44  1.10    leo #include <unistd.h>
     45  1.10    leo #include "libtos.h"
     46   1.1    leo #include "loader.h"
     47   1.1    leo 
     48   1.1    leo char	*Progname;		/* How are we called		*/
     49  1.10    leo int	d_flag  = 0;		/* Output debugging output?	*/
     50  1.10    leo int	h_flag  = 0;		/* show help			*/
     51  1.10    leo int	s_flag  = 0;		/* St-ram only			*/
     52  1.10    leo int	t_flag  = 0;		/* Just test, do not execute	*/
     53  1.10    leo int	v_flag  = 0;		/* show version			*/
     54   1.1    leo 
     55  1.14    leo const char version[] = "$Revision: 1.14 $";
     56   1.1    leo 
     57   1.1    leo /*
     58   1.1    leo  * Default name of kernel to boot, large enough to patch
     59   1.1    leo  */
     60  1.10    leo char	kname[80] = "n:/netbsd";
     61  1.10    leo 
     62  1.10    leo static struct kparamb kparam;
     63   1.1    leo 
     64  1.10    leo void help  PROTO((void));
     65  1.10    leo void usage PROTO((void));
     66  1.10    leo void get_sys_info PROTO((void));
     67  1.10    leo void start_kernel PROTO((void));
     68   1.1    leo 
     69  1.10    leo int
     70  1.10    leo main(argc, argv)
     71   1.1    leo int	argc;
     72   1.1    leo char	**argv;
     73   1.1    leo {
     74   1.1    leo 	/*
     75   1.1    leo 	 * Option parsing
     76   1.1    leo 	 */
     77   1.1    leo 	extern	int	optind;
     78   1.1    leo 	extern	char	*optarg;
     79   1.1    leo 	int		ch;
     80   1.1    leo 	int		fd;
     81   1.1    leo 	long		textsz, stringsz;
     82   1.1    leo 	struct exec	ehdr;
     83   1.1    leo 
     84  1.10    leo 	init_toslib(argv[0]);
     85   1.1    leo 	Progname = argv[0];
     86   1.1    leo 
     87   1.1    leo 	kparam.boothowto = RB_SINGLE;
     88   1.1    leo 
     89  1.13  lukem 	while ((ch = getopt(argc, argv, "abdhstVwDo:S:T:")) != -1) {
     90  1.10    leo 		switch (ch) {
     91   1.1    leo 		case 'a':
     92   1.1    leo 			kparam.boothowto &= ~(RB_SINGLE);
     93   1.1    leo 			kparam.boothowto |= RB_AUTOBOOT;
     94   1.1    leo 			break;
     95   1.1    leo 		case 'b':
     96   1.1    leo 			kparam.boothowto |= RB_ASKNAME;
     97   1.1    leo 			break;
     98   1.1    leo 		case 'd':
     99   1.1    leo 			kparam.boothowto |= RB_KDB;
    100   1.1    leo 			break;
    101   1.3    leo 		case 'D':
    102   1.3    leo 			d_flag = 1;
    103   1.3    leo 			break;
    104  1.10    leo 		case 'h':
    105  1.10    leo 			h_flag = 1;
    106  1.10    leo 			break;
    107  1.10    leo 		case 'o':
    108  1.10    leo 			redirect_output(optarg);
    109  1.10    leo 			break;
    110   1.3    leo 		case 's':
    111   1.3    leo 			s_flag = 1;
    112   1.3    leo 			break;
    113   1.3    leo 		case 'S':
    114   1.3    leo 			kparam.stmem_size = atoi(optarg);
    115   1.3    leo 			break;
    116   1.1    leo 		case 't':
    117   1.1    leo 			t_flag = 1;
    118   1.1    leo 			break;
    119   1.5    leo 		case 'T':
    120   1.5    leo 			kparam.ttmem_size = atoi(optarg);
    121   1.5    leo 			break;
    122  1.10    leo 		case 'V':
    123  1.10    leo 			v_flag = 1;
    124  1.10    leo 			break;
    125  1.10    leo 		case 'w':
    126  1.10    leo 			set_wait_for_key();
    127   1.1    leo 			break;
    128   1.1    leo 		default:
    129   1.1    leo 			usage();
    130   1.1    leo 		}
    131   1.1    leo 	}
    132   1.1    leo 	argc -= optind;
    133   1.1    leo 	argv += optind;
    134  1.10    leo 	if (argc == 1)
    135   1.1    leo 		strcpy(kname, argv[0]);
    136   1.1    leo 
    137  1.10    leo 	if (h_flag)
    138  1.10    leo 		help();
    139  1.10    leo 	if (v_flag)
    140  1.10    leo 		eprintf("%s\r\n", version);
    141  1.10    leo 
    142   1.1    leo 	/*
    143   1.2    leo 	 * Get system info to pass to NetBSD
    144   1.1    leo 	 */
    145   1.1    leo 	get_sys_info();
    146   1.1    leo 
    147   1.1    leo 	/*
    148   1.1    leo 	 * Find the kernel to boot and read it's exec-header
    149   1.1    leo 	 */
    150  1.10    leo 	if ((fd = open(kname, O_RDONLY)) < 0)
    151  1.10    leo 		fatal(-1, "Cannot open kernel '%s'", kname);
    152  1.10    leo 	if (read(fd, (char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr))
    153  1.10    leo 		fatal(-1, "Cannot read exec-header of '%s'", kname);
    154  1.14    leo 
    155  1.10    leo 	if (N_MAGIC(ehdr) != NMAGIC)
    156  1.10    leo 		fatal(-1, "Not an NMAGIC file '%s'", kname);
    157   1.1    leo 
    158   1.1    leo 	/*
    159   1.1    leo 	 * Extract various sizes from the kernel executable
    160   1.1    leo 	 */
    161   1.1    leo 	textsz          = (ehdr.a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1);
    162   1.1    leo 	kparam.esym_loc = 0;
    163   1.1    leo 	kparam.ksize    = textsz + ehdr.a_data + ehdr.a_bss;
    164   1.1    leo 	kparam.entry    = ehdr.a_entry;
    165   1.1    leo 
    166  1.10    leo 	if (ehdr.a_syms) {
    167  1.10    leo 	  if (lseek(fd,ehdr.a_text+ehdr.a_data+ehdr.a_syms+sizeof(ehdr),0) <= 0)
    168  1.10    leo 		fatal(-1, "Cannot seek to string table in '%s'", kname);
    169  1.10    leo 	  if (read(fd, (char *)&stringsz, sizeof(long)) != sizeof(long))
    170  1.10    leo 		fatal(-1, "Cannot read string-table size");
    171  1.10    leo 	  if (lseek(fd, sizeof(ehdr), 0) <= 0)
    172  1.10    leo 		fatal(-1, "Cannot seek back to text start");
    173   1.1    leo 	  kparam.ksize += ehdr.a_syms + sizeof(long) + stringsz;
    174   1.1    leo 	}
    175   1.1    leo 
    176  1.10    leo 	if ((kparam.kp = (u_char *)malloc(kparam.ksize)) == NULL)
    177  1.10    leo 		fatal(-1, "Cannot malloc kernel image space");
    178   1.1    leo 
    179   1.1    leo 	/*
    180   1.1    leo 	 * Read text & data, clear bss
    181   1.1    leo 	 */
    182  1.10    leo 	if ((read(fd, (char *)kparam.kp, ehdr.a_text) != ehdr.a_text)
    183  1.10    leo 	    || (read(fd,(char *)(kparam.kp+textsz),ehdr.a_data) != ehdr.a_data))
    184  1.10    leo 		fatal(-1, "Unable to read kernel image\n");
    185   1.1    leo 	memset(kparam.kp + textsz + ehdr.a_data, 0, ehdr.a_bss);
    186   1.1    leo 
    187   1.1    leo 	/*
    188   1.1    leo 	 * Read symbol and string table
    189   1.1    leo 	 */
    190  1.10    leo 	if (ehdr.a_syms) {
    191  1.14    leo 	    long	*p;
    192   1.1    leo 
    193  1.14    leo 	    p = (long *)(kparam.kp + textsz + ehdr.a_data + ehdr.a_bss);
    194  1.14    leo 	    *p++ = ehdr.a_syms;
    195  1.14    leo 	    if (read(fd, (char *)p, ehdr.a_syms) != ehdr.a_syms)
    196  1.14    leo 		fatal(-1, "Cannot read symbol table\n");
    197  1.14    leo 	    p = (long *)((char *)p + ehdr.a_syms);
    198  1.14    leo 	    if (read(fd, (char *)p, stringsz) != stringsz)
    199  1.14    leo 		fatal(-1, "Cannot read string table\n");
    200  1.14    leo 	    kparam.esym_loc = (long)((char *)p-(char *)kparam.kp +stringsz);
    201   1.1    leo 	}
    202  1.14    leo 	close(fd);
    203   1.1    leo 
    204  1.10    leo 	if (d_flag) {
    205  1.10    leo 	    eprintf("\r\nKernel info:\r\n");
    206  1.10    leo 	    eprintf("Kernel loadaddr\t: 0x%08x\r\n", kparam.kp);
    207  1.10    leo 	    eprintf("Kernel size\t: %10d bytes\r\n", kparam.ksize);
    208  1.10    leo 	    eprintf("Kernel entry\t: 0x%08x\r\n", kparam.entry);
    209  1.10    leo 	    eprintf("Kernel esym\t: 0x%08x\r\n", kparam.esym_loc);
    210   1.4    leo 	}
    211   1.4    leo 
    212  1.10    leo 	if (!t_flag)
    213   1.1    leo 		start_kernel();
    214   1.1    leo 		/* NOT REACHED */
    215   1.1    leo 
    216  1.10    leo 	eprintf("Kernel '%s' was loaded OK\r\n", kname);
    217  1.10    leo 	xexit(0);
    218   1.1    leo }
    219   1.1    leo 
    220   1.1    leo /*
    221   1.1    leo  * Extract memory and cpu/fpu info from system.
    222   1.1    leo  */
    223  1.10    leo void
    224  1.10    leo get_sys_info()
    225   1.1    leo {
    226   1.1    leo 	long	stck;
    227   1.1    leo 	long	*jar;
    228   1.7    leo 	OSH	*oshdr;
    229   1.1    leo 
    230  1.10    leo 	kparam.bootflags = 0;
    231   1.1    leo 
    232   1.1    leo 	stck = Super(0);
    233   1.7    leo 
    234   1.7    leo 	/*
    235   1.7    leo 	 * Some GEMDOS versions use a different year-base in the RTC.
    236   1.7    leo 	 */
    237   1.7    leo 	oshdr = *ADDR_OSHEAD;
    238   1.7    leo 	oshdr = oshdr->os_beg;
    239  1.10    leo 	if ((oshdr->os_version > 0x0300) && (oshdr->os_version < 0x0306))
    240  1.10    leo 		kparam.bootflags |= ATARI_CLKBROKEN;
    241   1.1    leo 
    242  1.10    leo 	if (kparam.stmem_size <= 0)
    243   1.3    leo 		kparam.stmem_size  = *ADDR_PHYSTOP;
    244   1.3    leo 
    245  1.10    leo 	if (kparam.ttmem_size)
    246   1.5    leo 		kparam.ttmem_start  = TTRAM_BASE;
    247   1.5    leo 	else {
    248  1.10    leo 		if (!s_flag && (*ADDR_CHKRAMTOP == RAM_TOP_MAGIC)) {
    249   1.5    leo 			kparam.ttmem_size  = *ADDR_RAMTOP;
    250  1.10    leo 			if (kparam.ttmem_size > TTRAM_BASE) {
    251   1.5    leo 				kparam.ttmem_size  -= TTRAM_BASE;
    252   1.5    leo 				kparam.ttmem_start  = TTRAM_BASE;
    253   1.5    leo 			}
    254   1.5    leo 			else kparam.ttmem_size = 0;
    255   1.4    leo 		}
    256   1.4    leo 	}
    257   1.1    leo 
    258   1.1    leo 	/*
    259   1.8    leo 	 * Scan cookiejar for cpu types
    260   1.1    leo 	 */
    261   1.1    leo 	jar = *ADDR_P_COOKIE;
    262  1.10    leo 	if (jar != NULL) {
    263   1.1    leo 		do {
    264  1.14    leo 		    if (jar[0] == 0x5f435055) { /* _CPU	*/
    265  1.14    leo 			switch (jar[1]) {
    266  1.14    leo 				case 0:
    267  1.14    leo 					kparam.bootflags |= ATARI_68000;
    268  1.14    leo 					break;
    269  1.14    leo 				case 10:
    270  1.14    leo 					kparam.bootflags |= ATARI_68010;
    271  1.14    leo 					break;
    272  1.14    leo 				case 20:
    273  1.14    leo 					kparam.bootflags |= ATARI_68020;
    274  1.14    leo 					break;
    275  1.14    leo 				case 30:
    276  1.14    leo 					kparam.bootflags |= ATARI_68030;
    277  1.14    leo 					break;
    278  1.14    leo 				case 40:
    279  1.14    leo 					kparam.bootflags |= ATARI_68040;
    280  1.14    leo 					break;
    281  1.14    leo 				case 60:
    282  1.14    leo 					kparam.bootflags |= ATARI_68060;
    283  1.14    leo 					break;
    284  1.14    leo 				default:
    285  1.14    leo 					fatal(-1, "Unknown CPU-type");
    286   1.1    leo 			}
    287  1.14    leo 		    }
    288  1.14    leo 		    if (jar[0] == 0x42504658) { /* BPFX	*/
    289  1.14    leo 			unsigned long	*p;
    290  1.14    leo 
    291  1.14    leo 			p = (unsigned long*)jar[1];
    292  1.14    leo 
    293  1.14    leo 			kparam.ttmem_start = p[1];
    294  1.14    leo 			kparam.ttmem_size  = p[2];
    295  1.14    leo 		    }
    296  1.14    leo 		    if (jar[0] == 0x5f435432) { /* _CT2	*/
    297  1.14    leo 			/*
    298  1.14    leo 			 * The CT2 board has a different physical base address!
    299  1.14    leo 			 */
    300  1.14    leo 			kparam.ttmem_start = CTRAM_BASE;
    301  1.14    leo 		    }
    302  1.14    leo 		    jar = &jar[2];
    303  1.10    leo 		} while (jar[-2]);
    304   1.1    leo 	}
    305  1.10    leo 	if (!(kparam.bootflags & ATARI_ANYCPU))
    306  1.10    leo 		fatal(-1, "Cannot determine CPU-type");
    307   1.1    leo 
    308  1.10    leo 	(void)Super(stck);
    309   1.3    leo 
    310  1.10    leo 	if (d_flag) {
    311  1.10    leo 	    eprintf("Machine info:\r\n");
    312  1.10    leo 	    eprintf("ST-RAM size\t: %10d bytes\r\n",kparam.stmem_size);
    313  1.10    leo 	    eprintf("TT-RAM size\t: %10d bytes\r\n",kparam.ttmem_size);
    314  1.10    leo 	    eprintf("TT-RAM start\t: 0x%08x\r\n", kparam.ttmem_start);
    315  1.10    leo 	    eprintf("Cpu-type\t: 0x%08x\r\n", kparam.bootflags);
    316   1.3    leo 	}
    317   1.1    leo }
    318   1.1    leo 
    319  1.10    leo void
    320  1.10    leo help()
    321   1.1    leo {
    322  1.10    leo 	eprintf("\r
    323   1.3    leo NetBSD loader for the Atari-TT\r
    324   1.3    leo \r
    325  1.10    leo Usage: %s [-abdhstVD] [-S <stram-size>] [-T <ttram-size>] [kernel]\r
    326   1.3    leo \r
    327   1.3    leo Description of options:\r
    328   1.3    leo \r
    329   1.3    leo \t-a  Boot up to multi-user mode.\r
    330   1.3    leo \t-b  Ask for root device to use.\r
    331   1.3    leo \t-d  Enter kernel debugger.\r
    332  1.10    leo \t-D  printout debug information while loading\r
    333  1.11    leo \t-h  What you're getting right now.\r
    334  1.10    leo \t-o  Write output to both <output file> and stdout.\r
    335   1.3    leo \t-s  Use only ST-compatible RAM\r
    336   1.3    leo \t-S  Set amount of ST-compatible RAM\r
    337   1.5    leo \t-T  Set amount of TT-compatible RAM\r
    338   1.3    leo \t-t  Test the loader. It will do everything except executing the\r
    339   1.3    leo \t    loaded kernel.\r
    340  1.10    leo \t-V  Print loader version.\r
    341  1.10    leo \t-w  Wait for a keypress before exiting.\r
    342   1.1    leo ", Progname);
    343  1.10    leo 	xexit(0);
    344   1.1    leo }
    345   1.1    leo 
    346  1.10    leo void
    347  1.10    leo usage()
    348   1.1    leo {
    349  1.10    leo 	eprintf("Usage: %s [-abdhstVD] [-S <stram-size>] "
    350  1.10    leo 		"[-T <ttram-size>] [kernel]\r\n", Progname);
    351  1.10    leo 	xexit(1);
    352   1.3    leo }
    353   1.3    leo 
    354  1.10    leo void
    355  1.10    leo start_kernel()
    356   1.1    leo {
    357   1.1    leo 	long	stck;
    358   1.1    leo 
    359   1.1    leo 	stck = Super(0);
    360  1.10    leo 	bsd_startup(&kparam);
    361   1.1    leo 	/* NOT REACHED */
    362   1.1    leo 
    363  1.10    leo 	(void)Super(stck);
    364   1.1    leo }
    365