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