main.c revision 1.7.2.3 1 1.7.2.2 rmind /* $NetBSD: main.c,v 1.7.2.3 2011/04/21 01:41:22 rmind Exp $ */
2 1.7.2.2 rmind
3 1.7.2.2 rmind /*-
4 1.7.2.2 rmind * Copyright (c) 2007 The NetBSD Foundation, Inc.
5 1.7.2.2 rmind * All rights reserved.
6 1.7.2.2 rmind *
7 1.7.2.2 rmind * This code is derived from software contributed to The NetBSD Foundation
8 1.7.2.2 rmind * by Tohru Nishimura.
9 1.7.2.2 rmind *
10 1.7.2.2 rmind * Redistribution and use in source and binary forms, with or without
11 1.7.2.2 rmind * modification, are permitted provided that the following conditions
12 1.7.2.2 rmind * are met:
13 1.7.2.2 rmind * 1. Redistributions of source code must retain the above copyright
14 1.7.2.2 rmind * notice, this list of conditions and the following disclaimer.
15 1.7.2.2 rmind * 2. Redistributions in binary form must reproduce the above copyright
16 1.7.2.2 rmind * notice, this list of conditions and the following disclaimer in the
17 1.7.2.2 rmind * documentation and/or other materials provided with the distribution.
18 1.7.2.2 rmind *
19 1.7.2.2 rmind * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.7.2.2 rmind * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.7.2.2 rmind * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.7.2.2 rmind * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.7.2.2 rmind * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.7.2.2 rmind * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.7.2.2 rmind * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.7.2.2 rmind * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.7.2.2 rmind * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.7.2.2 rmind * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.7.2.2 rmind * POSSIBILITY OF SUCH DAMAGE.
30 1.7.2.2 rmind */
31 1.7.2.2 rmind
32 1.7.2.2 rmind #include <sys/param.h>
33 1.7.2.2 rmind #include <sys/reboot.h>
34 1.7.2.2 rmind
35 1.7.2.2 rmind #include <lib/libsa/stand.h>
36 1.7.2.2 rmind #include <lib/libsa/loadfile.h>
37 1.7.2.2 rmind #include <lib/libkern/libkern.h>
38 1.7.2.2 rmind
39 1.7.2.2 rmind #include <machine/bootinfo.h>
40 1.7.2.2 rmind
41 1.7.2.2 rmind #include "globals.h"
42 1.7.2.2 rmind
43 1.7.2.2 rmind static const struct bootarg {
44 1.7.2.2 rmind const char *name;
45 1.7.2.2 rmind int value;
46 1.7.2.2 rmind } bootargs[] = {
47 1.7.2.2 rmind { "multi", RB_AUTOBOOT },
48 1.7.2.2 rmind { "auto", RB_AUTOBOOT },
49 1.7.2.2 rmind { "ask", RB_ASKNAME },
50 1.7.2.2 rmind { "single", RB_SINGLE },
51 1.7.2.2 rmind { "ddb", RB_KDB },
52 1.7.2.2 rmind { "userconf", RB_USERCONF },
53 1.7.2.2 rmind { "norm", AB_NORMAL },
54 1.7.2.2 rmind { "quiet", AB_QUIET },
55 1.7.2.2 rmind { "verb", AB_VERBOSE },
56 1.7.2.2 rmind { "silent", AB_SILENT },
57 1.7.2.3 rmind { "debug", AB_DEBUG },
58 1.7.2.3 rmind { "altboot", -1 }
59 1.7.2.2 rmind };
60 1.7.2.2 rmind
61 1.7.2.2 rmind void *bootinfo; /* low memory reserved to pass bootinfo structures */
62 1.7.2.2 rmind int bi_size; /* BOOTINFO_MAXSIZE */
63 1.7.2.2 rmind char *bi_next;
64 1.7.2.2 rmind
65 1.7.2.2 rmind void bi_init(void *);
66 1.7.2.2 rmind void bi_add(void *, int, int);
67 1.7.2.2 rmind
68 1.7.2.2 rmind struct btinfo_memory bi_mem;
69 1.7.2.2 rmind struct btinfo_console bi_cons;
70 1.7.2.2 rmind struct btinfo_clock bi_clk;
71 1.7.2.2 rmind struct btinfo_prodfamily bi_fam;
72 1.7.2.2 rmind struct btinfo_bootpath bi_path;
73 1.7.2.2 rmind struct btinfo_rootdevice bi_rdev;
74 1.7.2.2 rmind struct btinfo_net bi_net;
75 1.7.2.2 rmind struct btinfo_modulelist *btinfo_modulelist;
76 1.7.2.2 rmind size_t btinfo_modulelist_size;
77 1.7.2.2 rmind
78 1.7.2.2 rmind struct boot_module {
79 1.7.2.2 rmind char *bm_kmod;
80 1.7.2.2 rmind ssize_t bm_len;
81 1.7.2.2 rmind struct boot_module *bm_next;
82 1.7.2.2 rmind };
83 1.7.2.2 rmind struct boot_module *boot_modules;
84 1.7.2.2 rmind char module_base[80];
85 1.7.2.2 rmind uint32_t kmodloadp;
86 1.7.2.2 rmind int modules_enabled = 0;
87 1.7.2.2 rmind
88 1.7.2.2 rmind void module_add(char *);
89 1.7.2.2 rmind void module_load(char *);
90 1.7.2.2 rmind int module_open(struct boot_module *);
91 1.7.2.2 rmind
92 1.7.2.2 rmind void main(int, char **, char *, char *);
93 1.7.2.3 rmind
94 1.7.2.2 rmind extern char bootprog_name[], bootprog_rev[];
95 1.7.2.3 rmind extern char newaltboot[], newaltboot_end[];
96 1.7.2.2 rmind
97 1.7.2.2 rmind struct pcidev lata[2];
98 1.7.2.2 rmind struct pcidev lnif[1];
99 1.7.2.2 rmind struct pcidev lusb[3];
100 1.7.2.2 rmind int nata, nnif, nusb;
101 1.7.2.2 rmind
102 1.7.2.2 rmind int brdtype;
103 1.7.2.2 rmind uint32_t busclock, cpuclock;
104 1.7.2.2 rmind
105 1.7.2.2 rmind static int check_bootname(char *);
106 1.7.2.3 rmind static int input_cmdline(char **, int);
107 1.7.2.2 rmind static int parse_cmdline(char **, int, char *, char *);
108 1.7.2.2 rmind static int is_space(char);
109 1.7.2.2 rmind
110 1.7.2.3 rmind #define BNAME_DEFAULT "wd0:"
111 1.7.2.2 rmind #define MAX_ARGS 10
112 1.7.2.2 rmind
113 1.7.2.2 rmind void
114 1.7.2.2 rmind main(int argc, char *argv[], char *bootargs_start, char *bootargs_end)
115 1.7.2.2 rmind {
116 1.7.2.2 rmind struct brdprop *brdprop;
117 1.7.2.2 rmind unsigned long marks[MARK_MAX];
118 1.7.2.2 rmind char *new_argv[MAX_ARGS];
119 1.7.2.3 rmind ssize_t len;
120 1.7.2.2 rmind int n, i, fd, howto;
121 1.7.2.2 rmind char *bname;
122 1.7.2.2 rmind
123 1.7.2.2 rmind printf("\n");
124 1.7.2.2 rmind printf(">> %s altboot, revision %s\n", bootprog_name, bootprog_rev);
125 1.7.2.2 rmind
126 1.7.2.2 rmind brdprop = brd_lookup(brdtype);
127 1.7.2.2 rmind printf(">> %s, cpu %u MHz, bus %u MHz, %dMB SDRAM\n", brdprop->verbose,
128 1.7.2.2 rmind cpuclock / 1000000, busclock / 1000000, bi_mem.memsize >> 20);
129 1.7.2.2 rmind
130 1.7.2.2 rmind nata = pcilookup(PCI_CLASS_IDE, lata, 2);
131 1.7.2.2 rmind if (nata == 0)
132 1.7.2.2 rmind nata = pcilookup(PCI_CLASS_MISCSTORAGE, lata, 2);
133 1.7.2.3 rmind if (nata == 0)
134 1.7.2.3 rmind nata = pcilookup(PCI_CLASS_SCSI, lata, 2);
135 1.7.2.2 rmind nnif = pcilookup(PCI_CLASS_ETH, lnif, 1);
136 1.7.2.2 rmind nusb = pcilookup(PCI_CLASS_USB, lusb, 3);
137 1.7.2.2 rmind
138 1.7.2.2 rmind #ifdef DEBUG
139 1.7.2.2 rmind if (nata == 0)
140 1.7.2.2 rmind printf("No IDE/SATA found\n");
141 1.7.2.2 rmind else for (n = 0; n < nata; n++) {
142 1.7.2.2 rmind int b, d, f, bdf, pvd;
143 1.7.2.2 rmind bdf = lata[n].bdf;
144 1.7.2.2 rmind pvd = lata[n].pvd;
145 1.7.2.2 rmind pcidecomposetag(bdf, &b, &d, &f);
146 1.7.2.2 rmind printf("%04x.%04x DSK %02d:%02d:%02d\n",
147 1.7.2.2 rmind PCI_VENDOR(pvd), PCI_PRODUCT(pvd), b, d, f);
148 1.7.2.2 rmind }
149 1.7.2.2 rmind if (nnif == 0)
150 1.7.2.2 rmind printf("no NET found\n");
151 1.7.2.2 rmind else {
152 1.7.2.2 rmind int b, d, f, bdf, pvd;
153 1.7.2.2 rmind bdf = lnif[0].bdf;
154 1.7.2.2 rmind pvd = lnif[0].pvd;
155 1.7.2.2 rmind pcidecomposetag(bdf, &b, &d, &f);
156 1.7.2.2 rmind printf("%04x.%04x NET %02d:%02d:%02d\n",
157 1.7.2.2 rmind PCI_VENDOR(pvd), PCI_PRODUCT(pvd), b, d, f);
158 1.7.2.2 rmind }
159 1.7.2.2 rmind if (nusb == 0)
160 1.7.2.2 rmind printf("no USB found\n");
161 1.7.2.2 rmind else for (n = 0; n < nusb; n++) {
162 1.7.2.2 rmind int b, d, f, bdf, pvd;
163 1.7.2.2 rmind bdf = lusb[0].bdf;
164 1.7.2.2 rmind pvd = lusb[0].pvd;
165 1.7.2.2 rmind pcidecomposetag(bdf, &b, &d, &f);
166 1.7.2.2 rmind printf("%04x.%04x USB %02d:%02d:%02d\n",
167 1.7.2.2 rmind PCI_VENDOR(pvd), PCI_PRODUCT(pvd), b, d, f);
168 1.7.2.2 rmind }
169 1.7.2.2 rmind #endif
170 1.7.2.2 rmind
171 1.7.2.2 rmind pcisetup();
172 1.7.2.2 rmind pcifixup();
173 1.7.2.2 rmind
174 1.7.2.2 rmind if (dskdv_init(&lata[0]) == 0
175 1.7.2.2 rmind || (nata == 2 && dskdv_init(&lata[1]) == 0))
176 1.7.2.2 rmind printf("IDE/SATA device driver was not found\n");
177 1.7.2.2 rmind
178 1.7.2.2 rmind if (netif_init(&lnif[0]) == 0)
179 1.7.2.2 rmind printf("no NET device driver was found\n");
180 1.7.2.2 rmind
181 1.7.2.2 rmind /*
182 1.7.2.2 rmind * When argc is too big then it is probably a pointer, which could
183 1.7.2.2 rmind * indicate that we were launched as a Linux kernel module using
184 1.7.2.2 rmind * "bootm".
185 1.7.2.2 rmind */
186 1.7.2.2 rmind if (argc > MAX_ARGS) {
187 1.7.2.3 rmind if (argv != NULL) {
188 1.7.2.3 rmind /*
189 1.7.2.3 rmind * initrd image was loaded: assume extremely
190 1.7.2.3 rmind * restricted firmware and boot default
191 1.7.2.3 rmind */
192 1.7.2.3 rmind argc = 0;
193 1.7.2.3 rmind } else {
194 1.7.2.3 rmind /* parse standard Linux bootargs */
195 1.7.2.3 rmind argc = parse_cmdline(new_argv, MAX_ARGS,
196 1.7.2.3 rmind bootargs_start, bootargs_end);
197 1.7.2.3 rmind argv = new_argv;
198 1.7.2.3 rmind }
199 1.7.2.3 rmind }
200 1.7.2.3 rmind
201 1.7.2.3 rmind /* wait 2s for user to enter interactive mode */
202 1.7.2.3 rmind for (n = 200; n >= 0; n--) {
203 1.7.2.3 rmind if (n % 100 == 0)
204 1.7.2.3 rmind printf("Hit any key to enter interactive mode: %d\r",
205 1.7.2.3 rmind n / 100);
206 1.7.2.3 rmind if (tstchar()) {
207 1.7.2.3 rmind (void)getchar();
208 1.7.2.3 rmind argv = new_argv;
209 1.7.2.3 rmind argc = input_cmdline(argv, MAX_ARGS);
210 1.7.2.3 rmind break;
211 1.7.2.3 rmind }
212 1.7.2.3 rmind delay(10000);
213 1.7.2.2 rmind }
214 1.7.2.3 rmind putchar('\n');
215 1.7.2.2 rmind
216 1.7.2.2 rmind howto = RB_AUTOBOOT; /* default is autoboot = 0 */
217 1.7.2.2 rmind
218 1.7.2.2 rmind /* get boot options and determine bootname */
219 1.7.2.2 rmind for (n = 1; n < argc; n++) {
220 1.7.2.2 rmind for (i = 0; i < sizeof(bootargs) / sizeof(bootargs[0]); i++) {
221 1.7.2.2 rmind if (strncasecmp(argv[n], bootargs[i].name,
222 1.7.2.2 rmind strlen(bootargs[i].name)) == 0) {
223 1.7.2.2 rmind howto |= bootargs[i].value;
224 1.7.2.2 rmind break;
225 1.7.2.2 rmind }
226 1.7.2.2 rmind }
227 1.7.2.2 rmind if (i >= sizeof(bootargs) / sizeof(bootargs[0]))
228 1.7.2.2 rmind break; /* break on first unknown string */
229 1.7.2.2 rmind }
230 1.7.2.2 rmind if (n >= argc)
231 1.7.2.2 rmind bname = BNAME_DEFAULT;
232 1.7.2.2 rmind else {
233 1.7.2.2 rmind bname = argv[n];
234 1.7.2.2 rmind if (check_bootname(bname) == 0) {
235 1.7.2.2 rmind printf("%s not a valid bootname\n", bname);
236 1.7.2.2 rmind goto loadfail;
237 1.7.2.2 rmind }
238 1.7.2.2 rmind }
239 1.7.2.2 rmind
240 1.7.2.2 rmind if ((fd = open(bname, 0)) < 0) {
241 1.7.2.2 rmind if (errno == ENOENT)
242 1.7.2.2 rmind printf("\"%s\" not found\n", bi_path.bootpath);
243 1.7.2.2 rmind goto loadfail;
244 1.7.2.2 rmind }
245 1.7.2.2 rmind printf("loading \"%s\" ", bi_path.bootpath);
246 1.7.2.2 rmind marks[MARK_START] = 0;
247 1.7.2.3 rmind
248 1.7.2.3 rmind if (howto == -1) {
249 1.7.2.3 rmind /* load another altboot binary and replace ourselves */
250 1.7.2.3 rmind len = read(fd, (void *)0x100000, 0x1000000 - 0x100000);
251 1.7.2.3 rmind if (len == -1)
252 1.7.2.3 rmind goto loadfail;
253 1.7.2.3 rmind close(fd);
254 1.7.2.3 rmind netif_shutdown_all();
255 1.7.2.3 rmind
256 1.7.2.3 rmind memcpy((void *)0xf0000, newaltboot,
257 1.7.2.3 rmind newaltboot_end - newaltboot);
258 1.7.2.3 rmind __syncicache((void *)0xf0000, newaltboot_end - newaltboot);
259 1.7.2.3 rmind printf("Restarting...\n");
260 1.7.2.3 rmind run((void *)1, argv, (void *)0x100000, (void *)len,
261 1.7.2.3 rmind (void *)0xf0000);
262 1.7.2.3 rmind } else if (fdloadfile(fd, marks, LOAD_KERNEL) < 0)
263 1.7.2.2 rmind goto loadfail;
264 1.7.2.2 rmind close(fd);
265 1.7.2.2 rmind
266 1.7.2.2 rmind printf("entry=%p, ssym=%p, esym=%p\n",
267 1.7.2.2 rmind (void *)marks[MARK_ENTRY],
268 1.7.2.2 rmind (void *)marks[MARK_SYM],
269 1.7.2.2 rmind (void *)marks[MARK_END]);
270 1.7.2.2 rmind
271 1.7.2.2 rmind bootinfo = (void *)0x4000;
272 1.7.2.2 rmind bi_init(bootinfo);
273 1.7.2.2 rmind bi_add(&bi_cons, BTINFO_CONSOLE, sizeof(bi_cons));
274 1.7.2.2 rmind bi_add(&bi_mem, BTINFO_MEMORY, sizeof(bi_mem));
275 1.7.2.2 rmind bi_add(&bi_clk, BTINFO_CLOCK, sizeof(bi_clk));
276 1.7.2.2 rmind bi_add(&bi_path, BTINFO_BOOTPATH, sizeof(bi_path));
277 1.7.2.2 rmind bi_add(&bi_rdev, BTINFO_ROOTDEVICE, sizeof(bi_rdev));
278 1.7.2.2 rmind bi_add(&bi_fam, BTINFO_PRODFAMILY, sizeof(bi_fam));
279 1.7.2.3 rmind if (brdtype == BRD_SYNOLOGY || brdtype == BRD_DLINKDSM) {
280 1.7.2.3 rmind /* need to set this MAC address in kernel driver later */
281 1.7.2.2 rmind bi_add(&bi_net, BTINFO_NET, sizeof(bi_net));
282 1.7.2.2 rmind }
283 1.7.2.2 rmind
284 1.7.2.2 rmind if (modules_enabled) {
285 1.7.2.2 rmind module_add(fsmod);
286 1.7.2.2 rmind if (fsmod2 != NULL && strcmp(fsmod, fsmod2) != 0)
287 1.7.2.2 rmind module_add(fsmod2);
288 1.7.2.2 rmind kmodloadp = marks[MARK_END];
289 1.7.2.2 rmind btinfo_modulelist = NULL;
290 1.7.2.2 rmind module_load(bname);
291 1.7.2.2 rmind if (btinfo_modulelist != NULL && btinfo_modulelist->num > 0)
292 1.7.2.2 rmind bi_add(btinfo_modulelist, BTINFO_MODULELIST,
293 1.7.2.2 rmind btinfo_modulelist_size);
294 1.7.2.2 rmind }
295 1.7.2.2 rmind
296 1.7.2.3 rmind netif_shutdown_all();
297 1.7.2.3 rmind
298 1.7.2.2 rmind __syncicache((void *)marks[MARK_ENTRY],
299 1.7.2.2 rmind (u_int)marks[MARK_SYM] - (u_int)marks[MARK_ENTRY]);
300 1.7.2.2 rmind
301 1.7.2.2 rmind run((void *)marks[MARK_SYM], (void *)marks[MARK_END],
302 1.7.2.2 rmind (void *)howto, bootinfo, (void *)marks[MARK_ENTRY]);
303 1.7.2.2 rmind
304 1.7.2.2 rmind /* should never come here */
305 1.7.2.2 rmind printf("exec returned. Restarting...\n");
306 1.7.2.2 rmind _rtt();
307 1.7.2.2 rmind
308 1.7.2.2 rmind loadfail:
309 1.7.2.2 rmind printf("load failed. Restarting...\n");
310 1.7.2.2 rmind _rtt();
311 1.7.2.2 rmind }
312 1.7.2.2 rmind
313 1.7.2.2 rmind void
314 1.7.2.2 rmind bi_init(void *addr)
315 1.7.2.2 rmind {
316 1.7.2.2 rmind struct btinfo_magic bi_magic;
317 1.7.2.2 rmind
318 1.7.2.2 rmind memset(addr, 0, BOOTINFO_MAXSIZE);
319 1.7.2.2 rmind bi_next = (char *)addr;
320 1.7.2.2 rmind bi_size = 0;
321 1.7.2.2 rmind
322 1.7.2.2 rmind bi_magic.magic = BOOTINFO_MAGIC;
323 1.7.2.2 rmind bi_add(&bi_magic, BTINFO_MAGIC, sizeof(bi_magic));
324 1.7.2.2 rmind }
325 1.7.2.2 rmind
326 1.7.2.2 rmind void
327 1.7.2.2 rmind bi_add(void *new, int type, int size)
328 1.7.2.2 rmind {
329 1.7.2.2 rmind struct btinfo_common *bi;
330 1.7.2.2 rmind
331 1.7.2.2 rmind if (bi_size + size > BOOTINFO_MAXSIZE)
332 1.7.2.2 rmind return; /* XXX error? */
333 1.7.2.2 rmind
334 1.7.2.2 rmind bi = new;
335 1.7.2.2 rmind bi->next = size;
336 1.7.2.2 rmind bi->type = type;
337 1.7.2.2 rmind memcpy(bi_next, new, size);
338 1.7.2.2 rmind bi_next += size;
339 1.7.2.2 rmind }
340 1.7.2.2 rmind
341 1.7.2.2 rmind void
342 1.7.2.2 rmind module_add(char *name)
343 1.7.2.2 rmind {
344 1.7.2.2 rmind struct boot_module *bm, *bmp;
345 1.7.2.2 rmind
346 1.7.2.2 rmind while (*name == ' ' || *name == '\t')
347 1.7.2.2 rmind ++name;
348 1.7.2.2 rmind
349 1.7.2.2 rmind bm = alloc(sizeof(struct boot_module) + strlen(name) + 1);
350 1.7.2.2 rmind if (bm == NULL) {
351 1.7.2.2 rmind printf("couldn't allocate module %s\n", name);
352 1.7.2.2 rmind return;
353 1.7.2.2 rmind }
354 1.7.2.2 rmind
355 1.7.2.2 rmind bm->bm_kmod = (char *)(bm + 1);
356 1.7.2.2 rmind bm->bm_len = -1;
357 1.7.2.2 rmind bm->bm_next = NULL;
358 1.7.2.2 rmind strcpy(bm->bm_kmod, name);
359 1.7.2.2 rmind if ((bmp = boot_modules) == NULL)
360 1.7.2.2 rmind boot_modules = bm;
361 1.7.2.2 rmind else {
362 1.7.2.2 rmind while (bmp->bm_next != NULL)
363 1.7.2.2 rmind bmp = bmp->bm_next;
364 1.7.2.2 rmind bmp->bm_next = bm;
365 1.7.2.2 rmind }
366 1.7.2.2 rmind }
367 1.7.2.2 rmind
368 1.7.2.2 rmind #define PAGE_SIZE 4096
369 1.7.2.2 rmind #define alignpg(x) (((x)+PAGE_SIZE-1) & ~(PAGE_SIZE-1))
370 1.7.2.2 rmind
371 1.7.2.2 rmind void
372 1.7.2.2 rmind module_load(char *kernel_path)
373 1.7.2.2 rmind {
374 1.7.2.2 rmind struct boot_module *bm;
375 1.7.2.2 rmind struct bi_modulelist_entry *bi;
376 1.7.2.2 rmind struct stat st;
377 1.7.2.2 rmind char *p;
378 1.7.2.2 rmind int size, fd;
379 1.7.2.2 rmind
380 1.7.2.2 rmind strcpy(module_base, kernel_path);
381 1.7.2.2 rmind if ((p = strchr(module_base, ':')) == NULL)
382 1.7.2.2 rmind return; /* eeh?! */
383 1.7.2.2 rmind p += 1;
384 1.7.2.2 rmind size = sizeof(module_base) - (p - module_base);
385 1.7.2.2 rmind
386 1.7.2.2 rmind if (netbsd_version / 1000000 % 100 == 99) {
387 1.7.2.2 rmind /* -current */
388 1.7.2.2 rmind snprintf(p, size,
389 1.7.2.2 rmind "/stand/sandpoint/%d.%d.%d/modules",
390 1.7.2.2 rmind netbsd_version / 100000000,
391 1.7.2.2 rmind netbsd_version / 1000000 % 100,
392 1.7.2.2 rmind netbsd_version / 100 % 100);
393 1.7.2.2 rmind }
394 1.7.2.2 rmind else if (netbsd_version != 0) {
395 1.7.2.2 rmind /* release */
396 1.7.2.2 rmind snprintf(p, size,
397 1.7.2.2 rmind "/stand/sandpoint/%d.%d/modules",
398 1.7.2.2 rmind netbsd_version / 100000000,
399 1.7.2.2 rmind netbsd_version / 1000000 % 100);
400 1.7.2.2 rmind }
401 1.7.2.2 rmind
402 1.7.2.2 rmind /*
403 1.7.2.2 rmind * 1st pass; determine module existence
404 1.7.2.2 rmind */
405 1.7.2.2 rmind size = 0;
406 1.7.2.2 rmind for (bm = boot_modules; bm != NULL; bm = bm->bm_next) {
407 1.7.2.2 rmind fd = module_open(bm);
408 1.7.2.2 rmind if (fd == -1)
409 1.7.2.2 rmind continue;
410 1.7.2.2 rmind if (fstat(fd, &st) == -1 || st.st_size == -1) {
411 1.7.2.2 rmind printf("WARNING: couldn't stat %s\n", bm->bm_kmod);
412 1.7.2.2 rmind close(fd);
413 1.7.2.2 rmind continue;
414 1.7.2.2 rmind }
415 1.7.2.2 rmind bm->bm_len = (int)st.st_size;
416 1.7.2.2 rmind close(fd);
417 1.7.2.2 rmind size += sizeof(struct bi_modulelist_entry);
418 1.7.2.2 rmind }
419 1.7.2.2 rmind if (size == 0)
420 1.7.2.2 rmind return;
421 1.7.2.2 rmind
422 1.7.2.2 rmind size += sizeof(struct btinfo_modulelist);
423 1.7.2.2 rmind btinfo_modulelist = alloc(size);
424 1.7.2.2 rmind if (btinfo_modulelist == NULL) {
425 1.7.2.2 rmind printf("WARNING: couldn't allocate module list\n");
426 1.7.2.2 rmind return;
427 1.7.2.2 rmind }
428 1.7.2.2 rmind btinfo_modulelist_size = size;
429 1.7.2.2 rmind btinfo_modulelist->num = 0;
430 1.7.2.2 rmind
431 1.7.2.2 rmind /*
432 1.7.2.2 rmind * 2nd pass; load modules into memory
433 1.7.2.2 rmind */
434 1.7.2.2 rmind kmodloadp = alignpg(kmodloadp);
435 1.7.2.2 rmind bi = (struct bi_modulelist_entry *)(btinfo_modulelist + 1);
436 1.7.2.2 rmind for (bm = boot_modules; bm != NULL; bm = bm->bm_next) {
437 1.7.2.2 rmind if (bm->bm_len == -1)
438 1.7.2.2 rmind continue; /* already found unavailable */
439 1.7.2.2 rmind fd = module_open(bm);
440 1.7.2.2 rmind printf("module \"%s\" ", bm->bm_kmod);
441 1.7.2.2 rmind size = read(fd, (char *)kmodloadp, SSIZE_MAX);
442 1.7.2.2 rmind if (size < bm->bm_len)
443 1.7.2.2 rmind printf("WARNING: couldn't load");
444 1.7.2.2 rmind else {
445 1.7.2.2 rmind snprintf(bi->kmod, sizeof(bi->kmod), bm->bm_kmod);
446 1.7.2.2 rmind bi->type = BI_MODULE_ELF;
447 1.7.2.2 rmind bi->len = size;
448 1.7.2.2 rmind bi->base = kmodloadp;
449 1.7.2.2 rmind btinfo_modulelist->num += 1;
450 1.7.2.2 rmind printf("loaded at 0x%08x size 0x%x", kmodloadp, size);
451 1.7.2.2 rmind kmodloadp += alignpg(size);
452 1.7.2.2 rmind bi += 1;
453 1.7.2.2 rmind }
454 1.7.2.2 rmind printf("\n");
455 1.7.2.2 rmind close(fd);
456 1.7.2.2 rmind }
457 1.7.2.2 rmind btinfo_modulelist->endpa = kmodloadp;
458 1.7.2.2 rmind }
459 1.7.2.2 rmind
460 1.7.2.2 rmind int
461 1.7.2.2 rmind module_open(struct boot_module *bm)
462 1.7.2.2 rmind {
463 1.7.2.2 rmind char path[80];
464 1.7.2.2 rmind int fd;
465 1.7.2.2 rmind
466 1.7.2.2 rmind snprintf(path, sizeof(path),
467 1.7.2.2 rmind "%s/%s/%s.kmod", module_base, bm->bm_kmod, bm->bm_kmod);
468 1.7.2.2 rmind fd = open(path, 0);
469 1.7.2.2 rmind return fd;
470 1.7.2.2 rmind }
471 1.7.2.2 rmind
472 1.7.2.2 rmind #if 0
473 1.7.2.2 rmind static const char *cmdln[] = {
474 1.7.2.2 rmind "console=ttyS0,115200 root=/dev/sda1 rw initrd=0x200000,2M",
475 1.7.2.2 rmind "console=ttyS0,115200 root=/dev/nfs ip=dhcp"
476 1.7.2.2 rmind };
477 1.7.2.2 rmind
478 1.7.2.2 rmind void
479 1.7.2.2 rmind mkatagparams(unsigned addr, char *kcmd)
480 1.7.2.2 rmind {
481 1.7.2.2 rmind struct tag {
482 1.7.2.2 rmind unsigned siz;
483 1.7.2.2 rmind unsigned tag;
484 1.7.2.2 rmind unsigned val[1];
485 1.7.2.2 rmind };
486 1.7.2.2 rmind struct tag *p;
487 1.7.2.2 rmind #define ATAG_CORE 0x54410001
488 1.7.2.2 rmind #define ATAG_MEM 0x54410002
489 1.7.2.2 rmind #define ATAG_INITRD 0x54410005
490 1.7.2.2 rmind #define ATAG_CMDLINE 0x54410009
491 1.7.2.2 rmind #define ATAG_NONE 0x00000000
492 1.7.2.2 rmind #define tagnext(p) (struct tag *)((unsigned *)(p) + (p)->siz)
493 1.7.2.2 rmind #define tagsize(n) (2 + (n))
494 1.7.2.2 rmind
495 1.7.2.2 rmind p = (struct tag *)addr;
496 1.7.2.2 rmind p->tag = ATAG_CORE;
497 1.7.2.2 rmind p->siz = tagsize(3);
498 1.7.2.2 rmind p->val[0] = 0; /* flags */
499 1.7.2.2 rmind p->val[1] = 0; /* pagesize */
500 1.7.2.2 rmind p->val[2] = 0; /* rootdev */
501 1.7.2.2 rmind p = tagnext(p);
502 1.7.2.2 rmind p->tag = ATAG_MEM;
503 1.7.2.2 rmind p->siz = tagsize(2);
504 1.7.2.2 rmind p->val[0] = 64 * 1024 * 1024;
505 1.7.2.2 rmind p->val[1] = 0; /* start */
506 1.7.2.2 rmind p = tagnext(p);
507 1.7.2.2 rmind if (kcmd != NULL) {
508 1.7.2.2 rmind p = tagnext(p);
509 1.7.2.2 rmind p->tag = ATAG_CMDLINE;
510 1.7.2.2 rmind p->siz = tagsize((strlen(kcmd) + 1 + 3) >> 2);
511 1.7.2.2 rmind strcpy((void *)p->val, kcmd);
512 1.7.2.2 rmind }
513 1.7.2.2 rmind p = tagnext(p);
514 1.7.2.2 rmind p->tag = ATAG_NONE;
515 1.7.2.2 rmind p->siz = 0;
516 1.7.2.2 rmind }
517 1.7.2.2 rmind #endif
518 1.7.2.2 rmind
519 1.7.2.2 rmind void *
520 1.7.2.2 rmind allocaligned(size_t size, size_t align)
521 1.7.2.2 rmind {
522 1.7.2.2 rmind uint32_t p;
523 1.7.2.2 rmind
524 1.7.2.2 rmind if (align-- < 2)
525 1.7.2.2 rmind return alloc(size);
526 1.7.2.2 rmind p = (uint32_t)alloc(size + align);
527 1.7.2.2 rmind return (void *)((p + align) & ~align);
528 1.7.2.2 rmind }
529 1.7.2.2 rmind
530 1.7.2.3 rmind static int hex2nibble(char c)
531 1.7.2.3 rmind {
532 1.7.2.3 rmind
533 1.7.2.3 rmind if (c >= 'a')
534 1.7.2.3 rmind c &= ~0x20;
535 1.7.2.3 rmind if (c >= 'A' && c <= 'F')
536 1.7.2.3 rmind c -= 'A' - ('9' + 1);
537 1.7.2.3 rmind else if (c < '0' || c > '9')
538 1.7.2.3 rmind return -1;
539 1.7.2.3 rmind
540 1.7.2.3 rmind return c - '0';
541 1.7.2.3 rmind }
542 1.7.2.3 rmind
543 1.7.2.3 rmind uint32_t
544 1.7.2.3 rmind read_hex(const char *s)
545 1.7.2.3 rmind {
546 1.7.2.3 rmind int n;
547 1.7.2.3 rmind uint32_t val;
548 1.7.2.3 rmind
549 1.7.2.3 rmind val = 0;
550 1.7.2.3 rmind while ((n = hex2nibble(*s++)) >= 0)
551 1.7.2.3 rmind val = (val << 4) | n;
552 1.7.2.3 rmind return val;
553 1.7.2.3 rmind }
554 1.7.2.3 rmind
555 1.7.2.2 rmind static int
556 1.7.2.2 rmind check_bootname(char *s)
557 1.7.2.2 rmind {
558 1.7.2.2 rmind /*
559 1.7.2.2 rmind * nfs:
560 1.7.2.2 rmind * nfs:<bootfile>
561 1.7.2.2 rmind * tftp:
562 1.7.2.2 rmind * tftp:<bootfile>
563 1.7.2.2 rmind * wd[N[P]]:<bootfile>
564 1.7.2.3 rmind * mem:<address>
565 1.7.2.2 rmind *
566 1.7.2.2 rmind * net is a synonym of nfs.
567 1.7.2.2 rmind */
568 1.7.2.3 rmind if (strncmp(s, "nfs:", 4) == 0 || strncmp(s, "net:", 4) == 0 ||
569 1.7.2.3 rmind strncmp(s, "tftp:", 5) == 0 || strncmp(s, "mem:", 4) == 0)
570 1.7.2.2 rmind return 1;
571 1.7.2.2 rmind if (s[0] == 'w' && s[1] == 'd') {
572 1.7.2.2 rmind s += 2;
573 1.7.2.2 rmind if (*s != ':' && *s >= '0' && *s <= '3') {
574 1.7.2.2 rmind ++s;
575 1.7.2.2 rmind if (*s != ':' && *s >= 'a' && *s <= 'p')
576 1.7.2.2 rmind ++s;
577 1.7.2.2 rmind }
578 1.7.2.2 rmind return *s == ':';
579 1.7.2.2 rmind }
580 1.7.2.2 rmind return 0;
581 1.7.2.2 rmind }
582 1.7.2.2 rmind
583 1.7.2.3 rmind static int input_cmdline(char **argv, int maxargc)
584 1.7.2.3 rmind {
585 1.7.2.3 rmind char *cmdline;
586 1.7.2.3 rmind
587 1.7.2.3 rmind printf("\nbootargs> ");
588 1.7.2.3 rmind cmdline = alloc(256);
589 1.7.2.3 rmind gets(cmdline);
590 1.7.2.3 rmind
591 1.7.2.3 rmind return parse_cmdline(argv, maxargc, cmdline,
592 1.7.2.3 rmind cmdline + strlen(cmdline));
593 1.7.2.3 rmind }
594 1.7.2.3 rmind
595 1.7.2.2 rmind static int
596 1.7.2.2 rmind parse_cmdline(char **argv, int maxargc, char *p, char *end)
597 1.7.2.2 rmind {
598 1.7.2.2 rmind int argc;
599 1.7.2.2 rmind
600 1.7.2.2 rmind argv[0] = "";
601 1.7.2.2 rmind for (argc = 1; argc < maxargc && p < end; argc++) {
602 1.7.2.2 rmind while (is_space(*p))
603 1.7.2.2 rmind p++;
604 1.7.2.2 rmind if (p >= end)
605 1.7.2.2 rmind break;
606 1.7.2.2 rmind argv[argc] = p;
607 1.7.2.2 rmind while (!is_space(*p) && p < end)
608 1.7.2.2 rmind p++;
609 1.7.2.2 rmind *p++ = '\0';
610 1.7.2.2 rmind }
611 1.7.2.2 rmind
612 1.7.2.2 rmind return argc;
613 1.7.2.2 rmind }
614 1.7.2.2 rmind
615 1.7.2.2 rmind static int
616 1.7.2.2 rmind is_space(char c)
617 1.7.2.2 rmind {
618 1.7.2.2 rmind return c > '\0' && c <= ' ';
619 1.7.2.2 rmind }
620