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