Home | History | Annotate | Line # | Download | only in common
boot.c revision 1.2
      1 /*	$NetBSD: boot.c,v 1.2 2006/01/26 16:26:58 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  * 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 boolean_t 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 boolean_t
    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 infomation 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