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