boot.c revision 1.1 1 1.1 pooka /* $NetBSD: boot.c,v 1.1 2011/01/26 01:18:54 pooka Exp $ */
2 1.1 pooka
3 1.1 pooka /*-
4 1.1 pooka * Copyright (c) 2010 The NetBSD Foundation, Inc.
5 1.1 pooka * Copyright (c) 1999 The NetBSD Foundation, Inc.
6 1.1 pooka * All rights reserved.
7 1.1 pooka *
8 1.1 pooka * This code was written by Alessandro Forin and Neil Pittman
9 1.1 pooka * at Microsoft Research and contributed to The NetBSD Foundation
10 1.1 pooka * by Microsoft Corporation.
11 1.1 pooka *
12 1.1 pooka * Redistribution and use in source and binary forms, with or without
13 1.1 pooka * modification, are permitted provided that the following conditions
14 1.1 pooka * are met:
15 1.1 pooka * 1. Redistributions of source code must retain the above copyright
16 1.1 pooka * notice, this list of conditions and the following disclaimer.
17 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright
18 1.1 pooka * notice, this list of conditions and the following disclaimer in the
19 1.1 pooka * documentation and/or other materials provided with the distribution.
20 1.1 pooka *
21 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 1.1 pooka * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 1.1 pooka * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 1.1 pooka * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 1.1 pooka * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 1.1 pooka * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 1.1 pooka * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 1.1 pooka * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 1.1 pooka * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 1.1 pooka * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 1.1 pooka * POSSIBILITY OF SUCH DAMAGE.
32 1.1 pooka */
33 1.1 pooka
34 1.1 pooka #include <lib/libsa/stand.h>
35 1.1 pooka #include <lib/libsa/loadfile.h>
36 1.1 pooka #include <lib/libkern/libkern.h>
37 1.1 pooka
38 1.1 pooka #include <sys/param.h>
39 1.1 pooka #include <sys/exec.h>
40 1.1 pooka #include <sys/exec_elf.h>
41 1.1 pooka
42 1.1 pooka #include "common.h"
43 1.1 pooka #include "bootinfo.h"
44 1.1 pooka #include "start.h"
45 1.1 pooka
46 1.1 pooka /*
47 1.1 pooka * We won't go overboard with gzip'd kernel names. After all we can
48 1.1 pooka * still boot a gzip'd kernel called "netbsd.emips" - it doesn't need
49 1.1 pooka * the .gz suffix.
50 1.1 pooka */
51 1.1 pooka char *kernelnames[] = {
52 1.1 pooka "netbsd", "netbsd.gz",
53 1.1 pooka "netbsd.old",
54 1.1 pooka "onetbsd",
55 1.1 pooka "gennetbsd",
56 1.1 pooka "nfsnetbsd",
57 1.1 pooka NULL
58 1.1 pooka };
59 1.1 pooka
60 1.1 pooka
61 1.1 pooka void main (char *);
62 1.1 pooka char *getboot(char *, char*);
63 1.1 pooka static int devcanon(char *);
64 1.1 pooka
65 1.1 pooka #define OPT_MAX PATH_MAX /* way overkill */
66 1.1 pooka
67 1.1 pooka static int loadit(char *name, u_long marks[MARK_MAX])
68 1.1 pooka {
69 1.1 pooka printf("Loading: %s\n", name);
70 1.1 pooka memset(marks, 0, sizeof marks);
71 1.1 pooka return (loadfile(name, marks, LOAD_ALL));
72 1.1 pooka }
73 1.1 pooka
74 1.1 pooka /*
75 1.1 pooka * The locore in start.S calls us with an 8KB stack carved after _end.
76 1.1 pooka *
77 1.1 pooka */
78 1.1 pooka void
79 1.1 pooka main(char *stack_top)
80 1.1 pooka {
81 1.1 pooka int argc;
82 1.1 pooka int autoboot = 1, win;
83 1.1 pooka char *name, **namep, *dev, *kernel;
84 1.1 pooka char bootname[PATH_MAX], bootpath[PATH_MAX], options[OPT_MAX];
85 1.1 pooka uint32_t entry;
86 1.1 pooka u_long marks[MARK_MAX];
87 1.1 pooka struct btinfo_symtab bi_syms;
88 1.1 pooka struct btinfo_bootpath bi_bpath;
89 1.1 pooka
90 1.1 pooka /* Init all peripherals, esp USART for printf and memory */
91 1.1 pooka init_board();
92 1.1 pooka
93 1.1 pooka /* On account of compression, we need a fairly large heap.
94 1.1 pooka * To keep things simple, take one meg just below the 16 meg mark.
95 1.1 pooka * That allows for a large kernel, and a 16MB configuration still works.
96 1.1 pooka */
97 1.1 pooka setheap((void *)(0x81000000-(1024*1024)), (void *)0x81000000);
98 1.1 pooka
99 1.1 pooka /* On the BEE3 and the Giano simulator, we need a sec between the serial-line download complete
100 1.1 pooka * and switching the serial line to PuTTY as console. Get a char to pause.
101 1.1 pooka * This delay is also the practice on PCs so.
102 1.1 pooka */
103 1.1 pooka Delay(200000);
104 1.1 pooka printf("Hit any char to boot..");
105 1.1 pooka argc = GetChar();
106 1.1 pooka
107 1.1 pooka /* print a banner */
108 1.1 pooka printf("\n");
109 1.1 pooka printf("NetBSD/emips " NETBSD_VERS " " BOOT_TYPE_NAME " Bootstrap, Revision %s\n",
110 1.1 pooka bootprog_rev);
111 1.1 pooka
112 1.1 pooka /* initialise bootinfo structure early */
113 1.1 pooka bi_init(BOOTINFO_ADDR);
114 1.1 pooka
115 1.1 pooka /* Default is to auto-boot from the first disk */
116 1.1 pooka dev = "0/ace(0,0)/";
117 1.1 pooka kernel = kernelnames[0];
118 1.1 pooka options[0] = 0;
119 1.1 pooka
120 1.1 pooka win = 0;
121 1.1 pooka for (;!win;) {
122 1.1 pooka strcpy(bootpath, dev);
123 1.1 pooka strcat(bootpath, kernel);
124 1.1 pooka name = getboot(bootpath,options);
125 1.1 pooka
126 1.1 pooka if (name != NULL) {
127 1.1 pooka win = (loadit(name, marks) == 0);
128 1.1 pooka } else if (autoboot)
129 1.1 pooka break;
130 1.1 pooka autoboot = 0;
131 1.1 pooka }
132 1.1 pooka
133 1.1 pooka if (!win) {
134 1.1 pooka for (namep = kernelnames, win = 0; *namep != NULL && !win;
135 1.1 pooka namep++) {
136 1.1 pooka kernel = *namep;
137 1.1 pooka strcpy(bootpath, dev);
138 1.1 pooka strcat(bootpath, kernel);
139 1.1 pooka win = (loadit(bootpath, marks) == 0);
140 1.1 pooka if (win) {
141 1.1 pooka name = bootpath;
142 1.1 pooka }
143 1.1 pooka }
144 1.1 pooka }
145 1.1 pooka if (!win)
146 1.1 pooka goto fail;
147 1.1 pooka
148 1.1 pooka strncpy(bi_bpath.bootpath, name/*kernel?*/, BTINFO_BOOTPATH_LEN);
149 1.1 pooka bi_add(&bi_bpath, BTINFO_BOOTPATH, sizeof(bi_bpath));
150 1.1 pooka
151 1.1 pooka entry = marks[MARK_ENTRY];
152 1.1 pooka bi_syms.nsym = marks[MARK_NSYM];
153 1.1 pooka bi_syms.ssym = marks[MARK_SYM];
154 1.1 pooka bi_syms.esym = marks[MARK_END];
155 1.1 pooka bi_add(&bi_syms, BTINFO_SYMTAB, sizeof(bi_syms));
156 1.1 pooka
157 1.1 pooka printf("Starting at 0x%x\n\n", entry);
158 1.1 pooka call_kernel(entry, name, options, BOOTINFO_MAGIC, bootinfo);
159 1.1 pooka (void)printf("KERNEL RETURNED!\n");
160 1.1 pooka
161 1.1 pooka fail:
162 1.1 pooka (void)printf("Boot failed! Halting...\n");
163 1.1 pooka }
164 1.1 pooka
165 1.1 pooka static inline int
166 1.1 pooka parse(char *cmd, char *kname, char *optarg)
167 1.1 pooka {
168 1.1 pooka char *arg = cmd;
169 1.1 pooka char *ep, *p;
170 1.1 pooka int c, i;
171 1.1 pooka
172 1.1 pooka while ((c = *arg++)) {
173 1.1 pooka /* skip leading blanks */
174 1.1 pooka if (c == ' ' || c == '\t' || c == '\n')
175 1.1 pooka continue;
176 1.1 pooka /* find separator, or eol */
177 1.1 pooka for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++);
178 1.1 pooka ep = p;
179 1.1 pooka /* trim if separator */
180 1.1 pooka if (*p)
181 1.1 pooka *p++ = 0;
182 1.1 pooka /* token is either "-opts" or "kernelname" */
183 1.1 pooka if (c == '-') {
184 1.1 pooka /* no overflow because whole line same length as optarg anyways */
185 1.1 pooka while ((c = *arg++)) {
186 1.1 pooka *optarg++ = c;
187 1.1 pooka }
188 1.1 pooka *optarg = 0;
189 1.1 pooka } else {
190 1.1 pooka arg--;
191 1.1 pooka if ((i = ep - arg)) {
192 1.1 pooka if ((size_t)i >= PATH_MAX)
193 1.1 pooka return -1;
194 1.1 pooka memcpy(kname, arg, i + 1);
195 1.1 pooka }
196 1.1 pooka }
197 1.1 pooka arg = p;
198 1.1 pooka }
199 1.1 pooka return 0;
200 1.1 pooka }
201 1.1 pooka
202 1.1 pooka /* String returned is zero-terminated and at most PATH_MAX chars */
203 1.1 pooka static inline void
204 1.1 pooka getstr(char *cmd, int c)
205 1.1 pooka {
206 1.1 pooka char *s;
207 1.1 pooka
208 1.1 pooka s = cmd;
209 1.1 pooka if (c == 0)
210 1.1 pooka c = GetChar();
211 1.1 pooka for (;;) {
212 1.1 pooka switch (c) {
213 1.1 pooka case 0:
214 1.1 pooka break;
215 1.1 pooka case '\177':
216 1.1 pooka case '\b':
217 1.1 pooka if (s > cmd) {
218 1.1 pooka s--;
219 1.1 pooka printf("\b \b");
220 1.1 pooka }
221 1.1 pooka break;
222 1.1 pooka case '\n':
223 1.1 pooka case '\r':
224 1.1 pooka *s = 0;
225 1.1 pooka return;
226 1.1 pooka default:
227 1.1 pooka if ((s - cmd) < (PATH_MAX - 1))
228 1.1 pooka *s++ = c;
229 1.1 pooka xputchar(c);
230 1.1 pooka }
231 1.1 pooka c = GetChar();
232 1.1 pooka }
233 1.1 pooka }
234 1.1 pooka
235 1.1 pooka char *getboot(char *kname, char* optarg)
236 1.1 pooka {
237 1.1 pooka char c = 0;
238 1.1 pooka char cmd[PATH_MAX];
239 1.1 pooka
240 1.1 pooka printf("\nDefault: %s%s %s\nboot: ", (*optarg) ? "-" : "", optarg, kname);
241 1.1 pooka if ((c = GetChar()) == -1)
242 1.1 pooka return NULL;
243 1.1 pooka
244 1.1 pooka cmd[0] = 0;
245 1.1 pooka getstr(cmd,c);
246 1.1 pooka xputchar('\n');
247 1.1 pooka if (parse(cmd,kname,optarg))
248 1.1 pooka xputchar('\a');
249 1.1 pooka else if (devcanon(kname) == 0)
250 1.1 pooka return kname;
251 1.1 pooka return NULL;
252 1.1 pooka }
253 1.1 pooka
254 1.1 pooka /*
255 1.1 pooka * Make bootpath canonical, provides defaults when missing
256 1.1 pooka */
257 1.1 pooka static int
258 1.1 pooka devcanon(char *fname)
259 1.1 pooka {
260 1.1 pooka int ctlr = 0, unit = 0, part = 0;
261 1.1 pooka int c, rc;
262 1.1 pooka char device_name[20];
263 1.1 pooka char file_name[PATH_MAX];
264 1.1 pooka const char *cp;
265 1.1 pooka char *ncp;
266 1.1 pooka
267 1.1 pooka //printf("devcanon(%s)\n",fname);
268 1.1 pooka
269 1.1 pooka cp = fname;
270 1.1 pooka ncp = device_name;
271 1.1 pooka
272 1.1 pooka /* expect a string like '0/ace(0,0)/netbsd' e.g. ctrl/name(unit,part)/file
273 1.1 pooka * Defaults: ctrl=0, name='ace', unit=0, part=0, file=<none>
274 1.1 pooka */
275 1.1 pooka
276 1.1 pooka /* get controller number */
277 1.1 pooka if ((c = *cp) >= '0' && c <= '9') {
278 1.1 pooka ctlr = c - '0';
279 1.1 pooka c = *++cp;
280 1.1 pooka if (c != '/')
281 1.1 pooka return (ENXIO);
282 1.1 pooka c = *++cp;
283 1.1 pooka }
284 1.1 pooka
285 1.1 pooka /* get device name */
286 1.1 pooka while ((c = *cp) != '\0') {
287 1.1 pooka if ((c == '(') || (c == '/')) {
288 1.1 pooka cp++;
289 1.1 pooka break;
290 1.1 pooka }
291 1.1 pooka if (ncp < device_name + sizeof(device_name) - 1)
292 1.1 pooka *ncp++ = c;
293 1.1 pooka cp++;
294 1.1 pooka }
295 1.1 pooka /* set default if missing */
296 1.1 pooka if (ncp == device_name) {
297 1.1 pooka strcpy(device_name,"ace");
298 1.1 pooka ncp += 3;
299 1.1 pooka }
300 1.1 pooka
301 1.1 pooka /* get device number */
302 1.1 pooka if ((c = *cp) >= '0' && c <= '9') {
303 1.1 pooka unit = c - '0';
304 1.1 pooka c = *++cp;
305 1.1 pooka }
306 1.1 pooka
307 1.1 pooka if (c == ',') {
308 1.1 pooka /* get partition number */
309 1.1 pooka if ((c = *++cp) >= '0' && c <= '9') {
310 1.1 pooka part = c - '0';
311 1.1 pooka c = *++cp;
312 1.1 pooka }
313 1.1 pooka }
314 1.1 pooka
315 1.1 pooka if (c == ')')
316 1.1 pooka c = *++cp;
317 1.1 pooka if (c == '/')
318 1.1 pooka cp++;
319 1.1 pooka
320 1.1 pooka *ncp = '\0';
321 1.1 pooka
322 1.1 pooka /* Copy kernel name before we overwrite, then do it */
323 1.1 pooka strcpy(file_name, (*cp) ? cp : kernelnames[0]);
324 1.1 pooka sprintf(fname,"%c/%s(%c,%c)/%s",
325 1.1 pooka ctlr + '0', device_name, unit + '0', part + '0', file_name);
326 1.1 pooka
327 1.1 pooka //printf("devcanon -> %s\n",fname);
328 1.1 pooka
329 1.1 pooka return (0);
330 1.1 pooka }
331