exec.c revision 1.72 1 /* $NetBSD: exec.c,v 1.72 2019/06/24 13:58:24 pgoyette Exp $ */
2
3 /*
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * Copyright (c) 1982, 1986, 1990, 1993
31 * The Regents of the University of California. All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 *
57 * @(#)boot.c 8.1 (Berkeley) 6/10/93
58 */
59
60 /*
61 * Copyright (c) 1996
62 * Matthias Drochner. All rights reserved.
63 * Copyright (c) 1996
64 * Perry E. Metzger. All rights reserved.
65 *
66 * Redistribution and use in source and binary forms, with or without
67 * modification, are permitted provided that the following conditions
68 * are met:
69 * 1. Redistributions of source code must retain the above copyright
70 * notice, this list of conditions and the following disclaimer.
71 * 2. Redistributions in binary form must reproduce the above copyright
72 * notice, this list of conditions and the following disclaimer in the
73 * documentation and/or other materials provided with the distribution.
74 *
75 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
76 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
77 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
78 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
79 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
80 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
81 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
82 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
83 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
84 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
85 * SUCH DAMAGE.
86 *
87 * @(#)boot.c 8.1 (Berkeley) 6/10/93
88 */
89
90 /*
91 * Starts a NetBSD ELF kernel. The low level startup is done in startprog.S.
92 * This is a special version of exec.c to support use of XMS.
93 */
94
95 #include <sys/param.h>
96 #include <sys/reboot.h>
97
98 #include <i386/multiboot.h>
99
100 #include <lib/libsa/stand.h>
101 #include <lib/libkern/libkern.h>
102
103 #include "loadfile.h"
104 #include "libi386.h"
105 #include "bootinfo.h"
106 #include "bootmod.h"
107 #include "vbe.h"
108 #ifdef SUPPORT_PS2
109 #include "biosmca.h"
110 #endif
111 #ifdef EFIBOOT
112 #include "efiboot.h"
113 #undef DEBUG /* XXX */
114 #endif
115
116 #define BOOT_NARGS 6
117
118 #ifndef PAGE_SIZE
119 #define PAGE_SIZE 4096
120 #endif
121
122 #define MODULE_WARNING_SEC 5
123
124 #define MAXMODNAME 32 /* from <sys/module.h> */
125
126 extern struct btinfo_console btinfo_console;
127
128 boot_module_t *boot_modules;
129 bool boot_modules_enabled = true;
130 bool kernel_loaded;
131
132 typedef struct userconf_command {
133 char *uc_text;
134 size_t uc_len;
135 struct userconf_command *uc_next;
136 } userconf_command_t;
137 userconf_command_t *userconf_commands = NULL;
138
139 static struct btinfo_framebuffer btinfo_framebuffer;
140
141 static struct btinfo_modulelist *btinfo_modulelist;
142 static size_t btinfo_modulelist_size;
143 static uint32_t image_end;
144 static char module_base[64] = "/";
145 static int howto;
146
147 static struct btinfo_userconfcommands *btinfo_userconfcommands = NULL;
148 static size_t btinfo_userconfcommands_size = 0;
149
150 static void module_init(const char *);
151 static void module_add_common(const char *, uint8_t);
152
153 static void userconf_init(void);
154
155 static void extract_device(const char *, char *, size_t);
156 static void module_base_path(char *, size_t);
157 static int module_open(boot_module_t *, int, const char *, const char *,
158 bool);
159
160 void
161 framebuffer_configure(struct btinfo_framebuffer *fb)
162 {
163 if (fb)
164 btinfo_framebuffer = *fb;
165 else {
166 btinfo_framebuffer.physaddr = 0;
167 btinfo_framebuffer.flags = 0;
168 }
169 }
170
171 void
172 module_add(char *name)
173 {
174 return module_add_common(name, BM_TYPE_KMOD);
175 }
176
177 void
178 splash_add(char *name)
179 {
180 return module_add_common(name, BM_TYPE_IMAGE);
181 }
182
183 void
184 rnd_add(char *name)
185 {
186 return module_add_common(name, BM_TYPE_RND);
187 }
188
189 void
190 fs_add(char *name)
191 {
192 return module_add_common(name, BM_TYPE_FS);
193 }
194
195 /*
196 * Add a /-separated list of module names to the boot list
197 */
198 void
199 module_add_split(const char *name, uint8_t type)
200 {
201 char mod_name[MAXMODNAME];
202 int i;
203 const char *mp = name;
204 char *ep;
205
206 while (*mp) { /* scan list of module names */
207 i = MAXMODNAME;
208 ep = mod_name;
209 while (--i) { /* scan for end of first name */
210 *ep = *mp;
211 if (*ep == '/') /* NUL-terminate the name */
212 *ep = '\0';
213
214 if (*ep == 0 ) { /* add non-empty name */
215 if (ep != mod_name)
216 module_add_common(mod_name, type);
217 break;
218 }
219 ep++; mp++;
220 }
221 if (*ep != 0) {
222 printf("module name too long\n");
223 return;
224 }
225 if (*mp == '/') { /* skip separator if more */
226 mp++;
227 }
228 }
229 }
230
231 static void
232 module_add_common(const char *name, uint8_t type)
233 {
234 boot_module_t *bm, *bmp;
235 size_t len;
236 char *str;
237
238 while (*name == ' ' || *name == '\t')
239 ++name;
240
241 for (bm = boot_modules; bm != NULL; bm = bm->bm_next)
242 if (bm->bm_type == type && strcmp(bm->bm_path, name) == 0)
243 return;
244
245 bm = alloc(sizeof(boot_module_t));
246 len = strlen(name) + 1;
247 str = alloc(len);
248 if (bm == NULL || str == NULL) {
249 printf("couldn't allocate module\n");
250 return;
251 }
252 memcpy(str, name, len);
253 bm->bm_path = str;
254 bm->bm_next = NULL;
255 bm->bm_type = type;
256 if (boot_modules == NULL)
257 boot_modules = bm;
258 else {
259 for (bmp = boot_modules; bmp->bm_next;
260 bmp = bmp->bm_next)
261 ;
262 bmp->bm_next = bm;
263 }
264 }
265
266 void
267 userconf_add(char *cmd)
268 {
269 userconf_command_t *uc;
270 size_t len;
271 char *text;
272
273 while (*cmd == ' ' || *cmd == '\t')
274 ++cmd;
275
276 uc = alloc(sizeof(*uc));
277 if (uc == NULL) {
278 printf("couldn't allocate command\n");
279 return;
280 }
281
282 len = strlen(cmd) + 1;
283 text = alloc(len);
284 if (text == NULL) {
285 dealloc(uc, sizeof(*uc));
286 printf("couldn't allocate command\n");
287 return;
288 }
289 memcpy(text, cmd, len);
290
291 uc->uc_text = text;
292 uc->uc_len = len;
293 uc->uc_next = NULL;
294
295 if (userconf_commands == NULL)
296 userconf_commands = uc;
297 else {
298 userconf_command_t *ucp;
299 for (ucp = userconf_commands; ucp->uc_next != NULL;
300 ucp = ucp->uc_next)
301 ;
302 ucp->uc_next = uc;
303 }
304 }
305
306 struct btinfo_prekern bi_prekern;
307 int has_prekern = 0;
308
309 static int
310 common_load_prekern(const char *file, u_long *basemem, u_long *extmem,
311 physaddr_t loadaddr, int floppy, u_long marks[MARK_MAX])
312 {
313 paddr_t kernpa_start, kernpa_end;
314 char prekernpath[] = "/prekern";
315 u_long prekern_start;
316 int fd, flags;
317
318 *extmem = getextmem();
319 *basemem = getbasemem();
320
321 marks[MARK_START] = loadaddr;
322
323 /* Load the prekern (static) */
324 flags = LOAD_KERNEL & ~(LOAD_HDR|LOAD_SYM);
325 if ((fd = loadfile(prekernpath, marks, flags)) == -1)
326 return EIO;
327 close(fd);
328
329 prekern_start = marks[MARK_START];
330
331 /* The kernel starts at 2MB. */
332 marks[MARK_START] = loadaddr;
333 marks[MARK_END] = loadaddr + (1UL << 21);
334 kernpa_start = (1UL << 21);
335
336 /* Load the kernel (dynamic) */
337 flags = (LOAD_KERNEL | LOAD_DYN) & ~(floppy ? LOAD_BACKWARDS : 0);
338 if ((fd = loadfile(file, marks, flags)) == -1)
339 return EIO;
340 close(fd);
341
342 kernpa_end = marks[MARK_END] - loadaddr;
343
344 /* If the root fs type is unusual, load its module. */
345 if (fsmod != NULL)
346 module_add_split(fsmod, BM_TYPE_KMOD);
347
348 bi_prekern.kernpa_start = kernpa_start;
349 bi_prekern.kernpa_end = kernpa_end;
350 BI_ADD(&bi_prekern, BTINFO_PREKERN, sizeof(struct btinfo_prekern));
351
352 /*
353 * Gather some information for the kernel. Do this after the
354 * "point of no return" to avoid memory leaks.
355 * (but before DOS might be trashed in the XMS case)
356 */
357 #ifdef PASS_BIOSGEOM
358 bi_getbiosgeom();
359 #endif
360 #ifdef PASS_MEMMAP
361 bi_getmemmap();
362 #endif
363
364 marks[MARK_START] = prekern_start;
365 marks[MARK_END] = (((u_long)marks[MARK_END] + sizeof(int) - 1)) &
366 (-sizeof(int));
367 image_end = marks[MARK_END];
368 kernel_loaded = true;
369
370 return 0;
371 }
372
373 static int
374 common_load_kernel(const char *file, u_long *basemem, u_long *extmem,
375 physaddr_t loadaddr, int floppy, u_long marks[MARK_MAX])
376 {
377 int fd;
378 #ifdef XMS
379 u_long xmsmem;
380 physaddr_t origaddr = loadaddr;
381 #endif
382
383 *extmem = getextmem();
384 *basemem = getbasemem();
385
386 #ifdef XMS
387 if ((getextmem1() == 0) && (xmsmem = checkxms())) {
388 u_long kernsize;
389
390 /*
391 * With "CONSERVATIVE_MEMDETECT", extmem is 0 because
392 * getextmem() is getextmem1(). Without, the "smart"
393 * methods could fail to report all memory as well.
394 * xmsmem is a few kB less than the actual size, but
395 * better than nothing.
396 */
397 if (xmsmem > *extmem)
398 *extmem = xmsmem;
399 /*
400 * Get the size of the kernel
401 */
402 marks[MARK_START] = loadaddr;
403 if ((fd = loadfile(file, marks, COUNT_KERNEL)) == -1)
404 return EIO;
405 close(fd);
406
407 kernsize = marks[MARK_END];
408 kernsize = (kernsize + 1023) / 1024;
409
410 loadaddr = xmsalloc(kernsize);
411 if (!loadaddr)
412 return ENOMEM;
413 }
414 #endif
415 marks[MARK_START] = loadaddr;
416 if ((fd = loadfile(file, marks,
417 LOAD_KERNEL & ~(floppy ? LOAD_BACKWARDS : 0))) == -1)
418 return EIO;
419
420 close(fd);
421
422 /* If the root fs type is unusual, load its module. */
423 if (fsmod != NULL)
424 module_add_split(fsmod, BM_TYPE_KMOD);
425
426 /*
427 * Gather some information for the kernel. Do this after the
428 * "point of no return" to avoid memory leaks.
429 * (but before DOS might be trashed in the XMS case)
430 */
431 #ifdef PASS_BIOSGEOM
432 bi_getbiosgeom();
433 #endif
434 #ifdef PASS_MEMMAP
435 bi_getmemmap();
436 #endif
437
438 #ifdef XMS
439 if (loadaddr != origaddr) {
440 /*
441 * We now have done our last DOS IO, so we may
442 * trash the OS. Copy the data from the temporary
443 * buffer to its real address.
444 */
445 marks[MARK_START] -= loadaddr;
446 marks[MARK_END] -= loadaddr;
447 marks[MARK_SYM] -= loadaddr;
448 marks[MARK_END] -= loadaddr;
449 ppbcopy(loadaddr, origaddr, marks[MARK_END]);
450 }
451 #endif
452 marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) &
453 (-sizeof(int));
454 image_end = marks[MARK_END];
455 kernel_loaded = true;
456
457 return 0;
458 }
459
460 int
461 exec_netbsd(const char *file, physaddr_t loadaddr, int boothowto, int floppy,
462 void (*callback)(void))
463 {
464 uint32_t boot_argv[BOOT_NARGS];
465 u_long marks[MARK_MAX];
466 struct btinfo_symtab btinfo_symtab;
467 u_long extmem;
468 u_long basemem;
469 int error;
470 #ifdef EFIBOOT
471 int i;
472 #endif
473
474 #ifdef DEBUG
475 printf("exec: file=%s loadaddr=0x%lx\n", file ? file : "NULL",
476 loadaddr);
477 #endif
478
479 BI_ALLOC(BTINFO_MAX);
480
481 BI_ADD(&btinfo_console, BTINFO_CONSOLE, sizeof(struct btinfo_console));
482
483 howto = boothowto;
484
485 memset(marks, 0, sizeof(marks));
486
487 if (has_prekern) {
488 error = common_load_prekern(file, &basemem, &extmem, loadaddr,
489 floppy, marks);
490 } else {
491 error = common_load_kernel(file, &basemem, &extmem, loadaddr,
492 floppy, marks);
493 }
494 if (error) {
495 errno = error;
496 goto out;
497 }
498 #ifdef EFIBOOT
499 /* adjust to the real load address */
500 marks[MARK_START] -= efi_loadaddr;
501 marks[MARK_ENTRY] -= efi_loadaddr;
502 marks[MARK_DATA] -= efi_loadaddr;
503 /* MARK_NSYM */
504 marks[MARK_SYM] -= efi_loadaddr;
505 marks[MARK_END] -= efi_loadaddr;
506 #endif
507
508 boot_argv[0] = boothowto;
509 boot_argv[1] = 0;
510 boot_argv[2] = vtophys(bootinfo); /* old cyl offset */
511 boot_argv[3] = marks[MARK_END];
512 boot_argv[4] = extmem;
513 boot_argv[5] = basemem;
514
515 /* pull in any modules if necessary */
516 if (boot_modules_enabled) {
517 module_init(file);
518 if (btinfo_modulelist) {
519 #ifdef EFIBOOT
520 /* convert module loaded address to paddr */
521 struct bi_modulelist_entry *bim;
522 bim = (void *)(btinfo_modulelist + 1);
523 for (i = 0; i < btinfo_modulelist->num; i++, bim++)
524 bim->base -= efi_loadaddr;
525 btinfo_modulelist->endpa -= efi_loadaddr;
526 #endif
527 BI_ADD(btinfo_modulelist, BTINFO_MODULELIST,
528 btinfo_modulelist_size);
529 }
530 }
531
532 userconf_init();
533 if (btinfo_userconfcommands != NULL)
534 BI_ADD(btinfo_userconfcommands, BTINFO_USERCONFCOMMANDS,
535 btinfo_userconfcommands_size);
536
537 #ifdef DEBUG
538 printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY],
539 marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]);
540 #endif
541
542 btinfo_symtab.nsym = marks[MARK_NSYM];
543 btinfo_symtab.ssym = marks[MARK_SYM];
544 btinfo_symtab.esym = marks[MARK_END];
545 BI_ADD(&btinfo_symtab, BTINFO_SYMTAB, sizeof(struct btinfo_symtab));
546
547 /* set new video mode if necessary */
548 vbe_commit();
549 BI_ADD(&btinfo_framebuffer, BTINFO_FRAMEBUFFER,
550 sizeof(struct btinfo_framebuffer));
551
552 if (callback != NULL)
553 (*callback)();
554 #ifdef EFIBOOT
555 /* Copy bootinfo to safe arena. */
556 for (i = 0; i < bootinfo->nentries; i++) {
557 struct btinfo_common *bi = (void *)(u_long)bootinfo->entry[i];
558 char *p = alloc(bi->len);
559 memcpy(p, bi, bi->len);
560 bootinfo->entry[i] = vtophys(p);
561 }
562
563 efi_kernel_start = marks[MARK_START];
564 efi_kernel_size = image_end - (efi_loadaddr + efi_kernel_start);
565 #endif
566 startprog(marks[MARK_ENTRY], BOOT_NARGS, boot_argv,
567 x86_trunc_page(basemem * 1024));
568 panic("exec returned");
569
570 out:
571 BI_FREE();
572 bootinfo = NULL;
573 return -1;
574 }
575
576 int
577 count_netbsd(const char *file, u_long *rsz)
578 {
579 u_long marks[MARK_MAX];
580 char kdev[64];
581 char base_path[64] = "/";
582 struct stat st;
583 boot_module_t *bm;
584 u_long sz;
585 int err, fd;
586
587 if (has_prekern) {
588 /*
589 * Hardcoded for now. Need to count both the prekern and the
590 * kernel. 128MB is enough in all cases, so use that.
591 */
592 *rsz = (128UL << 20);
593 return 0;
594 }
595
596 howto = AB_SILENT;
597
598 memset(marks, 0, sizeof(marks));
599 if ((fd = loadfile(file, marks, COUNT_KERNEL | LOAD_NOTE)) == -1)
600 return -1;
601 close(fd);
602 marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) &
603 (-sizeof(int));
604 sz = marks[MARK_END];
605
606 /* The modules must be allocated after the kernel */
607 if (boot_modules_enabled) {
608 extract_device(file, kdev, sizeof(kdev));
609 module_base_path(base_path, sizeof(base_path));
610
611 /* If the root fs type is unusual, load its module. */
612 if (fsmod != NULL)
613 module_add_split(fsmod, BM_TYPE_KMOD);
614
615 for (bm = boot_modules; bm; bm = bm->bm_next) {
616 fd = module_open(bm, 0, kdev, base_path, false);
617 if (fd == -1)
618 continue;
619 sz = (sz + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
620 err = fstat(fd, &st);
621 if (err == -1 || st.st_size == -1) {
622 close(fd);
623 continue;
624 }
625 sz += st.st_size;
626 close(fd);
627 }
628 }
629
630 *rsz = sz;
631 return 0;
632 }
633
634 static void
635 extract_device(const char *path, char *buf, size_t buflen)
636 {
637 size_t i;
638
639 if (strchr(path, ':') != NULL) {
640 for (i = 0; i < buflen - 2 && path[i] != ':'; i++)
641 buf[i] = path[i];
642 buf[i++] = ':';
643 buf[i] = '\0';
644 } else
645 buf[0] = '\0';
646 }
647
648 static const char *
649 module_path(boot_module_t *bm, const char *kdev, const char *base_path)
650 {
651 static char buf[256];
652 char name_buf[256], dev_buf[64];
653 const char *name, *name2, *p;
654
655 name = bm->bm_path;
656 for (name2 = name; *name2; ++name2) {
657 if (*name2 == ' ' || *name2 == '\t') {
658 strlcpy(name_buf, name, sizeof(name_buf));
659 if ((uintptr_t)name2 - (uintptr_t)name < sizeof(name_buf))
660 name_buf[name2 - name] = '\0';
661 name = name_buf;
662 break;
663 }
664 }
665 if ((p = strchr(name, ':')) != NULL) {
666 /* device specified, use it */
667 if (p[1] == '/')
668 snprintf(buf, sizeof(buf), "%s", name);
669 else {
670 p++;
671 extract_device(name, dev_buf, sizeof(dev_buf));
672 snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod",
673 dev_buf, base_path, p, p);
674 }
675 } else {
676 /* device not specified; load from kernel device if known */
677 if (name[0] == '/')
678 snprintf(buf, sizeof(buf), "%s%s", kdev, name);
679 else
680 snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod",
681 kdev, base_path, name, name);
682 }
683
684 return buf;
685 }
686
687 static int
688 module_open(boot_module_t *bm, int mode, const char *kdev,
689 const char *base_path, bool doload)
690 {
691 int fd;
692 const char *path;
693
694 /* check the expanded path first */
695 path = module_path(bm, kdev, base_path);
696 fd = open(path, mode);
697 if (fd != -1) {
698 if ((howto & AB_SILENT) == 0 && doload)
699 printf("Loading %s ", path);
700 } else {
701 /* now attempt the raw path provided */
702 fd = open(bm->bm_path, mode);
703 if (fd != -1 && (howto & AB_SILENT) == 0 && doload)
704 printf("Loading %s ", bm->bm_path);
705 }
706 if (!doload && fd == -1) {
707 printf("WARNING: couldn't open %s", bm->bm_path);
708 if (strcmp(bm->bm_path, path) != 0)
709 printf(" (%s)", path);
710 printf("\n");
711 }
712 return fd;
713 }
714
715 static void
716 module_base_path(char *buf, size_t bufsize)
717 {
718 const char *machine;
719
720 switch (netbsd_elf_class) {
721 case ELFCLASS32:
722 machine = "i386";
723 break;
724 case ELFCLASS64:
725 machine = "amd64";
726 break;
727 default:
728 machine = "generic";
729 break;
730 }
731 if (netbsd_version / 1000000 % 100 == 99) {
732 /* -current */
733 snprintf(buf, bufsize,
734 "/stand/%s/%d.%d.%d/modules", machine,
735 netbsd_version / 100000000,
736 netbsd_version / 1000000 % 100,
737 netbsd_version / 100 % 100);
738 } else if (netbsd_version != 0) {
739 /* release */
740 snprintf(buf, bufsize,
741 "/stand/%s/%d.%d/modules", machine,
742 netbsd_version / 100000000,
743 netbsd_version / 1000000 % 100);
744 }
745 }
746
747 static void
748 module_init(const char *kernel_path)
749 {
750 struct bi_modulelist_entry *bi;
751 struct stat st;
752 char kdev[64];
753 char *buf;
754 boot_module_t *bm;
755 ssize_t len;
756 off_t off;
757 int err, fd, nfail = 0;
758
759 extract_device(kernel_path, kdev, sizeof(kdev));
760 module_base_path(module_base, sizeof(module_base));
761
762 /* First, see which modules are valid and calculate btinfo size */
763 len = sizeof(struct btinfo_modulelist);
764 for (bm = boot_modules; bm; bm = bm->bm_next) {
765 fd = module_open(bm, 0, kdev, module_base, false);
766 if (fd == -1) {
767 bm->bm_len = -1;
768 ++nfail;
769 continue;
770 }
771 err = fstat(fd, &st);
772 if (err == -1 || st.st_size == -1) {
773 printf("WARNING: couldn't stat %s\n", bm->bm_path);
774 close(fd);
775 bm->bm_len = -1;
776 ++nfail;
777 continue;
778 }
779 bm->bm_len = st.st_size;
780 close(fd);
781 len += sizeof(struct bi_modulelist_entry);
782 }
783
784 /* Allocate the module list */
785 btinfo_modulelist = alloc(len);
786 if (btinfo_modulelist == NULL) {
787 printf("WARNING: couldn't allocate module list\n");
788 wait_sec(MODULE_WARNING_SEC);
789 return;
790 }
791 memset(btinfo_modulelist, 0, len);
792 btinfo_modulelist_size = len;
793
794 /* Fill in btinfo structure */
795 buf = (char *)btinfo_modulelist;
796 btinfo_modulelist->num = 0;
797 off = sizeof(struct btinfo_modulelist);
798
799 for (bm = boot_modules; bm; bm = bm->bm_next) {
800 if (bm->bm_len == -1)
801 continue;
802 fd = module_open(bm, 0, kdev, module_base, true);
803 if (fd == -1)
804 continue;
805 image_end = (image_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
806 len = pread(fd, (void *)(uintptr_t)image_end, SSIZE_MAX);
807 if (len < bm->bm_len) {
808 if ((howto & AB_SILENT) != 0)
809 printf("Loading %s ", bm->bm_path);
810 printf(" FAILED\n");
811 } else {
812 btinfo_modulelist->num++;
813 bi = (struct bi_modulelist_entry *)(buf + off);
814 off += sizeof(struct bi_modulelist_entry);
815 strncpy(bi->path, bm->bm_path, sizeof(bi->path) - 1);
816 bi->base = image_end;
817 bi->len = len;
818 switch (bm->bm_type) {
819 case BM_TYPE_KMOD:
820 bi->type = BI_MODULE_ELF;
821 break;
822 case BM_TYPE_IMAGE:
823 bi->type = BI_MODULE_IMAGE;
824 break;
825 case BM_TYPE_FS:
826 bi->type = BI_MODULE_FS;
827 break;
828 case BM_TYPE_RND:
829 default:
830 /* safest -- rnd checks the sha1 */
831 bi->type = BI_MODULE_RND;
832 break;
833 }
834 if ((howto & AB_SILENT) == 0)
835 printf(" \n");
836 }
837 if (len > 0)
838 image_end += len;
839 close(fd);
840 }
841 btinfo_modulelist->endpa = image_end;
842
843 if (nfail > 0) {
844 printf("WARNING: %d module%s failed to load\n",
845 nfail, nfail == 1 ? "" : "s");
846 #if notyet
847 wait_sec(MODULE_WARNING_SEC);
848 #endif
849 }
850 }
851
852 static void
853 userconf_init(void)
854 {
855 size_t count, len;
856 userconf_command_t *uc;
857 char *buf;
858 off_t off;
859
860 /* Calculate the userconf commands list size */
861 count = 0;
862 for (uc = userconf_commands; uc != NULL; uc = uc->uc_next)
863 count++;
864 len = sizeof(*btinfo_userconfcommands) +
865 count * sizeof(struct bi_userconfcommand);
866
867 /* Allocate the userconf commands list */
868 btinfo_userconfcommands = alloc(len);
869 if (btinfo_userconfcommands == NULL) {
870 printf("WARNING: couldn't allocate userconf commands list\n");
871 return;
872 }
873 memset(btinfo_userconfcommands, 0, len);
874 btinfo_userconfcommands_size = len;
875
876 /* Fill in btinfo structure */
877 buf = (char *)btinfo_userconfcommands;
878 off = sizeof(*btinfo_userconfcommands);
879 btinfo_userconfcommands->num = 0;
880 for (uc = userconf_commands; uc != NULL; uc = uc->uc_next) {
881 struct bi_userconfcommand *bi;
882 bi = (struct bi_userconfcommand *)(buf + off);
883 strncpy(bi->text, uc->uc_text, sizeof(bi->text) - 1);
884
885 off += sizeof(*bi);
886 btinfo_userconfcommands->num++;
887 }
888 }
889
890 int
891 exec_multiboot(const char *file, char *args)
892 {
893 struct multiboot_info *mbi;
894 struct multiboot_module *mbm;
895 struct bi_modulelist_entry *bim;
896 int i, len;
897 u_long marks[MARK_MAX];
898 u_long extmem;
899 u_long basemem;
900 char *cmdline;
901
902 mbi = alloc(sizeof(struct multiboot_info));
903 mbi->mi_flags = MULTIBOOT_INFO_HAS_MEMORY;
904
905 if (common_load_kernel(file, &basemem, &extmem, 0, 0, marks))
906 goto out;
907
908 mbi->mi_mem_upper = extmem;
909 mbi->mi_mem_lower = basemem;
910
911 if (args) {
912 mbi->mi_flags |= MULTIBOOT_INFO_HAS_CMDLINE;
913 len = strlen(file) + 1 + strlen(args) + 1;
914 cmdline = alloc(len);
915 snprintf(cmdline, len, "%s %s", file, args);
916 mbi->mi_cmdline = (char *) vtophys(cmdline);
917 }
918
919 /* pull in any modules if necessary */
920 if (boot_modules_enabled) {
921 module_init(file);
922 if (btinfo_modulelist) {
923 mbm = alloc(sizeof(struct multiboot_module) *
924 btinfo_modulelist->num);
925
926 bim = (struct bi_modulelist_entry *)
927 (((char *) btinfo_modulelist) +
928 sizeof(struct btinfo_modulelist));
929 for (i = 0; i < btinfo_modulelist->num; i++) {
930 mbm[i].mmo_start = bim->base;
931 mbm[i].mmo_end = bim->base + bim->len;
932 mbm[i].mmo_string = (char *)vtophys(bim->path);
933 mbm[i].mmo_reserved = 0;
934 bim++;
935 }
936 mbi->mi_flags |= MULTIBOOT_INFO_HAS_MODS;
937 mbi->mi_mods_count = btinfo_modulelist->num;
938 mbi->mi_mods_addr = vtophys(mbm);
939 }
940 }
941
942 #ifdef DEBUG
943 printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY],
944 marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]);
945 #endif
946
947 #if 0
948 if (btinfo_symtab.nsym) {
949 mbi->mi_flags |= MULTIBOOT_INFO_HAS_ELF_SYMS;
950 mbi->mi_elfshdr_addr = marks[MARK_SYM];
951 btinfo_symtab.nsym = marks[MARK_NSYM];
952 btinfo_symtab.ssym = marks[MARK_SYM];
953 btinfo_symtab.esym = marks[MARK_END];
954 #endif
955
956 multiboot(marks[MARK_ENTRY], vtophys(mbi),
957 x86_trunc_page(mbi->mi_mem_lower * 1024));
958 panic("exec returned");
959
960 out:
961 dealloc(mbi, 0);
962 return -1;
963 }
964
965 void
966 x86_progress(const char *fmt, ...)
967 {
968 va_list ap;
969
970 if ((howto & AB_SILENT) != 0)
971 return;
972 va_start(ap, fmt);
973 vprintf(fmt, ap);
974 va_end(ap);
975 }
976