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