xref: /netbsd-src/sys/arch/ews4800mips/stand/common/boot.c (revision 6415b4ca38d415d384ccf3837d33b125dba8c6a0)
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
main(int a0,int v0,int v1)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
guess_boot_kernel(char * name,size_t len,int pri)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
cmd_info(int argc,char * argp[],int interactive)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
cmd_reboot(int argc,char * argp[],int interactive)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
set_device_capability(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
cmd_test(int argc,char * argp[],int interactive)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