1 /* $NetBSD: boot.c,v 1.16 2011/01/22 19:19:24 joerg 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(void *); 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 short *p; 108 int loadflag; 109 110 printf("Starting %s, flags 0x%x\n", file, flags); 111 112 loadflag = LOAD_KERNEL; 113 if (file[0] == 'f') 114 loadflag &= ~LOAD_BACKWARDS; 115 116 marks[MARK_START] = 0x100000; 117 if ((fd = loadfile(file, marks, loadflag)) == -1) { 118 printf("loadfile failed\n"); 119 return; 120 } 121 close(fd); 122 123 if (devparse(file, &dev, &unit, &part, &name) != 0) { 124 printf("XXX: unknown corruption in /boot.\n"); 125 } 126 127 printf("dev = %x, unit = %d, part = %c, name = %s\n", 128 dev, unit, part + 'a', name); 129 130 if (dev == 0) { /* SCSI */ 131 dev = X68K_MAKESCSIBOOTDEV(X68K_MAJOR_SD, 132 hostadaptor >> 4, 133 hostadaptor & 15, 134 unit & 7, 0, 0); 135 } else { 136 dev = X68K_MAKEBOOTDEV(X68K_MAJOR_FD, unit & 3, 0); 137 } 138 printf("boot device = %x\n", dev); 139 printf("if = %d, unit = %d, id = %d, lun = %d, part = %c\n", 140 B_X68K_SCSI_IF(dev), 141 B_X68K_SCSI_IF_UN(dev), 142 B_X68K_SCSI_ID(dev), 143 B_X68K_SCSI_LUN(dev), 144 B_X68K_SCSI_PART(dev) + 'a'); 145 146 p = ((short*) marks[MARK_ENTRY]) - 1; 147 printf("Kernel Version: 0x%x\n", *p); 148 if (*p != 0x4e73 && *p != 0) { 149 /* 150 * XXX temporary solution; compatibility loader 151 * must be written. 152 */ 153 printf("This kernel is too new to be loaded by " 154 "this version of /boot.\n"); 155 return; 156 } 157 158 exec_image(marks[MARK_START], 0, marks[MARK_ENTRY]-marks[MARK_START], 159 marks[MARK_END]-marks[MARK_START], dev, flags); 160 161 return; 162 } 163 164 static void 165 boot(char *arg) 166 { 167 char filename[80]; 168 char *p; 169 int flags = 0; 170 171 if (*arg == 0 || *arg == '-') { 172 strcpy(filename, default_kernel); 173 if (*arg == '-') 174 if (parseopts(arg, &flags) == 0) { 175 help(); 176 return; 177 } 178 doboot(filename, flags); 179 return; 180 } else { 181 p = gettrailer(arg); 182 if (strchr(arg, ':')) { 183 strcpy(filename, arg); 184 if (arg[strlen(arg) - 1] == ':') 185 strcat(filename, "netbsd"); 186 } else { 187 strcpy(filename, default_kernel); 188 strcpy(strchr(filename, ':') + 1, arg); 189 } 190 if (*p == '-') { 191 if (parseopts(p, &flags) == 0) 192 return; 193 } else if (*p != 0) { 194 help(); 195 return; 196 } 197 198 doboot(filename, flags); 199 return; 200 } 201 } 202 203 static void 204 ls(char *arg) 205 { 206 char filename[80]; 207 208 devopen_open_dir = 1; 209 if (*arg == 0) { 210 strcpy(filename, default_kernel); 211 strcpy(strchr(filename, ':')+1, "/"); 212 } else if (strchr(arg, ':') == 0) { 213 strcpy(filename, default_kernel); 214 strcpy(strchr(filename, ':')+1, arg); 215 } else { 216 strcpy(filename, arg); 217 if (*(strchr(arg, ':')+1) == 0) 218 strcat(filename, "/"); 219 } 220 ufs_ls(filename); 221 devopen_open_dir = 0; 222 } 223 224 int 225 bootmenu(void) 226 { 227 char input[80]; 228 int n = 5, c; 229 230 printf("Press return to boot now, any other key for boot menu\n"); 231 printf("booting %s - starting in %d seconds. ", 232 default_kernel, n); 233 while (n-- > 0 && (c = awaitkey_1sec()) == 0) { 234 printf("\r"); 235 printf("booting %s - starting in %d seconds. ", 236 default_kernel, n); 237 } 238 printf("\r"); 239 printf("booting %s - starting in %d seconds. ", default_kernel, 0); 240 printf("\n"); 241 242 if (c == 0 || c == '\r') { 243 doboot(default_kernel, 0); 244 printf("Could not start %s; ", default_kernel); 245 strcat(default_kernel, ".gz"); 246 printf("trying %s.\n", default_kernel); 247 doboot(default_kernel, 0); 248 printf("Could not start %s; ", default_kernel); 249 } 250 251 printf("Please use the absolute unit# (e.g. SCSI ID)" 252 " instead of the NetBSD logical #.\n"); 253 for (;;) { 254 char *p, *options; 255 256 printf("> "); 257 gets(input); 258 259 for (p = &input[0]; p - &input[0] < 80 && *p == ' '; p++); 260 options = gettrailer(p); 261 if (strcmp("boot", p) == 0) 262 boot(options); 263 else if (strcmp("help", p) == 0 || 264 strcmp("?", p) == 0) 265 help(); 266 else if ((strcmp("halt", p) == 0) ||(strcmp("reboot", p) == 0)) 267 exit(0); 268 else if (strcmp("ls", p) == 0) 269 ls(options); 270 else 271 printf("Unknown command %s\n", p); 272 } 273 } 274 275 276 extern const char bootprog_rev[]; 277 extern const char bootprog_name[]; 278 279 /* 280 * Arguments from the boot block: 281 * bootdev - specifies the device from which /boot was read, in 282 * bootdev format. 283 */ 284 void 285 bootmain(int bootdev) 286 { 287 hostadaptor = get_scsi_host_adapter(); 288 mpu = detectmpu(); 289 290 if (mpu < 3) { /* not tested on 68020 */ 291 printf("This MPU cannot run NetBSD.\n"); 292 exit(1); 293 } 294 if (SRAM_MEMSIZE < 4*1024*1024) { 295 printf("Main memory too small.\n"); 296 exit(1); 297 } 298 299 console_device = consio_init(console_device); 300 setheap(HEAP_START, HEAP_END); 301 302 switch (B_TYPE(bootdev)) { 303 case X68K_MAJOR_FD: 304 default_kernel[0] = 'f'; 305 default_kernel[2] = '0' + B_UNIT(bootdev); 306 default_kernel[3] = 'a'; 307 break; 308 case X68K_MAJOR_SD: 309 default_kernel[2] = '0' + B_X68K_SCSI_ID(bootdev); 310 default_kernel[3] = 311 'a' + sd_getbsdpartition(B_X68K_SCSI_ID(bootdev), 312 B_X68K_SCSI_PART(bootdev)); 313 break; 314 case X68K_MAJOR_CD: 315 default_kernel[0] = 'c'; 316 default_kernel[2] = '0' + B_X68K_SCSI_ID(bootdev); 317 default_kernel[3] = 'a'; 318 break; 319 default: 320 printf("Warning: unknown boot device: %x\n", bootdev); 321 } 322 print_title("%s, Revision %s\n", bootprog_name, bootprog_rev); 323 bootmenu(); 324 } 325