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