1 /* $NetBSD: bootmain.c,v 1.6 2003/10/30 22:27:05 he 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 (ino_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 ino_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