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