Home | History | Annotate | Line # | Download | only in boot_ufs
bootmain.c revision 1.2
      1  1.2  minoura /*	$NetBSD: bootmain.c,v 1.2 2001/10/15 16:13:40 minoura Exp $	*/
      2  1.1  minoura 
      3  1.1  minoura /*-
      4  1.1  minoura  * Copyright (c) 1993, 1994 Takumi Nakamura.
      5  1.1  minoura  * Copyright (c) 1999, 2000 Itoh Yasufumi.
      6  1.1  minoura  * Copyright (c) 2001 Minoura Makoto.
      7  1.1  minoura  *
      8  1.1  minoura  * Redistribution and use in source and binary forms, with or without
      9  1.1  minoura  * modification, are permitted provided that the following conditions
     10  1.1  minoura  * are met:
     11  1.1  minoura  * 1. Redistributions of source code must retain the above copyright
     12  1.1  minoura  *    notice, this list of conditions and the following disclaimer.
     13  1.1  minoura  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.1  minoura  *    notice, this list of conditions and the following disclaimer in the
     15  1.1  minoura  *    documentation and/or other materials provided with the distribution.
     16  1.1  minoura  * 3. All advertising materials mentioning features or use of this software
     17  1.1  minoura  *    must display the following acknowledgement:
     18  1.1  minoura  *	This product includes software developed by Takumi Nakamura.
     19  1.1  minoura  * 4. Neither the name of the University nor the names of its contributors
     20  1.1  minoura  *    may be used to endorse or promote products derived from this software
     21  1.1  minoura  *    without specific prior written permission.
     22  1.1  minoura  *
     23  1.1  minoura  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  1.1  minoura  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  1.1  minoura  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  1.1  minoura  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  1.1  minoura  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  1.1  minoura  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  1.1  minoura  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  1.1  minoura  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  1.1  minoura  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  1.1  minoura  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  1.1  minoura  * SUCH DAMAGE.
     34  1.1  minoura  */
     35  1.1  minoura 
     36  1.1  minoura #include <sys/param.h>
     37  1.1  minoura #include <sys/reboot.h>
     38  1.1  minoura #include <sys/types.h>
     39  1.1  minoura #include <sys/exec_aout.h>
     40  1.1  minoura #include <ufs/ufs/dinode.h>
     41  1.1  minoura #include <ufs/ffs/fs.h>
     42  1.1  minoura #include <ufs/ufs/dir.h>
     43  1.1  minoura #include <machine/bootinfo.h>
     44  1.1  minoura #ifdef SCSI_ADHOC_BOOTPART
     45  1.1  minoura #include <machine/disklabel.h>
     46  1.1  minoura #endif
     47  1.1  minoura 
     48  1.1  minoura #include "boot_ufs.h"
     49  1.1  minoura #include "readufs.h"
     50  1.1  minoura #include "exec_image.h"
     51  1.1  minoura #include "../../x68k/iodevice.h"
     52  1.1  minoura #define IODEVbase ((volatile struct IODEVICE *)PHYS_IODEV)
     53  1.1  minoura 
     54  1.1  minoura /* for debug;  */
     55  1.1  minoura unsigned int startregs[16];
     56  1.1  minoura 
     57  1.1  minoura #ifdef SCSI_ADHOC_BOOTPART
     58  1.1  minoura static int get_scsi_part (void);
     59  1.1  minoura #endif
     60  1.1  minoura #ifdef BOOT_DEBUG
     61  1.1  minoura static int get_scsi_host_adapter (char *);
     62  1.1  minoura #else
     63  1.1  minoura static int get_scsi_host_adapter (void);
     64  1.1  minoura #endif
     65  1.1  minoura 
     66  1.1  minoura #ifdef BOOT_DEBUG
     67  1.1  minoura void print_hex (unsigned int, int);
     68  1.1  minoura #endif
     69  1.1  minoura 
     70  1.1  minoura static int load_file (const char*, unsigned int, struct exec *);
     71  1.1  minoura static int load_file_ino (ino_t, const char*, unsigned int, struct exec *);
     72  1.1  minoura 
     73  1.1  minoura void bootufs (void) __attribute__ ((__noreturn__));
     74  1.1  minoura 
     75  1.1  minoura #ifdef BOOT_DEBUG
     76  1.1  minoura void
     77  1.1  minoura print_hex(x, l)
     78  1.1  minoura 	unsigned int x;	/*  */
     79  1.1  minoura 	int l;		/*  */
     80  1.1  minoura {
     81  1.1  minoura 
     82  1.1  minoura 	if (l > 0) {
     83  1.1  minoura 		print_hex(x >> 4, l - 1);
     84  1.1  minoura 		x &= 0x0F;
     85  1.1  minoura 		if (x > 9)
     86  1.1  minoura 			x += 7;
     87  1.1  minoura 		B_PUTC((unsigned int) '0' + x);
     88  1.1  minoura 	}
     89  1.1  minoura }
     90  1.1  minoura #endif
     91  1.1  minoura 
     92  1.1  minoura #ifdef SCSI_ADHOC_BOOTPART
     93  1.1  minoura /*
     94  1.1  minoura  * get partition # from partition start position
     95  1.1  minoura  */
     96  1.1  minoura 
     97  1.1  minoura #define NPART		15
     98  1.1  minoura #define PARTTBL_TOP	((unsigned)4)	/* pos of part inf in 512byte-blocks */
     99  1.1  minoura #define MAXPART		6
    100  1.1  minoura const unsigned char partition_conv[MAXPART + 1] = { 0, 1, 3, 4, 5, 6, 7 };
    101  1.1  minoura 
    102  1.1  minoura static int
    103  1.1  minoura get_scsi_part()
    104  1.1  minoura {
    105  1.1  minoura 	struct {
    106  1.1  minoura 		u_int32_t	magic;		/* 0x5836384B ("X68K") */
    107  1.1  minoura 		u_int32_t	parttotal;
    108  1.1  minoura 		u_int32_t	diskblocks;
    109  1.1  minoura 		u_int32_t	diskblocks2;	/* backup? */
    110  1.1  minoura 		struct dos_partition parttbl[NPART];
    111  1.1  minoura 		unsigned char	formatstr[256];
    112  1.1  minoura 		unsigned char	rest[512];
    113  1.1  minoura 	} partbuf;
    114  1.1  minoura 	int i;
    115  1.1  minoura 	u_int32_t part_top;
    116  1.1  minoura 
    117  1.1  minoura #ifdef BOOT_DEBUG
    118  1.1  minoura 	B_PRINT("seclen: ");
    119  1.1  minoura 	print_hex(SCSI_BLKLEN, 8);	/* 0: 256, 1: 512, 2: 1024 */
    120  1.1  minoura 	B_PRINT(", topsec: ");
    121  1.1  minoura 	print_hex(SCSI_PARTTOP, 8);	/* partition top in sector */
    122  1.1  minoura #endif
    123  1.1  minoura 	/*
    124  1.1  minoura 	 * read partition table
    125  1.1  minoura 	 */
    126  1.1  minoura 	RAW_READ0(&partbuf, PARTTBL_TOP, sizeof partbuf);
    127  1.1  minoura 
    128  1.1  minoura 	part_top = SCSI_PARTTOP >> (2 - SCSI_BLKLEN);
    129  1.1  minoura 	for (i = 0; i < MAXPART; i++)
    130  1.1  minoura 		if ((u_int32_t) partbuf.parttbl[i].dp_start == part_top)
    131  1.1  minoura 			goto found;
    132  1.1  minoura 
    133  1.1  minoura 	BOOT_ERROR("Can't boot from this partition");
    134  1.1  minoura 	/* NOTREACHED */
    135  1.1  minoura found:
    136  1.1  minoura #ifdef BOOT_DEBUG
    137  1.1  minoura 	B_PRINT("; sd");
    138  1.1  minoura 	B_PUTC(ID + '0');	/* SCSI ID (not NetBSD unit #) */
    139  1.1  minoura 	B_PUTC((unsigned int) partition_conv[i] + 'a');
    140  1.1  minoura 	B_PRINT("\r\n");
    141  1.1  minoura #endif
    142  1.1  minoura 	return partition_conv[i];
    143  1.1  minoura }
    144  1.1  minoura #endif	/* SCSI_ADHOC_BOOTPART */
    145  1.1  minoura 
    146  1.1  minoura /*
    147  1.1  minoura  * Check the type of SCSI interface
    148  1.1  minoura  */
    149  1.1  minoura #ifdef BOOT_DEBUG
    150  1.1  minoura static int
    151  1.1  minoura get_scsi_host_adapter(devstr)
    152  1.1  minoura 	char *devstr;
    153  1.1  minoura #else
    154  1.1  minoura static int
    155  1.1  minoura get_scsi_host_adapter(void)
    156  1.1  minoura #endif
    157  1.1  minoura {
    158  1.1  minoura 	char *bootrom;
    159  1.1  minoura 	int ha;
    160  1.1  minoura 
    161  1.1  minoura #ifdef BOOT_DEBUG
    162  1.1  minoura 	B_PRINT(" at ");
    163  1.1  minoura 	*(int *)devstr = '/' << 24 | 's' << 16 | 'p' << 8 | 'c';
    164  1.1  minoura 	*(int *)(devstr + 4) = '@' << 24 | '0' << 16 | '/' << 8 | 's';
    165  1.1  minoura 	*(int *)(devstr + 8) = 'd' << 24 | '@' << 16 | '0' << 8 | ',';
    166  1.1  minoura 	*(int *)(devstr + 12) = '0' << 24 | ':' << 16 | 'a' << 8 | '\0';
    167  1.1  minoura #endif
    168  1.1  minoura 
    169  1.1  minoura 	bootrom = (char *) (BOOT_INFO & 0x00ffffe0);
    170  1.1  minoura 	/*
    171  1.1  minoura 	 * bootrom+0x24	"SCSIIN" ... Internal SCSI (spc@0)
    172  1.1  minoura 	 *		"SCSIEX" ... External SCSI (spc@1 or mha@0)
    173  1.1  minoura 	 */
    174  1.1  minoura 	if (*(u_short *)(bootrom + 0x24 + 4) == 0x494e) {	/* "IN" */
    175  1.1  minoura #ifdef BOOT_DEBUG
    176  1.1  minoura 		B_PRINT("spc0");
    177  1.1  minoura #endif
    178  1.1  minoura 		ha = (X68K_BOOT_SCSIIF_SPC << 4) | 0;
    179  1.1  minoura 	} else if (badbaddr(&IODEVbase->io_exspc.bdid)) {
    180  1.1  minoura #ifdef BOOT_DEBUG
    181  1.1  minoura 		B_PRINT("mha0");
    182  1.1  minoura #endif
    183  1.1  minoura 		ha = (X68K_BOOT_SCSIIF_MHA << 4) | 0;
    184  1.1  minoura #ifdef BOOT_DEBUG
    185  1.1  minoura 		*(int *)devstr = '/' << 24 | 'm' << 16 | 'h' << 8 | 'a';
    186  1.1  minoura #endif
    187  1.1  minoura 	} else {
    188  1.1  minoura #ifdef BOOT_DEBUG
    189  1.1  minoura 		B_PRINT("spc1");
    190  1.1  minoura #endif
    191  1.1  minoura 		ha = (X68K_BOOT_SCSIIF_SPC << 4) | 1;
    192  1.1  minoura #ifdef BOOT_DEBUG
    193  1.1  minoura 		devstr[5] = '1';
    194  1.1  minoura #endif
    195  1.1  minoura 	}
    196  1.1  minoura 
    197  1.1  minoura 	return ha;
    198  1.1  minoura }
    199  1.1  minoura 
    200  1.1  minoura static int
    201  1.1  minoura load_file(path, addr, header)
    202  1.1  minoura 	const char *path;
    203  1.1  minoura 	unsigned int addr;
    204  1.1  minoura 	struct exec *header;
    205  1.1  minoura {
    206  1.1  minoura 
    207  1.1  minoura 	return load_file_ino(ufs_lookup_path(path), path, addr, header);
    208  1.1  minoura }
    209  1.1  minoura 
    210  1.1  minoura static int
    211  1.1  minoura load_file_ino(ino, fn, addr, header)
    212  1.1  minoura 	ino_t ino;
    213  1.1  minoura 	const char *fn;		/* for message only */
    214  1.1  minoura 	unsigned int addr;
    215  1.1  minoura 	struct exec *header;
    216  1.1  minoura {
    217  1.1  minoura 	struct dinode dinode;
    218  1.1  minoura 
    219  1.1  minoura 	/* look-up the file */
    220  1.1  minoura 	if (ino == 0 || ufs_get_inode(ino, &dinode)) {
    221  1.1  minoura 		B_PRINT(fn);
    222  1.1  minoura 		B_PRINT(": not found\r\n");
    223  1.1  minoura 		return 0;
    224  1.1  minoura 	}
    225  1.1  minoura 
    226  1.1  minoura 	ufs_read(&dinode, (void *)addr, 0, sizeof(struct exec));
    227  1.1  minoura 	memcpy(header, (void *)addr, sizeof(struct exec));
    228  1.1  minoura 
    229  1.1  minoura 	if ((N_GETMAGIC(*header) != OMAGIC) ||
    230  1.1  minoura 	    (N_GETMID(*header) != MID_M68K)) {
    231  1.1  minoura 		B_PRINT(fn);
    232  1.1  minoura 		B_PRINT(": inappropriate format");
    233  1.1  minoura 		return 0;
    234  1.1  minoura 	}
    235  1.1  minoura 
    236  1.1  minoura 	/* read text and data */
    237  1.2  minoura 	ufs_read(&dinode, ((char *)addr)-sizeof(struct exec), 0,/* XXX */
    238  1.1  minoura 		 header->a_text+header->a_data);
    239  1.1  minoura 
    240  1.1  minoura 	/* clear out bss */
    241  1.1  minoura 	memset((char*) addr + header->a_text+header->a_data,
    242  1.1  minoura 	       0, header->a_bss);
    243  1.1  minoura 
    244  1.1  minoura 	/* PLANNED: fallback NMAGIC loader for the kernel. */
    245  1.1  minoura 
    246  1.1  minoura 	/* return the image size. */
    247  1.1  minoura 	return header->a_text+header->a_data+header->a_bss;
    248  1.1  minoura }
    249  1.1  minoura 
    250  1.1  minoura 
    251  1.1  minoura void
    252  1.1  minoura bootufs(void)
    253  1.1  minoura {
    254  1.1  minoura 	int bootdev;
    255  1.1  minoura #ifdef BOOT_DEBUG
    256  1.1  minoura 	int i;
    257  1.1  minoura 	char bootdevstr[16];
    258  1.1  minoura #endif
    259  1.1  minoura 	struct exec header;
    260  1.1  minoura 	int size;
    261  1.1  minoura 
    262  1.1  minoura #ifdef BOOT_DEBUG
    263  1.1  minoura 	/* for debug;  */
    264  1.1  minoura 	for (i = 0; i < 16; i++) {
    265  1.1  minoura 		print_hex(startregs[i], 8);
    266  1.1  minoura 		B_PRINT((i & 7) == 7 ? "\r\n" : " ");
    267  1.1  minoura 	}
    268  1.1  minoura #endif
    269  1.1  minoura 
    270  1.1  minoura 	/*
    271  1.1  minoura 	 * get boot device
    272  1.1  minoura 	 */
    273  1.1  minoura 	if (BINF_ISFD(&BOOT_INFO)) {
    274  1.1  minoura 		/* floppy */
    275  1.1  minoura #ifdef BOOT_DEBUG
    276  1.1  minoura 		*(int *)bootdevstr = ('f' << 24 | 'd' << 16 | '@' << 8 | '0') +
    277  1.1  minoura 					(BOOT_INFO & 3);
    278  1.1  minoura 		bootdevstr[4] = '\0';
    279  1.1  minoura #endif
    280  1.1  minoura 		bootdev = X68K_MAKEBOOTDEV(X68K_MAJOR_FD, BOOT_INFO & 3,
    281  1.1  minoura 				(FDSECMINMAX.minsec.N == 3) ? 0 : 2);
    282  1.1  minoura 	} else {
    283  1.1  minoura 		/* SCSI */
    284  1.1  minoura 		int part, ha;
    285  1.1  minoura 
    286  1.1  minoura #ifdef SCSI_ADHOC_BOOTPART
    287  1.1  minoura 		part = get_scsi_part();
    288  1.1  minoura #else
    289  1.1  minoura 		part = 0;			/* sd?a only */
    290  1.1  minoura #endif
    291  1.1  minoura #ifndef BOOT_DEBUG
    292  1.1  minoura 		ha = get_scsi_host_adapter();
    293  1.1  minoura #else
    294  1.1  minoura 		ha = get_scsi_host_adapter(bootdevstr);
    295  1.1  minoura 		bootdevstr[10] = '0' + (ID & 7);
    296  1.1  minoura 		bootdevstr[14] = 'a' + part;
    297  1.1  minoura #endif
    298  1.1  minoura 		bootdev = X68K_MAKESCSIBOOTDEV(X68K_MAJOR_SD, ha >> 4, ha & 15,
    299  1.1  minoura 						ID & 7, 0, part);
    300  1.1  minoura 	}
    301  1.1  minoura #ifdef BOOT_DEBUG
    302  1.1  minoura 	B_PRINT("boot device: ");
    303  1.1  minoura 	B_PRINT(bootdevstr);
    304  1.1  minoura #endif
    305  1.1  minoura 	B_PRINT("\r\n");
    306  1.1  minoura 
    307  1.1  minoura 	/* initialize filesystem code */
    308  1.1  minoura 	if (ufs_init()) {
    309  1.1  minoura 		BOOT_ERROR("bogus super block: "
    310  1.1  minoura 			   "");
    311  1.1  minoura 		/* NOTREACHED */
    312  1.1  minoura 	}
    313  1.1  minoura #if defined(BOOT_DEBUG) && defined(USE_FFS) && defined(USE_LFS)
    314  1.1  minoura 	B_PRINT("file system: ");
    315  1.1  minoura 	B_PUTC(ufs_info.fstype == UFSTYPE_FFS ?
    316  1.1  minoura 			(unsigned int) 'F' : (unsigned int) 'L');
    317  1.1  minoura 	B_PRINT("FS\r\n");
    318  1.1  minoura #endif
    319  1.1  minoura 
    320  1.1  minoura #ifdef BOOT_DEBUG
    321  1.1  minoura 	B_PRINT("\r\nlooking up secondary boot... ");
    322  1.1  minoura #endif
    323  1.1  minoura 
    324  1.1  minoura 	/*
    325  1.1  minoura 	 * Look for the 2nd stage boot.
    326  1.1  minoura 	 */
    327  1.1  minoura 
    328  1.1  minoura 	/* Try "boot" first */
    329  1.1  minoura 	size = load_file("boot", BOOT_TEXTADDR, &header);
    330  1.1  minoura #ifdef BOOT_DEBUG
    331  1.1  minoura 	B_PRINT("done.\r\n");
    332  1.1  minoura #endif
    333  1.1  minoura 	if (size > 0)
    334  1.1  minoura 		exec_image(BOOT_TEXTADDR, /* image loaded at */
    335  1.1  minoura 			   BOOT_TEXTADDR, /* image executed at */
    336  1.1  minoura 			   header.a_entry, /* entry point */
    337  1.1  minoura 			   size, /* image size */
    338  1.1  minoura 			   bootdev, RB_SINGLE); /* arguments */
    339  1.1  minoura 
    340  1.1  minoura 	B_PRINT("can't load the secondary bootstrap.;"
    341  1.1  minoura 		"trying /netbsd...\r\n");
    342  1.1  minoura 
    343  1.1  minoura 	/* fallback to /netbsd. */
    344  1.1  minoura 	/* always fails since NMAGIC loader is not yet implemented. */
    345  1.1  minoura 
    346  1.1  minoura 	size = load_file("netbsd", 0x6000, &header);
    347  1.1  minoura 	if (size > 0) {
    348  1.1  minoura 		if (*((short *)(0x6000 + header.a_entry - 2)) != 0) {
    349  1.1  minoura 			B_PRINT("boot interface of /netbsd is too new!\r\n");
    350  1.1  minoura 			goto fail;
    351  1.1  minoura 		}
    352  1.1  minoura 		exec_image(0x6000, /* image loaded at */
    353  1.1  minoura 			   0,	/* image executed at */
    354  1.1  minoura 			   header.a_entry, /* entry point */
    355  1.1  minoura 			   size, /* image size */
    356  1.1  minoura 			   bootdev, RB_SINGLE); /* arguments */
    357  1.1  minoura 		/* NOTREACHED */
    358  1.1  minoura 	}
    359  1.1  minoura 
    360  1.1  minoura  fail:
    361  1.1  minoura 	BOOT_ERROR("can't load the secondary bootstrap nor the kernel.");
    362  1.1  minoura 	/* NOTREACHED */
    363  1.1  minoura }
    364