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