exec.c revision 1.81 1 /* $NetBSD: exec.c,v 1.81 2024/09/11 20:15:36 andvar 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 */
93
94 #include <sys/param.h>
95 #include <sys/reboot.h>
96
97 #include <lib/libsa/stand.h>
98 #include <lib/libkern/libkern.h>
99
100 #include "loadfile.h"
101 #include "libi386.h"
102 #include "bootinfo.h"
103 #include "bootmod.h"
104 #include "vbe.h"
105 #ifdef SUPPORT_PS2
106 #include "biosmca.h"
107 #endif
108 #ifdef EFIBOOT
109 #include "efiboot.h"
110 #include "biosdisk.h"
111 #include "efidisk.h"
112 #undef DEBUG /* XXX */
113 #endif
114
115 #define BOOT_NARGS 6
116
117 #ifndef PAGE_SIZE
118 #define PAGE_SIZE 4096
119 #endif
120
121 #define MODULE_WARNING_SEC 5
122
123 #define MAXMODNAME 32 /* from <sys/module.h> */
124
125 extern struct btinfo_console btinfo_console;
126 extern struct btinfo_rootdevice bi_root;
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 struct btinfo_framebuffer btinfo_framebuffer;
140
141 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, const char *);
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 errno;
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 errno;
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 */
356 #ifdef PASS_BIOSGEOM
357 bi_getbiosgeom();
358 #endif
359 #ifdef PASS_MEMMAP
360 bi_getmemmap();
361 #endif
362
363 marks[MARK_START] = prekern_start;
364 marks[MARK_END] = (((u_long)marks[MARK_END] + sizeof(int) - 1)) &
365 (-sizeof(int));
366 image_end = marks[MARK_END];
367 kernel_loaded = true;
368
369 return 0;
370 }
371
372 static int
373 common_load_kernel(const char *file, u_long *basemem, u_long *extmem,
374 physaddr_t loadaddr, int floppy, u_long marks[MARK_MAX])
375 {
376 int fd;
377
378 *extmem = getextmem();
379 *basemem = getbasemem();
380
381 marks[MARK_START] = loadaddr;
382 if ((fd = loadfile(file, marks,
383 LOAD_KERNEL & ~(floppy ? LOAD_BACKWARDS : 0))) == -1)
384 return errno;
385
386 close(fd);
387
388 /* If the root fs type is unusual, load its module. */
389 if (fsmod != NULL)
390 module_add_split(fsmod, BM_TYPE_KMOD);
391
392 /*
393 * Gather some information for the kernel. Do this after the
394 * "point of no return" to avoid memory leaks.
395 */
396 #ifdef PASS_BIOSGEOM
397 bi_getbiosgeom();
398 #endif
399 #ifdef PASS_MEMMAP
400 bi_getmemmap();
401 #endif
402
403 marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) &
404 (-sizeof(int));
405 image_end = marks[MARK_END];
406 kernel_loaded = true;
407
408 return 0;
409 }
410
411 int
412 exec_netbsd(const char *file, physaddr_t loadaddr, int boothowto, int floppy,
413 void (*callback)(void))
414 {
415 uint32_t boot_argv[BOOT_NARGS];
416 u_long marks[MARK_MAX];
417 struct btinfo_symtab btinfo_symtab;
418 u_long extmem;
419 u_long basemem;
420 u_long entry;
421 int error;
422 #ifdef EFIBOOT
423 int i;
424 #endif
425
426 #ifdef DEBUG
427 printf("exec: file=%s loadaddr=0x%lx\n", file ? file : "NULL",
428 loadaddr);
429 #endif
430
431 BI_ALLOC(BTINFO_MAX);
432
433 BI_ADD(&btinfo_console, BTINFO_CONSOLE, sizeof(struct btinfo_console));
434 if (bi_root.devname[0])
435 BI_ADD(&bi_root, BTINFO_ROOTDEVICE, sizeof(struct btinfo_rootdevice));
436
437 howto = boothowto;
438
439 memset(marks, 0, sizeof(marks));
440
441 if (has_prekern) {
442 error = common_load_prekern(file, &basemem, &extmem, loadaddr,
443 floppy, marks);
444 } else {
445 error = common_load_kernel(file, &basemem, &extmem, loadaddr,
446 floppy, marks);
447 }
448 if (error) {
449 errno = error;
450 goto out;
451 }
452 #ifdef EFIBOOT
453 BI_ADD(&bi_disk, BTINFO_BOOTDISK, sizeof(bi_disk));
454 BI_ADD(&bi_wedge, BTINFO_BOOTWEDGE, sizeof(bi_wedge));
455 efidisk_getbiosgeom();
456
457 efi_load_start = marks[MARK_START];
458
459 /* adjust to the real load address */
460 marks[MARK_START] -= efi_loadaddr;
461 marks[MARK_ENTRY] -= efi_loadaddr;
462 marks[MARK_DATA] -= efi_loadaddr;
463 /* MARK_NSYM */
464 marks[MARK_SYM] -= efi_loadaddr;
465 marks[MARK_END] -= efi_loadaddr;
466 #endif
467
468 boot_argv[0] = boothowto;
469 boot_argv[1] = 0;
470 boot_argv[2] = vtophys(bootinfo); /* old cyl offset */
471 boot_argv[3] = marks[MARK_END];
472 boot_argv[4] = extmem;
473 boot_argv[5] = basemem;
474
475 /* pull in any modules if necessary */
476 if (boot_modules_enabled) {
477 module_init(file);
478 if (btinfo_modulelist) {
479 #ifdef EFIBOOT
480 /* convert module loaded address to paddr */
481 struct bi_modulelist_entry *bim;
482 bim = (void *)(btinfo_modulelist + 1);
483 for (i = 0; i < btinfo_modulelist->num; i++, bim++)
484 bim->base -= efi_loadaddr;
485 btinfo_modulelist->endpa -= efi_loadaddr;
486 #endif
487 BI_ADD(btinfo_modulelist, BTINFO_MODULELIST,
488 btinfo_modulelist_size);
489 }
490 }
491
492 userconf_init();
493 if (btinfo_userconfcommands != NULL)
494 BI_ADD(btinfo_userconfcommands, BTINFO_USERCONFCOMMANDS,
495 btinfo_userconfcommands_size);
496
497 #ifdef DEBUG
498 printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY],
499 marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]);
500 #endif
501
502 btinfo_symtab.nsym = marks[MARK_NSYM];
503 btinfo_symtab.ssym = marks[MARK_SYM];
504 btinfo_symtab.esym = marks[MARK_END];
505 BI_ADD(&btinfo_symtab, BTINFO_SYMTAB, sizeof(struct btinfo_symtab));
506
507 /* set new video mode if necessary */
508 vbe_commit();
509 BI_ADD(&btinfo_framebuffer, BTINFO_FRAMEBUFFER,
510 sizeof(struct btinfo_framebuffer));
511
512 if (callback != NULL)
513 (*callback)();
514
515 entry = marks[MARK_ENTRY];
516 #ifdef EFIBOOT
517 /* Copy bootinfo to safe arena. */
518 for (i = 0; i < bootinfo->nentries; i++) {
519 struct btinfo_common *bi = (void *)(u_long)bootinfo->entry[i];
520 char *p = alloc(bi->len);
521 memcpy(p, bi, bi->len);
522 bootinfo->entry[i] = vtophys(p);
523 }
524
525 efi_kernel_start = marks[MARK_START];
526 efi_kernel_size = image_end - (efi_loadaddr + efi_kernel_start);
527
528 switch (efi_reloc_type) {
529 case RELOC_NONE:
530 entry += (efi_load_start - efi_kernel_start);
531 efi_kernel_start = efi_load_start;
532 break;
533 case RELOC_ADDR:
534 entry += (efi_kernel_reloc - efi_kernel_start);
535 efi_kernel_start = efi_kernel_reloc;
536 break;
537 case RELOC_DEFAULT:
538 default:
539 break;
540 }
541 #endif
542 startprog(entry, BOOT_NARGS, boot_argv,
543 x86_trunc_page(basemem * 1024));
544 panic("exec returned");
545
546 out:
547 BI_FREE();
548 bootinfo = NULL;
549 return -1;
550 }
551
552 static void
553 extract_device(const char *path, char *buf, size_t buflen)
554 {
555 size_t i;
556
557 if (strchr(path, ':') != NULL) {
558 for (i = 0; i < buflen - 2 && path[i] != ':'; i++)
559 buf[i] = path[i];
560 buf[i++] = ':';
561 buf[i] = '\0';
562 } else
563 buf[0] = '\0';
564 }
565
566 static const char *
567 module_path(boot_module_t *bm, const char *kdev, const char *base_path)
568 {
569 static char buf[256];
570 char name_buf[256], dev_buf[64];
571 const char *name, *name2, *p;
572
573 name = bm->bm_path;
574 for (name2 = name; *name2; ++name2) {
575 if (*name2 == ' ' || *name2 == '\t') {
576 strlcpy(name_buf, name, sizeof(name_buf));
577 if ((uintptr_t)name2 - (uintptr_t)name < sizeof(name_buf))
578 name_buf[name2 - name] = '\0';
579 name = name_buf;
580 break;
581 }
582 }
583 if ((p = strchr(name, ':')) != NULL) {
584 /* device specified, use it */
585 if (p[1] == '/')
586 snprintf(buf, sizeof(buf), "%s", name);
587 else {
588 p++;
589 extract_device(name, dev_buf, sizeof(dev_buf));
590 snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod",
591 dev_buf, base_path, p, p);
592 }
593 } else {
594 /* device not specified; load from kernel device if known */
595 if (name[0] == '/')
596 snprintf(buf, sizeof(buf), "%s%s", kdev, name);
597 else
598 snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod",
599 kdev, base_path, name, name);
600 }
601
602 return buf;
603 }
604
605 static int
606 module_open(boot_module_t *bm, int mode, const char *kdev,
607 const char *base_path, bool doload)
608 {
609 int fd;
610 const char *path;
611
612 /* check the expanded path first */
613 path = module_path(bm, kdev, base_path);
614 fd = open(path, mode);
615 if (fd != -1) {
616 if ((howto & AB_SILENT) == 0 && doload)
617 printf("Loading %s ", path);
618 } else {
619 /* now attempt the raw path provided */
620 fd = open(bm->bm_path, mode);
621 if (fd != -1 && (howto & AB_SILENT) == 0 && doload)
622 printf("Loading %s ", bm->bm_path);
623 }
624 if (!doload && fd == -1) {
625 printf("WARNING: couldn't open %s", bm->bm_path);
626 if (strcmp(bm->bm_path, path) != 0)
627 printf(" (%s)", path);
628 printf("\n");
629 }
630 return fd;
631 }
632
633 static void
634 module_base_path(char *buf, size_t bufsize, const char *kernel_path)
635 {
636 #ifdef KERNEL_DIR
637 /* we cheat here, because %.* does not work with the mini printf */
638 char *ptr = strrchr(kernel_path, '/');
639 if (ptr) *ptr = '\0';
640 snprintf(buf, bufsize, "%s/modules", kernel_path);
641 if (ptr) *ptr = '/';
642 #else
643 const char *machine;
644
645 switch (netbsd_elf_class) {
646 case ELFCLASS32:
647 machine = "i386";
648 break;
649 case ELFCLASS64:
650 machine = "amd64";
651 break;
652 default:
653 machine = "generic";
654 break;
655 }
656 if (netbsd_version / 1000000 % 100 == 99) {
657 /* -current */
658 snprintf(buf, bufsize,
659 "/stand/%s/%d.%d.%d/modules", machine,
660 netbsd_version / 100000000,
661 netbsd_version / 1000000 % 100,
662 netbsd_version / 100 % 10000);
663 } else if (netbsd_version != 0) {
664 /* release */
665 snprintf(buf, bufsize,
666 "/stand/%s/%d.%d/modules", machine,
667 netbsd_version / 100000000,
668 netbsd_version / 1000000 % 100);
669 }
670 #endif
671 }
672
673 static void
674 module_init(const char *kernel_path)
675 {
676 struct bi_modulelist_entry *bi;
677 struct stat st;
678 char kdev[64];
679 char *buf;
680 boot_module_t *bm;
681 ssize_t len;
682 off_t off;
683 int err, fd, nfail = 0;
684
685 extract_device(kernel_path, kdev, sizeof(kdev));
686 module_base_path(module_base, sizeof(module_base), kernel_path);
687
688 /* First, see which modules are valid and calculate btinfo size */
689 len = sizeof(struct btinfo_modulelist);
690 for (bm = boot_modules; bm; bm = bm->bm_next) {
691 fd = module_open(bm, 0, kdev, module_base, false);
692 if (fd == -1) {
693 bm->bm_len = -1;
694 ++nfail;
695 continue;
696 }
697 err = fstat(fd, &st);
698 if (err == -1 || st.st_size == -1) {
699 printf("WARNING: couldn't stat %s\n", bm->bm_path);
700 close(fd);
701 bm->bm_len = -1;
702 ++nfail;
703 continue;
704 }
705 bm->bm_len = st.st_size;
706 close(fd);
707 len += sizeof(struct bi_modulelist_entry);
708 }
709
710 /* Allocate the module list */
711 btinfo_modulelist = alloc(len);
712 if (btinfo_modulelist == NULL) {
713 printf("WARNING: couldn't allocate module list\n");
714 wait_sec(MODULE_WARNING_SEC);
715 return;
716 }
717 memset(btinfo_modulelist, 0, len);
718 btinfo_modulelist_size = len;
719
720 /* Fill in btinfo structure */
721 buf = (char *)btinfo_modulelist;
722 btinfo_modulelist->num = 0;
723 off = sizeof(struct btinfo_modulelist);
724
725 for (bm = boot_modules; bm; bm = bm->bm_next) {
726 if (bm->bm_len == -1)
727 continue;
728 fd = module_open(bm, 0, kdev, module_base, true);
729 if (fd == -1)
730 continue;
731 image_end = (image_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
732 len = pread(fd, (void *)(uintptr_t)image_end, SSIZE_MAX);
733 if (len < bm->bm_len) {
734 if ((howto & AB_SILENT) != 0)
735 printf("Loading %s ", bm->bm_path);
736 printf(" FAILED\n");
737 } else {
738 btinfo_modulelist->num++;
739 bi = (struct bi_modulelist_entry *)(buf + off);
740 off += sizeof(struct bi_modulelist_entry);
741 strncpy(bi->path, bm->bm_path, sizeof(bi->path) - 1);
742 bi->base = image_end;
743 bi->len = len;
744 switch (bm->bm_type) {
745 case BM_TYPE_KMOD:
746 bi->type = BI_MODULE_ELF;
747 break;
748 case BM_TYPE_IMAGE:
749 bi->type = BI_MODULE_IMAGE;
750 break;
751 case BM_TYPE_FS:
752 bi->type = BI_MODULE_FS;
753 break;
754 case BM_TYPE_RND:
755 default:
756 /* safest -- rnd checks the sha1 */
757 bi->type = BI_MODULE_RND;
758 break;
759 }
760 if ((howto & AB_SILENT) == 0)
761 printf(" \n");
762 }
763 if (len > 0)
764 image_end += len;
765 close(fd);
766 }
767 btinfo_modulelist->endpa = image_end;
768
769 if (nfail > 0) {
770 printf("WARNING: %d module%s failed to load\n",
771 nfail, nfail == 1 ? "" : "s");
772 #if notyet
773 wait_sec(MODULE_WARNING_SEC);
774 #endif
775 }
776 }
777
778 static void
779 userconf_init(void)
780 {
781 size_t count, len;
782 userconf_command_t *uc;
783 char *buf;
784 off_t off;
785
786 /* Calculate the userconf commands list size */
787 count = 0;
788 for (uc = userconf_commands; uc != NULL; uc = uc->uc_next)
789 count++;
790 len = sizeof(*btinfo_userconfcommands) +
791 count * sizeof(struct bi_userconfcommand);
792
793 /* Allocate the userconf commands list */
794 btinfo_userconfcommands = alloc(len);
795 if (btinfo_userconfcommands == NULL) {
796 printf("WARNING: couldn't allocate userconf commands list\n");
797 return;
798 }
799 memset(btinfo_userconfcommands, 0, len);
800 btinfo_userconfcommands_size = len;
801
802 /* Fill in btinfo structure */
803 buf = (char *)btinfo_userconfcommands;
804 off = sizeof(*btinfo_userconfcommands);
805 btinfo_userconfcommands->num = 0;
806 for (uc = userconf_commands; uc != NULL; uc = uc->uc_next) {
807 struct bi_userconfcommand *bi;
808 bi = (struct bi_userconfcommand *)(buf + off);
809 strncpy(bi->text, uc->uc_text, sizeof(bi->text) - 1);
810
811 off += sizeof(*bi);
812 btinfo_userconfcommands->num++;
813 }
814 }
815
816 int
817 exec_multiboot(const char *file, char *args)
818 {
819 physaddr_t loadaddr = 0;
820 u_long marks[MARK_MAX];
821 u_long extmem;
822 u_long basemem;
823 struct multiboot_package *mbp = NULL;
824
825 #ifndef NO_MULTIBOOT2
826 if ((mbp = probe_multiboot2(file)) != NULL)
827 goto is_multiboot;
828 #endif
829
830 if ((mbp = probe_multiboot1(file)) != NULL) {
831 #ifdef EFIBOOT
832 printf("EFI boot requires multiboot 2 kernel\n");
833 goto out;
834 #else
835 goto is_multiboot;
836 #endif
837 }
838
839 #ifndef NO_MULTIBOOT2
840 printf("%s is not a multiboot kernel\n", file);
841 #else
842 printf("%s is not a multiboot 1 kernel "
843 "(multiboot 2 support is not built in)\n", file);
844 #endif
845 goto out;
846
847 is_multiboot:
848 #ifdef EFIBOOT
849 loadaddr = efi_loadaddr;
850 #endif
851 if (common_load_kernel(file, &basemem, &extmem, loadaddr, 0, marks))
852 goto out;
853
854 if (boot_modules_enabled)
855 module_init(file);
856
857 mbp->mbp_args = args;
858 mbp->mbp_basemem = basemem;
859 mbp->mbp_extmem = extmem;
860 mbp->mbp_loadaddr = loadaddr;
861 mbp->mbp_marks = marks;
862
863 /* Only returns on error */
864 (void)mbp->mbp_exec(mbp);
865
866 out:
867 if (mbp != NULL)
868 mbp->mbp_cleanup(mbp);
869
870 return -1;
871 }
872
873 void
874 x86_progress(const char *fmt, ...)
875 {
876 va_list ap;
877
878 if ((howto & AB_SILENT) != 0)
879 return;
880 va_start(ap, fmt);
881 vprintf(fmt, ap);
882 va_end(ap);
883 }
884