1 /* $NetBSD: boot.c,v 1.13 2007/10/17 19:58:03 garbled Exp $ */
4 * Copyright (c) 2001 Minoura Makoto
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
29 #include <sys/param.h>
30 #include <machine/bootinfo.h>
32 #include <lib/libsa/stand.h>
33 #include <lib/libsa/loadfile.h>
34 #include <lib/libsa/ufs.h>
35 #include <lib/libkern/libkern.h>
40 #include "exec_image.h"
43 #define HEAP_START ((void*) 0x00080000)
44 #define HEAP_END ((void*) 0x000fffff)
45 #define EXSCSI_BDID ((void*) 0x00ea0001)
46 #define SRAM_MEMSIZE (*((long*) 0x00ed0008))
48 char default_kernel
[20] = "sd0a:netbsd";
50 int console_device
= -1;
52 static void help(void);
53 static int get_scsi_host_adapter(void);
54 static void doboot(const char *, int);
55 static void boot(char *);
56 static void ls(char *);
59 extern int detectmpu(void);
60 extern int badbaddr(void *);
62 /* from boot_ufs/bootmain.c */
64 get_scsi_host_adapter(void)
69 bootrom
= (char *) (IOCS_BOOTINF() & 0x00ffffe0);
71 * bootrom+0x24 "SCSIIN" ... Internal SCSI (spc@0)
72 * "SCSIEX" ... External SCSI (spc@1 or mha@0)
74 if (*(u_short
*)(bootrom
+ 0x24 + 4) == 0x494e) { /* "IN" */
75 ha
= (X68K_BOOT_SCSIIF_SPC
<< 4) | 0;
76 } else if (badbaddr(EXSCSI_BDID
)) {
77 ha
= (X68K_BOOT_SCSIIF_MHA
<< 4) | 0;
79 ha
= (X68K_BOOT_SCSIIF_SPC
<< 4) | 1;
90 printf("boot [dev:][file] -[flags]\n");
91 printf(" dev: sd<ID><PART>, ID=0-7, PART=a-p\n");
92 printf(" cd<ID>a, ID=0-7\n");
93 printf(" fd<UNIT>a, UNIT=0-3, format is detected.\n");
94 printf(" file: netbsd, netbsd.gz, etc.\n");
95 printf(" flags: abdqsv\n");
96 printf("ls [dev:][directory]\n");
97 printf("halt\nreboot\n");
101 doboot(const char *file
, int flags
)
103 u_long marks
[MARK_MAX
];
110 printf("Starting %s, flags 0x%x\n", file
, flags
);
112 loadflag
= LOAD_KERNEL
;
114 loadflag
&= ~LOAD_NOTE
;
116 marks
[MARK_START
] = 0x100000;
117 if ((fd
= loadfile(file
, marks
, loadflag
)) == -1) {
118 printf("loadfile failed\n");
123 if (devparse(file
, &dev
, &unit
, &part
, &name
) != 0) {
124 printf("XXX: unknown corruption in /boot.\n");
127 printf("dev = %x, unit = %d, part = %c, name = %s\n",
128 dev
, unit
, part
+ 'a', name
);
130 if (dev
== 0) { /* SCSI */
131 dev
= X68K_MAKESCSIBOOTDEV(X68K_MAJOR_SD
,
136 dev
= X68K_MAKEBOOTDEV(X68K_MAJOR_FD
, unit
& 3, 0);
138 printf("boot device = %x\n", dev
);
139 printf("if = %d, unit = %d, id = %d, lun = %d, part = %c\n",
141 B_X68K_SCSI_IF_UN(dev
),
143 B_X68K_SCSI_LUN(dev
),
144 B_X68K_SCSI_PART(dev
) + 'a');
146 p
= ((short*) marks
[MARK_ENTRY
]) - 1;
147 printf("Kernel Version: 0x%x\n", *p
);
148 if (*p
!= 0x4e73 && *p
!= 0) {
150 * XXX temporary solution; compatibility loader
153 printf("This kernel is too new to be loaded by "
154 "this version of /boot.\n");
158 exec_image(marks
[MARK_START
], 0, marks
[MARK_ENTRY
]-marks
[MARK_START
],
159 marks
[MARK_END
]-marks
[MARK_START
], dev
, flags
);
171 if (*arg
== 0 || *arg
== '-') {
172 strcpy(filename
, default_kernel
);
174 if (parseopts(arg
, &flags
) == 0) {
178 doboot(filename
, flags
);
182 if (strchr(arg
, ':')) {
183 strcpy(filename
, arg
);
184 if (arg
[strlen(arg
) - 1] == ':')
185 strcat(filename
, "netbsd");
187 strcpy(filename
, default_kernel
);
188 strcpy(strchr(filename
, ':') + 1, arg
);
191 if (parseopts(p
, &flags
) == 0)
193 } else if (*p
!= 0) {
198 doboot(filename
, flags
);
208 devopen_open_dir
= 1;
210 strcpy(filename
, default_kernel
);
211 strcpy(strchr(filename
, ':')+1, "/");
212 } else if (strchr(arg
, ':') == 0) {
213 strcpy(filename
, default_kernel
);
214 strcpy(strchr(filename
, ':')+1, arg
);
216 strcpy(filename
, arg
);
217 if (*(strchr(arg
, ':')+1) == 0)
218 strcat(filename
, "/");
221 devopen_open_dir
= 0;
230 printf("Press return to boot now, any other key for boot menu\n");
231 printf("booting %s - starting in %d seconds. ",
233 while (n
-- > 0 && (c
= awaitkey_1sec()) == 0) {
235 printf("booting %s - starting in %d seconds. ",
239 printf("booting %s - starting in %d seconds. ", default_kernel
, 0);
242 if (c
== 0 || c
== '\r') {
243 doboot(default_kernel
, 0);
244 printf("Could not start %s; ", default_kernel
);
245 strcat(default_kernel
, ".gz");
246 printf("trying %s.\n", default_kernel
);
247 doboot(default_kernel
, 0);
248 printf("Could not start %s; ", default_kernel
);
251 printf("Please use the absolute unit# (e.g. SCSI ID)"
252 " instead of the NetBSD logical #.\n");
259 for (p
= &input
[0]; p
- &input
[0] < 80 && *p
== ' '; p
++);
260 options
= gettrailer(p
);
261 if (strcmp("boot", p
) == 0)
263 else if (strcmp("help", p
) == 0 ||
266 else if ((strcmp("halt", p
) == 0) ||(strcmp("reboot", p
) == 0))
268 else if (strcmp("ls", p
) == 0)
271 printf("Unknown command %s\n", p
);
276 extern const char bootprog_rev
[];
277 extern const char bootprog_name
[];
278 extern const char bootprog_date
[];
279 extern const char bootprog_maker
[];
282 * Arguments from the boot block:
283 * bootdev - specifies the device from which /boot was read, in
287 bootmain(int bootdev
)
289 hostadaptor
= get_scsi_host_adapter();
292 if (mpu
< 3) { /* not tested on 68020 */
293 printf("This MPU cannot run NetBSD.\n");
296 if (SRAM_MEMSIZE
< 4*1024*1024) {
297 printf("Main memory too small.\n");
301 console_device
= consio_init(console_device
);
302 setheap(HEAP_START
, HEAP_END
);
304 switch (B_TYPE(bootdev
)) {
306 default_kernel
[0] = 'f';
307 default_kernel
[2] = '0' + B_UNIT(bootdev
);
308 default_kernel
[3] = 'a';
311 default_kernel
[2] = '0' + B_X68K_SCSI_ID(bootdev
);
313 'a' + sd_getbsdpartition(B_X68K_SCSI_ID(bootdev
),
314 B_X68K_SCSI_PART(bootdev
));
317 default_kernel
[0] = 'c';
318 default_kernel
[2] = '0' + B_X68K_SCSI_ID(bootdev
);
319 default_kernel
[3] = 'a';
322 printf("Warning: unknown boot device: %x\n", bootdev
);
324 print_title("%s, Revision %s\n\t(%s, %s)",
325 bootprog_name
, bootprog_rev
,
326 bootprog_maker
, bootprog_date
);