boot.c revision 1.7 1 1.7 tsutsui /* $NetBSD: boot.c,v 1.7 2008/07/16 14:45:17 tsutsui Exp $ */
2 1.1 tsutsui
3 1.1 tsutsui /*-
4 1.1 tsutsui * Copyright (c) 2004 The NetBSD Foundation, Inc.
5 1.1 tsutsui * All rights reserved.
6 1.1 tsutsui *
7 1.1 tsutsui * This code is derived from software contributed to The NetBSD Foundation
8 1.1 tsutsui * by UCHIYAMA Yasushi.
9 1.1 tsutsui *
10 1.1 tsutsui * Redistribution and use in source and binary forms, with or without
11 1.1 tsutsui * modification, are permitted provided that the following conditions
12 1.1 tsutsui * are met:
13 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright
14 1.1 tsutsui * notice, this list of conditions and the following disclaimer.
15 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the
17 1.1 tsutsui * documentation and/or other materials provided with the distribution.
18 1.1 tsutsui *
19 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 tsutsui * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 tsutsui * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 tsutsui * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 tsutsui * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 tsutsui * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 tsutsui * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 tsutsui * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 tsutsui * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 tsutsui * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 tsutsui * POSSIBILITY OF SUCH DAMAGE.
30 1.1 tsutsui */
31 1.1 tsutsui
32 1.1 tsutsui #include <lib/libsa/stand.h>
33 1.1 tsutsui #include <lib/libkern/libkern.h>
34 1.1 tsutsui
35 1.1 tsutsui #include "local.h"
36 1.1 tsutsui #include "cmd.h"
37 1.1 tsutsui #include "common.h"
38 1.1 tsutsui
39 1.1 tsutsui #include <machine/sbd.h>
40 1.1 tsutsui #include <machine/pdinfo.h>
41 1.1 tsutsui #include <machine/vtoc.h>
42 1.1 tsutsui
43 1.1 tsutsui #include "console.h"
44 1.1 tsutsui
45 1.1 tsutsui
46 1.1 tsutsui extern const char bootprog_name[];
47 1.1 tsutsui extern const char bootprog_rev[];
48 1.7 tsutsui extern const char bootprog_kernrev[];
49 1.1 tsutsui
50 1.1 tsutsui struct cmd_batch_tab cmd_batch_tab[] = {
51 1.1 tsutsui /* func argc argp... */
52 1.1 tsutsui #if 0
53 1.1 tsutsui { cmd_boot, 1, { "mem:", 0, 0, 0, 0, 0, 0 } },
54 1.1 tsutsui { cmd_boot, 1, { "sd0k:netbsd", 0, 0, 0, 0, 0, 0 } },
55 1.1 tsutsui { cmd_load_binary, 1, { "0x80001000", 0, 0, 0, 0, 0, 0 } },
56 1.1 tsutsui { cmd_jump, 2, { "0x80001000", "0x80001000", 0, 0, 0, 0, 0 } },
57 1.1 tsutsui #endif
58 1.1 tsutsui { NULL, 0, { 0, 0, 0, 0, 0, 0, 0 } } /* terminate */
59 1.1 tsutsui };
60 1.1 tsutsui
61 1.1 tsutsui struct ipl_args ipl_args;
62 1.1 tsutsui struct device_capability DEVICE_CAPABILITY;
63 1.1 tsutsui void set_device_capability(void);
64 1.4 thorpej bool guess_boot_kernel(char *, size_t, int);
65 1.1 tsutsui extern int kernel_binary_size;
66 1.1 tsutsui
67 1.1 tsutsui void
68 1.1 tsutsui main(int a0, int v0, int v1)
69 1.1 tsutsui {
70 1.1 tsutsui extern char edata[], end[];
71 1.1 tsutsui char boot_kernel[32];
72 1.1 tsutsui char *args[CMDARG_MAX];
73 1.1 tsutsui int i;
74 1.1 tsutsui
75 1.1 tsutsui memset(edata, 0, end - edata);
76 1.1 tsutsui /* Save args for chain-boot to iopboot */
77 1.1 tsutsui ipl_args.a0 = a0;
78 1.1 tsutsui ipl_args.v0 = v0;
79 1.1 tsutsui ipl_args.v1 = v1;
80 1.1 tsutsui
81 1.1 tsutsui console_init();
82 1.1 tsutsui
83 1.1 tsutsui printf("\n");
84 1.7 tsutsui printf("%s boot, Revision %s (from NetBSD %s)\n",
85 1.7 tsutsui bootprog_name, bootprog_rev, bootprog_kernrev);
86 1.1 tsutsui
87 1.1 tsutsui
88 1.1 tsutsui /* Inquire IPL activated device */
89 1.1 tsutsui set_device_capability();
90 1.1 tsutsui
91 1.1 tsutsui if (!guess_boot_kernel(boot_kernel, sizeof boot_kernel, 0))
92 1.1 tsutsui goto prompt;
93 1.1 tsutsui printf(
94 1.1 tsutsui ">> Press return to boot now, any other key for boot console.\n");
95 1.1 tsutsui
96 1.1 tsutsui for (i = 5000; i >= 0; i--) {
97 1.1 tsutsui int c;
98 1.1 tsutsui if (i % 1000 == 0)
99 1.1 tsutsui printf("booting %s - starting %d\r",
100 1.1 tsutsui boot_kernel, i / 1000);
101 1.1 tsutsui if ((c = cnscan()) == -1) {
102 1.1 tsutsui delay(10);
103 1.1 tsutsui continue;
104 1.1 tsutsui }
105 1.1 tsutsui else if (c == '\r')
106 1.1 tsutsui break;
107 1.1 tsutsui else
108 1.1 tsutsui goto prompt;
109 1.1 tsutsui }
110 1.1 tsutsui printf("\n[non-interactive mode]\n");
111 1.1 tsutsui args[0] = "boot";
112 1.1 tsutsui args[1] = boot_kernel;
113 1.5 thorpej cmd_boot(2, args, false);
114 1.1 tsutsui prompt:
115 1.1 tsutsui
116 1.1 tsutsui printf("\ntype \"help\" for help.\n");
117 1.5 thorpej console_cursor(true);
118 1.1 tsutsui prompt();
119 1.1 tsutsui /* NOTREACHED */
120 1.1 tsutsui }
121 1.1 tsutsui
122 1.4 thorpej bool
123 1.1 tsutsui guess_boot_kernel(char *name, size_t len, int pri)
124 1.1 tsutsui {
125 1.1 tsutsui extern struct vtoc_sector vtoc;
126 1.1 tsutsui struct ux_partition *partition;
127 1.1 tsutsui int i, unit;
128 1.1 tsutsui
129 1.1 tsutsui if (!DEVICE_CAPABILITY.active)
130 1.5 thorpej return false;
131 1.1 tsutsui
132 1.1 tsutsui unit = DEVICE_CAPABILITY.booted_unit;
133 1.1 tsutsui
134 1.1 tsutsui switch (DEVICE_CAPABILITY.booted_device) {
135 1.1 tsutsui default:
136 1.5 thorpej return false;
137 1.1 tsutsui case NVSRAM_BOOTDEV_FLOPPYDISK:
138 1.1 tsutsui strncpy(name, "fd:netbsd", len); /* ustarfs */
139 1.5 thorpej return true;
140 1.1 tsutsui
141 1.1 tsutsui case NVSRAM_BOOTDEV_HARDDISK:
142 1.1 tsutsui snprintf(name, len, "sd%d:netbsd", unit); /* ustarfs */
143 1.1 tsutsui if (!read_vtoc())
144 1.5 thorpej return true;
145 1.1 tsutsui
146 1.1 tsutsui partition = vtoc.partition;
147 1.1 tsutsui for (i = 0; i < VTOC_MAXPARTITIONS; i++, partition++) {
148 1.1 tsutsui if (partition->tag != __VTOC_TAG_BSDFFS)
149 1.1 tsutsui continue;
150 1.1 tsutsui /* ffs */
151 1.1 tsutsui snprintf(name, len, "sd%d%c:netbsd", unit, 'a' + i);
152 1.5 thorpej return true;
153 1.1 tsutsui }
154 1.5 thorpej return true;
155 1.1 tsutsui
156 1.1 tsutsui case NVSRAM_BOOTDEV_CGMT:
157 1.1 tsutsui break;
158 1.1 tsutsui case NVSRAM_BOOTDEV_NETWORK:
159 1.1 tsutsui /*FALLTHROUGH*/
160 1.1 tsutsui case NVSRAM_BOOTDEV_NETWORK_T_AND_D:
161 1.1 tsutsui if (kernel_binary_size) {
162 1.1 tsutsui strncpy(name, "mem:", len); /* datafs */
163 1.5 thorpej return true;
164 1.1 tsutsui }
165 1.1 tsutsui if (DEVICE_CAPABILITY.network_enabled) {
166 1.1 tsutsui strncpy(name, "nfs:netbsd", len); /* nfs */
167 1.5 thorpej return true;
168 1.1 tsutsui }
169 1.1 tsutsui break;
170 1.1 tsutsui }
171 1.1 tsutsui
172 1.5 thorpej return false;
173 1.1 tsutsui }
174 1.1 tsutsui
175 1.1 tsutsui int
176 1.1 tsutsui cmd_info(int argc, char *argp[], int interactive)
177 1.1 tsutsui {
178 1.1 tsutsui extern char _ftext[], _etext[], _fdata[], _edata[];
179 1.1 tsutsui extern char _fbss[], end[];
180 1.1 tsutsui uint32_t m;
181 1.1 tsutsui int i, size, total;
182 1.1 tsutsui struct sbdinfo *sbd = SBD_INFO;
183 1.1 tsutsui
184 1.7 tsutsui printf("\n>> %s boot, Revision %s (from NetBSD %s) <<\n",
185 1.7 tsutsui bootprog_name, bootprog_rev, bootprog_kernrev);
186 1.1 tsutsui
187 1.1 tsutsui printf("IPL args: 0x%x 0x%x 0x%x\n", ipl_args.a0, ipl_args.v0,
188 1.1 tsutsui ipl_args.v1);
189 1.1 tsutsui printf("\ttext : %p-%p\n\tdata : %p-%p\n\t"
190 1.1 tsutsui "bss : %p-%p\n\tstack: %p\n\theap : %p\n",
191 1.1 tsutsui _ftext, _etext, _fdata, _edata,
192 1.1 tsutsui _fbss, end, _ftext, end);
193 1.1 tsutsui
194 1.1 tsutsui m = ipl_args.v1;
195 1.1 tsutsui total = 0;
196 1.1 tsutsui printf("Memory Area:\n\t");
197 1.1 tsutsui for (i = 0; i < 8; i++, m >>= 4) {
198 1.1 tsutsui size = m & 0xf ? ((m & 0xf) << 4) : 0;
199 1.1 tsutsui total += size;
200 1.1 tsutsui if (size)
201 1.1 tsutsui printf("M%d=%dMB ", i, size);
202 1.1 tsutsui }
203 1.1 tsutsui printf(" total %dMB\n", total);
204 1.1 tsutsui
205 1.1 tsutsui printf("Board Revision:\n");
206 1.1 tsutsui printf("\tmachine=0x%x, ", sbd->machine);
207 1.1 tsutsui printf("model=0x%x\n", sbd->model);
208 1.1 tsutsui printf("\tpmmu=%d, ", sbd->mmu);
209 1.1 tsutsui printf("cache=%d, ", sbd->cache);
210 1.1 tsutsui printf("panel=%d, ", sbd->panel);
211 1.1 tsutsui printf("fdd=%d\n", sbd->fdd);
212 1.1 tsutsui printf("\tcpu=%d, fpp=%d, fpa=%d, iop=%d\n",
213 1.1 tsutsui sbd->cpu, sbd->fpp, sbd->fpa, sbd->iop);
214 1.1 tsutsui printf("\tclock=%d\n", sbd->clock);
215 1.1 tsutsui printf("\tipl=%d, cpu_ex=%d, fpp_ex=%d\n",
216 1.1 tsutsui sbd->ipl, sbd->cpu_ex, sbd->fpp_ex);
217 1.1 tsutsui printf("\tkbms=%d, sio=%d, battery=%d, scsi=%d\n",
218 1.1 tsutsui sbd->kbms, sbd->sio, sbd->battery, sbd->scsi);
219 1.1 tsutsui printf("model name=%s\n", sbd->model_name);
220 1.1 tsutsui
221 1.1 tsutsui return 0;
222 1.1 tsutsui }
223 1.1 tsutsui
224 1.1 tsutsui int
225 1.1 tsutsui cmd_reboot(int argc, char *argp[], int interactive)
226 1.1 tsutsui {
227 1.1 tsutsui int bootdev = -1;
228 1.1 tsutsui
229 1.1 tsutsui if (argc > 1)
230 1.1 tsutsui bootdev = strtoul(argp[1], 0, 0); /* next boot device. */
231 1.1 tsutsui if (bootdev != NVSRAM_BOOTDEV_FLOPPYDISK &&
232 1.1 tsutsui bootdev != NVSRAM_BOOTDEV_HARDDISK &&
233 1.1 tsutsui bootdev != NVSRAM_BOOTDEV_CGMT &&
234 1.1 tsutsui bootdev != NVSRAM_BOOTDEV_NETWORK) {
235 1.1 tsutsui printf("invalid boot device.");
236 1.1 tsutsui bootdev = -1;
237 1.1 tsutsui }
238 1.1 tsutsui
239 1.1 tsutsui switch (SBD_INFO->machine) {
240 1.1 tsutsui case MACHINE_TR2A:
241 1.1 tsutsui if (bootdev != -1)
242 1.1 tsutsui *(uint8_t *)0xbe493030 = bootdev;
243 1.1 tsutsui *(volatile uint32_t *)0xbe000064 |= 0x80000000;
244 1.1 tsutsui *(volatile uint8_t *)0xba000004 = 1;
245 1.1 tsutsui *(uint8_t *)0xbfbffffc = 255;
246 1.1 tsutsui break;
247 1.1 tsutsui case MACHINE_TR2:
248 1.1 tsutsui if (bootdev != -1)
249 1.1 tsutsui *(uint8_t *)0xbb023030 = bootdev;
250 1.1 tsutsui *(volatile uint32_t *)0xbfb00000 |= 0x10;
251 1.1 tsutsui break;
252 1.1 tsutsui default:
253 1.1 tsutsui ROM_MONITOR();
254 1.1 tsutsui }
255 1.1 tsutsui
256 1.1 tsutsui while (/*CONSTCOND*/1)
257 1.1 tsutsui ;
258 1.1 tsutsui /* NOTREACHED */
259 1.1 tsutsui return 0;
260 1.1 tsutsui }
261 1.1 tsutsui
262 1.1 tsutsui void
263 1.1 tsutsui set_device_capability(void)
264 1.1 tsutsui {
265 1.1 tsutsui const char *devname[] = {
266 1.1 tsutsui "Floppy disk",
267 1.1 tsutsui "Unknown",
268 1.1 tsutsui "Hard disk",
269 1.1 tsutsui "Unknown",
270 1.1 tsutsui "CGMT",
271 1.1 tsutsui "Unknown",
272 1.1 tsutsui "Network",
273 1.1 tsutsui "Unknown",
274 1.1 tsutsui "Network T&D"
275 1.1 tsutsui };
276 1.1 tsutsui int booted_device, booted_unit, fd_format;
277 1.1 tsutsui
278 1.1 tsutsui boot_device(&booted_device, &booted_unit, &fd_format);
279 1.1 tsutsui if (booted_device > NVSRAM_BOOTDEV_MAX ||
280 1.1 tsutsui booted_device < NVSRAM_BOOTDEV_MIN) {
281 1.1 tsutsui printf(
282 1.3 wiz "invalid booted device. NVSRAM information isn't valid\n");
283 1.1 tsutsui } else {
284 1.1 tsutsui DEVICE_CAPABILITY.booted_device = booted_device;
285 1.1 tsutsui }
286 1.1 tsutsui DEVICE_CAPABILITY.booted_unit = booted_unit;
287 1.1 tsutsui
288 1.1 tsutsui switch (SBD_INFO->machine) {
289 1.1 tsutsui case MACHINE_TR2A:
290 1.5 thorpej DEVICE_CAPABILITY.active = true;
291 1.1 tsutsui /* boot has LANCE driver */
292 1.5 thorpej DEVICE_CAPABILITY.network_enabled = true;
293 1.1 tsutsui break;
294 1.1 tsutsui case MACHINE_TR2:
295 1.5 thorpej DEVICE_CAPABILITY.active = true;
296 1.1 tsutsui break;
297 1.1 tsutsui default:
298 1.5 thorpej DEVICE_CAPABILITY.active = false;
299 1.1 tsutsui break;
300 1.1 tsutsui }
301 1.1 tsutsui
302 1.5 thorpej DEVICE_CAPABILITY.fd_enabled = true; /* always enabled */
303 1.1 tsutsui
304 1.1 tsutsui if (DEVICE_CAPABILITY.active) {
305 1.1 tsutsui /*
306 1.1 tsutsui * When NETWORK IPL, FD IPL doesn't activate ROM DISK routine.
307 1.1 tsutsui */
308 1.1 tsutsui if (DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_HARDDISK)
309 1.5 thorpej DEVICE_CAPABILITY.disk_enabled = true;
310 1.1 tsutsui }
311 1.1 tsutsui
312 1.1 tsutsui printf("FD[%c] DISK[%c] NETWORK[%c] COMPILED[%c]\n",
313 1.1 tsutsui DEVICE_CAPABILITY.fd_enabled ? 'x' : '_',
314 1.1 tsutsui DEVICE_CAPABILITY.disk_enabled ? 'x' : '_',
315 1.1 tsutsui DEVICE_CAPABILITY.network_enabled ? 'x' : '_',
316 1.1 tsutsui kernel_binary_size ? 'x' : '_');
317 1.1 tsutsui
318 1.2 tsutsui printf("booted from %s IPL", devname[DEVICE_CAPABILITY.booted_device]);
319 1.1 tsutsui if ((DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_NETWORK) ||
320 1.1 tsutsui (DEVICE_CAPABILITY.booted_device == NVSRAM_BOOTDEV_NETWORK_T_AND_D))
321 1.1 tsutsui {
322 1.1 tsutsui printf("\n");
323 1.1 tsutsui } else {
324 1.1 tsutsui printf(" unit %d\n", DEVICE_CAPABILITY.booted_unit);
325 1.1 tsutsui }
326 1.1 tsutsui }
327 1.1 tsutsui
328 1.1 tsutsui int
329 1.1 tsutsui cmd_test(int argc, char *argp[], int interactive)
330 1.1 tsutsui {
331 1.1 tsutsui
332 1.1 tsutsui /* MISC TEST ROUTINE */
333 1.1 tsutsui extern int fdd_test(void);
334 1.1 tsutsui fdd_test();
335 1.1 tsutsui #if 0
336 1.1 tsutsui int i;
337 1.1 tsutsui
338 1.1 tsutsui printf("argc=%d\n", argc);
339 1.1 tsutsui for (i = 0; i < argc; i++)
340 1.1 tsutsui printf("[%d] %s\n", i, argp[i]);
341 1.1 tsutsui #endif
342 1.1 tsutsui #if 0 /* Recover my 360ADII NVSRAM.. */
343 1.1 tsutsui uint8_t *p = (uint8_t *)0xbe490000;
344 1.1 tsutsui uint8_t *q = nvsram_tr2a;
345 1.1 tsutsui int i;
346 1.1 tsutsui
347 1.1 tsutsui for (i = 0; i < sizeof nvsram_tr2a; i++) {
348 1.1 tsutsui *p = *q;
349 1.1 tsutsui p += 4;
350 1.1 tsutsui q += 1;
351 1.1 tsutsui }
352 1.1 tsutsui #endif
353 1.1 tsutsui #if 0 /* ROM PUTC test */
354 1.1 tsutsui char a[]= "ohayotest!";
355 1.1 tsutsui int i;
356 1.1 tsutsui for (i = 0; i < 10; i++)
357 1.1 tsutsui ROM_PUTC(120 + i * 12, 24 * 10, a[i]);
358 1.1 tsutsui #endif
359 1.1 tsutsui #if 0 /* ROM SCSI disk routine test TR2 */
360 1.1 tsutsui uint8_t buf[512*2];
361 1.1 tsutsui uint8_t *p;
362 1.1 tsutsui int i;
363 1.1 tsutsui
364 1.1 tsutsui printf("type=%d\n", *(uint8_t *)0xbb023034);
365 1.1 tsutsui memset(buf, 0, sizeof buf);
366 1.1 tsutsui p = (uint8_t *)(((uint32_t)buf + 511) & ~511);
367 1.1 tsutsui i = ROM_DK_READ(0, 0, 1, p);
368 1.1 tsutsui printf("err=%d\n", i);
369 1.1 tsutsui for (i = 0; i < 64; i++) {
370 1.1 tsutsui printf("%x ", p[i]);
371 1.1 tsutsui if (((i + 1) & 0xf) == 0)
372 1.1 tsutsui printf("\n");
373 1.1 tsutsui }
374 1.1 tsutsui #endif
375 1.1 tsutsui #if 0
376 1.1 tsutsui /*XXX failed. */
377 1.1 tsutsui __asm volatile(
378 1.1 tsutsui ".set noreorder;"
379 1.1 tsutsui "li $4, 2;"
380 1.1 tsutsui "mtc0 $4, $16;" /* Config */
381 1.1 tsutsui "lui $4, 0xbfc2;"
382 1.1 tsutsui "jr $4;"
383 1.1 tsutsui "nop;"
384 1.1 tsutsui ".set reorder");
385 1.1 tsutsui /* NOTREACHED */
386 1.1 tsutsui #endif
387 1.1 tsutsui #if 0
388 1.1 tsutsui /* FPU test */
389 1.1 tsutsui {
390 1.1 tsutsui int v;
391 1.1 tsutsui __asm volatile(
392 1.1 tsutsui ".set noreorder;"
393 1.1 tsutsui "lui %0, 0x2000;"
394 1.1 tsutsui "mtc0 %0, $12;" /* Cu1 */
395 1.1 tsutsui "nop;"
396 1.1 tsutsui "nop;"
397 1.1 tsutsui "cfc1 %0, $%1;"
398 1.1 tsutsui "nop;"
399 1.1 tsutsui "nop;"
400 1.1 tsutsui ".set reorder"
401 1.1 tsutsui : "=r"(v) : "i"(0));
402 1.1 tsutsui printf("FPUId: %x\n", v);
403 1.1 tsutsui }
404 1.1 tsutsui #endif
405 1.1 tsutsui return 0;
406 1.1 tsutsui }
407