Home | History | Annotate | Line # | Download | only in xxboot
      1 /*	$NetBSD: bootmain.c,v 1.9 2024/01/07 07:58:34 isaki 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/types.h>
     38 #include <machine/bootinfo.h>
     39 #include <machine/disklabel.h>
     40 #include <lib/libsa/stand.h>
     41 #include <lib/libsa/loadfile.h>
     42 
     43 #include "xxboot.h"
     44 #include "libx68k.h"
     45 #include "iocs.h"
     46 #include "exec_image.h"
     47 
     48 #define EXSCSI_BDID	((void *)0x00ea0001)
     49 
     50 static int get_scsi_host_adapter(char *);
     51 int get_scsi_part(void);
     52 void bootmain(void) __attribute__ ((__noreturn__));
     53 
     54 #if defined(XXBOOT_DEBUG)
     55 /* Print 'x' as 'width' digit hex number */
     56 void
     57 print_hex(unsigned int x, int width)
     58 {
     59 
     60 	if (width > 0) {
     61 		print_hex(x >> 4, width - 1);
     62 		x &= 0x0F;
     63 		if (x > 9)
     64 			x += 7;
     65 		IOCS_B_PUTC((unsigned int) '0' + x);
     66 	}
     67 }
     68 #endif
     69 
     70 /*
     71  * Check the type of SCSI interface
     72  */
     73 static int
     74 get_scsi_host_adapter(char *devstr)
     75 {
     76 	uint8_t *bootrom;
     77 	int ha;
     78 
     79 #ifdef XXBOOT_DEBUG
     80 	*(uint32_t *)(devstr +  0) = '/' << 24 | 's' << 16 | 'p' << 8 | 'c';
     81 #if defined(CDBOOT)
     82 	*(uint32_t *)(devstr +  4) = '@' << 24 | '0' << 16 | '/' << 8 | 'c';
     83 #else
     84 	*(uint32_t *)(devstr +  4) = '@' << 24 | '0' << 16 | '/' << 8 | 's';
     85 #endif
     86 	*(uint32_t *)(devstr +  8) = 'd' << 24 | '@' << 16 | '0' << 8 | ',';
     87 	*(uint32_t *)(devstr + 12) = '0' << 24 | ':' << 16 | 'a' << 8 | '\0';
     88 #endif
     89 
     90 	bootrom = (uint8_t *)(BOOT_INFO & 0x00ffffe0);
     91 	/*
     92 	 * bootrom+0x24	"SCSIIN" ... Internal SCSI (spc@0)
     93 	 *		"SCSIEX" ... External SCSI (spc@1 or mha@0)
     94 	 */
     95 	if (*(uint16_t *)(bootrom + 0x24 + 4) == 0x494e) {	/* "IN" */
     96 		ha = (X68K_BOOT_SCSIIF_SPC << 4) | 0;
     97 	} else if (badbaddr(EXSCSI_BDID)) {
     98 		ha = (X68K_BOOT_SCSIIF_MHA << 4) | 0;
     99 #ifdef XXBOOT_DEBUG
    100 		*(uint32_t *)devstr =
    101 		    ('/' << 24) | ('m' << 16) | ('h' << 8) | 'a';
    102 #endif
    103 	} else {
    104 		ha = (X68K_BOOT_SCSIIF_SPC << 4) | 1;
    105 #ifdef XXBOOT_DEBUG
    106 		devstr[5] = '1';
    107 #endif
    108 	}
    109 
    110 	return ha;
    111 }
    112 
    113 #define PARTTBL_TOP	(4)	/* sector pos of part info in 512byte/sector */
    114 #define NPART		(15)	/* total number of Human68k partitions */
    115 #define MAXPART		(6)
    116 int
    117 get_scsi_part(void)
    118 {
    119 	union {
    120 		char pad[1024];
    121 		struct {
    122 			uint32_t magic;		/* 0x5836384b ("X68k") */
    123 			uint32_t parttotal;	/* total block# -1 */
    124 			uint32_t diskblocks;
    125 			uint32_t diskblocks2;	/* backup? */
    126 			struct dos_partition parttbl[NPART];
    127 		} __packed;
    128 	} partbuf;
    129 	int i;
    130 	int part_top;
    131 
    132 	/*
    133 	 * Read partition table.
    134 	 * The actual partition table size we want to read is 256 bytes but
    135 	 * raw_read() for SCSI requires bytelen a multiple of sector size
    136 	 * (SCSI_CAP.blocksize).  Human68k supports sector size only 256,
    137 	 * 512 and 1024 so that we always use 1024 bytes fixed length buffer.
    138 	 */
    139 	raw_read(PARTTBL_TOP, SCSI_CAP.blocksize, &partbuf);
    140 
    141 	if (partbuf.magic != 0x5836384b/*"X68k"*/) {
    142 		BOOT_ERROR("Bad Human68k partition table");
    143 		/* NOTREACHED */
    144 	}
    145 
    146 	/*
    147 	 * SCSI_PARTTOP is top sector # of this partition in sector size
    148 	 * of this device (normally 512 bytes/sector).
    149 	 * part_top is top block # of this partition in 1024 bytes/block.
    150 	 * Human68k partition table uses 1024 bytes/block unit.
    151 	 */
    152 	part_top = SCSI_PARTTOP >> (2 - SCSI_BLKLEN);
    153 	for (i = 0; i < MAXPART; i++) {
    154 		if ((uint32_t)partbuf.parttbl[i].dp_start == part_top)
    155 			goto found;
    156 	}
    157 	BOOT_ERROR("Can't find this partition?");
    158 	/* NOTREACHED */
    159 found:
    160 	/* bsd disklabel's c: means whole disk.  Skip it */
    161 	if (i >= 2)
    162 		i++;
    163 	return i;
    164 }
    165 
    166 void
    167 bootmain(void)
    168 {
    169 	int bootdev, fd;
    170 	char bootdevstr[16];
    171 	u_long marks[MARK_MAX];
    172 
    173 	IOCS_B_PRINT(bootprog_name);
    174 	IOCS_B_PRINT(" rev.");
    175 	IOCS_B_PRINT(bootprog_rev);
    176 	IOCS_B_PRINT("\r\n");
    177 
    178 #if defined(XXBOOT_DEBUG)
    179 	/* Print the initial registers */
    180 	int i;
    181 	for (i = 0; i < __arraycount(startregs); i++) {
    182 		print_hex(startregs[i], 8);
    183 		IOCS_B_PRINT((i & 7) == 7 ? "\r\n" : " ");
    184 	}
    185 	IOCS_B_PRINT("BOOT_INFO ");
    186 	print_hex(BOOT_INFO, 8);
    187 	IOCS_B_PRINT("\r\n");
    188 #endif
    189 
    190 	if (BINF_ISFD(&BOOT_INFO)) {
    191 		/* floppy */
    192 		int minor;
    193 		/* fdNa for 1024 bytes/sector, fdNc for 512 bytes/sector */
    194 		minor = (FDSEC.minsec.N == 3) ? 0 : 2;
    195 		bootdev = X68K_MAKEBOOTDEV(X68K_MAJOR_FD, BOOT_INFO & 3, minor);
    196 #ifdef XXBOOT_DEBUG
    197 		*(uint32_t *)bootdevstr =
    198 		    ('f' << 24) | ('d' << 16) | ('@' << 8) |
    199 		    ('0' + (BOOT_INFO & 3));
    200 		bootdevstr[4] = 'a' + minor;
    201 		bootdevstr[5] = '\0';
    202 #endif
    203 	} else {
    204 		/* SCSI */
    205 		int major, ha, part;
    206 		ha = get_scsi_host_adapter(bootdevstr);
    207 		part = 0;
    208 #if defined(CDBOOT)
    209 		major = X68K_MAJOR_CD;
    210 #else
    211 		major = X68K_MAJOR_SD;
    212 		if (SCSI_PARTTOP != 0)
    213 			part = get_scsi_part();
    214 #endif
    215 		bootdev = X68K_MAKESCSIBOOTDEV(major, ha >> 4, ha & 15,
    216 		    SCSI_ID & 7, 0, part);
    217 #ifdef XXBOOT_DEBUG
    218 		bootdevstr[10] = '0' + (SCSI_ID & 7);
    219 		bootdevstr[14] = 'a' + part;
    220 #endif
    221 	}
    222 
    223 #ifdef XXBOOT_DEBUG
    224 	IOCS_B_PRINT("boot device: ");
    225 	IOCS_B_PRINT(bootdevstr);
    226 #endif
    227 	IOCS_B_PRINT("\r\n");
    228 
    229 	marks[MARK_START] = BOOT_TEXTADDR;
    230 
    231 #if defined(XXBOOT_USTARFS)
    232 	/* ustarfs requires mangled filename... */
    233 	fd = loadfile("USTAR.volsize.4540", marks,
    234 	    LOAD_TEXT|LOAD_DATA|LOAD_BSS);
    235 #else
    236 	/* XXX what is x68k/boot? */
    237 	fd = loadfile("x68k/boot", marks, LOAD_TEXT|LOAD_DATA|LOAD_BSS);
    238 	if (fd < 0)
    239 		fd = loadfile("boot", marks, LOAD_TEXT|LOAD_DATA|LOAD_BSS);
    240 #endif
    241 	if (fd >= 0) {
    242 		close(fd);
    243 		exec_image(BOOT_TEXTADDR, /* image loaded at */
    244 			   BOOT_TEXTADDR, /* image executed at */
    245 			   BOOT_TEXTADDR, /* XXX: entry point */
    246 			   0,		  /* XXX: image size */
    247 			   bootdev, 0);   /* arguments */
    248 	}
    249 	IOCS_B_PRINT("can't load the secondary bootstrap.");
    250 	exit(0);
    251 }
    252 
    253 int
    254 devopen(struct open_file *f, const char *fname, char **file)
    255 {
    256 
    257 	*file = __UNCONST(fname);
    258 	return DEV_OPEN()(f);
    259 }
    260