Home | History | Annotate | Line # | Download | only in boot_ufs
bootmain.c revision 1.6.16.1
      1 /*	$NetBSD: bootmain.c,v 1.6.16.1 2006/06/21 14:57:55 yamt 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 #include <lib/libsa/stand.h>
     48 
     49 #include "boot_ufs.h"
     50 #include "readufs.h"
     51 #include "exec_image.h"
     52 #include "../../x68k/iodevice.h"
     53 #define IODEVbase ((volatile struct IODEVICE *)PHYS_IODEV)
     54 
     55 /* for debug;  */
     56 unsigned int startregs[16];
     57 
     58 #ifdef SCSI_ADHOC_BOOTPART
     59 static int get_scsi_part (void);
     60 #endif
     61 #ifdef BOOT_DEBUG
     62 static int get_scsi_host_adapter (char *);
     63 #else
     64 static int get_scsi_host_adapter (void);
     65 #endif
     66 
     67 #ifdef BOOT_DEBUG
     68 void print_hex (unsigned int, int);
     69 #endif
     70 
     71 static int load_file (const char*, unsigned int, struct exec *);
     72 static int load_file_ino (ino32_t, const char*, unsigned int, struct exec *);
     73 
     74 void bootufs (void) __attribute__ ((__noreturn__));
     75 
     76 #ifdef BOOT_DEBUG
     77 void
     78 print_hex(x, l)
     79 	unsigned int x;	/*  */
     80 	int l;		/*  */
     81 {
     82 
     83 	if (l > 0) {
     84 		print_hex(x >> 4, l - 1);
     85 		x &= 0x0F;
     86 		if (x > 9)
     87 			x += 7;
     88 		B_PUTC((unsigned int) '0' + x);
     89 	}
     90 }
     91 #endif
     92 
     93 #ifdef SCSI_ADHOC_BOOTPART
     94 /*
     95  * get partition # from partition start position
     96  */
     97 
     98 #define NPART		15
     99 #define PARTTBL_TOP	((unsigned)4)	/* pos of part inf in 512byte-blocks */
    100 #define MAXPART		6
    101 const unsigned char partition_conv[MAXPART + 1] = { 0, 1, 3, 4, 5, 6, 7 };
    102 
    103 static int
    104 get_scsi_part()
    105 {
    106 	struct {
    107 		u_int32_t	magic;		/* 0x5836384B ("X68K") */
    108 		u_int32_t	parttotal;
    109 		u_int32_t	diskblocks;
    110 		u_int32_t	diskblocks2;	/* backup? */
    111 		struct dos_partition parttbl[NPART];
    112 		unsigned char	formatstr[256];
    113 		unsigned char	rest[512];
    114 	} partbuf;
    115 	int i;
    116 	u_int32_t part_top;
    117 
    118 #ifdef BOOT_DEBUG
    119 	B_PRINT("seclen: ");
    120 	print_hex(SCSI_BLKLEN, 8);	/* 0: 256, 1: 512, 2: 1024 */
    121 	B_PRINT(", topsec: ");
    122 	print_hex(SCSI_PARTTOP, 8);	/* partition top in sector */
    123 #endif
    124 	/*
    125 	 * read partition table
    126 	 */
    127 	RAW_READ0(&partbuf, PARTTBL_TOP, sizeof partbuf);
    128 
    129 	part_top = SCSI_PARTTOP >> (2 - SCSI_BLKLEN);
    130 	for (i = 0; i < MAXPART; i++)
    131 		if ((u_int32_t) partbuf.parttbl[i].dp_start == part_top)
    132 			goto found;
    133 
    134 	BOOT_ERROR("Can't boot from this partition");
    135 	/* NOTREACHED */
    136 found:
    137 #ifdef BOOT_DEBUG
    138 	B_PRINT("; sd");
    139 	B_PUTC(ID + '0');	/* SCSI ID (not NetBSD unit #) */
    140 	B_PUTC((unsigned int) partition_conv[i] + 'a');
    141 	B_PRINT("\r\n");
    142 #endif
    143 	return partition_conv[i];
    144 }
    145 #endif	/* SCSI_ADHOC_BOOTPART */
    146 
    147 /*
    148  * Check the type of SCSI interface
    149  */
    150 #ifdef BOOT_DEBUG
    151 static int
    152 get_scsi_host_adapter(devstr)
    153 	char *devstr;
    154 #else
    155 static int
    156 get_scsi_host_adapter(void)
    157 #endif
    158 {
    159 	char *bootrom;
    160 	int ha;
    161 
    162 #ifdef BOOT_DEBUG
    163 	B_PRINT(" at ");
    164 	*(int *)devstr = '/' << 24 | 's' << 16 | 'p' << 8 | 'c';
    165 	*(int *)(devstr + 4) = '@' << 24 | '0' << 16 | '/' << 8 | 's';
    166 	*(int *)(devstr + 8) = 'd' << 24 | '@' << 16 | '0' << 8 | ',';
    167 	*(int *)(devstr + 12) = '0' << 24 | ':' << 16 | 'a' << 8 | '\0';
    168 #endif
    169 
    170 	bootrom = (char *) (BOOT_INFO & 0x00ffffe0);
    171 	/*
    172 	 * bootrom+0x24	"SCSIIN" ... Internal SCSI (spc@0)
    173 	 *		"SCSIEX" ... External SCSI (spc@1 or mha@0)
    174 	 */
    175 	if (*(u_short *)(bootrom + 0x24 + 4) == 0x494e) {	/* "IN" */
    176 #ifdef BOOT_DEBUG
    177 		B_PRINT("spc0");
    178 #endif
    179 		ha = (X68K_BOOT_SCSIIF_SPC << 4) | 0;
    180 	} else if (badbaddr(&IODEVbase->io_exspc.bdid)) {
    181 #ifdef BOOT_DEBUG
    182 		B_PRINT("mha0");
    183 #endif
    184 		ha = (X68K_BOOT_SCSIIF_MHA << 4) | 0;
    185 #ifdef BOOT_DEBUG
    186 		*(int *)devstr = '/' << 24 | 'm' << 16 | 'h' << 8 | 'a';
    187 #endif
    188 	} else {
    189 #ifdef BOOT_DEBUG
    190 		B_PRINT("spc1");
    191 #endif
    192 		ha = (X68K_BOOT_SCSIIF_SPC << 4) | 1;
    193 #ifdef BOOT_DEBUG
    194 		devstr[5] = '1';
    195 #endif
    196 	}
    197 
    198 	return ha;
    199 }
    200 
    201 static int
    202 load_file(path, addr, header)
    203 	const char *path;
    204 	unsigned int addr;
    205 	struct exec *header;
    206 {
    207 
    208 	return load_file_ino(ufs_lookup_path(path), path, addr, header);
    209 }
    210 
    211 static int
    212 load_file_ino(ino, fn, addr, header)
    213 	ino32_t ino;
    214 	const char *fn;		/* for message only */
    215 	unsigned int addr;
    216 	struct exec *header;
    217 {
    218 	union ufs_dinode dinode;
    219 
    220 	/* look-up the file */
    221 	if (ino == 0 || ufs_get_inode(ino, &dinode)) {
    222 		B_PRINT(fn);
    223 		B_PRINT(": not found\r\n");
    224 		return 0;
    225 	}
    226 
    227 	ufs_read(&dinode, (void *)addr, 0, sizeof(struct exec));
    228 	memcpy(header, (void *)addr, sizeof(struct exec));
    229 
    230 	if ((N_GETMAGIC(*header) != OMAGIC) ||
    231 	    (N_GETMID(*header) != MID_M68K)) {
    232 		B_PRINT(fn);
    233 		B_PRINT(": inappropriate format");
    234 		return 0;
    235 	}
    236 
    237 	/* read text and data */
    238 	ufs_read(&dinode, ((char *)addr)-sizeof(struct exec), 0,/* XXX */
    239 		 header->a_text+header->a_data);
    240 
    241 	/* clear out bss */
    242 	memset((char*) addr + header->a_text+header->a_data,
    243 	       0, header->a_bss);
    244 
    245 	/* PLANNED: fallback NMAGIC loader for the kernel. */
    246 
    247 	/* return the image size. */
    248 	return header->a_text+header->a_data+header->a_bss;
    249 }
    250 
    251 
    252 void
    253 bootufs(void)
    254 {
    255 	int bootdev;
    256 #ifdef BOOT_DEBUG
    257 	int i;
    258 	char bootdevstr[16];
    259 #endif
    260 	struct exec header;
    261 	int size;
    262 	extern const char bootprog_name[], bootprog_rev[];
    263 
    264 #ifdef BOOT_DEBUG
    265 	/* for debug;  */
    266 	for (i = 0; i < 16; i++) {
    267 		print_hex(startregs[i], 8);
    268 		B_PRINT((i & 7) == 7 ? "\r\n" : " ");
    269 	}
    270 #endif
    271 
    272 	B_PRINT(bootprog_name);
    273 	B_PRINT(" rev.");	B_PRINT(bootprog_rev);
    274 	B_PRINT("\r\n");
    275 
    276 	/*
    277 	 * get boot device
    278 	 */
    279 	if (BINF_ISFD(&BOOT_INFO)) {
    280 		/* floppy */
    281 #ifdef BOOT_DEBUG
    282 		*(int *)bootdevstr = ('f' << 24 | 'd' << 16 | '@' << 8 | '0') +
    283 					(BOOT_INFO & 3);
    284 		bootdevstr[4] = '\0';
    285 #endif
    286 		bootdev = X68K_MAKEBOOTDEV(X68K_MAJOR_FD, BOOT_INFO & 3,
    287 				(FDSECMINMAX.minsec.N == 3) ? 0 : 2);
    288 	} else {
    289 		/* SCSI */
    290 		int part, ha;
    291 
    292 #ifdef SCSI_ADHOC_BOOTPART
    293 		if (SCSI_PARTTOP == 0)
    294 			part = 0;
    295 		else
    296 			part = get_scsi_part();
    297 #else
    298 		part = 0;			/* sd?a only */
    299 #endif
    300 #ifndef BOOT_DEBUG
    301 		ha = get_scsi_host_adapter();
    302 #else
    303 		ha = get_scsi_host_adapter(bootdevstr);
    304 		bootdevstr[10] = '0' + (ID & 7);
    305 		bootdevstr[14] = 'a' + part;
    306 #endif
    307 		bootdev = X68K_MAKESCSIBOOTDEV(X68K_MAJOR_SD, ha >> 4, ha & 15,
    308 						ID & 7, 0, part);
    309 	}
    310 #ifdef BOOT_DEBUG
    311 	B_PRINT("boot device: ");
    312 	B_PRINT(bootdevstr);
    313 #endif
    314 	B_PRINT("\r\n");
    315 
    316 	/* initialize filesystem code */
    317 	if (ufs_init()) {
    318 		BOOT_ERROR("bogus super block: "
    319 			   "");
    320 		/* NOTREACHED */
    321 	}
    322 #if defined(BOOT_DEBUG) && defined(USE_FFS) && defined(USE_LFS)
    323 	B_PRINT("file system: ");
    324 	B_PUTC(ufs_info.fstype == UFSTYPE_FFS ?
    325 			(unsigned int) 'F' : (unsigned int) 'L');
    326 	B_PRINT("FS\r\n");
    327 #endif
    328 
    329 #ifdef BOOT_DEBUG
    330 	B_PRINT("\r\nlooking up secondary boot... ");
    331 #endif
    332 
    333 	/*
    334 	 * Look for the 2nd stage boot.
    335 	 */
    336 
    337 	/* Try "boot" first */
    338 	size = load_file("boot", BOOT_TEXTADDR, &header);
    339 #ifdef BOOT_DEBUG
    340 	B_PRINT("done.\r\n");
    341 #endif
    342 	if (size > 0)
    343 		exec_image(BOOT_TEXTADDR, /* image loaded at */
    344 			   BOOT_TEXTADDR, /* image executed at */
    345 			   header.a_entry, /* entry point */
    346 			   size, /* image size */
    347 			   bootdev, RB_SINGLE); /* arguments */
    348 
    349 	B_PRINT("can't load the secondary bootstrap.;"
    350 		"trying /netbsd...\r\n");
    351 
    352 	/* fallback to /netbsd. */
    353 	/* always fails since NMAGIC loader is not yet implemented. */
    354 
    355 	size = load_file("netbsd", 0x6000, &header);
    356 	if (size > 0) {
    357 		if (*((short *)(0x6000 + header.a_entry - 2)) != 0) {
    358 			B_PRINT("boot interface of /netbsd is too new!\r\n");
    359 			goto fail;
    360 		}
    361 		exec_image(0x6000, /* image loaded at */
    362 			   0,	/* image executed at */
    363 			   header.a_entry, /* entry point */
    364 			   size, /* image size */
    365 			   bootdev, RB_SINGLE); /* arguments */
    366 		/* NOTREACHED */
    367 	}
    368 
    369  fail:
    370 	BOOT_ERROR("can't load the secondary bootstrap nor the kernel.");
    371 	/* NOTREACHED */
    372 }
    373