1 /* $NetBSD: boot.c,v 1.8 2001/12/02 14:25:44 minoura Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Minoura Makoto 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 #include <machine/bootinfo.h> 31 32 #include <lib/libsa/stand.h> 33 #include <lib/libsa/loadfile.h> 34 #include <lib/libsa/ufs.h> 35 #include <lib/libkern/libkern.h> 36 37 #include "libx68k.h" 38 #include "iocs.h" 39 40 #include "exec_image.h" 41 42 43 #define HEAP_START ((void*) 0x00080000) 44 #define HEAP_END ((void*) 0x000fffff) 45 #define EXSCSI_BDID ((void*) 0x00ea0001) 46 #define SRAM_MEMSIZE (*((long*) 0x00ed0008)) 47 48 char default_kernel[20] = "sd0a:netbsd"; 49 int mpu, hostadaptor; 50 int console_device = -1; 51 52 static void help(void); 53 static int get_scsi_host_adapter(void); 54 static void doboot(const char *, int); 55 static void boot(char *); 56 static void ls(char *); 57 int bootmenu(void); 58 void bootmain(int); 59 extern int detectmpu(void); 60 extern int badbaddr(caddr_t); 61 62 /* from boot_ufs/bootmain.c */ 63 static int 64 get_scsi_host_adapter(void) 65 { 66 char *bootrom; 67 int ha; 68 69 bootrom = (char *) (IOCS_BOOTINF() & 0x00ffffe0); 70 /* 71 * bootrom+0x24 "SCSIIN" ... Internal SCSI (spc@0) 72 * "SCSIEX" ... External SCSI (spc@1 or mha@0) 73 */ 74 if (*(u_short *)(bootrom + 0x24 + 4) == 0x494e) { /* "IN" */ 75 ha = (X68K_BOOT_SCSIIF_SPC << 4) | 0; 76 } else if (badbaddr(EXSCSI_BDID)) { 77 ha = (X68K_BOOT_SCSIIF_MHA << 4) | 0; 78 } else { 79 ha = (X68K_BOOT_SCSIIF_SPC << 4) | 1; 80 } 81 82 return ha; 83 } 84 85 86 static void 87 help(void) 88 { 89 printf("Usage:\n"); 90 printf("boot [dev:][file] -[flags]\n"); 91 printf(" dev: sd<ID><PART>, ID=0-7, PART=a-p\n"); 92 printf(" cd<ID>a, ID=0-7\n"); 93 printf(" fd<UNIT>a, UNIT=0-3, format is detected.\n"); 94 printf(" file: netbsd, netbsd.gz, etc.\n"); 95 printf(" flags: abdqsv\n"); 96 printf("ls [dev:][directory]\n"); 97 printf("halt\nreboot\n"); 98 } 99 100 static void 101 doboot(const char *file, int flags) 102 { 103 u_long marks[MARK_MAX]; 104 int fd; 105 int dev, unit, part; 106 char *name; 107 108 printf("Starting %s, flags 0x%x\n", file, flags); 109 marks[MARK_START] = 0x100000; 110 if ((fd = loadfile(file, marks, LOAD_KERNEL)) == -1) 111 return; 112 close(fd); 113 114 if (devparse(file, &dev, &unit, &part, &name) != 0) { 115 printf("XXX: unknown corruption in /boot.\n"); 116 } 117 118 printf("dev = %x, unit = %d, part = %c, name = %s\n", 119 dev, unit, part + 'a', name); 120 121 if (dev == 0) { /* SCSI */ 122 dev = X68K_MAKESCSIBOOTDEV(X68K_MAJOR_SD, 123 hostadaptor >> 4, 124 hostadaptor & 15, 125 unit & 7, 0, 0); 126 } else { 127 dev = X68K_MAKEBOOTDEV(X68K_MAJOR_FD, unit & 3, 0); 128 } 129 printf("boot device = %x\n", dev); 130 printf("if = %d, unit = %d, id = %d, lun = %d, part = %c\n", 131 B_X68K_SCSI_IF(dev), 132 B_X68K_SCSI_IF_UN(dev), 133 B_X68K_SCSI_ID(dev), 134 B_X68K_SCSI_LUN(dev), 135 B_X68K_SCSI_PART(dev) + 'a'); 136 137 { 138 short *p = ((short*) marks[MARK_ENTRY]) - 1; 139 printf("Kernel Version: 0x%x\n", *p); 140 if (*p != 0x4e73 && *p != 0) { 141 /* 142 * XXX temporary solution; compatibility loader 143 * must be written. 144 */ 145 printf("This kernel is too new to be loaded by " 146 "this version of /boot.\n"); 147 return; 148 } 149 } 150 151 exec_image(marks[MARK_START], 0, marks[MARK_ENTRY]-marks[MARK_START], 152 marks[MARK_END]-marks[MARK_START], dev, flags); 153 154 return; 155 } 156 157 static void 158 boot(char *arg) 159 { 160 char filename[80]; 161 char *p; 162 int flags = 0; 163 164 if (*arg == 0 || *arg == '-') { 165 strcpy(filename, default_kernel); 166 if (*arg == '-') 167 if (parseopts(arg, &flags) == 0) { 168 help(); 169 return; 170 } 171 doboot(filename, flags); 172 return; 173 } else { 174 p = gettrailer(arg); 175 if (strchr(arg, ':')) { 176 strcpy(filename, arg); 177 if (arg[strlen(arg) - 1] == ':') 178 strcat(filename, "netbsd"); 179 } else { 180 strcpy(filename, default_kernel); 181 strcpy(strchr(filename, ':') + 1, arg); 182 } 183 if (*p == '-') { 184 if (parseopts(p, &flags) == 0) 185 return; 186 } else if (*p != 0) { 187 help(); 188 return; 189 } 190 191 doboot(filename, flags); 192 return; 193 } 194 } 195 196 static void 197 ls(char *arg) 198 { 199 char filename[80]; 200 201 devopen_open_dir = 1; 202 if (*arg == 0) { 203 strcpy(filename, default_kernel); 204 strcpy(strchr(filename, ':')+1, "/"); 205 } else if (strchr(arg, ':') == 0) { 206 strcpy(filename, default_kernel); 207 strcpy(strchr(filename, ':')+1, arg); 208 } else { 209 strcpy(filename, arg); 210 if (*(strchr(arg, ':')+1) == 0) 211 strcat(filename, "/"); 212 } 213 ufs_ls(filename); 214 devopen_open_dir = 0; 215 } 216 217 int 218 bootmenu(void) 219 { 220 char input[80]; 221 int n = 5, c; 222 223 printf("Press return to boot now, any other key for boot menu\n"); 224 printf("booting %s - starting in %d seconds. ", 225 default_kernel, n); 226 while (n-- > 0 && (c = awaitkey_1sec()) == 0) { 227 printf("\r"); 228 printf("booting %s - starting in %d seconds. ", 229 default_kernel, n); 230 } 231 printf("\r"); 232 printf("booting %s - starting in %d seconds. ", default_kernel, 0); 233 printf("\n"); 234 235 if (c == 0 || c == '\r') { 236 doboot(default_kernel, 0); 237 printf("Could not start %s; ", default_kernel); 238 strcat(default_kernel, ".gz"); 239 printf("trying %s.\n", default_kernel); 240 doboot(default_kernel, 0); 241 printf("Could not start %s; ", default_kernel); 242 } 243 244 printf("Please use the absolute unit# (e.g. SCSI ID)" 245 " instead of the NetBSD logical #.\n"); 246 for (;;) { 247 char *p, *options; 248 249 printf("> "); 250 gets(input); 251 252 for (p = &input[0]; p - &input[0] < 80 && *p == ' '; p++); 253 options = gettrailer(p); 254 if (strcmp("boot", p) == 0) 255 boot(options); 256 else if (strcmp("help", p) == 0 || 257 strcmp("?", p) == 0) 258 help(); 259 else if ((strcmp("halt", p) == 0) ||(strcmp("reboot", p) == 0)) 260 exit(0); 261 else if (strcmp("ls", p) == 0) 262 ls(options); 263 else 264 printf("Unknown command %s\n", p); 265 } 266 } 267 268 269 extern const char bootprog_rev[]; 270 extern const char bootprog_name[]; 271 extern const char bootprog_date[]; 272 extern const char bootprog_maker[]; 273 274 /* 275 * Arguments from the boot block: 276 * bootdev - specifies the device from which /boot was read, in 277 * bootdev format. 278 */ 279 void 280 bootmain(int bootdev) 281 { 282 hostadaptor = get_scsi_host_adapter(); 283 mpu = detectmpu(); 284 285 if (mpu < 3) { /* not tested on 68020 */ 286 printf("This MPU cannot run NetBSD.\n"); 287 exit(1); 288 } 289 if (SRAM_MEMSIZE < 4*1024*1024) { 290 printf("Main memory too small.\n"); 291 exit(1); 292 } 293 294 console_device = consio_init(console_device); 295 setheap(HEAP_START, HEAP_END); 296 297 switch (B_TYPE(bootdev)) { 298 case X68K_MAJOR_FD: 299 default_kernel[0] = 'f'; 300 default_kernel[2] = '0' + B_UNIT(bootdev); 301 default_kernel[3] = 'a'; 302 break; 303 case X68K_MAJOR_SD: 304 default_kernel[2] = '0' + B_X68K_SCSI_ID(bootdev); 305 default_kernel[3] = 306 'a' + sd_getbsdpartition(B_X68K_SCSI_ID(bootdev), 307 B_X68K_SCSI_PART(bootdev)); 308 break; 309 case X68K_MAJOR_CD: 310 default_kernel[0] = 'c'; 311 default_kernel[2] = '0' + B_X68K_SCSI_ID(bootdev); 312 default_kernel[3] = 'a'; 313 break; 314 default: 315 printf("Warning: unknown boot device: %x\n", bootdev); 316 } 317 print_title("%s, Revision %s\n\t(%s, %s)", 318 bootprog_name, bootprog_rev, 319 bootprog_maker, bootprog_date); 320 bootmenu(); 321 } 322