boot.c revision 1.6 1 /* $NetBSD: boot.c,v 1.6 2008/04/28 20:23:18 martin 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_date[];
49 extern const char bootprog_maker[];
50
51 struct cmd_batch_tab cmd_batch_tab[] = {
52 /* func argc argp... */
53 #if 0
54 { cmd_boot, 1, { "mem:", 0, 0, 0, 0, 0, 0 } },
55 { cmd_boot, 1, { "sd0k:netbsd", 0, 0, 0, 0, 0, 0 } },
56 { cmd_load_binary, 1, { "0x80001000", 0, 0, 0, 0, 0, 0 } },
57 { cmd_jump, 2, { "0x80001000", "0x80001000", 0, 0, 0, 0, 0 } },
58 #endif
59 { NULL, 0, { 0, 0, 0, 0, 0, 0, 0 } } /* terminate */
60 };
61
62 struct ipl_args ipl_args;
63 struct device_capability DEVICE_CAPABILITY;
64 void set_device_capability(void);
65 bool guess_boot_kernel(char *, size_t, int);
66 extern int kernel_binary_size;
67
68 void
69 main(int a0, int v0, int v1)
70 {
71 extern char edata[], end[];
72 char boot_kernel[32];
73 char *args[CMDARG_MAX];
74 int i;
75
76 memset(edata, 0, end - edata);
77 /* Save args for chain-boot to iopboot */
78 ipl_args.a0 = a0;
79 ipl_args.v0 = v0;
80 ipl_args.v1 = v1;
81
82 console_init();
83
84 printf("\n");
85 printf("%s boot, Revision %s\n", bootprog_name, bootprog_rev);
86 printf("(%s, %s)\n", bootprog_date, bootprog_maker);
87
88
89 /* Inquire IPL activated device */
90 set_device_capability();
91
92 if (!guess_boot_kernel(boot_kernel, sizeof boot_kernel, 0))
93 goto prompt;
94 printf(
95 ">> Press return to boot now, any other key for boot console.\n");
96
97 for (i = 5000; i >= 0; i--) {
98 int c;
99 if (i % 1000 == 0)
100 printf("booting %s - starting %d\r",
101 boot_kernel, i / 1000);
102 if ((c = cnscan()) == -1) {
103 delay(10);
104 continue;
105 }
106 else if (c == '\r')
107 break;
108 else
109 goto prompt;
110 }
111 printf("\n[non-interactive mode]\n");
112 args[0] = "boot";
113 args[1] = boot_kernel;
114 cmd_boot(2, args, false);
115 prompt:
116
117 printf("\ntype \"help\" for help.\n");
118 console_cursor(true);
119 prompt();
120 /* NOTREACHED */
121 }
122
123 bool
124 guess_boot_kernel(char *name, size_t len, int pri)
125 {
126 extern struct vtoc_sector vtoc;
127 struct ux_partition *partition;
128 int i, unit;
129
130 if (!DEVICE_CAPABILITY.active)
131 return false;
132
133 unit = DEVICE_CAPABILITY.booted_unit;
134
135 switch (DEVICE_CAPABILITY.booted_device) {
136 default:
137 return false;
138 case NVSRAM_BOOTDEV_FLOPPYDISK:
139 strncpy(name, "fd:netbsd", len); /* ustarfs */
140 return true;
141
142 case NVSRAM_BOOTDEV_HARDDISK:
143 snprintf(name, len, "sd%d:netbsd", unit); /* ustarfs */
144 if (!read_vtoc())
145 return true;
146
147 partition = vtoc.partition;
148 for (i = 0; i < VTOC_MAXPARTITIONS; i++, partition++) {
149 if (partition->tag != __VTOC_TAG_BSDFFS)
150 continue;
151 /* ffs */
152 snprintf(name, len, "sd%d%c:netbsd", unit, 'a' + i);
153 return true;
154 }
155 return true;
156
157 case NVSRAM_BOOTDEV_CGMT:
158 break;
159 case NVSRAM_BOOTDEV_NETWORK:
160 /*FALLTHROUGH*/
161 case NVSRAM_BOOTDEV_NETWORK_T_AND_D:
162 if (kernel_binary_size) {
163 strncpy(name, "mem:", len); /* datafs */
164 return true;
165 }
166 if (DEVICE_CAPABILITY.network_enabled) {
167 strncpy(name, "nfs:netbsd", len); /* nfs */
168 return true;
169 }
170 break;
171 }
172
173 return false;
174 }
175
176 int
177 cmd_info(int argc, char *argp[], int interactive)
178 {
179 extern char _ftext[], _etext[], _fdata[], _edata[];
180 extern char _fbss[], end[];
181 uint32_t m;
182 int i, size, total;
183 struct sbdinfo *sbd = SBD_INFO;
184
185 printf("\n>> %s boot, rev. %s [%s, %s] <<\n", bootprog_name,
186 bootprog_rev, bootprog_date, bootprog_maker);
187
188 printf("IPL args: 0x%x 0x%x 0x%x\n", ipl_args.a0, ipl_args.v0,
189 ipl_args.v1);
190 printf("\ttext : %p-%p\n\tdata : %p-%p\n\t"
191 "bss : %p-%p\n\tstack: %p\n\theap : %p\n",
192 _ftext, _etext, _fdata, _edata,
193 _fbss, end, _ftext, end);
194
195 m = ipl_args.v1;
196 total = 0;
197 printf("Memory Area:\n\t");
198 for (i = 0; i < 8; i++, m >>= 4) {
199 size = m & 0xf ? ((m & 0xf) << 4) : 0;
200 total += size;
201 if (size)
202 printf("M%d=%dMB ", i, size);
203 }
204 printf(" total %dMB\n", total);
205
206 printf("Board Revision:\n");
207 printf("\tmachine=0x%x, ", sbd->machine);
208 printf("model=0x%x\n", sbd->model);
209 printf("\tpmmu=%d, ", sbd->mmu);
210 printf("cache=%d, ", sbd->cache);
211 printf("panel=%d, ", sbd->panel);
212 printf("fdd=%d\n", sbd->fdd);
213 printf("\tcpu=%d, fpp=%d, fpa=%d, iop=%d\n",
214 sbd->cpu, sbd->fpp, sbd->fpa, sbd->iop);
215 printf("\tclock=%d\n", sbd->clock);
216 printf("\tipl=%d, cpu_ex=%d, fpp_ex=%d\n",
217 sbd->ipl, sbd->cpu_ex, sbd->fpp_ex);
218 printf("\tkbms=%d, sio=%d, battery=%d, scsi=%d\n",
219 sbd->kbms, sbd->sio, sbd->battery, sbd->scsi);
220 printf("model name=%s\n", sbd->model_name);
221
222 return 0;
223 }
224
225 int
226 cmd_reboot(int argc, char *argp[], int interactive)
227 {
228 int bootdev = -1;
229
230 if (argc > 1)
231 bootdev = strtoul(argp[1], 0, 0); /* next boot device. */
232 if (bootdev != NVSRAM_BOOTDEV_FLOPPYDISK &&
233 bootdev != NVSRAM_BOOTDEV_HARDDISK &&
234 bootdev != NVSRAM_BOOTDEV_CGMT &&
235 bootdev != NVSRAM_BOOTDEV_NETWORK) {
236 printf("invalid boot device.");
237 bootdev = -1;
238 }
239
240 switch (SBD_INFO->machine) {
241 case MACHINE_TR2A:
242 if (bootdev != -1)
243 *(uint8_t *)0xbe493030 = bootdev;
244 *(volatile uint32_t *)0xbe000064 |= 0x80000000;
245 *(volatile uint8_t *)0xba000004 = 1;
246 *(uint8_t *)0xbfbffffc = 255;
247 break;
248 case MACHINE_TR2:
249 if (bootdev != -1)
250 *(uint8_t *)0xbb023030 = bootdev;
251 *(volatile uint32_t *)0xbfb00000 |= 0x10;
252 break;
253 default:
254 ROM_MONITOR();
255 }
256
257 while (/*CONSTCOND*/1)
258 ;
259 /* NOTREACHED */
260 return 0;
261 }
262
263 void
264 set_device_capability(void)
265 {
266 const char *devname[] = {
267 "Floppy disk",
268 "Unknown",
269 "Hard disk",
270 "Unknown",
271 "CGMT",
272 "Unknown",
273 "Network",
274 "Unknown",
275 "Network T&D"
276 };
277 int booted_device, booted_unit, fd_format;
278
279 boot_device(&booted_device, &booted_unit, &fd_format);
280 if (booted_device > NVSRAM_BOOTDEV_MAX ||
281 booted_device < NVSRAM_BOOTDEV_MIN) {
282 printf(
283 "invalid booted device. NVSRAM information isn't valid\n");
284 } else {
285 DEVICE_CAPABILITY.booted_device = booted_device;
286 }
287 DEVICE_CAPABILITY.booted_unit = booted_unit;
288
289 switch (SBD_INFO->machine) {
290 case MACHINE_TR2A:
291 DEVICE_CAPABILITY.active = true;
292 /* boot has LANCE driver */
293 DEVICE_CAPABILITY.network_enabled = true;
294 break;
295 case MACHINE_TR2:
296 DEVICE_CAPABILITY.active = true;
297 break;
298 default:
299 DEVICE_CAPABILITY.active = false;
300 break;
301 }
302
303 DEVICE_CAPABILITY.fd_enabled = true; /* always enabled */
304
305 if (DEVICE_CAPABILITY.active) {
306 /*
307 * When NETWORK IPL, FD IPL doesn't activate ROM DISK routine.
308 */
309 if (DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_HARDDISK)
310 DEVICE_CAPABILITY.disk_enabled = true;
311 }
312
313 printf("FD[%c] DISK[%c] NETWORK[%c] COMPILED[%c]\n",
314 DEVICE_CAPABILITY.fd_enabled ? 'x' : '_',
315 DEVICE_CAPABILITY.disk_enabled ? 'x' : '_',
316 DEVICE_CAPABILITY.network_enabled ? 'x' : '_',
317 kernel_binary_size ? 'x' : '_');
318
319 printf("booted from %s IPL", devname[DEVICE_CAPABILITY.booted_device]);
320 if ((DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_NETWORK) ||
321 (DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_NETWORK_T_AND_D))
322 {
323 printf("\n");
324 } else {
325 printf(" unit %d\n", DEVICE_CAPABILITY.booted_unit);
326 }
327 }
328
329 int
330 cmd_test(int argc, char *argp[], int interactive)
331 {
332
333 /* MISC TEST ROUTINE */
334 extern int fdd_test(void);
335 fdd_test();
336 #if 0
337 int i;
338
339 printf("argc=%d\n", argc);
340 for (i = 0; i < argc; i++)
341 printf("[%d] %s\n", i, argp[i]);
342 #endif
343 #if 0 /* Recover my 360ADII NVSRAM.. */
344 uint8_t *p = (uint8_t *)0xbe490000;
345 uint8_t *q = nvsram_tr2a;
346 int i;
347
348 for (i = 0; i < sizeof nvsram_tr2a; i++) {
349 *p = *q;
350 p += 4;
351 q += 1;
352 }
353 #endif
354 #if 0 /* ROM PUTC test */
355 char a[]= "ohayotest!";
356 int i;
357 for (i = 0; i < 10; i++)
358 ROM_PUTC(120 + i * 12, 24 * 10, a[i]);
359 #endif
360 #if 0 /* ROM SCSI disk routine test TR2 */
361 uint8_t buf[512*2];
362 uint8_t *p;
363 int i;
364
365 printf("type=%d\n", *(uint8_t *)0xbb023034);
366 memset(buf, 0, sizeof buf);
367 p = (uint8_t *)(((uint32_t)buf + 511) & ~511);
368 i = ROM_DK_READ(0, 0, 1, p);
369 printf("err=%d\n", i);
370 for (i = 0; i < 64; i++) {
371 printf("%x ", p[i]);
372 if (((i + 1) & 0xf) == 0)
373 printf("\n");
374 }
375 #endif
376 #if 0
377 /*XXX failed. */
378 __asm volatile(
379 ".set noreorder;"
380 "li $4, 2;"
381 "mtc0 $4, $16;" /* Config */
382 "lui $4, 0xbfc2;"
383 "jr $4;"
384 "nop;"
385 ".set reorder");
386 /* NOTREACHED */
387 #endif
388 #if 0
389 /* FPU test */
390 {
391 int v;
392 __asm volatile(
393 ".set noreorder;"
394 "lui %0, 0x2000;"
395 "mtc0 %0, $12;" /* Cu1 */
396 "nop;"
397 "nop;"
398 "cfc1 %0, $%1;"
399 "nop;"
400 "nop;"
401 ".set reorder"
402 : "=r"(v) : "i"(0));
403 printf("FPUId: %x\n", v);
404 }
405 #endif
406 return 0;
407 }
408