Home | History | Annotate | Line # | Download | only in loadbsd
loadbsd.c revision 1.10
      1  1.10  leo /*	$NetBSD: loadbsd.c,v 1.10 1996/01/07 22:06:15 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.10  leo const char version[] = "$Revision: 1.10 $";
     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.10  leo 	while ((ch = getopt(argc, argv, "abdhstVwDo:S:T:")) != EOF) {
     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.10  leo 	if (N_MAGIC(ehdr) != NMAGIC)
    155  1.10  leo 		fatal(-1, "Not an NMAGIC file '%s'", kname);
    156   1.1  leo 
    157   1.1  leo 	/*
    158   1.1  leo 	 * Extract various sizes from the kernel executable
    159   1.1  leo 	 */
    160   1.1  leo 	textsz          = (ehdr.a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1);
    161   1.1  leo 	kparam.esym_loc = 0;
    162   1.1  leo 	kparam.ksize    = textsz + ehdr.a_data + ehdr.a_bss;
    163   1.1  leo 	kparam.entry    = ehdr.a_entry;
    164   1.1  leo 
    165  1.10  leo 	if (ehdr.a_syms) {
    166  1.10  leo 	  if (lseek(fd,ehdr.a_text+ehdr.a_data+ehdr.a_syms+sizeof(ehdr),0) <= 0)
    167  1.10  leo 		fatal(-1, "Cannot seek to string table in '%s'", kname);
    168  1.10  leo 	  if (read(fd, (char *)&stringsz, sizeof(long)) != sizeof(long))
    169  1.10  leo 		fatal(-1, "Cannot read string-table size");
    170  1.10  leo 	  if (lseek(fd, sizeof(ehdr), 0) <= 0)
    171  1.10  leo 		fatal(-1, "Cannot seek back to text start");
    172   1.1  leo 	  kparam.ksize += ehdr.a_syms + sizeof(long) + stringsz;
    173   1.1  leo 	}
    174   1.1  leo 
    175  1.10  leo 	if ((kparam.kp = (u_char *)malloc(kparam.ksize)) == NULL)
    176  1.10  leo 		fatal(-1, "Cannot malloc kernel image space");
    177   1.1  leo 
    178   1.1  leo 	/*
    179   1.1  leo 	 * Read text & data, clear bss
    180   1.1  leo 	 */
    181  1.10  leo 	if ((read(fd, (char *)kparam.kp, ehdr.a_text) != ehdr.a_text)
    182  1.10  leo 	    || (read(fd,(char *)(kparam.kp+textsz),ehdr.a_data) != ehdr.a_data))
    183  1.10  leo 		fatal(-1, "Unable to read kernel image\n");
    184   1.1  leo 	memset(kparam.kp + textsz + ehdr.a_data, 0, ehdr.a_bss);
    185   1.1  leo 
    186   1.1  leo 	/*
    187   1.1  leo 	 * Read symbol and string table
    188   1.1  leo 	 */
    189  1.10  leo 	if (ehdr.a_syms) {
    190   1.1  leo 		long	*p;
    191   1.1  leo 
    192   1.1  leo 		p = (long *)(kparam.kp + textsz + ehdr.a_data + ehdr.a_bss);
    193   1.1  leo 		*p++ = ehdr.a_syms;
    194  1.10  leo 		if (read(fd, (char *)p, ehdr.a_syms) != ehdr.a_syms)
    195  1.10  leo 			fatal(-1, "Cannot read symbol table\n");
    196   1.1  leo 		p = (long *)((char *)p + ehdr.a_syms);
    197  1.10  leo 		if (read(fd, (char *)p, stringsz) != stringsz)
    198  1.10  leo 			fatal(-1, "Cannot read string table\n");
    199   1.1  leo 		kparam.esym_loc = (long)((char *)p-(char *)kparam.kp +stringsz);
    200   1.1  leo 	}
    201   1.1  leo 
    202  1.10  leo 	if (d_flag) {
    203  1.10  leo 	    eprintf("\r\nKernel info:\r\n");
    204  1.10  leo 	    eprintf("Kernel loadaddr\t: 0x%08x\r\n", kparam.kp);
    205  1.10  leo 	    eprintf("Kernel size\t: %10d bytes\r\n", kparam.ksize);
    206  1.10  leo 	    eprintf("Kernel entry\t: 0x%08x\r\n", kparam.entry);
    207  1.10  leo 	    eprintf("Kernel esym\t: 0x%08x\r\n", kparam.esym_loc);
    208   1.4  leo 	}
    209   1.4  leo 
    210  1.10  leo 	if (!t_flag)
    211   1.1  leo 		start_kernel();
    212   1.1  leo 		/* NOT REACHED */
    213   1.1  leo 
    214  1.10  leo 	eprintf("Kernel '%s' was loaded OK\r\n", kname);
    215  1.10  leo 	xexit(0);
    216   1.1  leo }
    217   1.1  leo 
    218   1.1  leo /*
    219   1.1  leo  * Extract memory and cpu/fpu info from system.
    220   1.1  leo  */
    221  1.10  leo void
    222  1.10  leo get_sys_info()
    223   1.1  leo {
    224   1.1  leo 	long	stck;
    225   1.1  leo 	long	*jar;
    226   1.7  leo 	OSH	*oshdr;
    227   1.1  leo 
    228  1.10  leo 	kparam.bootflags = 0;
    229   1.1  leo 
    230   1.1  leo 	stck = Super(0);
    231   1.7  leo 
    232   1.7  leo 	/*
    233   1.7  leo 	 * Some GEMDOS versions use a different year-base in the RTC.
    234   1.7  leo 	 */
    235   1.7  leo 	oshdr = *ADDR_OSHEAD;
    236   1.7  leo 	oshdr = oshdr->os_beg;
    237  1.10  leo 	if ((oshdr->os_version > 0x0300) && (oshdr->os_version < 0x0306))
    238  1.10  leo 		kparam.bootflags |= ATARI_CLKBROKEN;
    239   1.1  leo 
    240  1.10  leo 	if (kparam.stmem_size <= 0)
    241   1.3  leo 		kparam.stmem_size  = *ADDR_PHYSTOP;
    242   1.3  leo 
    243  1.10  leo 	if (kparam.ttmem_size)
    244   1.5  leo 		kparam.ttmem_start  = TTRAM_BASE;
    245   1.5  leo 	else {
    246  1.10  leo 		if (!s_flag && (*ADDR_CHKRAMTOP == RAM_TOP_MAGIC)) {
    247   1.5  leo 			kparam.ttmem_size  = *ADDR_RAMTOP;
    248  1.10  leo 			if (kparam.ttmem_size > TTRAM_BASE) {
    249   1.5  leo 				kparam.ttmem_size  -= TTRAM_BASE;
    250   1.5  leo 				kparam.ttmem_start  = TTRAM_BASE;
    251   1.5  leo 			}
    252   1.5  leo 			else kparam.ttmem_size = 0;
    253   1.4  leo 		}
    254   1.4  leo 	}
    255   1.1  leo 
    256   1.1  leo 	/*
    257   1.8  leo 	 * Scan cookiejar for cpu types
    258   1.1  leo 	 */
    259   1.1  leo 	jar = *ADDR_P_COOKIE;
    260  1.10  leo 	if (jar != NULL) {
    261   1.1  leo 		do {
    262  1.10  leo 			if (jar[0] == 0x5f435055) { /* _CPU	*/
    263  1.10  leo 				switch (jar[1]) {
    264   1.1  leo 					case 0:
    265  1.10  leo 						kparam.bootflags |= ATARI_68000;
    266   1.1  leo 						break;
    267   1.1  leo 					case 10:
    268  1.10  leo 						kparam.bootflags |= ATARI_68010;
    269   1.1  leo 						break;
    270   1.1  leo 					case 20:
    271  1.10  leo 						kparam.bootflags |= ATARI_68020;
    272   1.1  leo 						break;
    273   1.1  leo 					case 30:
    274  1.10  leo 						kparam.bootflags |= ATARI_68030;
    275   1.1  leo 						break;
    276   1.1  leo 					case 40:
    277  1.10  leo 						kparam.bootflags |= ATARI_68040;
    278   1.1  leo 						break;
    279   1.1  leo 					default:
    280  1.10  leo 						fatal(-1, "Unknown CPU-type");
    281   1.1  leo 				}
    282   1.9  leo 			}
    283  1.10  leo 			if (jar[0] == 0x42504658) { /* BPFX	*/
    284   1.9  leo 				unsigned long	*p;
    285   1.9  leo 
    286   1.9  leo 				p = (unsigned long*)jar[1];
    287   1.9  leo 
    288   1.9  leo 				kparam.ttmem_start = p[1];
    289   1.9  leo 				kparam.ttmem_size  = p[2];
    290   1.1  leo 			}
    291   1.1  leo 			jar = &jar[2];
    292  1.10  leo 		} while (jar[-2]);
    293   1.1  leo 	}
    294  1.10  leo 	if (!(kparam.bootflags & ATARI_ANYCPU))
    295  1.10  leo 		fatal(-1, "Cannot determine CPU-type");
    296   1.1  leo 
    297  1.10  leo 	(void)Super(stck);
    298   1.3  leo 
    299  1.10  leo 	if (d_flag) {
    300  1.10  leo 	    eprintf("Machine info:\r\n");
    301  1.10  leo 	    eprintf("ST-RAM size\t: %10d bytes\r\n",kparam.stmem_size);
    302  1.10  leo 	    eprintf("TT-RAM size\t: %10d bytes\r\n",kparam.ttmem_size);
    303  1.10  leo 	    eprintf("TT-RAM start\t: 0x%08x\r\n", kparam.ttmem_start);
    304  1.10  leo 	    eprintf("Cpu-type\t: 0x%08x\r\n", kparam.bootflags);
    305   1.3  leo 	}
    306   1.1  leo }
    307   1.1  leo 
    308  1.10  leo void
    309  1.10  leo help()
    310   1.1  leo {
    311  1.10  leo 	eprintf("\r
    312   1.3  leo NetBSD loader for the Atari-TT\r
    313   1.3  leo \r
    314  1.10  leo Usage: %s [-abdhstVD] [-S <stram-size>] [-T <ttram-size>] [kernel]\r
    315   1.3  leo \r
    316   1.3  leo Description of options:\r
    317   1.3  leo \r
    318   1.3  leo \t-a  Boot up to multi-user mode.\r
    319   1.3  leo \t-b  Ask for root device to use.\r
    320   1.3  leo \t-d  Enter kernel debugger.\r
    321  1.10  leo \t-D  printout debug information while loading\r
    322   1.3  leo \t-h  What your getting right now.\r
    323  1.10  leo \t-o  Write output to both <output file> and stdout.\r
    324   1.3  leo \t-s  Use only ST-compatible RAM\r
    325   1.3  leo \t-S  Set amount of ST-compatible RAM\r
    326   1.5  leo \t-T  Set amount of TT-compatible RAM\r
    327   1.3  leo \t-t  Test the loader. It will do everything except executing the\r
    328   1.3  leo \t    loaded kernel.\r
    329  1.10  leo \t-V  Print loader version.\r
    330  1.10  leo \t-w  Wait for a keypress before exiting.\r
    331   1.1  leo ", Progname);
    332  1.10  leo 	xexit(0);
    333   1.1  leo }
    334   1.1  leo 
    335  1.10  leo void
    336  1.10  leo usage()
    337   1.1  leo {
    338  1.10  leo 	eprintf("Usage: %s [-abdhstVD] [-S <stram-size>] "
    339  1.10  leo 		"[-T <ttram-size>] [kernel]\r\n", Progname);
    340  1.10  leo 	xexit(1);
    341   1.3  leo }
    342   1.3  leo 
    343  1.10  leo void
    344  1.10  leo start_kernel()
    345   1.1  leo {
    346   1.1  leo 	long	stck;
    347   1.1  leo 
    348   1.1  leo 	stck = Super(0);
    349  1.10  leo 	bsd_startup(&kparam);
    350   1.1  leo 	/* NOT REACHED */
    351   1.1  leo 
    352  1.10  leo 	(void)Super(stck);
    353   1.1  leo }
    354