1 /* $NetBSD: multiboot2.c,v 1.8 2021/10/07 12:52:27 msaitoh 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: multiboot2.c,v 1.8 2021/10/07 12:52:27 msaitoh 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 #include <sys/common_ansi.h> 46 #include <sys/intr.h> 47 48 #include <x86/efi.h> 49 50 #include <machine/bootinfo.h> 51 #include <arch/i386/include/multiboot2.h> 52 53 #ifdef _LOCORE64 54 typedef uint64_t locore_vaddr_t; 55 typedef Elf64_Shdr locore_Elf_Shdr; 56 typedef Elf64_Word locore_Elf_Word; 57 typedef Elf64_Addr locore_Elf_Addr; 58 #else 59 typedef vaddr_t locore_vaddr_t; 60 typedef Elf_Shdr locore_Elf_Shdr; 61 typedef Elf_Word locore_Elf_Word; 62 typedef Elf_Addr locore_Elf_Addr; 63 #endif 64 65 #if !defined(MULTIBOOT) 66 # error "MULTIBOOT not defined; this cannot happen." 67 #endif 68 69 /* 70 * This is an attempt to get an early debug output. It 71 * requires EFI Boot Services, and it does not work anyway: 72 * it causes EFI to try to handle interrupts while the kernel 73 * already took that over, hence we get a reboot. 74 */ 75 #define BS_PRINT(efisystbl, wstring) \ 76 efi_systbl->st_coutif->ei_outputstring(efi_systbl->st_coutif, \ 77 (efi_char *)__UNCONST(wstring)) 78 79 struct multiboot_symbols { 80 uint32_t s_symstart; 81 uint32_t s_symsize; 82 uint32_t s_strstart; 83 uint32_t s_strsize; 84 }; 85 86 void multiboot2_copy_syms(struct multiboot_tag_elf_sections *, 87 struct multiboot_symbols *, 88 bool *, int **, void *, vaddr_t); 89 /* 90 * Because of clashes between multiboot.h and multiboot2.h we 91 * cannot include both, and we need to redefine here: 92 */ 93 void multiboot2_pre_reloc(char *); 94 void multiboot2_post_reloc(void); 95 void multiboot2_print_info(void); 96 bool multiboot2_ksyms_addsyms_elf(void); 97 98 extern int biosbasemem; 99 extern int biosextmem; 100 #ifdef __i386__ 101 extern int biosmem_implicit; 102 #endif 103 extern int boothowto; 104 extern struct bootinfo bootinfo; 105 extern int end; 106 extern int * esym; 107 extern char start; 108 109 /* 110 * There is no way to perform dynamic allocation 111 * at this time, hence we need to waste memory, 112 * with the hope data will fit. 113 */ 114 char multiboot_info[16384] = "\0\0\0\0"; 115 bool multiboot2_enabled = false; 116 bool has_syms = false; 117 struct multiboot_symbols Multiboot_Symbols; 118 119 #define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE)) 120 121 static void 122 efi_exit_bs(struct efi_systbl *efi_systbl, void *efi_ih) 123 { 124 struct efi_bs *efi_bs; 125 struct efi_md *desc; 126 uintn bufsize, key, size; 127 uint32_t vers; 128 129 if (efi_systbl == NULL) 130 panic("EFI system table is NULL"); 131 132 if (efi_systbl->st_hdr.th_sig != EFI_SYSTBL_SIG) 133 panic("EFI system table signature is wrong"); 134 135 efi_bs = efi_systbl->st_bs; 136 137 if (efi_bs == NULL) 138 panic("EFI BS is NULL"); 139 140 if (efi_bs->bs_hdr.th_sig != EFI_BS_SIG) 141 panic("EFI BS signature is wrong"); 142 143 if (efi_ih == NULL) 144 panic("EFI IH is NULL"); 145 146 bufsize = 16384; 147 148 if (efi_bs->bs_allocatepool(EFI_MD_TYPE_DATA, 149 bufsize, (void **)&desc) != 0) 150 panic("EFI AllocatePool failed"); 151 152 if (efi_bs->bs_getmemorymap(&bufsize, desc, &key, &size, &vers) == 0) 153 goto exit_bs; 154 155 (void)efi_bs->bs_freepool((void *)desc); 156 157 if (efi_bs->bs_allocatepool(EFI_MD_TYPE_DATA, 158 bufsize, (void **)&desc) != 0) 159 panic("EFI AllocatePool failed"); 160 161 if (efi_bs->bs_getmemorymap(&bufsize, desc, &key, &size, &vers) != 0) 162 panic("EFI GetMemoryMap failed"); 163 164 exit_bs: 165 if (efi_bs->bs_exitbootservices(efi_ih, key) != 0) 166 panic("EFI ExitBootServices failed"); 167 168 return; 169 } 170 171 void 172 multiboot2_copy_syms(struct multiboot_tag_elf_sections *mbt_elf, 173 struct multiboot_symbols *ms, 174 bool *has_symsp, int **esymp, void *endp, 175 vaddr_t kernbase) 176 { 177 int i; 178 locore_Elf_Shdr *symtabp, *strtabp; 179 locore_Elf_Word symsize, strsize; 180 locore_Elf_Addr symaddr, straddr; 181 locore_Elf_Addr symstart, strstart; 182 locore_Elf_Addr cp1src, cp1dst; 183 locore_Elf_Word cp1size; 184 locore_Elf_Addr cp2src, cp2dst; 185 locore_Elf_Word cp2size; 186 187 /* 188 * Locate a symbol table and its matching string table in the 189 * section headers passed in by the boot loader. Set 'symtabp' 190 * and 'strtabp' with pointers to the matching entries. 191 */ 192 symtabp = strtabp = NULL; 193 for (i = 0; i < mbt_elf->num && symtabp == NULL && 194 strtabp == NULL; i++) { 195 locore_Elf_Shdr *shdrp; 196 197 shdrp = &((locore_Elf_Shdr *)mbt_elf->sections)[i]; 198 199 if ((shdrp->sh_type == SHT_SYMTAB) && 200 shdrp->sh_link != SHN_UNDEF) { 201 locore_Elf_Shdr *shdrp2; 202 203 shdrp2 = &((locore_Elf_Shdr *)mbt_elf->sections) 204 [shdrp->sh_link]; 205 206 if (shdrp2->sh_type == SHT_STRTAB) { 207 symtabp = (locore_Elf_Shdr *)shdrp; 208 strtabp = (locore_Elf_Shdr *)shdrp2; 209 } 210 } 211 } 212 if (symtabp == NULL || strtabp == NULL) 213 return; 214 215 symaddr = symtabp->sh_addr; 216 straddr = strtabp->sh_addr; 217 symsize = symtabp->sh_size; 218 strsize = strtabp->sh_size; 219 220 /* 221 * Copy the symbol and string tables just after the kernel's 222 * end address, in this order. Only the contents of these ELF 223 * sections are copied; headers are discarded. esym is later 224 * updated to point to the lowest "free" address after the tables 225 * so that they are mapped appropriately when enabling paging. 226 * 227 * We need to be careful to not overwrite valid data doing the 228 * copies, hence all the different cases below. We can assume 229 * that if the tables start before the kernel's end address, 230 * they will not grow over this address. 231 */ 232 if ((void *)(uintptr_t)symaddr < endp && 233 (void *)(uintptr_t)straddr < endp) { 234 cp1src = symaddr; cp1size = symsize; 235 cp2src = straddr; cp2size = strsize; 236 } else if ((void *)(uintptr_t)symaddr > endp && 237 (void *)(uintptr_t)straddr < endp) { 238 cp1src = symaddr; cp1size = symsize; 239 cp2src = straddr; cp2size = strsize; 240 } else if ((void *)(uintptr_t)symaddr < endp && 241 (void *)(uintptr_t)straddr > endp) { 242 cp1src = straddr; cp1size = strsize; 243 cp2src = symaddr; cp2size = symsize; 244 } else { 245 /* symaddr and straddr are both over end */ 246 if (symaddr < straddr) { 247 cp1src = symaddr; cp1size = symsize; 248 cp2src = straddr; cp2size = strsize; 249 } else { 250 cp1src = straddr; cp1size = strsize; 251 cp2src = symaddr; cp2size = symsize; 252 } 253 } 254 255 cp1dst = (locore_Elf_Addr)(uintptr_t)endp; 256 cp2dst = (locore_Elf_Addr)(uintptr_t)endp + cp1size; 257 258 (void)memcpy((void *)(uintptr_t)cp1dst, 259 (void *)(uintptr_t)cp1src, cp1size); 260 (void)memcpy((void *)(uintptr_t)cp2dst, 261 (void *)(uintptr_t)cp2src, cp2size); 262 263 symstart = (cp1src == symaddr) ? cp1dst : cp2dst; 264 strstart = (cp1src == straddr) ? cp1dst : cp2dst; 265 266 ms->s_symstart = symstart + kernbase; 267 ms->s_symsize = symsize; 268 ms->s_strstart = strstart + kernbase; 269 ms->s_strsize = strsize; 270 271 *has_symsp = true; 272 *esymp = (int *)((uintptr_t)endp + symsize + strsize + kernbase); 273 274 } 275 276 void 277 multiboot2_pre_reloc(char *mbi) 278 { 279 uint32_t mbi_size; 280 void *mbidest = RELOC(void *, multiboot_info); 281 char *cp; 282 struct multiboot_tag_module *mbt; 283 struct multiboot_tag_elf_sections *mbt_elf = NULL; 284 struct efi_systbl *efi_systbl = NULL; 285 void *efi_ih = NULL; 286 bool has_bs = false; 287 288 mbi_size = *(uint32_t *)mbi; 289 if (mbi_size < sizeof(multiboot_info)) 290 memcpy(mbidest, mbi, mbi_size); 291 else 292 panic("multiboot_info too big"); /* will not show up */ 293 294 *RELOC(bool *, &multiboot2_enabled) = true; 295 296 for (cp = mbi + (2 * sizeof(uint32_t)); 297 cp - mbi < mbi_size; 298 cp += roundup(mbt->size, MULTIBOOT_INFO_ALIGN)) { 299 mbt = (struct multiboot_tag_module *)cp; 300 switch (mbt->type) { 301 case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: 302 mbt_elf = (struct multiboot_tag_elf_sections *)mbt; 303 break; 304 #ifdef __LP64__ 305 case MULTIBOOT_TAG_TYPE_EFI64: 306 efi_systbl = (struct efi_systbl *) 307 ((struct multiboot_tag_efi64 *)mbt)->pointer; 308 break; 309 case MULTIBOOT_TAG_TYPE_EFI64_IH: 310 efi_ih = (void *) 311 ((struct multiboot_tag_efi64_ih *)mbt)->pointer; 312 break; 313 #else 314 case MULTIBOOT_TAG_TYPE_EFI32: 315 efi_systbl = (struct efi_systbl *) 316 ((struct multiboot_tag_efi32 *)mbt)->pointer; 317 break; 318 case MULTIBOOT_TAG_TYPE_EFI32_IH: 319 efi_ih = (void *) 320 ((struct multiboot_tag_efi32_ih *)mbt)->pointer; 321 break; 322 #endif 323 case MULTIBOOT_TAG_TYPE_EFI_BS: 324 #if notyet 325 has_bs = true; 326 #endif 327 break; 328 default: 329 break; 330 } 331 } 332 333 /* Broken */ 334 if (has_bs) 335 efi_exit_bs(efi_systbl, efi_ih); 336 337 if (mbt_elf) 338 multiboot2_copy_syms(mbt_elf, 339 RELOC(struct multiboot_symbols *, &Multiboot_Symbols), 340 RELOC(bool *, &has_syms), 341 RELOC(int **, &esym), 342 RELOC(void *, &end), 343 KERNBASE); 344 345 return; 346 } 347 348 static struct btinfo_common * 349 bootinfo_init(int type, int len) 350 { 351 int i; 352 struct bootinfo *bip = (struct bootinfo *)&bootinfo; 353 vaddr_t data; 354 355 data = (vaddr_t)&bip->bi_data; 356 for (i = 0; i < bip->bi_nentries; i++) { 357 struct btinfo_common *tmp; 358 359 tmp = (struct btinfo_common *)data; 360 data += tmp->len; 361 } 362 if (data + len < (vaddr_t)&bip->bi_data + sizeof(bip->bi_data)) { 363 /* Initialize the common part */ 364 struct btinfo_common *item = (struct btinfo_common *)data; 365 item->type = type; 366 item->len = len; 367 bip->bi_nentries++; 368 return item; 369 } else { 370 return NULL; 371 } 372 } 373 374 static void 375 bootinfo_add(struct btinfo_common *item, int type, int len) 376 { 377 struct btinfo_common *bip = bootinfo_init(type, len); 378 if (bip == NULL) 379 return; 380 381 /* Copy the data after the common part over */ 382 memcpy(&bip[1], &item[1], len - sizeof(*item)); 383 } 384 385 static void 386 mbi_cmdline(struct multiboot_tag_string *mbt) 387 { 388 char *cmdline = mbt->string; 389 struct btinfo_console bic; 390 struct btinfo_rootdevice bir; 391 char *cl; 392 393 if (optstr_get(cmdline, "console", bic.devname, sizeof(bic.devname))) { 394 if (strncmp(bic.devname, "com", sizeof(bic.devname)) == 0) { 395 char opt[10]; 396 397 if (optstr_get(cmdline, "console_speed", 398 opt, sizeof(opt))) 399 bic.speed = strtoul(opt, NULL, 10); 400 else 401 bic.speed = 0; /* Use default speed. */ 402 403 if (optstr_get(cmdline, "console_addr", 404 opt, sizeof(opt))) { 405 if (opt[0] == '0' && opt[1] == 'x') 406 bic.addr = strtoul(opt + 2, NULL, 16); 407 else 408 bic.addr = strtoul(opt, NULL, 10); 409 } else { 410 bic.addr = 0; /* Use default address. */ 411 } 412 413 bootinfo_add((struct btinfo_common *)&bic, 414 BTINFO_CONSOLE, sizeof(bic)); 415 416 } 417 418 if (strncmp(bic.devname, "pc", sizeof(bic.devname)) == 0) 419 bootinfo_add((struct btinfo_common *)&bic, 420 BTINFO_CONSOLE, sizeof(bic)); 421 } 422 423 if (optstr_get(cmdline, "root", bir.devname, sizeof(bir.devname))) 424 bootinfo_add((struct btinfo_common *)&bir, BTINFO_ROOTDEVICE, 425 sizeof(bir)); 426 427 /* 428 * Parse boot flags (-s and friends) 429 */ 430 cl = cmdline; 431 432 /* Skip kernel file name. */ 433 while (*cl != '\0' && *cl != ' ') 434 cl++; 435 while (*cl == ' ') 436 cl++; 437 438 /* Check if there are flags and set 'howto' accordingly. */ 439 if (*cl == '-') { 440 int howto = 0; 441 442 cl++; 443 while (*cl != '\0' && *cl != ' ') { 444 BOOT_FLAG(*cl, howto); 445 cl++; 446 } 447 if (*cl == ' ') 448 cl++; 449 450 boothowto = howto; 451 } 452 453 return; 454 } 455 456 static void 457 mbi_modules(char *mbi, uint32_t mbi_size, int module_count) 458 { 459 char *cp; 460 struct multiboot_tag_module *mbt; 461 size_t bim_len; 462 struct bi_modulelist_entry *bie; 463 struct btinfo_modulelist *bim; 464 465 bim_len = sizeof(*bim) + (module_count * sizeof(*bie)); 466 bim = (struct btinfo_modulelist *)bootinfo_init(BTINFO_MODULELIST, 467 bim_len); 468 if (bim == NULL) 469 return; 470 471 bim->num = module_count; 472 bim->endpa = end; 473 474 bie = (struct bi_modulelist_entry *)(bim + 1); 475 476 for (cp = mbi + (2 * sizeof(uint32_t)); 477 cp - mbi < mbi_size; 478 cp += roundup(mbt->size, MULTIBOOT_INFO_ALIGN)) { 479 mbt = (struct multiboot_tag_module *)cp; 480 if (mbt->type != MULTIBOOT_TAG_TYPE_MODULE) 481 continue; 482 483 strncpy(bie->path, mbt->cmdline, sizeof(bie->path)); 484 bie->type = BI_MODULE_ELF; 485 bie->len = mbt->mod_end - mbt->mod_start; 486 bie->base = mbt->mod_start; 487 488 bie++; 489 } 490 } 491 492 static void 493 mbi_basic_meminfo(struct multiboot_tag_basic_meminfo *mbt) 494 { 495 /* Make sure we don't override user-set variables. */ 496 if (biosbasemem == 0) { 497 biosbasemem = mbt->mem_lower; 498 #ifdef __i386__ 499 biosmem_implicit = 1; 500 #endif 501 } 502 if (biosextmem == 0) { 503 biosextmem = mbt->mem_upper; 504 #ifdef __i386__ 505 biosmem_implicit = 1; 506 #endif 507 } 508 509 return; 510 } 511 512 static void 513 mbi_bootdev(struct multiboot_tag_bootdev *mbt) 514 { 515 struct btinfo_bootdisk bid; 516 517 bid.labelsector = -1; 518 bid.biosdev = mbt->biosdev; 519 bid.partition = mbt->slice; 520 521 bootinfo_add((struct btinfo_common *)&bid, 522 BTINFO_BOOTDISK, sizeof(bid)); 523 } 524 525 static void 526 mbi_mmap(struct multiboot_tag_mmap *mbt) 527 { 528 struct btinfo_memmap *bim; 529 int num; 530 char *cp; 531 532 if (mbt->entry_version != 0) 533 return; 534 535 /* Determine size */ 536 num = 0; 537 for (cp = (char *)(mbt + 1); 538 cp - (char *)mbt < mbt->size; 539 cp += mbt->entry_size) { 540 num++; 541 } 542 543 bim = (struct btinfo_memmap *)bootinfo_init(BTINFO_MEMMAP, 544 sizeof(num) + num * sizeof(struct bi_memmap_entry)); 545 if (bim == NULL) 546 return; 547 bim->num = 0; 548 549 for (cp = (char *)(mbt + 1); 550 cp - (char *)mbt < mbt->size; 551 cp += mbt->entry_size) { 552 struct multiboot_mmap_entry *mbe; 553 struct bi_memmap_entry *bie; 554 555 mbe = (struct multiboot_mmap_entry *)cp; 556 bie = &bim->entry[bim->num]; 557 558 bie->addr = mbe->addr; 559 bie->size = mbe->len; 560 switch (mbe->type) { 561 case MULTIBOOT_MEMORY_AVAILABLE: 562 bie->type = BIM_Memory; 563 break; 564 case MULTIBOOT_MEMORY_RESERVED: 565 bie->type = BIM_Reserved; 566 break; 567 case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE: 568 bie->type = BIM_ACPI; 569 break; 570 case MULTIBOOT_MEMORY_NVS: 571 bie->type = BIM_NVS; 572 break; 573 case MULTIBOOT_MEMORY_BADRAM: 574 default: 575 bie->type = BIM_Unusable; 576 break; 577 } 578 579 bim->num++; 580 } 581 582 KASSERT(bim->num == num); 583 } 584 585 static void 586 mbi_vbe(struct multiboot_tag_vbe *mbt, struct btinfo_framebuffer *bif) 587 { 588 bif->vbemode = mbt->vbe_mode; 589 return; 590 } 591 592 static void 593 mbi_framebuffer(struct multiboot_tag_framebuffer *mbt, 594 struct btinfo_framebuffer *bif) 595 { 596 bif->physaddr = mbt->common.framebuffer_addr; 597 bif->width = mbt->common.framebuffer_width; 598 bif->height = mbt->common.framebuffer_height; 599 bif->depth = mbt->common.framebuffer_bpp; 600 bif->stride = mbt->common.framebuffer_pitch; 601 602 return; 603 } 604 605 static void 606 mbi_efi32(struct multiboot_tag_efi32 *mbt) 607 { 608 struct btinfo_efi bie; 609 610 bie.systblpa = mbt->pointer; 611 bie.flags = BI_EFI_32BIT; 612 613 bootinfo_add((struct btinfo_common *)&bie, BTINFO_EFI, sizeof(bie)); 614 } 615 616 static void 617 mbi_efi64(struct multiboot_tag_efi64 *mbt) 618 { 619 struct btinfo_efi bie; 620 621 bie.systblpa = mbt->pointer; 622 623 bootinfo_add((struct btinfo_common *)&bie, BTINFO_EFI, sizeof(bie)); 624 } 625 626 static void 627 mbi_efi_mmap(struct multiboot_tag_efi_mmap *mbt) 628 { 629 struct btinfo_efimemmap *bie; 630 size_t bie_len; 631 632 if (mbt->descr_vers != 0) 633 return; 634 635 bie_len = sizeof(*bie) + mbt->size - sizeof(*mbt); 636 bie = (struct btinfo_efimemmap *)bootinfo_init(BTINFO_EFIMEMMAP, 637 bie_len); 638 if (bie == NULL) 639 return; 640 641 bie->num = (mbt->size - sizeof(*mbt)) / mbt->descr_size; 642 bie->version = mbt->descr_vers; 643 bie->size = mbt->descr_size; 644 memcpy(bie->memmap, mbt + 1, mbt->size - sizeof(*mbt)); 645 } 646 647 void 648 multiboot2_post_reloc(void) 649 { 650 uint32_t mbi_size; 651 struct multiboot_tag *mbt; 652 char *mbi = multiboot_info; 653 char *cp; 654 int module_count = 0; 655 struct btinfo_framebuffer fbinfo; 656 bool has_fbinfo = false; 657 658 if (multiboot2_enabled == false) 659 goto out; 660 661 mbi_size = *(uint32_t *)multiboot_info; 662 if (mbi_size < 2 * sizeof(uint32_t)) 663 goto out; 664 665 bootinfo.bi_nentries = 0; 666 667 memset(&fbinfo, 0, sizeof(fbinfo)); 668 669 for (cp = mbi + (2 * sizeof(uint32_t)); 670 cp - mbi < mbi_size; 671 cp += roundup(mbt->size, MULTIBOOT_INFO_ALIGN)) { 672 mbt = (struct multiboot_tag *)cp; 673 switch (mbt->type) { 674 case MULTIBOOT_TAG_TYPE_CMDLINE: 675 mbi_cmdline((void *)mbt); 676 break; 677 case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: 678 break; 679 case MULTIBOOT_TAG_TYPE_MMAP: 680 mbi_mmap((void *)mbt); 681 break; 682 case MULTIBOOT_TAG_TYPE_MODULE: 683 module_count++; 684 break; 685 case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: 686 mbi_basic_meminfo((void *)mbt); 687 break; 688 case MULTIBOOT_TAG_TYPE_BOOTDEV: 689 mbi_bootdev((void *)mbt); 690 break; 691 case MULTIBOOT_TAG_TYPE_VBE: 692 mbi_vbe((void *)mbt, &fbinfo); 693 break; 694 case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: 695 mbi_framebuffer((void *)mbt, &fbinfo); 696 has_fbinfo = true; 697 break; 698 case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: 699 case MULTIBOOT_TAG_TYPE_APM: 700 break; 701 case MULTIBOOT_TAG_TYPE_EFI32: 702 mbi_efi32((void *)mbt); 703 break; 704 case MULTIBOOT_TAG_TYPE_EFI64: 705 mbi_efi64((void *)mbt); 706 break; 707 case MULTIBOOT_TAG_TYPE_SMBIOS: 708 case MULTIBOOT_TAG_TYPE_ACPI_OLD: 709 case MULTIBOOT_TAG_TYPE_ACPI_NEW: 710 case MULTIBOOT_TAG_TYPE_NETWORK: 711 break; 712 case MULTIBOOT_TAG_TYPE_EFI_MMAP: 713 mbi_efi_mmap((void *)mbt); 714 break; 715 case MULTIBOOT_TAG_TYPE_EFI_BS: 716 case MULTIBOOT_TAG_TYPE_EFI32_IH: 717 case MULTIBOOT_TAG_TYPE_EFI64_IH: 718 case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: 719 case MULTIBOOT_TAG_TYPE_END: 720 default: 721 break; 722 } 723 } 724 725 if (has_fbinfo) 726 bootinfo_add((struct btinfo_common *)&fbinfo, 727 BTINFO_FRAMEBUFFER, sizeof(fbinfo)); 728 729 if (module_count > 0) 730 mbi_modules(mbi, mbi_size, module_count); 731 732 out: 733 return; 734 } 735 736 737 #ifdef DEBUG 738 static void 739 mbi_hexdump(char *addr, size_t len) 740 { 741 int i,j; 742 743 for (i = 0; i < len; i += 16) { 744 printf(" %p ", addr + i); 745 for (j = 0; j < 16 && i + j < len; j++) { 746 char *cp = addr + i + j; 747 printf("%s%s%x", 748 (i+j) % 4 ? "" : " ", 749 (unsigned char)*cp < 0x10 ? "0" : "", 750 (unsigned char)*cp); 751 } 752 printf("\n"); 753 } 754 755 return; 756 } 757 #endif 758 759 static const char * 760 mbi_tag_name(uint32_t type) 761 { 762 const char *tag_name; 763 764 switch (type) { 765 case MULTIBOOT_TAG_TYPE_END: 766 tag_name = ""; 767 break; 768 case MULTIBOOT_TAG_TYPE_CMDLINE: 769 tag_name = "command line"; break; 770 case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: 771 tag_name = "boot loader name"; break; 772 case MULTIBOOT_TAG_TYPE_MODULE: 773 tag_name = "module"; break; 774 case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: 775 tag_name = "basic meminfo"; break; 776 case MULTIBOOT_TAG_TYPE_BOOTDEV: 777 tag_name = "boot device"; break; 778 case MULTIBOOT_TAG_TYPE_MMAP: 779 tag_name = "memory map"; break; 780 case MULTIBOOT_TAG_TYPE_VBE: 781 tag_name = "VESA BIOS Extensions"; break; 782 case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: 783 tag_name = "framebuffer"; break; 784 case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: 785 tag_name = "ELF sections"; break; 786 case MULTIBOOT_TAG_TYPE_APM: 787 tag_name = "APM"; break; 788 case MULTIBOOT_TAG_TYPE_EFI32: 789 tag_name = "EFI system table"; break; 790 case MULTIBOOT_TAG_TYPE_EFI64: 791 tag_name = "EFI system table"; break; 792 case MULTIBOOT_TAG_TYPE_SMBIOS: 793 tag_name = "SMBIOS"; break; 794 case MULTIBOOT_TAG_TYPE_ACPI_OLD: 795 tag_name = "ACPI 2"; break; 796 case MULTIBOOT_TAG_TYPE_ACPI_NEW: 797 tag_name = "ACPI 3"; break; 798 case MULTIBOOT_TAG_TYPE_NETWORK: 799 tag_name = "network"; break; 800 case MULTIBOOT_TAG_TYPE_EFI_MMAP: 801 tag_name = "EFI memory map"; break; 802 case MULTIBOOT_TAG_TYPE_EFI_BS: 803 tag_name = "EFI boot services available"; break; 804 case MULTIBOOT_TAG_TYPE_EFI32_IH: 805 tag_name = "EFI ImageHandle"; break; 806 case MULTIBOOT_TAG_TYPE_EFI64_IH: 807 tag_name = "EFI ImaheHandle"; break; 808 case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: 809 tag_name = "load base"; break; 810 default: 811 tag_name = ""; break; 812 } 813 814 return tag_name; 815 } 816 817 void 818 multiboot2_print_info(void) 819 { 820 struct multiboot_tag *mbt; 821 char *cp; 822 uint32_t total_size; 823 uint32_t reserved; 824 #ifdef DEBUG 825 int i = 0; 826 #endif 827 828 if (multiboot2_enabled == false) 829 goto out; 830 831 total_size = *(uint32_t *)multiboot_info; 832 reserved = *(uint32_t *)multiboot_info + 1; 833 mbt = (struct multiboot_tag *)(uint32_t *)multiboot_info + 2; 834 835 for (cp = multiboot_info + sizeof(total_size) + sizeof(reserved); 836 cp - multiboot_info < total_size; 837 cp = cp + roundup(mbt->size, MULTIBOOT_TAG_ALIGN)) { 838 const char *tag_name; 839 840 mbt = (struct multiboot_tag *)cp; 841 tag_name = mbi_tag_name(mbt->type); 842 843 #ifdef DEBUG 844 printf("multiboot2: tag[%d].type = %d(%s), .size = %d ", 845 i++, mbt->type, tag_name, mbt->size); 846 #else 847 if (*tag_name == '\0') 848 break; 849 850 printf("multiboot2: %s ", mbi_tag_name(mbt->type)); 851 #endif 852 853 switch (mbt->type) { 854 case MULTIBOOT_TAG_TYPE_CMDLINE: 855 printf("%s\n", 856 ((struct multiboot_tag_string *)mbt)->string); 857 break; 858 case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: 859 printf("%s\n", 860 ((struct multiboot_tag_string *)mbt)->string); 861 break; 862 case MULTIBOOT_TAG_TYPE_MODULE: 863 printf("0x%08x - 0x%08x %s\n", 864 ((struct multiboot_tag_module *)mbt)->mod_start, 865 ((struct multiboot_tag_module *)mbt)->mod_end, 866 ((struct multiboot_tag_module *)mbt)->cmdline); 867 break; 868 case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: { 869 struct multiboot_tag_basic_meminfo *meminfo; 870 871 meminfo = (struct multiboot_tag_basic_meminfo *)mbt; 872 printf("ower = %uKB, upper = %uKB\n", 873 meminfo->mem_lower, meminfo->mem_upper); 874 break; 875 } 876 case MULTIBOOT_TAG_TYPE_BOOTDEV: 877 printf ("biosdev = 0x%x, slice = %d, part = %d\n", 878 ((struct multiboot_tag_bootdev *)mbt)->biosdev, 879 ((struct multiboot_tag_bootdev *)mbt)->slice, 880 ((struct multiboot_tag_bootdev *)mbt)->part); 881 break; 882 case MULTIBOOT_TAG_TYPE_MMAP: { 883 struct multiboot_tag_mmap *memmap; 884 multiboot_memory_map_t *mmap; 885 uint32_t entry_size; 886 uint32_t entry_version; 887 888 memmap = (struct multiboot_tag_mmap *)mbt; 889 entry_size = memmap->entry_size; 890 entry_version = memmap->entry_version; 891 printf ("entry version = %d\n", entry_version); 892 893 if (entry_version != 0) 894 break; 895 896 for (mmap = ((struct multiboot_tag_mmap *)mbt)->entries; 897 (char *)mmap - (char *)mbt < mbt->size; 898 mmap = (void *)((char *)mmap + entry_size)) 899 printf(" 0x%016"PRIx64" @ 0x%016"PRIx64" " 900 "type 0x%x\n", 901 (uint64_t)mmap->len, (uint64_t)mmap->addr, 902 mmap->type); 903 break; 904 } 905 case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: { 906 struct multiboot_tag_framebuffer *fb = (void *)mbt; 907 908 printf ("%dx%dx%d @ 0x%"PRIx64"\n", 909 fb->common.framebuffer_width, 910 fb->common.framebuffer_height, 911 fb->common.framebuffer_bpp, 912 (uint64_t)fb->common.framebuffer_addr); 913 #ifdef DEBUG 914 mbi_hexdump((char *)mbt, mbt->size); 915 #endif 916 break; 917 } 918 case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: 919 printf("num = %d, entsize = %d, shndx = %d\n", 920 ((struct multiboot_tag_elf_sections *)mbt)->num, 921 ((struct multiboot_tag_elf_sections *)mbt)->entsize, 922 ((struct multiboot_tag_elf_sections *)mbt)->shndx); 923 #ifdef DEBUG 924 mbi_hexdump((char *)mbt, mbt->size); 925 #endif 926 break; 927 case MULTIBOOT_TAG_TYPE_APM: 928 printf("version = %d, cseg = 0x%x, offset = 0x%x, " 929 "cseg_16 = 0x%x, dseg = 0x%x, flags = 0x%x, " 930 "cseg_len = %d, cseg_16_len = %d, " 931 "dseg_len = %d\n", 932 ((struct multiboot_tag_apm *)mbt)->version, 933 ((struct multiboot_tag_apm *)mbt)->cseg, 934 ((struct multiboot_tag_apm *)mbt)->offset, 935 ((struct multiboot_tag_apm *)mbt)->cseg_16, 936 ((struct multiboot_tag_apm *)mbt)->dseg, 937 ((struct multiboot_tag_apm *)mbt)->flags, 938 ((struct multiboot_tag_apm *)mbt)->cseg_len, 939 ((struct multiboot_tag_apm *)mbt)->cseg_16_len, 940 ((struct multiboot_tag_apm *)mbt)->dseg_len); 941 break; 942 case MULTIBOOT_TAG_TYPE_EFI32: 943 printf("0x%x\n", 944 ((struct multiboot_tag_efi32 *)mbt)->pointer); 945 break; 946 case MULTIBOOT_TAG_TYPE_EFI64: 947 printf("0x%"PRIx64"\n", (uint64_t) 948 ((struct multiboot_tag_efi64 *)mbt)->pointer); 949 break; 950 case MULTIBOOT_TAG_TYPE_SMBIOS: 951 printf("major = %d, minor = %d\n", 952 ((struct multiboot_tag_smbios *)mbt)->major, 953 ((struct multiboot_tag_smbios *)mbt)->minor); 954 #ifdef DEBUG 955 mbi_hexdump((char *)mbt, mbt->size); 956 #endif 957 break; 958 case MULTIBOOT_TAG_TYPE_ACPI_OLD: 959 printf("\n"); 960 #ifdef DEBUG 961 mbi_hexdump((char *)mbt, mbt->size); 962 #endif 963 break; 964 case MULTIBOOT_TAG_TYPE_ACPI_NEW: 965 printf("\n"); 966 #ifdef DEBUG 967 mbi_hexdump((char *)mbt, mbt->size); 968 #endif 969 break; 970 case MULTIBOOT_TAG_TYPE_NETWORK: 971 printf("\n"); 972 #ifdef DEBUG 973 mbi_hexdump((char *)mbt, mbt->size); 974 #endif 975 break; 976 case MULTIBOOT_TAG_TYPE_EFI_MMAP: 977 printf("\n"); 978 #ifdef DEBUG 979 mbi_hexdump((char *)mbt, mbt->size); 980 #endif 981 break; 982 case MULTIBOOT_TAG_TYPE_EFI_BS: 983 printf("\n"); 984 break; 985 case MULTIBOOT_TAG_TYPE_EFI32_IH: 986 printf("0x%"PRIx32"\n", 987 ((struct multiboot_tag_efi32_ih *)mbt)->pointer); 988 break; 989 case MULTIBOOT_TAG_TYPE_EFI64_IH: 990 printf("0x%"PRIx64"\n", (uint64_t) 991 ((struct multiboot_tag_efi64_ih *)mbt)->pointer); 992 break; 993 case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: { 994 struct multiboot_tag_load_base_addr *ld = (void *)mbt; 995 printf("0x%x\n", ld->load_base_addr); 996 break; 997 } 998 case MULTIBOOT_TAG_TYPE_END: 999 printf("\n"); 1000 break; 1001 default: 1002 printf("\n"); 1003 #ifdef DEBUG 1004 mbi_hexdump((char *)mbt, mbt->size); 1005 #endif 1006 break; 1007 } 1008 } 1009 1010 out: 1011 return; 1012 } 1013 1014 1015 1016 1017 /* 1018 * Sets up the initial kernel symbol table. Returns true if this was 1019 * passed in by Multiboot; false otherwise. 1020 */ 1021 bool 1022 multiboot2_ksyms_addsyms_elf(void) 1023 { 1024 struct multiboot_symbols *ms = &Multiboot_Symbols; 1025 vaddr_t symstart = (vaddr_t)ms->s_symstart; 1026 vaddr_t strstart = (vaddr_t)ms->s_strstart; 1027 Elf_Ehdr ehdr; 1028 1029 if (!multiboot2_enabled || !has_syms) 1030 return false; 1031 1032 KASSERT(esym != 0); 1033 1034 #ifdef __LP64__ 1035 /* Adjust pointer as 64 bits */ 1036 symstart &= 0xffffffff; 1037 symstart |= ((vaddr_t)KERNBASE_HI << 32); 1038 strstart &= 0xffffffff; 1039 strstart |= ((vaddr_t)KERNBASE_HI << 32); 1040 #endif 1041 1042 memset(&ehdr, 0, sizeof(ehdr)); 1043 memcpy(ehdr.e_ident, ELFMAG, SELFMAG); 1044 ehdr.e_ident[EI_CLASS] = ELFCLASS; 1045 ehdr.e_ident[EI_DATA] = ELFDATA2LSB; 1046 ehdr.e_ident[EI_VERSION] = EV_CURRENT; 1047 ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV; 1048 ehdr.e_ident[EI_ABIVERSION] = 0; 1049 ehdr.e_type = ET_EXEC; 1050 #ifdef __amd64__ 1051 ehdr.e_machine = EM_X86_64; 1052 #elif __i386__ 1053 ehdr.e_machine = EM_386; 1054 #else 1055 #error "Unknown ELF machine type" 1056 #endif 1057 ehdr.e_version = 1; 1058 ehdr.e_entry = (Elf_Addr)&start; 1059 ehdr.e_ehsize = sizeof(ehdr); 1060 1061 ksyms_addsyms_explicit((void *)&ehdr, 1062 (void *)symstart, ms->s_symsize, 1063 (void *)strstart, ms->s_strsize); 1064 1065 return true; 1066 } 1067