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