1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2017 Toomas Soome <tsoome@me.com> 14 * Copyright 2019, Joyent, Inc. 15 */ 16 17 /* 18 * This module adds support for loading and booting illumos multiboot2 19 * kernel. This code is only built to support the illumos kernel, it does 20 * not support xen. 21 */ 22 23 #include <sys/cdefs.h> 24 #include <sys/stddef.h> 25 26 #include <sys/param.h> 27 #include <sys/exec.h> 28 #include <sys/linker.h> 29 #include <sys/module.h> 30 #include <sys/stdint.h> 31 #include <sys/multiboot2.h> 32 #include <stand.h> 33 #include <stdbool.h> 34 #include <machine/elf.h> 35 #include "libzfs.h" 36 37 #include "bootstrap.h" 38 #include <sys/consplat.h> 39 40 #include <machine/metadata.h> 41 #include <machine/pc/bios.h> 42 43 #define SUPPORT_DHCP 44 #include <bootp.h> 45 46 #include <gfx_fb.h> 47 48 #if !defined(EFI) 49 #include "../i386/btx/lib/btxv86.h" 50 #include "libi386.h" 51 #include "vbe.h" 52 53 #else 54 #include <efi.h> 55 #include <efilib.h> 56 #include "loader_efi.h" 57 58 static void (*trampoline)(uint32_t, struct relocator *, uint64_t); 59 static UINTN efi_map_size; /* size of efi memory map */ 60 #endif 61 62 #include "platform/acfreebsd.h" 63 #include "acconfig.h" 64 #define ACPI_SYSTEM_XFACE 65 #include "actypes.h" 66 #include "actbl.h" 67 68 extern ACPI_TABLE_RSDP *rsdp; 69 70 /* MB data heap pointer. */ 71 static vm_offset_t last_addr; 72 73 static int multiboot2_loadfile(char *, uint64_t, struct preloaded_file **); 74 static int multiboot2_exec(struct preloaded_file *); 75 76 struct file_format multiboot2 = { multiboot2_loadfile, multiboot2_exec }; 77 static bool keep_bs = false; 78 static vm_offset_t load_addr; 79 static vm_offset_t entry_addr; 80 81 /* 82 * Validate tags in info request. This function is provided just to 83 * recognize the current tag list and only serves as a limited 84 * safe guard against possibly corrupt information. 85 */ 86 static bool 87 is_info_request_valid(multiboot_header_tag_information_request_t *rtag) 88 { 89 int i; 90 91 /* 92 * If the tag is optional and we do not support it, we do not 93 * have to do anything special, so we skip optional tags. 94 */ 95 if (rtag->mbh_flags & MULTIBOOT_HEADER_TAG_OPTIONAL) 96 return (true); 97 98 for (i = 0; i < (rtag->mbh_size - sizeof (*rtag)) / 99 sizeof (rtag->mbh_requests[0]); i++) 100 switch (rtag->mbh_requests[i]) { 101 case MULTIBOOT_TAG_TYPE_END: 102 case MULTIBOOT_TAG_TYPE_CMDLINE: 103 case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: 104 case MULTIBOOT_TAG_TYPE_MODULE: 105 case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: 106 case MULTIBOOT_TAG_TYPE_BOOTDEV: 107 case MULTIBOOT_TAG_TYPE_MMAP: 108 case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: 109 case MULTIBOOT_TAG_TYPE_VBE: 110 case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: 111 case MULTIBOOT_TAG_TYPE_APM: 112 case MULTIBOOT_TAG_TYPE_EFI32: 113 case MULTIBOOT_TAG_TYPE_EFI64: 114 case MULTIBOOT_TAG_TYPE_ACPI_OLD: 115 case MULTIBOOT_TAG_TYPE_ACPI_NEW: 116 case MULTIBOOT_TAG_TYPE_NETWORK: 117 case MULTIBOOT_TAG_TYPE_EFI_MMAP: 118 case MULTIBOOT_TAG_TYPE_EFI_BS: 119 case MULTIBOOT_TAG_TYPE_EFI32_IH: 120 case MULTIBOOT_TAG_TYPE_EFI64_IH: 121 case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: 122 break; 123 default: 124 printf("unsupported information tag: 0x%x\n", 125 rtag->mbh_requests[i]); 126 return (false); 127 } 128 return (true); 129 } 130 131 static int 132 multiboot2_loadfile(char *filename, uint64_t dest, 133 struct preloaded_file **result) 134 { 135 int fd, error; 136 uint32_t i; 137 struct stat st; 138 caddr_t header_search; 139 multiboot2_header_t *header; 140 multiboot_header_tag_t *tag; 141 multiboot_header_tag_address_t *addr_tag = NULL; 142 multiboot_header_tag_entry_address_t *entry_tag = NULL; 143 struct preloaded_file *fp; 144 145 /* This allows to check other file formats from file_formats array. */ 146 error = EFTYPE; 147 if (filename == NULL) 148 return (error); 149 150 /* is kernel already loaded? */ 151 fp = file_findfile(NULL, NULL); 152 if (fp != NULL) 153 return (error); 154 155 if ((fd = open(filename, O_RDONLY)) == -1) 156 return (errno); 157 158 /* 159 * Read MULTIBOOT_SEARCH size in order to search for the 160 * multiboot magic header. 161 */ 162 header_search = malloc(MULTIBOOT_SEARCH); 163 if (header_search == NULL) { 164 close(fd); 165 return (ENOMEM); 166 } 167 168 if (read(fd, header_search, MULTIBOOT_SEARCH) != MULTIBOOT_SEARCH) 169 goto out; 170 171 header = NULL; 172 for (i = 0; i <= (MULTIBOOT_SEARCH - sizeof (multiboot2_header_t)); 173 i += MULTIBOOT_HEADER_ALIGN) { 174 header = (multiboot2_header_t *)(header_search + i); 175 176 /* Do we have match on magic? */ 177 if (header->mb2_magic != MULTIBOOT2_HEADER_MAGIC) { 178 header = NULL; 179 continue; 180 } 181 /* 182 * Validate checksum, the sum of magic + architecture + 183 * header_length + checksum must equal 0. 184 */ 185 if (header->mb2_magic + header->mb2_architecture + 186 header->mb2_header_length + header->mb2_checksum != 0) { 187 header = NULL; 188 continue; 189 } 190 /* 191 * Finally, the entire header must fit within MULTIBOOT_SEARCH. 192 */ 193 if (i + header->mb2_header_length > MULTIBOOT_SEARCH) { 194 header = NULL; 195 continue; 196 } 197 break; 198 } 199 200 if (header == NULL) 201 goto out; 202 203 for (tag = header->mb2_tags; tag->mbh_type != MULTIBOOT_TAG_TYPE_END; 204 tag = (multiboot_header_tag_t *)((uintptr_t)tag + 205 roundup2(tag->mbh_size, MULTIBOOT_TAG_ALIGN))) { 206 switch (tag->mbh_type) { 207 case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST: 208 if (is_info_request_valid((void*)tag) == false) 209 goto out; 210 break; 211 case MULTIBOOT_HEADER_TAG_ADDRESS: 212 addr_tag = (multiboot_header_tag_address_t *)tag; 213 break; 214 case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS: 215 entry_tag = 216 (multiboot_header_tag_entry_address_t *)tag; 217 break; 218 case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS: 219 break; 220 case MULTIBOOT_HEADER_TAG_FRAMEBUFFER: 221 break; 222 case MULTIBOOT_HEADER_TAG_MODULE_ALIGN: 223 /* we always align modules */ 224 break; 225 case MULTIBOOT_HEADER_TAG_EFI_BS: 226 keep_bs = true; 227 break; 228 default: 229 if (!(tag->mbh_flags & MULTIBOOT_HEADER_TAG_OPTIONAL)) { 230 printf("unsupported tag: 0x%x\n", 231 tag->mbh_type); 232 goto out; 233 } 234 } 235 } 236 237 /* 238 * We must have addr_tag and entry_tag to load a 64-bit kernel. 239 * If these tags are missing, we either have a 32-bit kernel, or 240 * this is not our kernel at all. 241 */ 242 if (addr_tag != NULL && entry_tag != NULL) { 243 fp = file_alloc(); 244 if (fp == NULL) { 245 error = ENOMEM; 246 goto out; 247 } 248 if (lseek(fd, 0, SEEK_SET) == -1) { 249 printf("lseek failed\n"); 250 error = EIO; 251 file_discard(fp); 252 goto out; 253 } 254 if (fstat(fd, &st) < 0) { 255 printf("fstat failed\n"); 256 error = EIO; 257 file_discard(fp); 258 goto out; 259 } 260 261 load_addr = addr_tag->mbh_load_addr; 262 entry_addr = entry_tag->mbh_entry_addr; 263 fp->f_addr = archsw.arch_loadaddr(LOAD_KERN, filename, 264 addr_tag->mbh_load_addr); 265 if (fp->f_addr == 0) { 266 error = ENOMEM; 267 file_discard(fp); 268 goto out; 269 } 270 fp->f_size = archsw.arch_readin(fd, fp->f_addr, st.st_size); 271 272 if (fp->f_size != st.st_size) { 273 printf("error reading %s: %s\n", filename, 274 strerror(errno)); 275 file_discard(fp); 276 error = EIO; 277 goto out; 278 } 279 280 fp->f_name = strdup(filename); 281 fp->f_type = strdup("aout multiboot2 kernel"); 282 if (fp->f_name == NULL || fp->f_type == NULL) { 283 error = ENOMEM; 284 file_discard(fp); 285 goto out; 286 } 287 288 fp->f_metadata = NULL; 289 error = 0; 290 } else { 291 #if defined(EFI) 292 /* 32-bit kernel is not yet supported for EFI */ 293 printf("32-bit kernel is not supported by UEFI loader\n"); 294 error = ENOTSUP; 295 goto out; 296 #endif 297 /* elf32_loadfile_raw will fill the attributes in fp. */ 298 error = elf32_loadfile_raw(filename, dest, &fp, 2); 299 if (error != 0) { 300 printf("elf32_loadfile_raw failed: %d unable to " 301 "load multiboot2 kernel\n", error); 302 goto out; 303 } 304 entry_addr = fp->f_addr; 305 /* 306 * We want the load_addr to have some legal value, 307 * so we set it same as the entry_addr. 308 * The distinction is important with UEFI, but not 309 * with BIOS version, because BIOS version does not use 310 * staging area. 311 */ 312 load_addr = fp->f_addr; 313 } 314 315 setenv("kernelname", fp->f_name, 1); 316 #if defined(EFI) 317 efi_addsmapdata(fp); 318 #else 319 bios_addsmapdata(fp); 320 #endif 321 *result = fp; 322 out: 323 free(header_search); 324 close(fd); 325 return (error); 326 } 327 328 /* 329 * Search the command line for named property. 330 * 331 * Return codes: 332 * 0 The name is found, we return the data in value and len. 333 * ENOENT The name is not found. 334 * EINVAL The provided command line is badly formed. 335 */ 336 static int 337 find_property_value(const char *cmd, const char *name, const char **value, 338 size_t *len) 339 { 340 const char *namep, *valuep; 341 size_t name_len, value_len; 342 int quoted; 343 344 *value = NULL; 345 *len = 0; 346 347 if (cmd == NULL) 348 return (ENOENT); 349 350 while (*cmd != '\0') { 351 if (cmd[0] != '-' || cmd[1] != 'B') { 352 cmd++; 353 continue; 354 } 355 cmd += 2; /* Skip -B */ 356 while (cmd[0] == ' ' || cmd[0] == '\t') 357 cmd++; /* Skip whitespaces. */ 358 while (*cmd != '\0' && cmd[0] != ' ' && cmd[0] != '\t') { 359 namep = cmd; 360 valuep = strchr(cmd, '='); 361 if (valuep == NULL) 362 break; 363 name_len = valuep - namep; 364 valuep++; 365 value_len = 0; 366 quoted = 0; 367 for (;; ++value_len) { 368 if (valuep[value_len] == '\0') 369 break; 370 371 /* Is this value quoted? */ 372 if (value_len == 0 && 373 (valuep[0] == '\'' || valuep[0] == '"')) { 374 quoted = valuep[0]; 375 ++value_len; 376 } 377 378 /* 379 * In the quote accept any character, 380 * but look for ending quote. 381 */ 382 if (quoted != 0) { 383 if (valuep[value_len] == quoted) 384 quoted = 0; 385 continue; 386 } 387 388 /* A comma or white space ends the value. */ 389 if (valuep[value_len] == ',' || 390 valuep[value_len] == ' ' || 391 valuep[value_len] == '\t') 392 break; 393 } 394 if (quoted != 0) { 395 printf("Missing closing '%c' in \"%s\"\n", 396 quoted, valuep); 397 return (EINVAL); 398 } 399 if (value_len != 0) { 400 if (strncmp(namep, name, name_len) == 0) { 401 *value = valuep; 402 *len = value_len; 403 return (0); 404 } 405 } 406 cmd = valuep + value_len; 407 while (*cmd == ',') 408 cmd++; 409 } 410 } 411 return (ENOENT); 412 } 413 414 /* 415 * If command line has " -B ", insert property after "-B ", otherwise 416 * append to command line. 417 */ 418 static char * 419 insert_cmdline(const char *head, const char *prop) 420 { 421 const char *prop_opt = " -B "; 422 char *cmdline, *tail; 423 int len = 0; 424 425 tail = strstr(head, prop_opt); 426 if (tail != NULL) { 427 ptrdiff_t diff; 428 tail += strlen(prop_opt); 429 diff = tail - head; 430 if (diff >= INT_MAX) 431 return (NULL); 432 len = (int)diff; 433 } 434 435 if (tail == NULL) 436 asprintf(&cmdline, "%s%s%s", head, prop_opt, prop); 437 else 438 asprintf(&cmdline, "%.*s%s,%s", len, head, prop, tail); 439 440 return (cmdline); 441 } 442 443 /* 444 * Since we have no way to pass the environment to the mb1 kernel other than 445 * through arguments, we need to take care of console setup. 446 * 447 * If the console is in mirror mode, set the kernel console from $os_console. 448 * If it's unset, use first item from $console. 449 * If $console is "ttyX", also pass $ttyX-mode, since it may have been set by 450 * the user. 451 * 452 * In case of memory allocation errors, just return the original command line 453 * so we have a chance of booting. 454 * 455 * On success, cl will be freed and a new, allocated command line string is 456 * returned. 457 * 458 * For the mb2 kernel, we only set command line console if os_console is set. 459 * We can not overwrite console in the environment, as it can disrupt the 460 * loader console messages, and we do not want to deal with the os_console 461 * in the kernel. 462 */ 463 static char * 464 update_cmdline(char *cl, bool mb2) 465 { 466 char *os_console = getenv("os_console"); 467 char *ttymode = NULL; 468 char mode[10]; 469 char *tmp; 470 const char *prop; 471 size_t plen; 472 int rv; 473 474 if (mb2 == true && os_console == NULL) 475 return (cl); 476 477 if (os_console == NULL) { 478 tmp = strdup(getenv("console")); 479 os_console = strsep(&tmp, ", "); 480 } else { 481 os_console = strdup(os_console); 482 } 483 484 if (os_console == NULL) 485 return (cl); 486 487 if (mb2 == false && strncmp(os_console, "tty", 3) == 0) { 488 snprintf(mode, sizeof (mode), "%s-mode", os_console); 489 /* 490 * The ttyX-mode variable is set by our serial console 491 * driver for ttya-ttyd. However, since the os_console 492 * values are not verified, it is possible we get bogus 493 * name and no mode variable. If so, we do not set console 494 * property and let the kernel use defaults. 495 */ 496 if ((ttymode = getenv(mode)) == NULL) 497 return (cl); 498 } 499 500 rv = find_property_value(cl, "console", &prop, &plen); 501 if (rv != 0 && rv != ENOENT) { 502 free(os_console); 503 return (cl); 504 } 505 506 /* If console is set and this is MB2 boot, we are done. */ 507 if (rv == 0 && mb2 == true) { 508 free(os_console); 509 return (cl); 510 } 511 512 /* If console is set, do we need to set tty mode? */ 513 if (rv == 0) { 514 const char *ttyp = NULL; 515 size_t ttylen; 516 517 free(os_console); 518 os_console = NULL; 519 *mode = '\0'; 520 if (strncmp(prop, "tty", 3) == 0 && plen == 4) { 521 strncpy(mode, prop, plen); 522 mode[plen] = '\0'; 523 strncat(mode, "-mode", 5); 524 find_property_value(cl, mode, &ttyp, &ttylen); 525 } 526 527 if (*mode != '\0' && ttyp == NULL) 528 ttymode = getenv(mode); 529 else 530 return (cl); 531 } 532 533 /* Build updated command line. */ 534 if (os_console != NULL) { 535 char *propstr; 536 537 asprintf(&propstr, "console=%s", os_console); 538 free(os_console); 539 if (propstr == NULL) { 540 return (cl); 541 } 542 543 tmp = insert_cmdline(cl, propstr); 544 free(propstr); 545 if (tmp == NULL) 546 return (cl); 547 548 free(cl); 549 cl = tmp; 550 } 551 if (ttymode != NULL) { 552 char *propstr; 553 554 asprintf(&propstr, "%s=\"%s\"", mode, ttymode); 555 if (propstr == NULL) 556 return (cl); 557 558 tmp = insert_cmdline(cl, propstr); 559 free(propstr); 560 if (tmp == NULL) 561 return (cl); 562 free(cl); 563 cl = tmp; 564 } 565 566 return (cl); 567 } 568 569 /* 570 * Build the kernel command line. Shared function between MB1 and MB2. 571 * 572 * In both cases, if fstype is set and is not zfs, we do not set up 573 * zfs-bootfs property. But we set kernel file name and options. 574 * 575 * For the MB1, we only can pass properties on command line, so 576 * we will set console, ttyX-mode (for serial console) and zfs-bootfs. 577 * 578 * For the MB2, we can pass properties in environment, but if os_console 579 * is set in environment, we need to add console property on the kernel 580 * command line. 581 * 582 * The console properties are managed in update_cmdline(). 583 */ 584 int 585 mb_kernel_cmdline(struct preloaded_file *fp, struct devdesc *rootdev, 586 char **line) 587 { 588 const char *fs = getenv("fstype"); 589 char *cmdline; 590 size_t len; 591 bool zfs_root = false; 592 bool mb2; 593 int rv; 594 595 /* 596 * With multiple console devices and "os_console" variable not 597 * set, set os_console to last input device. 598 */ 599 rv = cons_inputdev(); 600 if (rv != -1) 601 (void) setenv("os_console", consoles[rv]->c_name, 0); 602 603 /* 604 * 64-bit kernel has aout header, 32-bit kernel is elf, and the 605 * type strings are different. Lets just search for "multiboot2". 606 */ 607 if (strstr(fp->f_type, "multiboot2") == NULL) 608 mb2 = false; 609 else 610 mb2 = true; 611 612 if (rootdev->d_dev->dv_type == DEVT_ZFS) 613 zfs_root = true; 614 615 /* If we have fstype set in env, reset zfs_root if needed. */ 616 if (fs != NULL && strcmp(fs, "zfs") != 0) 617 zfs_root = false; 618 619 /* 620 * If we have fstype set on the command line, 621 * reset zfs_root if needed. 622 */ 623 rv = find_property_value(fp->f_args, "fstype", &fs, &len); 624 if (rv != 0 && rv != ENOENT) 625 return (rv); 626 627 if (fs != NULL && strncmp(fs, "zfs", len) != 0) 628 zfs_root = false; 629 630 /* zfs_bootfs() will set the environment, it must be called. */ 631 if (zfs_root == true) 632 fs = zfs_bootfs(rootdev); 633 634 if (fp->f_args == NULL) 635 cmdline = strdup(fp->f_name); 636 else 637 asprintf(&cmdline, "%s %s", fp->f_name, fp->f_args); 638 639 if (cmdline == NULL) 640 return (ENOMEM); 641 642 /* Append zfs-bootfs for MB1 command line. */ 643 if (mb2 == false && zfs_root == true) { 644 char *tmp; 645 646 tmp = insert_cmdline(cmdline, fs); 647 free(cmdline); 648 if (tmp == NULL) 649 return (ENOMEM); 650 cmdline = tmp; 651 } 652 653 *line = update_cmdline(cmdline, mb2); 654 return (0); 655 } 656 657 /* 658 * Returns allocated virtual address from MB info area. 659 */ 660 static vm_offset_t 661 mb_malloc(size_t n) 662 { 663 vm_offset_t ptr = last_addr; 664 last_addr = roundup(last_addr + n, MULTIBOOT_TAG_ALIGN); 665 return (ptr); 666 } 667 668 /* 669 * Calculate size for module tag list. 670 */ 671 static size_t 672 module_size(struct preloaded_file *fp) 673 { 674 size_t len, size; 675 struct preloaded_file *mfp; 676 677 size = 0; 678 for (mfp = fp->f_next; mfp != NULL; mfp = mfp->f_next) { 679 len = strlen(mfp->f_name) + 1; 680 len += strlen(mfp->f_type) + 5 + 1; /* 5 is for "type=" */ 681 if (mfp->f_args != NULL) 682 len += strlen(mfp->f_args) + 1; 683 size += sizeof (multiboot_tag_module_t) + len; 684 size = roundup(size, MULTIBOOT_TAG_ALIGN); 685 } 686 return (size); 687 } 688 689 #if defined(EFI) 690 /* 691 * Calculate size for UEFI memory map tag. 692 */ 693 #define EFI_EXTRA_PAGES 3 694 695 static int 696 efimemmap_size(void) 697 { 698 UINTN size, cur_size, desc_size; 699 EFI_MEMORY_DESCRIPTOR *mmap; 700 EFI_STATUS ret; 701 702 size = EFI_PAGE_SIZE; /* Start with 4k. */ 703 while (1) { 704 cur_size = size; 705 mmap = malloc(cur_size); 706 if (mmap == NULL) 707 return (0); 708 ret = BS->GetMemoryMap(&cur_size, mmap, NULL, &desc_size, NULL); 709 free(mmap); 710 if (ret == EFI_SUCCESS) 711 break; 712 if (ret == EFI_BUFFER_TOO_SMALL) { 713 if (size < cur_size) 714 size = cur_size; 715 size += (EFI_PAGE_SIZE); 716 } else 717 return (0); 718 } 719 720 /* EFI MMAP will grow when we allocate MBI, set some buffer. */ 721 size += (EFI_EXTRA_PAGES << EFI_PAGE_SHIFT); 722 size = roundup2(size, EFI_PAGE_SIZE); 723 efi_map_size = size; /* Record the calculated size. */ 724 return (sizeof (multiboot_tag_efi_mmap_t) + size); 725 } 726 #endif 727 728 /* 729 * Calculate size for bios smap tag. 730 */ 731 static size_t 732 biossmap_size(struct preloaded_file *fp) 733 { 734 int num; 735 struct file_metadata *md; 736 737 md = file_findmetadata(fp, MODINFOMD_SMAP); 738 if (md == NULL) 739 return (0); 740 741 num = md->md_size / sizeof (struct bios_smap); /* number of entries */ 742 return (sizeof (multiboot_tag_mmap_t) + 743 num * sizeof (multiboot_mmap_entry_t)); 744 } 745 746 static size_t 747 mbi_size(struct preloaded_file *fp, char *cmdline) 748 { 749 size_t size; 750 751 size = sizeof (uint32_t) * 2; /* first 2 fields from MBI header */ 752 size += sizeof (multiboot_tag_string_t) + strlen(cmdline) + 1; 753 size = roundup2(size, MULTIBOOT_TAG_ALIGN); 754 size += sizeof (multiboot_tag_string_t) + strlen(bootprog_info) + 1; 755 size = roundup2(size, MULTIBOOT_TAG_ALIGN); 756 #if !defined(EFI) 757 size += sizeof (multiboot_tag_basic_meminfo_t); 758 size = roundup2(size, MULTIBOOT_TAG_ALIGN); 759 #endif 760 size += module_size(fp); 761 size = roundup2(size, MULTIBOOT_TAG_ALIGN); 762 #if defined(EFI) 763 size += sizeof (multiboot_tag_efi64_t); 764 size = roundup2(size, MULTIBOOT_TAG_ALIGN); 765 size += efimemmap_size(); 766 size = roundup2(size, MULTIBOOT_TAG_ALIGN); 767 #endif 768 769 size += biossmap_size(fp); 770 size = roundup2(size, MULTIBOOT_TAG_ALIGN); 771 772 if (has_framebuffer) { 773 if (gfx_fb.framebuffer_common.framebuffer_type == 774 MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED) { 775 uint16_t nc; 776 nc = gfx_fb.u.fb1.framebuffer_palette_num_colors; 777 size += 778 sizeof (struct multiboot_tag_framebuffer_common); 779 size += sizeof (uint16_t); 780 size += nc * sizeof (multiboot_color_t); 781 } else { 782 size += sizeof (multiboot_tag_framebuffer_t); 783 } 784 size = roundup2(size, MULTIBOOT_TAG_ALIGN); 785 } 786 787 if (bootp_response != NULL) { 788 size += sizeof (multiboot_tag_network_t) + bootp_response_size; 789 size = roundup2(size, MULTIBOOT_TAG_ALIGN); 790 } 791 792 if (rsdp != NULL) { 793 if (rsdp->Revision == 0) { 794 size += sizeof (multiboot_tag_old_acpi_t) + 795 sizeof (ACPI_RSDP_COMMON); 796 } else { 797 size += sizeof (multiboot_tag_new_acpi_t) + 798 rsdp->Length; 799 } 800 size = roundup2(size, MULTIBOOT_TAG_ALIGN); 801 } 802 size += sizeof (multiboot_tag_t); 803 804 return (size); 805 } 806 807 #if defined(EFI) 808 static bool 809 overlaps(uintptr_t start1, size_t size1, uintptr_t start2, size_t size2) 810 { 811 if (start1 < start2 + size2 && 812 start1 + size1 >= start2) { 813 printf("overlaps: %zx-%zx, %zx-%zx\n", 814 start1, start1 + size1, start2, start2 + size2); 815 return (true); 816 } 817 818 return (false); 819 } 820 #endif 821 822 static int 823 multiboot2_exec(struct preloaded_file *fp) 824 { 825 multiboot2_info_header_t *mbi = NULL; 826 struct preloaded_file *mfp; 827 char *cmdline = NULL; 828 struct devdesc *rootdev; 829 struct file_metadata *md; 830 int i, error, num; 831 int rootfs = 0; 832 size_t size; 833 struct bios_smap *smap; 834 #if defined(EFI) 835 multiboot_tag_module_t *module, *mp; 836 struct relocator *relocator = NULL; 837 EFI_MEMORY_DESCRIPTOR *map; 838 UINTN map_size, desc_size; 839 struct chunk_head *head; 840 struct chunk *chunk; 841 vm_offset_t tmp; 842 843 efi_getdev((void **)(&rootdev), NULL, NULL); 844 845 /* 846 * We need 5 pages for relocation. We'll allocate from the heap: while 847 * it's possible that our heap got placed low down enough to be in the 848 * way of where we're going to relocate our kernel, it's hopefully not 849 * likely. 850 */ 851 if ((relocator = malloc(EFI_PAGE_SIZE * 5)) == NULL) { 852 printf("relocator malloc failed!\n"); 853 error = ENOMEM; 854 goto error; 855 } 856 857 if (overlaps((uintptr_t)relocator, EFI_PAGE_SIZE * 5, 858 load_addr, fp->f_size)) { 859 printf("relocator pages overlap the kernel!\n"); 860 error = EINVAL; 861 goto error; 862 } 863 864 #else 865 i386_getdev((void **)(&rootdev), NULL, NULL); 866 #endif 867 868 error = EINVAL; 869 if (rootdev == NULL) { 870 printf("can't determine root device\n"); 871 goto error; 872 } 873 874 /* 875 * Set the image command line. 876 */ 877 if (fp->f_args == NULL) { 878 cmdline = getenv("boot-args"); 879 if (cmdline != NULL) { 880 fp->f_args = strdup(cmdline); 881 if (fp->f_args == NULL) { 882 error = ENOMEM; 883 goto error; 884 } 885 } 886 } 887 888 error = mb_kernel_cmdline(fp, rootdev, &cmdline); 889 if (error != 0) 890 goto error; 891 892 /* mb_kernel_cmdline() updates the environment. */ 893 build_environment_module(); 894 895 /* Pass the loaded console font for kernel. */ 896 build_font_module(); 897 898 size = mbi_size(fp, cmdline); /* Get the size for MBI. */ 899 900 /* Set up the base for mb_malloc. */ 901 i = 0; 902 for (mfp = fp; mfp->f_next != NULL; mfp = mfp->f_next) 903 i++; 904 905 #if defined(EFI) 906 /* We need space for kernel + MBI + # modules */ 907 num = (EFI_PAGE_SIZE - offsetof(struct relocator, rel_chunklist)) / 908 sizeof (struct chunk); 909 if (i + 2 >= num) { 910 printf("Too many modules, do not have space for relocator.\n"); 911 error = ENOMEM; 912 goto error; 913 } 914 915 last_addr = efi_loadaddr(LOAD_MEM, &size, mfp->f_addr + mfp->f_size); 916 mbi = (multiboot2_info_header_t *)last_addr; 917 if (mbi == NULL) { 918 error = ENOMEM; 919 goto error; 920 } 921 last_addr = (vm_offset_t)mbi->mbi_tags; 922 #else 923 /* Start info block from the new page. */ 924 last_addr = i386_loadaddr(LOAD_MEM, &size, mfp->f_addr + mfp->f_size); 925 926 /* Do we have space for multiboot info? */ 927 if (last_addr + size >= memtop_copyin) { 928 error = ENOMEM; 929 goto error; 930 } 931 932 mbi = (multiboot2_info_header_t *)PTOV(last_addr); 933 last_addr = (vm_offset_t)mbi->mbi_tags; 934 #endif /* EFI */ 935 936 { 937 multiboot_tag_string_t *tag; 938 i = sizeof (multiboot_tag_string_t) + strlen(cmdline) + 1; 939 tag = (multiboot_tag_string_t *)mb_malloc(i); 940 941 tag->mb_type = MULTIBOOT_TAG_TYPE_CMDLINE; 942 tag->mb_size = i; 943 memcpy(tag->mb_string, cmdline, strlen(cmdline) + 1); 944 free(cmdline); 945 cmdline = NULL; 946 } 947 948 { 949 multiboot_tag_string_t *tag; 950 i = sizeof (multiboot_tag_string_t) + strlen(bootprog_info) + 1; 951 tag = (multiboot_tag_string_t *)mb_malloc(i); 952 953 tag->mb_type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME; 954 tag->mb_size = i; 955 memcpy(tag->mb_string, bootprog_info, 956 strlen(bootprog_info) + 1); 957 } 958 959 #if !defined(EFI) 960 /* Only set in case of BIOS. */ 961 { 962 multiboot_tag_basic_meminfo_t *tag; 963 tag = (multiboot_tag_basic_meminfo_t *) 964 mb_malloc(sizeof (*tag)); 965 966 tag->mb_type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO; 967 tag->mb_size = sizeof (*tag); 968 tag->mb_mem_lower = bios_basemem / 1024; 969 tag->mb_mem_upper = bios_extmem / 1024; 970 } 971 #endif 972 973 num = 0; 974 for (mfp = fp->f_next; mfp != NULL; mfp = mfp->f_next) { 975 num++; 976 if (mfp->f_type != NULL && strcmp(mfp->f_type, "rootfs") == 0) 977 rootfs++; 978 } 979 980 if (num == 0 || rootfs == 0) { 981 /* We need at least one module - rootfs. */ 982 printf("No rootfs module provided, aborting\n"); 983 error = EINVAL; 984 goto error; 985 } 986 987 /* 988 * Set the stage for physical memory layout: 989 * - We have kernel at load_addr. 990 * - Modules are aligned to page boundary. 991 * - MBI is aligned to page boundary. 992 * - Set the tmp to point to physical address of the first module. 993 * - tmp != mfp->f_addr only in case of EFI. 994 */ 995 #if defined(EFI) 996 tmp = roundup2(load_addr + fp->f_size + 1, MULTIBOOT_MOD_ALIGN); 997 module = (multiboot_tag_module_t *)last_addr; 998 #endif 999 1000 for (mfp = fp->f_next; mfp != NULL; mfp = mfp->f_next) { 1001 multiboot_tag_module_t *tag; 1002 1003 num = strlen(mfp->f_name) + 1; 1004 num += strlen(mfp->f_type) + 5 + 1; 1005 if (mfp->f_args != NULL) { 1006 num += strlen(mfp->f_args) + 1; 1007 } 1008 cmdline = malloc(num); 1009 if (cmdline == NULL) { 1010 error = ENOMEM; 1011 goto error; 1012 } 1013 1014 if (mfp->f_args != NULL) 1015 snprintf(cmdline, num, "%s type=%s %s", 1016 mfp->f_name, mfp->f_type, mfp->f_args); 1017 else 1018 snprintf(cmdline, num, "%s type=%s", 1019 mfp->f_name, mfp->f_type); 1020 1021 tag = (multiboot_tag_module_t *)mb_malloc(sizeof (*tag) + num); 1022 1023 tag->mb_type = MULTIBOOT_TAG_TYPE_MODULE; 1024 tag->mb_size = sizeof (*tag) + num; 1025 #if defined(EFI) 1026 /* 1027 * We can assign module addresses only after BS have been 1028 * switched off. 1029 */ 1030 tag->mb_mod_start = 0; 1031 tag->mb_mod_end = mfp->f_size; 1032 #else 1033 tag->mb_mod_start = mfp->f_addr; 1034 tag->mb_mod_end = mfp->f_addr + mfp->f_size; 1035 #endif 1036 memcpy(tag->mb_cmdline, cmdline, num); 1037 free(cmdline); 1038 cmdline = NULL; 1039 } 1040 1041 md = file_findmetadata(fp, MODINFOMD_SMAP); 1042 if (md == NULL) { 1043 printf("no memory smap\n"); 1044 error = EINVAL; 1045 goto error; 1046 } 1047 1048 smap = (struct bios_smap *)md->md_data; 1049 num = md->md_size / sizeof (struct bios_smap); /* number of entries */ 1050 1051 { 1052 multiboot_tag_mmap_t *tag; 1053 multiboot_mmap_entry_t *mmap_entry; 1054 1055 tag = (multiboot_tag_mmap_t *) 1056 mb_malloc(sizeof (*tag) + 1057 num * sizeof (multiboot_mmap_entry_t)); 1058 1059 tag->mb_type = MULTIBOOT_TAG_TYPE_MMAP; 1060 tag->mb_size = sizeof (*tag) + 1061 num * sizeof (multiboot_mmap_entry_t); 1062 tag->mb_entry_size = sizeof (multiboot_mmap_entry_t); 1063 tag->mb_entry_version = 0; 1064 mmap_entry = (multiboot_mmap_entry_t *)tag->mb_entries; 1065 1066 for (i = 0; i < num; i++) { 1067 mmap_entry[i].mmap_addr = smap[i].base; 1068 mmap_entry[i].mmap_len = smap[i].length; 1069 mmap_entry[i].mmap_type = smap[i].type; 1070 mmap_entry[i].mmap_reserved = 0; 1071 } 1072 } 1073 1074 if (bootp_response != NULL) { 1075 multiboot_tag_network_t *tag; 1076 tag = (multiboot_tag_network_t *) 1077 mb_malloc(sizeof (*tag) + bootp_response_size); 1078 1079 tag->mb_type = MULTIBOOT_TAG_TYPE_NETWORK; 1080 tag->mb_size = sizeof (*tag) + bootp_response_size; 1081 memcpy(tag->mb_dhcpack, bootp_response, bootp_response_size); 1082 } 1083 1084 if (rsdp != NULL) { 1085 multiboot_tag_new_acpi_t *ntag; 1086 multiboot_tag_old_acpi_t *otag; 1087 uint32_t tsize; 1088 1089 if (rsdp->Revision == 0) { 1090 tsize = sizeof (*otag) + sizeof (ACPI_RSDP_COMMON); 1091 otag = (multiboot_tag_old_acpi_t *)mb_malloc(tsize); 1092 otag->mb_type = MULTIBOOT_TAG_TYPE_ACPI_OLD; 1093 otag->mb_size = tsize; 1094 memcpy(otag->mb_rsdp, rsdp, sizeof (ACPI_RSDP_COMMON)); 1095 } else { 1096 tsize = sizeof (*ntag) + rsdp->Length; 1097 ntag = (multiboot_tag_new_acpi_t *)mb_malloc(tsize); 1098 ntag->mb_type = MULTIBOOT_TAG_TYPE_ACPI_NEW; 1099 ntag->mb_size = tsize; 1100 memcpy(ntag->mb_rsdp, rsdp, rsdp->Length); 1101 } 1102 } 1103 1104 #if defined(EFI) 1105 #ifdef __LP64__ 1106 { 1107 multiboot_tag_efi64_t *tag; 1108 tag = (multiboot_tag_efi64_t *) 1109 mb_malloc(sizeof (*tag)); 1110 1111 tag->mb_type = MULTIBOOT_TAG_TYPE_EFI64; 1112 tag->mb_size = sizeof (*tag); 1113 tag->mb_pointer = (uint64_t)(uintptr_t)ST; 1114 } 1115 #else 1116 { 1117 multiboot_tag_efi32_t *tag; 1118 tag = (multiboot_tag_efi32_t *) 1119 mb_malloc(sizeof (*tag)); 1120 1121 tag->mb_type = MULTIBOOT_TAG_TYPE_EFI32; 1122 tag->mb_size = sizeof (*tag); 1123 tag->mb_pointer = (uint32_t)ST; 1124 } 1125 #endif /* __LP64__ */ 1126 #endif /* EFI */ 1127 1128 if (has_framebuffer) { 1129 multiboot_tag_framebuffer_t *tag; 1130 uint32_t size; 1131 1132 if (gfx_fb.framebuffer_common.framebuffer_type == 1133 MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED) { 1134 uint16_t nc; 1135 nc = gfx_fb.u.fb1.framebuffer_palette_num_colors; 1136 size = sizeof (struct multiboot_tag_framebuffer_common) 1137 + sizeof (nc) 1138 + nc * sizeof (multiboot_color_t); 1139 } else { 1140 size = sizeof (*tag); 1141 } 1142 1143 tag = (multiboot_tag_framebuffer_t *)mb_malloc(size); 1144 memcpy(tag, &gfx_fb, sizeof (*tag)); 1145 tag->framebuffer_common.mb_type = 1146 MULTIBOOT_TAG_TYPE_FRAMEBUFFER; 1147 tag->framebuffer_common.mb_size = size; 1148 1149 #if !defined(EFI) 1150 extern multiboot_color_t *cmap; 1151 1152 if (gfx_fb.framebuffer_common.framebuffer_type == 1153 MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED) { 1154 uint16_t nc; 1155 nc = gfx_fb.u.fb1.framebuffer_palette_num_colors; 1156 memcpy(tag->u.fb1.framebuffer_palette, cmap, 1157 sizeof (multiboot_color_t) * nc); 1158 } 1159 #endif /* !EFI */ 1160 } 1161 1162 #if defined(EFI) 1163 /* Leave EFI memmap last as we will also switch off the BS. */ 1164 { 1165 multiboot_tag_efi_mmap_t *tag; 1166 UINTN key; 1167 EFI_STATUS status; 1168 1169 tag = (multiboot_tag_efi_mmap_t *) 1170 mb_malloc(sizeof (*tag)); 1171 1172 map_size = 0; 1173 status = BS->GetMemoryMap(&map_size, 1174 (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap, &key, 1175 &desc_size, &tag->mb_descr_vers); 1176 if (status != EFI_BUFFER_TOO_SMALL) { 1177 error = EINVAL; 1178 goto error; 1179 } 1180 map_size = roundup2(map_size, EFI_PAGE_SIZE); 1181 1182 i = 2; /* Attempts to ExitBootServices() */ 1183 while (map_size <= efi_map_size && i > 0) { 1184 status = BS->GetMemoryMap(&map_size, 1185 (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap, &key, 1186 &desc_size, &tag->mb_descr_vers); 1187 if (status == EFI_BUFFER_TOO_SMALL) { 1188 /* Still too small? */ 1189 map_size += EFI_PAGE_SIZE; 1190 continue; 1191 } 1192 if (EFI_ERROR(status)) { 1193 error = EINVAL; 1194 goto error; 1195 } 1196 1197 if (keep_bs != 0) 1198 break; 1199 1200 status = BS->ExitBootServices(IH, key); 1201 if (status == EFI_SUCCESS) { 1202 has_boot_services = false; 1203 break; 1204 } 1205 i--; 1206 } 1207 if (status != EFI_SUCCESS) { 1208 error = EINVAL; 1209 goto error; 1210 } 1211 1212 tag->mb_type = MULTIBOOT_TAG_TYPE_EFI_MMAP; 1213 tag->mb_size = sizeof (*tag) + map_size; 1214 tag->mb_descr_size = (uint32_t)desc_size; 1215 1216 map = (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap; 1217 1218 last_addr += map_size; 1219 last_addr = roundup2(last_addr, MULTIBOOT_TAG_ALIGN); 1220 } 1221 #endif /* EFI */ 1222 1223 /* 1224 * MB tag list end marker. 1225 */ 1226 { 1227 multiboot_tag_t *tag = (multiboot_tag_t *) 1228 mb_malloc(sizeof (*tag)); 1229 tag->mb_type = MULTIBOOT_TAG_TYPE_END; 1230 tag->mb_size = sizeof (*tag); 1231 } 1232 1233 mbi->mbi_total_size = last_addr - (vm_offset_t)mbi; 1234 mbi->mbi_reserved = 0; 1235 1236 #if defined(EFI) 1237 /* 1238 * At this point we have load_addr pointing to kernel load 1239 * address, module list in MBI having physical addresses, 1240 * module list in fp having logical addresses and tmp pointing to 1241 * physical address for MBI. 1242 * Now we must move all pieces to place and start the kernel. 1243 */ 1244 head = &relocator->rel_chunk_head; 1245 STAILQ_INIT(head); 1246 1247 i = 0; 1248 chunk = &relocator->rel_chunklist[i++]; 1249 chunk->chunk_vaddr = fp->f_addr; 1250 chunk->chunk_paddr = load_addr; 1251 chunk->chunk_size = fp->f_size; 1252 1253 STAILQ_INSERT_TAIL(head, chunk, chunk_next); 1254 1255 mp = module; 1256 for (mfp = fp->f_next; mfp != NULL; mfp = mfp->f_next) { 1257 chunk = &relocator->rel_chunklist[i++]; 1258 chunk->chunk_vaddr = mfp->f_addr; 1259 1260 /* 1261 * fix the mb_mod_start and mb_mod_end. 1262 */ 1263 mp->mb_mod_start = efi_physaddr(module, tmp, map, 1264 map_size / desc_size, desc_size, mfp->f_addr, 1265 mp->mb_mod_end); 1266 if (mp->mb_mod_start == 0) 1267 panic("Could not find memory for module"); 1268 1269 mp->mb_mod_end += mp->mb_mod_start; 1270 chunk->chunk_paddr = mp->mb_mod_start; 1271 chunk->chunk_size = mfp->f_size; 1272 STAILQ_INSERT_TAIL(head, chunk, chunk_next); 1273 1274 mp = (multiboot_tag_module_t *) 1275 roundup2((uintptr_t)mp + mp->mb_size, 1276 MULTIBOOT_TAG_ALIGN); 1277 } 1278 chunk = &relocator->rel_chunklist[i++]; 1279 chunk->chunk_vaddr = (EFI_VIRTUAL_ADDRESS)(uintptr_t)mbi; 1280 chunk->chunk_paddr = efi_physaddr(module, tmp, map, 1281 map_size / desc_size, desc_size, (uintptr_t)mbi, 1282 mbi->mbi_total_size); 1283 chunk->chunk_size = mbi->mbi_total_size; 1284 STAILQ_INSERT_TAIL(head, chunk, chunk_next); 1285 1286 trampoline = (void *)(uintptr_t)relocator + EFI_PAGE_SIZE; 1287 memmove(trampoline, multiboot_tramp, EFI_PAGE_SIZE); 1288 1289 relocator->rel_copy = (uintptr_t)trampoline + EFI_PAGE_SIZE; 1290 memmove((void *)relocator->rel_copy, efi_copy_finish, EFI_PAGE_SIZE); 1291 1292 relocator->rel_memmove = (uintptr_t)relocator->rel_copy + EFI_PAGE_SIZE; 1293 memmove((void *)relocator->rel_memmove, memmove, EFI_PAGE_SIZE); 1294 relocator->rel_stack = relocator->rel_memmove + EFI_PAGE_SIZE - 8; 1295 1296 trampoline(MULTIBOOT2_BOOTLOADER_MAGIC, relocator, entry_addr); 1297 #else 1298 dev_cleanup(); 1299 __exec((void *)VTOP(multiboot_tramp), MULTIBOOT2_BOOTLOADER_MAGIC, 1300 (void *)entry_addr, (void *)VTOP(mbi)); 1301 #endif /* EFI */ 1302 panic("exec returned"); 1303 1304 error: 1305 free(cmdline); 1306 1307 #if defined(EFI) 1308 free(relocator); 1309 1310 if (mbi != NULL) 1311 efi_free_loadaddr((vm_offset_t)mbi, EFI_SIZE_TO_PAGES(size)); 1312 #endif 1313 1314 return (error); 1315 } 1316