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