1195033Salc/*	$NetBSD: boot.c,v 1.2.2.2 2012/11/18 19:05:21 riz Exp $	*/
2195033Salc
3195033Salc/*
4195033Salc * Copyright (c) 2001 Minoura Makoto
5195033Salc * All rights reserved.
6195033Salc *
7195033Salc * Redistribution and use in source and binary forms, with or without
8195033Salc * modification, are permitted provided that the following conditions
9195033Salc * are met:
10195033Salc * 1. Redistributions of source code must retain the above copyright
11195033Salc *    notice, this list of conditions and the following disclaimer.
12195033Salc * 2. Redistributions in binary form must reproduce the above copyright
13195033Salc *    notice, this list of conditions and the following disclaimer in the
14195033Salc *    documentation and/or other materials provided with the distribution.
15195033Salc *
16195033Salc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17195033Salc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18195033Salc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19195033Salc * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20195033Salc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21195033Salc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22195033Salc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23195033Salc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24195033Salc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25195033Salc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26195033Salc * SUCH DAMAGE.
27195033Salc */
28195033Salc
29195033Salc#include <sys/param.h>
30195033Salc#include <machine/bootinfo.h>
31195033Salc
32195033Salc#include <lib/libsa/stand.h>
33195033Salc#include <lib/libsa/loadfile.h>
34195033Salc#include <lib/libsa/ufs.h>
35195060Salc#include <lib/libsa/dev_net.h>
36#include <lib/libkern/libkern.h>
37
38#include "libx68k.h"
39#include "iocs.h"
40
41#include "exec_image.h"
42
43
44#define HEAP_START	((void*) 0x00080000)
45#define HEAP_END	((void*) 0x000fffff)
46#define EXSCSI_BDID	((void*) 0x00ea0001)
47#define SRAM_MEMSIZE	(*((long*) 0x00ed0008))
48
49char default_kernel[20] = "nfs:netbsd";
50int mpu;
51int console_device = -1;
52
53#ifdef DEBUG
54int debug = 1;
55#endif
56
57static void help(void);
58static void doboot(const char *, int);
59static void boot(char *);
60int bootmenu(void);
61void bootmain(int);
62extern int detectmpu(void);
63extern int badbaddr(void *);
64
65static void
66help(void)
67{
68	printf("Usage:\n");
69	printf("boot [dev:][file] -[flags]\n");
70	printf(" dev:   nfs, first probed NE2000 is used.\n");
71	printf(" file:  netbsd, netbsd.gz, etc.\n");
72	printf(" flags: abdqsv\n");
73	printf("halt\nreboot\n");
74}
75
76static void
77doboot(const char *file, int flags)
78{
79	u_long		marks[MARK_MAX];
80	int fd;
81	int dev, unit, part;
82	char *name;
83	short *p;
84	int loadflag;
85
86	printf("Starting %s, flags 0x%x\n", file, flags);
87
88	loadflag = LOAD_KERNEL;
89	if (file[0] == 'f')
90		loadflag &= ~LOAD_BACKWARDS;
91
92	marks[MARK_START] = 0x100000;
93	if ((fd = loadfile(file, marks, loadflag)) == -1) {
94		printf("loadfile failed\n");
95		return;
96	}
97	close(fd);
98
99	if (devparse(file, &dev, &unit, &part, &name) != 0) {
100		printf("XXX: unknown corruption in /boot.\n");
101	}
102
103	printf("dev = %x, unit = %d, name = %s\n",
104	       dev, unit, name);
105
106	dev = X68K_MAKEBOOTDEV(X68K_MAJOR_NE, unit, 0);
107	printf("boot device = %x\n", dev);
108	printf("if = %d, unit = %d\n",
109	       B_X68K_SCSI_IF(dev),
110	       B_X68K_SCSI_IF_UN(dev));
111
112	p = ((short*) marks[MARK_ENTRY]) - 1;
113	printf("Kernel Version: 0x%x\n", *p);
114	if (*p != 0x4e73 && *p != 0) {
115		/*
116		 * XXX temporary solution; compatibility loader
117		 * must be written.
118		 */
119		printf("This kernel is too new to be loaded by "
120		       "this version of /boot.\n");
121		return;
122	}
123
124	exec_image(marks[MARK_START], 0, marks[MARK_ENTRY]-marks[MARK_START],
125		   marks[MARK_END]-marks[MARK_START], dev, flags);
126
127	return;
128}
129
130static void
131boot(char *arg)
132{
133	char filename[80];
134	char *p;
135	int flags = 0;
136
137	if (*arg == 0 || *arg == '-') {
138		strcpy(filename, default_kernel);
139		if (*arg == '-')
140			if (parseopts(arg, &flags) == 0) {
141				help();
142				return;
143			}
144		doboot(filename, flags);
145		return;
146	} else {
147		p = gettrailer(arg);
148		if (strchr(arg, ':')) {
149			strcpy(filename, arg);
150			if (arg[strlen(arg) - 1] == ':')
151				strcat(filename, "netbsd");
152		} else {
153			strcpy(filename, default_kernel);
154			strcpy(strchr(filename, ':') + 1, arg);
155		}
156		if (*p == '-') {
157			if (parseopts(p, &flags) == 0)
158				return;
159		} else if (*p != 0) {
160			help();
161			return;
162		}
163
164		doboot(filename, flags);
165		return;
166	}
167}
168
169int
170bootmenu(void)
171{
172	char input[80];
173	int n = 5, c;
174
175	printf("Press return to boot now, any other key for boot menu\n");
176	printf("booting %s - starting in %d seconds. ",
177		default_kernel, n);
178	while (n-- > 0 && (c = awaitkey_1sec()) == 0) {
179		printf("\r");
180		printf("booting %s - starting in %d seconds. ",
181		       default_kernel, n);
182	}
183	printf("\r");
184	printf("booting %s - starting in %d seconds. ", default_kernel, 0);
185	printf("\n");
186
187	if (c == 0 || c == '\r') {
188		doboot(default_kernel, 0);
189		printf("Could not start %s; ", default_kernel);
190		strcat(default_kernel, ".gz");
191		printf("trying %s.\n", default_kernel);
192		doboot(default_kernel, 0);
193		printf("Could not start %s; ", default_kernel);
194	}
195
196	printf("Please use the absolute unit# (e.g. SCSI ID)"
197	       " instead of the NetBSD logical #.\n");
198	for (;;) {
199		char *p, *options;
200
201		printf("> ");
202		gets(input);
203
204		for (p = &input[0]; p - &input[0] < 80 && *p == ' '; p++)
205			;
206		options = gettrailer(p);
207		if (strcmp("boot", p) == 0)
208			boot(options);
209		else if (strcmp("help", p) == 0 || strcmp("?", p) == 0)
210			help();
211		else if (strcmp("halt", p) == 0 || strcmp("reboot", p) == 0)
212			exit(0);
213		else
214			printf("Unknown command %s\n", p);
215	}
216}
217
218
219extern const char bootprog_rev[];
220extern const char bootprog_name[];
221
222/*
223 * Arguments from the boot block:
224 *   bootdev - specifies the device from which /boot was read, in
225 *		bootdev format.
226 */
227void
228bootmain(int bootdev)
229{
230	mpu = detectmpu();
231	rtc_offset = RTC_OFFSET;
232	try_bootp = 1;
233
234	if (mpu < 3) {		/* not tested on 68020 */
235		printf("This MPU cannot run NetBSD.\n");
236		exit(1);
237	}
238	if (SRAM_MEMSIZE < 4*1024*1024) {
239		printf("Main memory too small.\n");
240		exit(1);
241	}
242
243	console_device = consio_init(console_device);
244	setheap(HEAP_START, HEAP_END);
245
246	print_title("%s, Revision %s\n", bootprog_name, bootprog_rev);
247	bootmenu();
248}
249