exec.c revision 1.42.4.3 1 /* $NetBSD: exec.c,v 1.42.4.3 2011/05/31 03:04:05 rmind 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 NetBSD a.out kernel
92 * needs lowlevel startup from startprog.S
93 * This is a special version of exec.c to support use of XMS.
94 */
95
96 #include <sys/param.h>
97 #include <sys/reboot.h>
98 #include <sys/reboot.h>
99
100 #include <machine/multiboot.h>
101 #include <machine/stdarg.h>
102
103 #include <lib/libsa/stand.h>
104 #include <lib/libkern/libkern.h>
105
106 #include "loadfile.h"
107 #include "libi386.h"
108 #include "bootinfo.h"
109 #include "bootmod.h"
110 #include "vbe.h"
111 #ifdef SUPPORT_PS2
112 #include "biosmca.h"
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 extern struct btinfo_console btinfo_console;
124
125 boot_module_t *boot_modules;
126 bool boot_modules_enabled = true;
127 bool kernel_loaded;
128
129 typedef struct userconf_command {
130 char *uc_text;
131 size_t uc_len;
132 struct userconf_command *uc_next;
133 } userconf_command_t;
134 userconf_command_t *userconf_commands = NULL;
135
136 static struct btinfo_framebuffer btinfo_framebuffer;
137
138 static struct btinfo_modulelist *btinfo_modulelist;
139 static size_t btinfo_modulelist_size;
140 static uint32_t image_end;
141 static char module_base[64] = "/";
142 static int howto;
143
144 static struct btinfo_userconfcommands *btinfo_userconfcommands = NULL;
145 static size_t btinfo_userconfcommands_size = 0;
146
147 static void module_init(const char *);
148 static void module_add_common(char *, uint8_t);
149
150 static void userconf_init(void);
151
152 void
153 framebuffer_configure(struct btinfo_framebuffer *fb)
154 {
155 if (fb)
156 btinfo_framebuffer = *fb;
157 else {
158 btinfo_framebuffer.physaddr = 0;
159 btinfo_framebuffer.flags = 0;
160 }
161 }
162
163 void
164 module_add(char *name)
165 {
166 return module_add_common(name, BM_TYPE_KMOD);
167 }
168
169 void
170 splash_add(char *name)
171 {
172 return module_add_common(name, BM_TYPE_IMAGE);
173 }
174
175 static void
176 module_add_common(char *name, uint8_t type)
177 {
178 boot_module_t *bm, *bmp;
179 size_t len;
180 char *str;
181
182 while (*name == ' ' || *name == '\t')
183 ++name;
184
185 bm = alloc(sizeof(boot_module_t));
186 len = strlen(name) + 1;
187 str = alloc(len);
188 if (bm == NULL || str == NULL) {
189 printf("couldn't allocate module\n");
190 return;
191 }
192 memcpy(str, name, len);
193 bm->bm_path = str;
194 bm->bm_next = NULL;
195 bm->bm_type = type;
196 if (boot_modules == NULL)
197 boot_modules = bm;
198 else {
199 for (bmp = boot_modules; bmp->bm_next;
200 bmp = bmp->bm_next)
201 ;
202 bmp->bm_next = bm;
203 }
204 }
205
206 void
207 userconf_add(char *cmd)
208 {
209 userconf_command_t *uc;
210 size_t len;
211 char *text;
212
213 while (*cmd == ' ' || *cmd == '\t')
214 ++cmd;
215
216 uc = alloc(sizeof(*uc));
217 if (uc == NULL) {
218 printf("couldn't allocate command\n");
219 return;
220 }
221
222 len = strlen(cmd) + 1;
223 text = alloc(len);
224 if (text == NULL) {
225 dealloc(uc, sizeof(*uc));
226 printf("couldn't allocate command\n");
227 return;
228 }
229 memcpy(text, cmd, len);
230
231 uc->uc_text = text;
232 uc->uc_len = len;
233 uc->uc_next = NULL;
234
235 if (userconf_commands == NULL)
236 userconf_commands = uc;
237 else {
238 userconf_command_t *ucp;
239 for (ucp = userconf_commands; ucp->uc_next != NULL;
240 ucp = ucp->uc_next)
241 ;
242 ucp->uc_next = uc;
243 }
244 }
245
246 static int
247 common_load_kernel(const char *file, u_long *basemem, u_long *extmem,
248 physaddr_t loadaddr, int floppy, u_long marks[MARK_MAX])
249 {
250 int fd;
251 #ifdef XMS
252 u_long xmsmem;
253 physaddr_t origaddr = loadaddr;
254 #endif
255
256 *extmem = getextmem();
257 *basemem = getbasemem();
258
259 #ifdef XMS
260 if ((getextmem1() == 0) && (xmsmem = checkxms())) {
261 u_long kernsize;
262
263 /*
264 * With "CONSERVATIVE_MEMDETECT", extmem is 0 because
265 * getextmem() is getextmem1(). Without, the "smart"
266 * methods could fail to report all memory as well.
267 * xmsmem is a few kB less than the actual size, but
268 * better than nothing.
269 */
270 if (xmsmem > *extmem)
271 *extmem = xmsmem;
272 /*
273 * Get the size of the kernel
274 */
275 marks[MARK_START] = loadaddr;
276 if ((fd = loadfile(file, marks, COUNT_KERNEL)) == -1)
277 return EIO;
278 close(fd);
279
280 kernsize = marks[MARK_END];
281 kernsize = (kernsize + 1023) / 1024;
282
283 loadaddr = xmsalloc(kernsize);
284 if (!loadaddr)
285 return ENOMEM;
286 }
287 #endif
288 marks[MARK_START] = loadaddr;
289 if ((fd = loadfile(file, marks,
290 LOAD_KERNEL & ~(floppy ? LOAD_BACKWARDS : 0))) == -1)
291 return EIO;
292
293 close(fd);
294
295 /* Now we know the root fs type, load modules for it. */
296 module_add(fsmod);
297 if (fsmod2 != NULL && strcmp(fsmod, fsmod2) != 0)
298 module_add(fsmod2);
299
300 /*
301 * Gather some information for the kernel. Do this after the
302 * "point of no return" to avoid memory leaks.
303 * (but before DOS might be trashed in the XMS case)
304 */
305 #ifdef PASS_BIOSGEOM
306 bi_getbiosgeom();
307 #endif
308 #ifdef PASS_MEMMAP
309 bi_getmemmap();
310 #endif
311
312 #ifdef XMS
313 if (loadaddr != origaddr) {
314 /*
315 * We now have done our last DOS IO, so we may
316 * trash the OS. Copy the data from the temporary
317 * buffer to its real address.
318 */
319 marks[MARK_START] -= loadaddr;
320 marks[MARK_END] -= loadaddr;
321 marks[MARK_SYM] -= loadaddr;
322 marks[MARK_END] -= loadaddr;
323 ppbcopy(loadaddr, origaddr, marks[MARK_END]);
324 }
325 #endif
326 marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) &
327 (-sizeof(int));
328 image_end = marks[MARK_END];
329 kernel_loaded = true;
330
331 return 0;
332 }
333
334 int
335 exec_netbsd(const char *file, physaddr_t loadaddr, int boothowto, int floppy,
336 void (*callback)(void))
337 {
338 u_long boot_argv[BOOT_NARGS];
339 u_long marks[MARK_MAX];
340 struct btinfo_symtab btinfo_symtab;
341 u_long extmem;
342 u_long basemem;
343
344 #ifdef DEBUG
345 printf("exec: file=%s loadaddr=0x%lx\n",
346 file ? file : "NULL", loadaddr);
347 #endif
348
349 BI_ALLOC(32); /* ??? */
350
351 BI_ADD(&btinfo_console, BTINFO_CONSOLE, sizeof(struct btinfo_console));
352
353 howto = boothowto;
354
355 if (common_load_kernel(file, &basemem, &extmem, loadaddr, floppy, marks))
356 goto out;
357
358 boot_argv[0] = boothowto;
359 boot_argv[1] = 0;
360 boot_argv[2] = vtophys(bootinfo); /* old cyl offset */
361 boot_argv[3] = marks[MARK_END];
362 boot_argv[4] = extmem;
363 boot_argv[5] = basemem;
364
365 /* pull in any modules if necessary */
366 if (boot_modules_enabled) {
367 module_init(file);
368 if (btinfo_modulelist) {
369 BI_ADD(btinfo_modulelist, BTINFO_MODULELIST,
370 btinfo_modulelist_size);
371 }
372 }
373
374 userconf_init();
375 if (btinfo_userconfcommands != NULL)
376 BI_ADD(btinfo_userconfcommands, BTINFO_USERCONFCOMMANDS,
377 btinfo_userconfcommands_size);
378
379 #ifdef DEBUG
380 printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY],
381 marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]);
382 #endif
383
384 btinfo_symtab.nsym = marks[MARK_NSYM];
385 btinfo_symtab.ssym = marks[MARK_SYM];
386 btinfo_symtab.esym = marks[MARK_END];
387 BI_ADD(&btinfo_symtab, BTINFO_SYMTAB, sizeof(struct btinfo_symtab));
388
389 /* set new video mode if necessary */
390 vbe_commit();
391 BI_ADD(&btinfo_framebuffer, BTINFO_FRAMEBUFFER,
392 sizeof(struct btinfo_framebuffer));
393
394 if (callback != NULL)
395 (*callback)();
396 startprog(marks[MARK_ENTRY], BOOT_NARGS, boot_argv,
397 x86_trunc_page(basemem*1024));
398 panic("exec returned");
399
400 out:
401 BI_FREE();
402 bootinfo = 0;
403 return -1;
404 }
405
406 static void
407 extract_device(const char *path, char *buf, size_t buflen)
408 {
409 int i;
410
411 if (strchr(path, ':') != NULL) {
412 for (i = 0; i < buflen - 2 && path[i] != ':'; i++)
413 buf[i] = path[i];
414 buf[i++] = ':';
415 buf[i] = '\0';
416 } else
417 buf[0] = '\0';
418 }
419
420 static const char *
421 module_path(boot_module_t *bm, const char *kdev)
422 {
423 static char buf[256];
424 char name_buf[256], dev_buf[64];
425 const char *name, *name2, *p;
426
427 name = bm->bm_path;
428 for (name2 = name; *name2; ++name2) {
429 if (*name2 == ' ' || *name2 == '\t') {
430 strlcpy(name_buf, name, sizeof(name_buf));
431 if (name2 - name < sizeof(name_buf))
432 name_buf[name2 - name] = '\0';
433 name = name_buf;
434 break;
435 }
436 }
437 if ((p = strchr(name, ':')) != NULL) {
438 /* device specified, use it */
439 if (p[1] == '/')
440 snprintf(buf, sizeof(buf), "%s", name);
441 else {
442 p++;
443 extract_device(name, dev_buf, sizeof(dev_buf));
444 snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod",
445 dev_buf, module_base, p, p);
446 }
447 } else {
448 /* device not specified; load from kernel device if known */
449 if (name[0] == '/')
450 snprintf(buf, sizeof(buf), "%s%s", kdev, name);
451 else
452 snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod",
453 kdev, module_base, name, name);
454 }
455
456 return buf;
457 }
458
459 static int
460 module_open(boot_module_t *bm, int mode, const char *kdev, bool doload)
461 {
462 int fd;
463 const char *path;
464
465 /* check the expanded path first */
466 path = module_path(bm, kdev);
467 fd = open(path, mode);
468 if (fd != -1) {
469 if ((howto & AB_SILENT) == 0 && doload)
470 printf("Loading %s ", path);
471 } else {
472 /* now attempt the raw path provided */
473 fd = open(bm->bm_path, mode);
474 if (fd != -1 && (howto & AB_SILENT) == 0 && doload)
475 printf("Loading %s ", bm->bm_path);
476 }
477 if (!doload && fd == -1) {
478 printf("WARNING: couldn't open %s", bm->bm_path);
479 if (strcmp(bm->bm_path, path) != 0)
480 printf(" (%s)", path);
481 printf("\n");
482 }
483 return fd;
484 }
485
486 static void
487 module_init(const char *kernel_path)
488 {
489 struct bi_modulelist_entry *bi;
490 struct stat st;
491 const char *machine;
492 char kdev[64];
493 char *buf;
494 boot_module_t *bm;
495 size_t len;
496 off_t off;
497 int err, fd, nfail = 0;
498
499 extract_device(kernel_path, kdev, sizeof(kdev));
500
501 switch (netbsd_elf_class) {
502 case ELFCLASS32:
503 machine = "i386";
504 break;
505 case ELFCLASS64:
506 machine = "amd64";
507 break;
508 default:
509 machine = "generic";
510 break;
511 }
512 if (netbsd_version / 1000000 % 100 == 99) {
513 /* -current */
514 snprintf(module_base, sizeof(module_base),
515 "/stand/%s/%d.%d.%d/modules", machine,
516 netbsd_version / 100000000,
517 netbsd_version / 1000000 % 100,
518 netbsd_version / 100 % 100);
519 } else if (netbsd_version != 0) {
520 /* release */
521 snprintf(module_base, sizeof(module_base),
522 "/stand/%s/%d.%d/modules", machine,
523 netbsd_version / 100000000,
524 netbsd_version / 1000000 % 100);
525 }
526
527 /* First, see which modules are valid and calculate btinfo size */
528 len = sizeof(struct btinfo_modulelist);
529 for (bm = boot_modules; bm; bm = bm->bm_next) {
530 fd = module_open(bm, 0, kdev, false);
531 if (fd == -1) {
532 bm->bm_len = -1;
533 ++nfail;
534 continue;
535 }
536 err = fstat(fd, &st);
537 if (err == -1 || st.st_size == -1) {
538 printf("WARNING: couldn't stat %s\n", bm->bm_path);
539 close(fd);
540 bm->bm_len = -1;
541 ++nfail;
542 continue;
543 }
544 bm->bm_len = st.st_size;
545 close(fd);
546 len += sizeof(struct bi_modulelist_entry);
547 }
548
549 /* Allocate the module list */
550 btinfo_modulelist = alloc(len);
551 if (btinfo_modulelist == NULL) {
552 printf("WARNING: couldn't allocate module list\n");
553 wait_sec(MODULE_WARNING_SEC);
554 return;
555 }
556 memset(btinfo_modulelist, 0, len);
557 btinfo_modulelist_size = len;
558
559 /* Fill in btinfo structure */
560 buf = (char *)btinfo_modulelist;
561 btinfo_modulelist->num = 0;
562 off = sizeof(struct btinfo_modulelist);
563
564 for (bm = boot_modules; bm; bm = bm->bm_next) {
565 if (bm->bm_len == -1)
566 continue;
567 fd = module_open(bm, 0, kdev, true);
568 if (fd == -1)
569 continue;
570 image_end = (image_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
571 len = pread(fd, (void *)image_end, SSIZE_MAX);
572 if (len < bm->bm_len) {
573 if ((howto & AB_SILENT) != 0)
574 printf("Loading %s ", bm->bm_path);
575 printf(" FAILED\n");
576 } else {
577 btinfo_modulelist->num++;
578 bi = (struct bi_modulelist_entry *)(buf + off);
579 off += sizeof(struct bi_modulelist_entry);
580 strncpy(bi->path, bm->bm_path, sizeof(bi->path) - 1);
581 bi->base = image_end;
582 bi->len = len;
583 bi->type = bm->bm_type == BM_TYPE_KMOD ?
584 BI_MODULE_ELF : BI_MODULE_IMAGE;
585 if ((howto & AB_SILENT) == 0)
586 printf(" \n");
587 }
588 if (len > 0)
589 image_end += len;
590 close(fd);
591 }
592 btinfo_modulelist->endpa = image_end;
593
594 if (nfail > 0) {
595 printf("WARNING: %d module%s failed to load\n",
596 nfail, nfail == 1 ? "" : "s");
597 #if notyet
598 wait_sec(MODULE_WARNING_SEC);
599 #endif
600 }
601 }
602
603 static void
604 userconf_init(void)
605 {
606 size_t count, len;
607 userconf_command_t *uc;
608 char *buf;
609 off_t off;
610
611 /* Calculate the userconf commands list size */
612 count = 0;
613 for (uc = userconf_commands; uc != NULL; uc = uc->uc_next)
614 count++;
615 len = sizeof(btinfo_userconfcommands) +
616 count * sizeof(struct bi_userconfcommand);
617
618 /* Allocate the userconf commands list */
619 btinfo_userconfcommands = alloc(len);
620 if (btinfo_userconfcommands == NULL) {
621 printf("WARNING: couldn't allocate userconf commands list\n");
622 return;
623 }
624 memset(btinfo_userconfcommands, 0, len);
625 btinfo_userconfcommands_size = len;
626
627 /* Fill in btinfo structure */
628 buf = (char *)btinfo_userconfcommands;
629 off = sizeof(*btinfo_userconfcommands);
630 btinfo_userconfcommands->num = 0;
631 for (uc = userconf_commands; uc != NULL; uc = uc->uc_next) {
632 struct bi_userconfcommand *bi;
633 bi = (struct bi_userconfcommand *)(buf + off);
634 strncpy(bi->text, uc->uc_text, sizeof(bi->text) - 1);
635
636 off += sizeof(*bi);
637 btinfo_userconfcommands->num++;
638 }
639 }
640
641 int
642 exec_multiboot(const char *file, char *args)
643 {
644 struct multiboot_info *mbi;
645 struct multiboot_module *mbm;
646 struct bi_modulelist_entry *bim;
647 int i, len;
648 u_long marks[MARK_MAX];
649 u_long extmem;
650 u_long basemem;
651 char *cmdline;
652
653 mbi = alloc(sizeof(struct multiboot_info));
654 mbi->mi_flags = MULTIBOOT_INFO_HAS_MEMORY;
655
656 if (common_load_kernel(file, &basemem, &extmem, 0, 0, marks))
657 goto out;
658
659 mbi->mi_mem_upper = extmem;
660 mbi->mi_mem_lower = basemem;
661
662 if (args) {
663 mbi->mi_flags |= MULTIBOOT_INFO_HAS_CMDLINE;
664 len = strlen(file) + 1 + strlen(args) + 1;
665 cmdline = alloc(len);
666 snprintf(cmdline, len, "%s %s", file, args);
667 mbi->mi_cmdline = (char *) vtophys(cmdline);
668 }
669
670 /* pull in any modules if necessary */
671 if (boot_modules_enabled) {
672 module_init(file);
673 if (btinfo_modulelist) {
674 mbm = alloc(sizeof(struct multiboot_module) *
675 btinfo_modulelist->num);
676
677 bim = (struct bi_modulelist_entry *)
678 (((char *) btinfo_modulelist) +
679 sizeof(struct btinfo_modulelist));
680 for (i = 0; i < btinfo_modulelist->num; i++) {
681 mbm[i].mmo_start = bim->base;
682 mbm[i].mmo_end = bim->base + bim->len;
683 mbm[i].mmo_string = (char *)vtophys(bim->path);
684 mbm[i].mmo_reserved = 0;
685 bim++;
686 }
687 mbi->mi_flags |= MULTIBOOT_INFO_HAS_MODS;
688 mbi->mi_mods_count = btinfo_modulelist->num;
689 mbi->mi_mods_addr = vtophys(mbm);
690 }
691 }
692
693 #ifdef DEBUG
694 printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY],
695 marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]);
696 #endif
697
698
699 #if 0
700 if (btinfo_symtab.nsym) {
701 mbi->mi_flags |= MULTIBOOT_INFO_HAS_ELF_SYMS;
702 mbi->mi_elfshdr_addr = marks[MARK_SYM];
703 btinfo_symtab.nsym = marks[MARK_NSYM];
704 btinfo_symtab.ssym = marks[MARK_SYM];
705 btinfo_symtab.esym = marks[MARK_END];
706 #endif
707
708 multiboot(marks[MARK_ENTRY], vtophys(mbi),
709 x86_trunc_page(mbi->mi_mem_lower*1024));
710 panic("exec returned");
711
712 out:
713 dealloc(mbi, 0);
714 return -1;
715 }
716
717 void
718 x86_progress(const char *fmt, ...)
719 {
720 va_list ap;
721
722 if ((howto & AB_SILENT) != 0)
723 return;
724 va_start(ap, fmt);
725 vprintf(fmt, ap);
726 va_end(ap);
727 }
728