boot.c revision 1.24 1 /* $NetBSD: boot.c,v 1.24 2016/06/11 06:57:46 dholland Exp $ */
2
3 /*
4 * Copyright (c) 2001 Minoura Makoto
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/param.h>
30 #include <machine/bootinfo.h>
31
32 #include <lib/libsa/stand.h>
33 #include <lib/libsa/loadfile.h>
34 #include <lib/libsa/ufs.h>
35 #ifdef NETBOOT
36 #include <lib/libsa/dev_net.h>
37 #endif
38 #include <lib/libkern/libkern.h>
39
40 #include "libx68k.h"
41 #include "iocs.h"
42 #include "switch.h"
43
44 #include "exec_image.h"
45
46
47 #define HEAP_START ((void*) 0x00080000)
48 #define HEAP_END ((void*) 0x000fffff)
49 #define EXSCSI_BDID ((void*) 0x00ea0001)
50 #define SRAM_MEMSIZE (*((long*) 0x00ed0008))
51
52 char default_kernel[20] =
53 #ifndef NETBOOT
54 "sd0a:netbsd";
55 #else
56 "nfs:netbsd";
57 #endif
58 int mpu;
59 #ifndef NETBOOT
60 int hostadaptor;
61 #endif
62 int console_device = -1;
63
64 #ifdef DEBUG
65 #ifdef NETBOOT
66 int debug = 1;
67 #endif
68 #endif
69
70 static void help(void);
71 #ifndef NETBOOT
72 static int get_scsi_host_adapter(void);
73 #endif
74 static void doboot(const char *, int);
75 static void boot(char *);
76 #ifndef NETBOOT
77 static void cmd_ls(char *);
78 #endif
79 int bootmenu(void);
80 void bootmain(int);
81 extern int detectmpu(void);
82 extern int badbaddr(void *);
83
84 #ifndef NETBOOT
85 /* from boot_ufs/bootmain.c */
86 static int
87 get_scsi_host_adapter(void)
88 {
89 char *bootrom;
90 int ha;
91
92 bootrom = (char *) (IOCS_BOOTINF() & 0x00ffffe0);
93 /*
94 * bootrom+0x24 "SCSIIN" ... Internal SCSI (spc@0)
95 * "SCSIEX" ... External SCSI (spc@1 or mha@0)
96 */
97 if (*(u_short *)(bootrom + 0x24 + 4) == 0x494e) { /* "IN" */
98 ha = (X68K_BOOT_SCSIIF_SPC << 4) | 0;
99 } else if (badbaddr(EXSCSI_BDID)) {
100 ha = (X68K_BOOT_SCSIIF_MHA << 4) | 0;
101 } else {
102 ha = (X68K_BOOT_SCSIIF_SPC << 4) | 1;
103 }
104
105 return ha;
106 }
107 #endif
108
109 static void
110 help(void)
111 {
112 printf("Usage:\n");
113 printf("boot [dev:][file] -[flags]\n");
114 #ifndef NETBOOT
115 printf(" dev: sd<ID><PART>, ID=0-7, PART=a-p\n");
116 printf(" cd<ID>a, ID=0-7\n");
117 printf(" fd<UNIT>a, UNIT=0-3, format is detected.\n");
118 #else
119 printf(" dev: nfs, first probed NE2000 is used.\n");
120 #endif
121 printf(" file: netbsd, netbsd.gz, etc.\n");
122 printf(" flags: abdqsv\n");
123 #ifndef NETBOOT
124 printf("ls [dev:][directory]\n");
125 #endif
126 printf("switch [show | key=val]\n");
127 printf("halt\nreboot\n");
128 }
129
130 static void
131 doboot(const char *file, int flags)
132 {
133 u_long marks[MARK_MAX];
134 int fd;
135 int dev, unit, part;
136 char *name;
137 short *p;
138 int loadflag;
139
140 printf("Starting %s, flags 0x%x\n", file, flags);
141
142 loadflag = LOAD_KERNEL;
143 if (file[0] == 'f')
144 loadflag &= ~LOAD_BACKWARDS;
145
146 marks[MARK_START] = 0x100000;
147 if ((fd = loadfile(file, marks, loadflag)) == -1) {
148 printf("loadfile failed\n");
149 return;
150 }
151 close(fd);
152
153 if (devparse(file, &dev, &unit, &part, &name) != 0) {
154 printf("XXX: unknown corruption in /boot.\n");
155 }
156
157 #ifdef DEBUG
158 #ifndef NETBOOT
159 printf("dev = %x, unit = %d, part = %c, name = %s\n",
160 dev, unit, part + 'a', name);
161 #else
162 printf("dev = %x, unit = %d, name = %s\n",
163 dev, unit, name);
164 #endif
165 #endif
166
167 #ifndef NETBOOT
168 if (dev == 0) { /* SCSI */
169 dev = X68K_MAKESCSIBOOTDEV(X68K_MAJOR_SD,
170 hostadaptor >> 4,
171 hostadaptor & 15,
172 unit & 7, 0, 0);
173 } else {
174 dev = X68K_MAKEBOOTDEV(X68K_MAJOR_FD, unit & 3, 0);
175 }
176 #else
177 dev = X68K_MAKEBOOTDEV(X68K_MAJOR_NE, unit, 0);
178 #endif
179 #ifdef DEBUG
180 printf("boot device = %x\n", dev);
181 #ifndef NETBOOT
182 printf("if = %d, unit = %d, id = %d, lun = %d, part = %c\n",
183 B_X68K_SCSI_IF(dev),
184 B_X68K_SCSI_IF_UN(dev),
185 B_X68K_SCSI_ID(dev),
186 B_X68K_SCSI_LUN(dev),
187 B_X68K_SCSI_PART(dev) + 'a');
188 #else
189 printf("if = %d, unit = %d\n",
190 B_X68K_SCSI_IF(dev),
191 B_X68K_SCSI_IF_UN(dev));
192 #endif
193 #endif
194
195 p = ((short*) marks[MARK_ENTRY]) - 1;
196 #ifdef DEBUG
197 printf("Kernel Version: 0x%x\n", *p);
198 #endif
199 if (*p != 0x4e73 && *p != 0) {
200 /*
201 * XXX temporary solution; compatibility loader
202 * must be written.
203 */
204 printf("This kernel is too new to be loaded by "
205 "this version of /boot.\n");
206 return;
207 }
208
209 exec_image(marks[MARK_START], 0, marks[MARK_ENTRY]-marks[MARK_START],
210 marks[MARK_END]-marks[MARK_START], dev, flags);
211
212 return;
213 }
214
215 static void
216 boot(char *arg)
217 {
218 char filename[80];
219 char *p;
220 int flags = 0;
221
222 if (*arg == 0 || *arg == '-') {
223 strcpy(filename, default_kernel);
224 if (*arg == '-')
225 if (parseopts(arg, &flags) == 0) {
226 help();
227 return;
228 }
229 doboot(filename, flags);
230 return;
231 } else {
232 p = gettrailer(arg);
233 if (strchr(arg, ':')) {
234 strcpy(filename, arg);
235 if (arg[strlen(arg) - 1] == ':')
236 strcat(filename, "netbsd");
237 } else {
238 strcpy(filename, default_kernel);
239 strcpy(strchr(filename, ':') + 1, arg);
240 }
241 if (*p == '-') {
242 if (parseopts(p, &flags) == 0)
243 return;
244 } else if (*p != 0) {
245 help();
246 return;
247 }
248
249 doboot(filename, flags);
250 return;
251 }
252 }
253
254 #ifndef NETBOOT
255 static void
256 cmd_ls(char *arg)
257 {
258 char filename[80];
259
260 devopen_open_dir = 1;
261 if (*arg == 0) {
262 strcpy(filename, default_kernel);
263 strcpy(strchr(filename, ':')+1, "/");
264 } else if (strchr(arg, ':') == 0) {
265 strcpy(filename, default_kernel);
266 strcpy(strchr(filename, ':')+1, arg);
267 } else {
268 strcpy(filename, arg);
269 if (*(strchr(arg, ':')+1) == 0)
270 strcat(filename, "/");
271 }
272 ls(filename);
273 devopen_open_dir = 0;
274 }
275 #endif
276
277 int
278 bootmenu(void)
279 {
280 char input[80];
281 int n = 5, c;
282
283 printf("Press return to boot now, any other key for boot menu\n");
284 printf("booting %s - starting in %d seconds. ",
285 default_kernel, n);
286 while (n-- > 0 && (c = awaitkey_1sec()) == 0) {
287 printf("\r");
288 printf("booting %s - starting in %d seconds. ",
289 default_kernel, n);
290 }
291 printf("\r");
292 printf("booting %s - starting in %d seconds. ", default_kernel, 0);
293 printf("\n");
294
295 if (c == 0 || c == '\r') {
296 doboot(default_kernel, 0);
297 printf("Could not start %s; ", default_kernel);
298 strcat(default_kernel, ".gz");
299 printf("trying %s.\n", default_kernel);
300 doboot(default_kernel, 0);
301 printf("Could not start %s; ", default_kernel);
302 }
303
304 printf("Please use the absolute unit# (e.g. SCSI ID)"
305 " instead of the NetBSD logical #.\n");
306 for (;;) {
307 char *p, *options;
308
309 printf("> ");
310 gets(input);
311
312 for (p = &input[0]; p - &input[0] < 80 && *p == ' '; p++)
313 ;
314 options = gettrailer(p);
315 if (strcmp("boot", p) == 0)
316 boot(options);
317 else if (strcmp("help", p) == 0 ||
318 strcmp("?", p) == 0)
319 help();
320 else if (strcmp("halt", p) == 0 ||
321 strcmp("reboot", p) == 0)
322 exit(0);
323 else if (strcmp("switch", p) == 0)
324 cmd_switch(options);
325 #ifndef NETBOOT
326 else if (strcmp("ls", p) == 0)
327 cmd_ls(options);
328 #endif
329 else
330 printf("Unknown command %s\n", p);
331 }
332 }
333
334 static u_int
335 checkmemsize(void)
336 {
337 u_int m;
338
339 #define MIN_MB 4
340 #define MAX_MB 12
341
342 for (m = MIN_MB; m <= MAX_MB; m++) {
343 if (badbaddr((void *)(m * 1024 * 1024 - 1))) {
344 /* no memory */
345 break;
346 }
347 }
348
349 return (m - 1) * 1024 * 1024;
350 }
351
352 extern const char bootprog_rev[];
353 extern const char bootprog_name[];
354
355 /*
356 * Arguments from the boot block:
357 * bootdev - specifies the device from which /boot was read, in
358 * bootdev format.
359 */
360 void
361 bootmain(int bootdev)
362 {
363 u_int sram_memsize;
364 u_int probed_memsize;
365
366 #ifndef NETBOOT
367 hostadaptor = get_scsi_host_adapter();
368 #else
369 rtc_offset = RTC_OFFSET;
370 try_bootp = 1;
371 #endif
372 mpu = detectmpu();
373
374 if (mpu < 3) { /* not tested on 68020 */
375 printf("This MPU cannot run NetBSD.\n");
376 exit(1);
377 }
378 sram_memsize = SRAM_MEMSIZE;
379 if (sram_memsize < 4*1024*1024) {
380 printf("Main memory too small.\n");
381 exit(1);
382 }
383
384 console_device = consio_init(console_device);
385 setheap(HEAP_START, HEAP_END);
386
387 #ifndef NETBOOT
388 switch (B_TYPE(bootdev)) {
389 case X68K_MAJOR_FD:
390 default_kernel[0] = 'f';
391 default_kernel[2] = '0' + B_UNIT(bootdev);
392 default_kernel[3] = 'a';
393 break;
394 case X68K_MAJOR_SD:
395 default_kernel[2] = '0' + B_X68K_SCSI_ID(bootdev);
396 default_kernel[3] =
397 'a' + sd_getbsdpartition(B_X68K_SCSI_ID(bootdev),
398 B_X68K_SCSI_PART(bootdev));
399 break;
400 case X68K_MAJOR_CD:
401 default_kernel[0] = 'c';
402 default_kernel[2] = '0' + B_X68K_SCSI_ID(bootdev);
403 default_kernel[3] = 'a';
404 break;
405 default:
406 printf("Warning: unknown boot device: %x\n", bootdev);
407 }
408 #endif
409 print_title("%s, Revision %s\n", bootprog_name, bootprog_rev);
410
411 /* check actual memory size for machines with a dead SRAM battery */
412 probed_memsize = checkmemsize();
413 if (sram_memsize != probed_memsize) {
414 printf("\x1b[1mWarning: SRAM Memory Size (%d MB) "
415 "is different from probed Memory Size (%d MB)\n"
416 " Check and reset SRAM values.\x1b[m\n\n",
417 sram_memsize / (1024 * 1024),
418 probed_memsize / (1024 * 1024));
419 }
420
421 bootmenu();
422 }
423