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