1 /* $NetBSD: boot.c,v 1.7 2008/07/16 14:45:17 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (c) 2004 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <lib/libsa/stand.h> 33 #include <lib/libkern/libkern.h> 34 35 #include "local.h" 36 #include "cmd.h" 37 #include "common.h" 38 39 #include <machine/sbd.h> 40 #include <machine/pdinfo.h> 41 #include <machine/vtoc.h> 42 43 #include "console.h" 44 45 46 extern const char bootprog_name[]; 47 extern const char bootprog_rev[]; 48 extern const char bootprog_kernrev[]; 49 50 struct cmd_batch_tab cmd_batch_tab[] = { 51 /* func argc argp... */ 52 #if 0 53 { cmd_boot, 1, { "mem:", 0, 0, 0, 0, 0, 0 } }, 54 { cmd_boot, 1, { "sd0k:netbsd", 0, 0, 0, 0, 0, 0 } }, 55 { cmd_load_binary, 1, { "0x80001000", 0, 0, 0, 0, 0, 0 } }, 56 { cmd_jump, 2, { "0x80001000", "0x80001000", 0, 0, 0, 0, 0 } }, 57 #endif 58 { NULL, 0, { 0, 0, 0, 0, 0, 0, 0 } } /* terminate */ 59 }; 60 61 struct ipl_args ipl_args; 62 struct device_capability DEVICE_CAPABILITY; 63 void set_device_capability(void); 64 bool guess_boot_kernel(char *, size_t, int); 65 extern int kernel_binary_size; 66 67 void 68 main(int a0, int v0, int v1) 69 { 70 extern char edata[], end[]; 71 char boot_kernel[32]; 72 char *args[CMDARG_MAX]; 73 int i; 74 75 memset(edata, 0, end - edata); 76 /* Save args for chain-boot to iopboot */ 77 ipl_args.a0 = a0; 78 ipl_args.v0 = v0; 79 ipl_args.v1 = v1; 80 81 console_init(); 82 83 printf("\n"); 84 printf("%s boot, Revision %s (from NetBSD %s)\n", 85 bootprog_name, bootprog_rev, bootprog_kernrev); 86 87 88 /* Inquire IPL activated device */ 89 set_device_capability(); 90 91 if (!guess_boot_kernel(boot_kernel, sizeof boot_kernel, 0)) 92 goto prompt; 93 printf( 94 ">> Press return to boot now, any other key for boot console.\n"); 95 96 for (i = 5000; i >= 0; i--) { 97 int c; 98 if (i % 1000 == 0) 99 printf("booting %s - starting %d\r", 100 boot_kernel, i / 1000); 101 if ((c = cnscan()) == -1) { 102 delay(10); 103 continue; 104 } 105 else if (c == '\r') 106 break; 107 else 108 goto prompt; 109 } 110 printf("\n[non-interactive mode]\n"); 111 args[0] = "boot"; 112 args[1] = boot_kernel; 113 cmd_boot(2, args, false); 114 prompt: 115 116 printf("\ntype \"help\" for help.\n"); 117 console_cursor(true); 118 prompt(); 119 /* NOTREACHED */ 120 } 121 122 bool 123 guess_boot_kernel(char *name, size_t len, int pri) 124 { 125 extern struct vtoc_sector vtoc; 126 struct ux_partition *partition; 127 int i, unit; 128 129 if (!DEVICE_CAPABILITY.active) 130 return false; 131 132 unit = DEVICE_CAPABILITY.booted_unit; 133 134 switch (DEVICE_CAPABILITY.booted_device) { 135 default: 136 return false; 137 case NVSRAM_BOOTDEV_FLOPPYDISK: 138 strncpy(name, "fd:netbsd", len); /* ustarfs */ 139 return true; 140 141 case NVSRAM_BOOTDEV_HARDDISK: 142 snprintf(name, len, "sd%d:netbsd", unit); /* ustarfs */ 143 if (!read_vtoc()) 144 return true; 145 146 partition = vtoc.partition; 147 for (i = 0; i < VTOC_MAXPARTITIONS; i++, partition++) { 148 if (partition->tag != __VTOC_TAG_BSDFFS) 149 continue; 150 /* ffs */ 151 snprintf(name, len, "sd%d%c:netbsd", unit, 'a' + i); 152 return true; 153 } 154 return true; 155 156 case NVSRAM_BOOTDEV_CGMT: 157 break; 158 case NVSRAM_BOOTDEV_NETWORK: 159 /*FALLTHROUGH*/ 160 case NVSRAM_BOOTDEV_NETWORK_T_AND_D: 161 if (kernel_binary_size) { 162 strncpy(name, "mem:", len); /* datafs */ 163 return true; 164 } 165 if (DEVICE_CAPABILITY.network_enabled) { 166 strncpy(name, "nfs:netbsd", len); /* nfs */ 167 return true; 168 } 169 break; 170 } 171 172 return false; 173 } 174 175 int 176 cmd_info(int argc, char *argp[], int interactive) 177 { 178 extern char _ftext[], _etext[], _fdata[], _edata[]; 179 extern char _fbss[], end[]; 180 uint32_t m; 181 int i, size, total; 182 struct sbdinfo *sbd = SBD_INFO; 183 184 printf("\n>> %s boot, Revision %s (from NetBSD %s) <<\n", 185 bootprog_name, bootprog_rev, bootprog_kernrev); 186 187 printf("IPL args: 0x%x 0x%x 0x%x\n", ipl_args.a0, ipl_args.v0, 188 ipl_args.v1); 189 printf("\ttext : %p-%p\n\tdata : %p-%p\n\t" 190 "bss : %p-%p\n\tstack: %p\n\theap : %p\n", 191 _ftext, _etext, _fdata, _edata, 192 _fbss, end, _ftext, end); 193 194 m = ipl_args.v1; 195 total = 0; 196 printf("Memory Area:\n\t"); 197 for (i = 0; i < 8; i++, m >>= 4) { 198 size = m & 0xf ? ((m & 0xf) << 4) : 0; 199 total += size; 200 if (size) 201 printf("M%d=%dMB ", i, size); 202 } 203 printf(" total %dMB\n", total); 204 205 printf("Board Revision:\n"); 206 printf("\tmachine=0x%x, ", sbd->machine); 207 printf("model=0x%x\n", sbd->model); 208 printf("\tpmmu=%d, ", sbd->mmu); 209 printf("cache=%d, ", sbd->cache); 210 printf("panel=%d, ", sbd->panel); 211 printf("fdd=%d\n", sbd->fdd); 212 printf("\tcpu=%d, fpp=%d, fpa=%d, iop=%d\n", 213 sbd->cpu, sbd->fpp, sbd->fpa, sbd->iop); 214 printf("\tclock=%d\n", sbd->clock); 215 printf("\tipl=%d, cpu_ex=%d, fpp_ex=%d\n", 216 sbd->ipl, sbd->cpu_ex, sbd->fpp_ex); 217 printf("\tkbms=%d, sio=%d, battery=%d, scsi=%d\n", 218 sbd->kbms, sbd->sio, sbd->battery, sbd->scsi); 219 printf("model name=%s\n", sbd->model_name); 220 221 return 0; 222 } 223 224 int 225 cmd_reboot(int argc, char *argp[], int interactive) 226 { 227 int bootdev = -1; 228 229 if (argc > 1) 230 bootdev = strtoul(argp[1], 0, 0); /* next boot device. */ 231 if (bootdev != NVSRAM_BOOTDEV_FLOPPYDISK && 232 bootdev != NVSRAM_BOOTDEV_HARDDISK && 233 bootdev != NVSRAM_BOOTDEV_CGMT && 234 bootdev != NVSRAM_BOOTDEV_NETWORK) { 235 printf("invalid boot device."); 236 bootdev = -1; 237 } 238 239 switch (SBD_INFO->machine) { 240 case MACHINE_TR2A: 241 if (bootdev != -1) 242 *(uint8_t *)0xbe493030 = bootdev; 243 *(volatile uint32_t *)0xbe000064 |= 0x80000000; 244 *(volatile uint8_t *)0xba000004 = 1; 245 *(uint8_t *)0xbfbffffc = 255; 246 break; 247 case MACHINE_TR2: 248 if (bootdev != -1) 249 *(uint8_t *)0xbb023030 = bootdev; 250 *(volatile uint32_t *)0xbfb00000 |= 0x10; 251 break; 252 default: 253 ROM_MONITOR(); 254 } 255 256 while (/*CONSTCOND*/1) 257 ; 258 /* NOTREACHED */ 259 return 0; 260 } 261 262 void 263 set_device_capability(void) 264 { 265 const char *devname[] = { 266 "Floppy disk", 267 "Unknown", 268 "Hard disk", 269 "Unknown", 270 "CGMT", 271 "Unknown", 272 "Network", 273 "Unknown", 274 "Network T&D" 275 }; 276 int booted_device, booted_unit, fd_format; 277 278 boot_device(&booted_device, &booted_unit, &fd_format); 279 if (booted_device > NVSRAM_BOOTDEV_MAX || 280 booted_device < NVSRAM_BOOTDEV_MIN) { 281 printf( 282 "invalid booted device. NVSRAM information isn't valid\n"); 283 } else { 284 DEVICE_CAPABILITY.booted_device = booted_device; 285 } 286 DEVICE_CAPABILITY.booted_unit = booted_unit; 287 288 switch (SBD_INFO->machine) { 289 case MACHINE_TR2A: 290 DEVICE_CAPABILITY.active = true; 291 /* boot has LANCE driver */ 292 DEVICE_CAPABILITY.network_enabled = true; 293 break; 294 case MACHINE_TR2: 295 DEVICE_CAPABILITY.active = true; 296 break; 297 default: 298 DEVICE_CAPABILITY.active = false; 299 break; 300 } 301 302 DEVICE_CAPABILITY.fd_enabled = true; /* always enabled */ 303 304 if (DEVICE_CAPABILITY.active) { 305 /* 306 * When NETWORK IPL, FD IPL doesn't activate ROM DISK routine. 307 */ 308 if (DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_HARDDISK) 309 DEVICE_CAPABILITY.disk_enabled = true; 310 } 311 312 printf("FD[%c] DISK[%c] NETWORK[%c] COMPILED[%c]\n", 313 DEVICE_CAPABILITY.fd_enabled ? 'x' : '_', 314 DEVICE_CAPABILITY.disk_enabled ? 'x' : '_', 315 DEVICE_CAPABILITY.network_enabled ? 'x' : '_', 316 kernel_binary_size ? 'x' : '_'); 317 318 printf("booted from %s IPL", devname[DEVICE_CAPABILITY.booted_device]); 319 if ((DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_NETWORK) || 320 (DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_NETWORK_T_AND_D)) 321 { 322 printf("\n"); 323 } else { 324 printf(" unit %d\n", DEVICE_CAPABILITY.booted_unit); 325 } 326 } 327 328 int 329 cmd_test(int argc, char *argp[], int interactive) 330 { 331 332 /* MISC TEST ROUTINE */ 333 extern int fdd_test(void); 334 fdd_test(); 335 #if 0 336 int i; 337 338 printf("argc=%d\n", argc); 339 for (i = 0; i < argc; i++) 340 printf("[%d] %s\n", i, argp[i]); 341 #endif 342 #if 0 /* Recover my 360ADII NVSRAM.. */ 343 uint8_t *p = (uint8_t *)0xbe490000; 344 uint8_t *q = nvsram_tr2a; 345 int i; 346 347 for (i = 0; i < sizeof nvsram_tr2a; i++) { 348 *p = *q; 349 p += 4; 350 q += 1; 351 } 352 #endif 353 #if 0 /* ROM PUTC test */ 354 char a[]= "ohayotest!"; 355 int i; 356 for (i = 0; i < 10; i++) 357 ROM_PUTC(120 + i * 12, 24 * 10, a[i]); 358 #endif 359 #if 0 /* ROM SCSI disk routine test TR2 */ 360 uint8_t buf[512*2]; 361 uint8_t *p; 362 int i; 363 364 printf("type=%d\n", *(uint8_t *)0xbb023034); 365 memset(buf, 0, sizeof buf); 366 p = (uint8_t *)(((uint32_t)buf + 511) & ~511); 367 i = ROM_DK_READ(0, 0, 1, p); 368 printf("err=%d\n", i); 369 for (i = 0; i < 64; i++) { 370 printf("%x ", p[i]); 371 if (((i + 1) & 0xf) == 0) 372 printf("\n"); 373 } 374 #endif 375 #if 0 376 /*XXX failed. */ 377 __asm volatile( 378 ".set noreorder;" 379 "li $4, 2;" 380 "mtc0 $4, $16;" /* Config */ 381 "lui $4, 0xbfc2;" 382 "jr $4;" 383 "nop;" 384 ".set reorder"); 385 /* NOTREACHED */ 386 #endif 387 #if 0 388 /* FPU test */ 389 { 390 int v; 391 __asm volatile( 392 ".set noreorder;" 393 "lui %0, 0x2000;" 394 "mtc0 %0, $12;" /* Cu1 */ 395 "nop;" 396 "nop;" 397 "cfc1 %0, $%1;" 398 "nop;" 399 "nop;" 400 ".set reorder" 401 : "=r"(v) : "i"(0)); 402 printf("FPUId: %x\n", v); 403 } 404 #endif 405 return 0; 406 } 407