xref: /netbsd-src/sys/arch/ews4800mips/stand/common/boot.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
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