1 /* $NetBSD: multiboot.c,v 1.21 2011/01/11 12:24:37 gsutre Exp $ */ 2 3 /*- 4 * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Julio M. Merino Vidal. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: multiboot.c,v 1.21 2011/01/11 12:24:37 gsutre Exp $"); 34 35 #include "opt_multiboot.h" 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/cdefs_elf.h> 40 #include <sys/boot_flag.h> 41 #include <sys/exec.h> 42 #include <sys/exec_elf.h> 43 #include <sys/optstr.h> 44 #include <sys/ksyms.h> 45 46 #include <machine/bootinfo.h> 47 #include <machine/multiboot.h> 48 49 #if !defined(MULTIBOOT) 50 # error "MULTIBOOT not defined; this cannot happen." 51 #endif 52 53 /* --------------------------------------------------------------------- */ 54 55 /* 56 * Symbol and string table for the loaded kernel. 57 */ 58 59 struct multiboot_symbols { 60 void * s_symstart; 61 size_t s_symsize; 62 void * s_strstart; 63 size_t s_strsize; 64 }; 65 66 /* --------------------------------------------------------------------- */ 67 68 /* 69 * External variables. All of them, with the exception of 'end', must 70 * be set at some point within this file. 71 * 72 * XXX these should be found in a header file! 73 */ 74 extern int biosbasemem; 75 extern int biosextmem; 76 extern int biosmem_implicit; 77 extern int boothowto; 78 extern struct bootinfo bootinfo; 79 extern int end; 80 extern int * esym; 81 82 /* --------------------------------------------------------------------- */ 83 84 /* 85 * Copy of the Multiboot information structure passed to us by the boot 86 * loader. The Multiboot_Info structure has some pointers adjusted to the 87 * other variables -- see multiboot_pre_reloc() -- so you oughtn't access 88 * them directly. In other words, always access them through the 89 * Multiboot_Info variable. 90 */ 91 static char Multiboot_Cmdline[255]; 92 static uint8_t Multiboot_Drives[255]; 93 static struct multiboot_info Multiboot_Info; 94 static bool Multiboot_Loader = false; 95 static char Multiboot_Loader_Name[255]; 96 static uint8_t Multiboot_Mmap[1024]; 97 static struct multiboot_symbols Multiboot_Symbols; 98 99 /* --------------------------------------------------------------------- */ 100 101 /* 102 * Prototypes for private functions. 103 */ 104 static void bootinfo_add(struct btinfo_common *, int, int); 105 static void copy_syms(struct multiboot_info *); 106 static void setup_biosgeom(struct multiboot_info *); 107 static void setup_bootdisk(struct multiboot_info *); 108 static void setup_bootpath(struct multiboot_info *); 109 static void setup_console(struct multiboot_info *); 110 static void setup_howto(struct multiboot_info *); 111 static void setup_memory(struct multiboot_info *); 112 static void setup_memmap(struct multiboot_info *); 113 114 /* --------------------------------------------------------------------- */ 115 116 /* 117 * Sets up the kernel if it was booted by a Multiboot-compliant boot 118 * loader. This is executed before the kernel has relocated itself. 119 * The main purpose of this function is to copy all the information 120 * passed in by the boot loader to a safe place, so that it is available 121 * after it has been relocated. 122 * 123 * WARNING: Because the kernel has not yet relocated itself to KERNBASE, 124 * special care has to be taken when accessing memory because absolute 125 * addresses (referring to kernel symbols) do not work. So: 126 * 127 * 1) Avoid jumps to absolute addresses (such as gotos and switches). 128 * 2) To access global variables use their physical address, which 129 * can be obtained using the RELOC macro. 130 */ 131 void 132 multiboot_pre_reloc(struct multiboot_info *mi) 133 { 134 #define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE)) 135 struct multiboot_info *midest = 136 RELOC(struct multiboot_info *, &Multiboot_Info); 137 138 *RELOC(bool *, &Multiboot_Loader) = true; 139 memcpy(midest, mi, sizeof(Multiboot_Info)); 140 141 if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) { 142 strncpy(RELOC(void *, Multiboot_Cmdline), mi->mi_cmdline, 143 sizeof(Multiboot_Cmdline)); 144 midest->mi_cmdline = (char *)&Multiboot_Cmdline; 145 } 146 147 if (mi->mi_flags & MULTIBOOT_INFO_HAS_LOADER_NAME) { 148 strncpy(RELOC(void *, Multiboot_Loader_Name), 149 mi->mi_loader_name, sizeof(Multiboot_Loader_Name)); 150 midest->mi_loader_name = (char *)&Multiboot_Loader_Name; 151 } 152 153 if (mi->mi_flags & MULTIBOOT_INFO_HAS_MMAP) { 154 memcpy(RELOC(void *, Multiboot_Mmap), 155 (void *)mi->mi_mmap_addr, mi->mi_mmap_length); 156 midest->mi_mmap_addr = (vaddr_t)&Multiboot_Mmap; 157 } 158 159 if (mi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES) { 160 memcpy(RELOC(void *, Multiboot_Drives), 161 (void *)mi->mi_drives_addr, mi->mi_drives_length); 162 midest->mi_drives_addr = (vaddr_t)&Multiboot_Drives; 163 } 164 165 copy_syms(mi); 166 #undef RELOC 167 } 168 169 /* --------------------------------------------------------------------- */ 170 171 /* 172 * Sets up the kernel if it was booted by a Multiboot-compliant boot 173 * loader. This is executed just after the kernel has relocated itself. 174 * At this point, executing any kind of code is safe, keeping in mind 175 * that no devices have been initialized yet (not even the console!). 176 */ 177 void 178 multiboot_post_reloc(void) 179 { 180 struct multiboot_info *mi; 181 182 if (! Multiboot_Loader) 183 return; 184 185 mi = &Multiboot_Info; 186 bootinfo.bi_nentries = 0; 187 188 setup_memory(mi); 189 setup_console(mi); 190 setup_howto(mi); 191 setup_bootpath(mi); 192 setup_biosgeom(mi); 193 setup_bootdisk(mi); 194 setup_memmap(mi); 195 } 196 197 /* --------------------------------------------------------------------- */ 198 199 /* 200 * Prints a summary of the information collected in the Multiboot 201 * information header (if present). Done as a separate function because 202 * the console has to be available. 203 */ 204 void 205 multiboot_print_info(void) 206 { 207 struct multiboot_info *mi = &Multiboot_Info; 208 struct multiboot_symbols *ms = &Multiboot_Symbols; 209 210 if (! Multiboot_Loader) 211 return; 212 213 printf("multiboot: Information structure flags: 0x%08x\n", 214 mi->mi_flags); 215 216 if (mi->mi_flags & MULTIBOOT_INFO_HAS_LOADER_NAME) 217 printf("multiboot: Boot loader: %s\n", mi->mi_loader_name); 218 219 if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) 220 printf("multiboot: Command line: %s\n", mi->mi_cmdline); 221 222 if (mi->mi_flags & MULTIBOOT_INFO_HAS_MEMORY) 223 printf("multiboot: %u KB lower memory, %u KB upper memory\n", 224 mi->mi_mem_lower, mi->mi_mem_upper); 225 226 if (mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS) { 227 KASSERT(esym != 0); 228 printf("multiboot: Symbol table at %p, length %d bytes\n", 229 ms->s_symstart, ms->s_symsize); 230 printf("multiboot: String table at %p, length %d bytes\n", 231 ms->s_strstart, ms->s_strsize); 232 } 233 } 234 235 /* --------------------------------------------------------------------- */ 236 237 /* 238 * Adds the bootinfo entry given in 'item' to the bootinfo tables. 239 * Sets the item type to 'type' and its length to 'len'. 240 */ 241 static void 242 bootinfo_add(struct btinfo_common *item, int type, int len) 243 { 244 int i; 245 struct bootinfo *bip = (struct bootinfo *)&bootinfo; 246 vaddr_t data; 247 248 item->type = type; 249 item->len = len; 250 251 data = (vaddr_t)&bip->bi_data; 252 for (i = 0; i < bip->bi_nentries; i++) { 253 struct btinfo_common *tmp; 254 255 tmp = (struct btinfo_common *)data; 256 data += tmp->len; 257 } 258 if (data + len < (vaddr_t)&bip->bi_data + sizeof(bip->bi_data)) { 259 memcpy((void *)data, item, len); 260 bip->bi_nentries++; 261 } 262 } 263 264 /* --------------------------------------------------------------------- */ 265 266 /* 267 * Copies the symbol table and the strings table passed in by the boot 268 * loader after the kernel's image, and sets up 'esym' accordingly so 269 * that this data is properly copied into upper memory during relocation. 270 * 271 * WARNING: This code runs before the kernel has relocated itself. See 272 * the note in multiboot_pre_reloc() for more information. 273 */ 274 static void 275 copy_syms(struct multiboot_info *mi) 276 { 277 #define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE)) 278 int i; 279 struct multiboot_symbols *ms; 280 Elf32_Shdr *symtabp, *strtabp; 281 Elf32_Word symsize, strsize; 282 Elf32_Addr symaddr, straddr; 283 Elf32_Addr symstart, strstart; 284 285 /* 286 * Check if the Multiboot information header has symbols or not. 287 */ 288 if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS)) 289 return; 290 291 ms = RELOC(struct multiboot_symbols *, &Multiboot_Symbols); 292 293 /* 294 * Locate a symbol table and its matching string table in the 295 * section headers passed in by the boot loader. Set 'symtabp' 296 * and 'strtabp' with pointers to the matching entries. 297 */ 298 symtabp = strtabp = NULL; 299 for (i = 0; i < mi->mi_elfshdr_num && symtabp == NULL && 300 strtabp == NULL; i++) { 301 Elf32_Shdr *shdrp; 302 303 shdrp = &((Elf32_Shdr *)mi->mi_elfshdr_addr)[i]; 304 305 if ((shdrp->sh_type & SHT_SYMTAB) && 306 shdrp->sh_link != SHN_UNDEF) { 307 Elf32_Shdr *shdrp2; 308 309 shdrp2 = &((Elf32_Shdr *)mi->mi_elfshdr_addr) 310 [shdrp->sh_link]; 311 312 if (shdrp2->sh_type & SHT_STRTAB) { 313 symtabp = shdrp; 314 strtabp = shdrp2; 315 } 316 } 317 } 318 if (symtabp == NULL || strtabp == NULL) 319 return; 320 321 symaddr = symtabp->sh_addr; 322 straddr = strtabp->sh_addr; 323 symsize = symtabp->sh_size; 324 strsize = strtabp->sh_size; 325 326 /* 327 * Copy the symbol and string tables just after the kernel's 328 * end address, in this order. Only the contents of these ELF 329 * sections are copied; headers are discarded. esym is later 330 * updated to point to the lowest "free" address after the tables 331 * so that they are mapped appropriately when enabling paging. 332 * 333 * We need to be careful to not overwrite valid data doing the 334 * copies, hence all the different cases below. We can assume 335 * that if the tables start before the kernel's end address, 336 * they will not grow over this address. 337 */ 338 if ((void *)symtabp < RELOC(void *, &end) && 339 (void *)strtabp < RELOC(void *, &end)) { 340 symstart = RELOC(Elf32_Addr, &end); 341 strstart = symstart + symsize; 342 memcpy((void *)symstart, (void *)symaddr, symsize); 343 memcpy((void *)strstart, (void *)straddr, strsize); 344 } else if ((void *)symtabp > RELOC(void *, &end) && 345 (void *)strtabp < RELOC(void *, &end)) { 346 symstart = RELOC(Elf32_Addr, &end); 347 strstart = symstart + symsize; 348 memcpy((void *)symstart, (void *)symaddr, symsize); 349 memcpy((void *)strstart, (void *)straddr, strsize); 350 } else if ((void *)symtabp < RELOC(void *, &end) && 351 (void *)strtabp > RELOC(void *, &end)) { 352 strstart = RELOC(Elf32_Addr, &end); 353 symstart = strstart + strsize; 354 memcpy((void *)strstart, (void *)straddr, strsize); 355 memcpy((void *)symstart, (void *)symaddr, symsize); 356 } else { 357 /* symtabp and strtabp are both over end */ 358 if (symtabp < strtabp) { 359 symstart = RELOC(Elf32_Addr, &end); 360 strstart = symstart + symsize; 361 memcpy((void *)symstart, (void *)symaddr, symsize); 362 memcpy((void *)strstart, (void *)straddr, strsize); 363 } else { 364 strstart = RELOC(Elf32_Addr, &end); 365 symstart = strstart + strsize; 366 memcpy((void *)strstart, (void *)straddr, strsize); 367 memcpy((void *)symstart, (void *)symaddr, symsize); 368 } 369 } 370 371 *RELOC(int *, &esym) = 372 (int)(symstart + symsize + strsize + KERNBASE); 373 374 ms->s_symstart = (void *)(symstart + KERNBASE); 375 ms->s_symsize = symsize; 376 ms->s_strstart = (void *)(strstart + KERNBASE); 377 ms->s_strsize = strsize; 378 #undef RELOC 379 } 380 381 /* --------------------------------------------------------------------- */ 382 383 /* 384 * Sets up the biosgeom bootinfo structure if the Multiboot information 385 * structure provides information about disk drives. 386 */ 387 static void 388 setup_biosgeom(struct multiboot_info *mi) 389 { 390 size_t pos; 391 uint8_t bidata[1024]; 392 struct btinfo_biosgeom *bi; 393 394 if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES)) 395 return; 396 397 memset(bidata, 0, sizeof(bidata)); 398 bi = (struct btinfo_biosgeom *)bidata; 399 pos = 0; 400 401 while (pos < mi->mi_drives_length) { 402 struct multiboot_drive *md; 403 struct bi_biosgeom_entry bbe; 404 405 md = (struct multiboot_drive *) 406 &((uint8_t *)mi->mi_drives_addr)[pos]; 407 408 memset(&bbe, 0, sizeof(bbe)); 409 bbe.sec = md->md_sectors; 410 bbe.head = md->md_heads; 411 bbe.cyl = md->md_cylinders; 412 bbe.dev = md->md_number; 413 414 memcpy(&bi->disk[bi->num], &bbe, sizeof(bbe)); 415 bi->num++; 416 417 pos += md->md_length; 418 } 419 420 bootinfo_add((struct btinfo_common *)bi, BTINFO_BIOSGEOM, 421 sizeof(struct btinfo_biosgeom) + 422 bi->num * sizeof(struct bi_biosgeom_entry)); 423 } 424 425 /* --------------------------------------------------------------------- */ 426 427 /* 428 * Sets up the default root device if the Multiboot information 429 * structure provides information about the boot drive (where the kernel 430 * image was loaded from) or if the user gave a 'root' parameter on the 431 * boot command line. 432 */ 433 static void 434 setup_bootdisk(struct multiboot_info *mi) 435 { 436 bool found; 437 struct btinfo_rootdevice bi; 438 439 found = false; 440 441 if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) 442 found = optstr_get(mi->mi_cmdline, "root", bi.devname, 443 sizeof(bi.devname)); 444 445 if (!found && (mi->mi_flags & MULTIBOOT_INFO_HAS_BOOT_DEVICE)) { 446 const char *devprefix; 447 448 /* Attempt to match the BIOS boot disk to a device. There 449 * is not much we can do to get it right. (Well, strictly 450 * speaking, we could, but it is certainly not worth the 451 * extra effort.) */ 452 switch (mi->mi_boot_device_drive) { 453 case 0x00: devprefix = "fd0"; break; 454 case 0x01: devprefix = "fd1"; break; 455 case 0x80: devprefix = "wd0"; break; 456 case 0x81: devprefix = "wd1"; break; 457 case 0x82: devprefix = "wd2"; break; 458 case 0x83: devprefix = "wd3"; break; 459 default: devprefix = "wd0"; 460 } 461 462 strcpy(bi.devname, devprefix); 463 if (mi->mi_boot_device_part2 != 0xFF) 464 bi.devname[3] = mi->mi_boot_device_part2 + 'a'; 465 else 466 bi.devname[3] = 'a'; 467 bi.devname[4] = '\0'; 468 469 found = true; 470 } 471 472 if (found) { 473 bootinfo_add((struct btinfo_common *)&bi, BTINFO_ROOTDEVICE, 474 sizeof(struct btinfo_rootdevice)); 475 } 476 } 477 478 /* --------------------------------------------------------------------- */ 479 480 /* 481 * Sets up the bootpath bootinfo structure with an appropriate kernel 482 * name derived from the boot command line. The Multiboot information 483 * structure does not provide this detail directly, so we try to derive 484 * it from the command line setting. 485 */ 486 static void 487 setup_bootpath(struct multiboot_info *mi) 488 { 489 struct btinfo_bootpath bi; 490 char *cl, *cl2, old; 491 int len; 492 493 if (strncmp(Multiboot_Loader_Name, "GNU GRUB ", 494 sizeof(Multiboot_Loader_Name)) > 0) { 495 cl = mi->mi_cmdline; 496 while (*cl != '\0' && *cl != '/') 497 cl++; 498 cl2 = cl; 499 len = 0; 500 while (*cl2 != '\0' && *cl2 != ' ') { 501 len++; 502 cl2++; 503 } 504 505 old = *cl2; 506 *cl2 = '\0'; 507 memcpy(bi.bootpath, cl, MIN(sizeof(bi.bootpath), len)); 508 *cl2 = old; 509 bi.bootpath[MIN(sizeof(bi.bootpath), len)] = '\0'; 510 511 bootinfo_add((struct btinfo_common *)&bi, BTINFO_BOOTPATH, 512 sizeof(struct btinfo_bootpath)); 513 } 514 } 515 516 /* --------------------------------------------------------------------- */ 517 518 /* 519 * Sets up the console bootinfo structure if the user gave a 'console' 520 * argument on the boot command line. The Multiboot information 521 * structure gives no hint about this, so the only way to know where the 522 * console is is to let the user specify it. 523 * 524 * If there wasn't any 'console' argument, this does not generate any 525 * bootinfo entry, falling back to the kernel's default console. 526 * 527 * If there weren't any of 'console_speed' or 'console_addr' arguments, 528 * this falls back to the default values for the serial port. 529 */ 530 static void 531 setup_console(struct multiboot_info *mi) 532 { 533 struct btinfo_console bi; 534 bool found; 535 536 found = false; 537 538 if (mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) 539 found = optstr_get(mi->mi_cmdline, "console", bi.devname, 540 sizeof(bi.devname)); 541 542 if (found) { 543 bool valid; 544 545 if (strncmp(bi.devname, "com", sizeof(bi.devname)) == 0) { 546 char tmp[10]; 547 548 found = optstr_get(mi->mi_cmdline, "console_speed", 549 tmp, sizeof(tmp)); 550 if (found) 551 bi.speed = strtoul(tmp, NULL, 10); 552 else 553 bi.speed = 0; /* Use default speed. */ 554 555 found = optstr_get(mi->mi_cmdline, "console_addr", 556 tmp, sizeof(tmp)); 557 if (found) { 558 if (tmp[0] == '0' && tmp[1] == 'x') 559 bi.addr = strtoul(tmp + 2, NULL, 16); 560 else 561 bi.addr = strtoul(tmp, NULL, 10); 562 } else 563 bi.addr = 0; /* Use default address. */ 564 565 valid = true; 566 } else if (strncmp(bi.devname, "pc", sizeof(bi.devname)) == 0) 567 valid = true; 568 else 569 valid = false; 570 571 if (valid) 572 bootinfo_add((struct btinfo_common *)&bi, 573 BTINFO_CONSOLE, sizeof(struct btinfo_console)); 574 } 575 } 576 577 /* --------------------------------------------------------------------- */ 578 579 /* 580 * Sets up the 'boothowto' variable based on the options given in the 581 * boot command line, if any. 582 */ 583 static void 584 setup_howto(struct multiboot_info *mi) 585 { 586 char *cl; 587 588 if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE)) 589 return; 590 591 cl = mi->mi_cmdline; 592 593 /* Skip kernel file name. */ 594 while (*cl != '\0' && *cl != ' ') 595 cl++; 596 while (*cl != '\0' && *cl == ' ') 597 cl++; 598 599 /* Check if there are flags and set 'howto' accordingly. */ 600 if (*cl == '-') { 601 int howto = 0; 602 603 cl++; 604 while (*cl != '\0' && *cl != ' ') { 605 BOOT_FLAG(*cl, howto); 606 cl++; 607 } 608 if (*cl == ' ') 609 cl++; 610 611 boothowto = howto; 612 } 613 } 614 615 /* --------------------------------------------------------------------- */ 616 617 /* 618 * Sets up the memmap bootinfo structure to describe available memory as 619 * given by the BIOS. 620 */ 621 static void 622 setup_memmap(struct multiboot_info *mi) 623 { 624 char data[1024]; 625 size_t i; 626 struct btinfo_memmap *bi; 627 628 if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_MMAP)) 629 return; 630 631 bi = (struct btinfo_memmap *)data; 632 bi->num = 0; 633 634 i = 0; 635 while (i < mi->mi_mmap_length) { 636 struct multiboot_mmap *mm; 637 struct bi_memmap_entry *bie; 638 639 bie = &bi->entry[bi->num]; 640 641 mm = (struct multiboot_mmap *)(mi->mi_mmap_addr + i); 642 bie->addr = mm->mm_base_addr; 643 bie->size = mm->mm_length; 644 if (mm->mm_type == 1) 645 bie->type = BIM_Memory; 646 else 647 bie->type = BIM_Reserved; 648 649 bi->num++; 650 i += mm->mm_size + 4; 651 } 652 653 bootinfo_add((struct btinfo_common *)bi, BTINFO_MEMMAP, 654 sizeof(data)); 655 } 656 657 /* --------------------------------------------------------------------- */ 658 659 /* 660 * Sets up the 'biosbasemem' and 'biosextmem' variables if the 661 * Multiboot information structure provides information about memory. 662 */ 663 static void 664 setup_memory(struct multiboot_info *mi) 665 { 666 667 if (!(mi->mi_flags & MULTIBOOT_INFO_HAS_MEMORY)) 668 return; 669 670 /* Make sure we don't override user-set variables. */ 671 if (biosbasemem == 0) { 672 biosbasemem = mi->mi_mem_lower; 673 biosmem_implicit = 1; 674 } 675 if (biosextmem == 0) { 676 biosextmem = mi->mi_mem_upper; 677 biosmem_implicit = 1; 678 } 679 } 680 681 /* --------------------------------------------------------------------- */ 682 683 /* 684 * Sets up the initial kernel symbol table. Returns true if this was 685 * passed in by Multiboot; false otherwise. 686 */ 687 bool 688 multiboot_ksyms_addsyms_elf(void) 689 { 690 struct multiboot_info *mi = &Multiboot_Info; 691 struct multiboot_symbols *ms = &Multiboot_Symbols; 692 693 if (mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS) { 694 Elf32_Ehdr ehdr; 695 696 KASSERT(esym != 0); 697 698 memcpy(ehdr.e_ident, ELFMAG, SELFMAG); 699 ehdr.e_ident[EI_CLASS] = ELFCLASS32; 700 ehdr.e_ident[EI_DATA] = ELFDATA2LSB; 701 ehdr.e_ident[EI_VERSION] = EV_CURRENT; 702 ehdr.e_type = ET_EXEC; 703 ehdr.e_machine = EM_386; 704 ehdr.e_version = 1; 705 ehdr.e_ehsize = sizeof(ehdr); 706 707 ksyms_addsyms_explicit((void *)&ehdr, 708 ms->s_symstart, ms->s_symsize, 709 ms->s_strstart, ms->s_strsize); 710 } 711 712 return mi->mi_flags & MULTIBOOT_INFO_HAS_ELF_SYMS; 713 } 714