Print this page
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    9259 libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Revert "NEX-16819 loader UEFI support"
This reverts commit ec06b9fc617b99234e538bf2e7e4d02a24993e0c.
Reverting due to failures in the zfs-tests and the sharefs-tests
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>


  17  * This module adds support for loading and booting illumos multiboot2
  18  * kernel. This code is only built to support the illumos kernel, it does
  19  * not support xen.
  20  */
  21 
  22 #include <sys/cdefs.h>
  23 #include <sys/stddef.h>
  24 
  25 #include <sys/param.h>
  26 #include <sys/exec.h>
  27 #include <sys/linker.h>
  28 #include <sys/module.h>
  29 #include <sys/stdint.h>
  30 #include <sys/multiboot2.h>
  31 #include <stand.h>
  32 #include <stdbool.h>
  33 #include <machine/elf.h>
  34 #include "libzfs.h"
  35 
  36 #include "bootstrap.h"

  37 
  38 #include <machine/metadata.h>
  39 #include <machine/pc/bios.h>
  40 
  41 #define SUPPORT_DHCP
  42 #include <bootp.h>
  43 
  44 #if !defined(EFI)
  45 #include "../i386/libi386/libi386.h"
  46 #include "../i386/btx/lib/btxv86.h"


  47 
  48 #else
  49 #include <efi.h>
  50 #include <efilib.h>
  51 #include "loader_efi.h"
  52 
  53 static void (*trampoline)(uint32_t, struct relocator *, uint64_t);
  54 #endif
  55 
  56 #include "platform/acfreebsd.h"
  57 #include "acconfig.h"
  58 #define ACPI_SYSTEM_XFACE
  59 #include "actypes.h"
  60 #include "actbl.h"
  61 
  62 extern ACPI_TABLE_RSDP *rsdp;
  63 
  64 /* MB data heap pointer. */
  65 static vm_offset_t last_addr;
  66 extern char bootprog_info[];


 179                  * header_length + checksum must equal 0.
 180                  */
 181                 if (header->mb2_magic + header->mb2_architecture +
 182                     header->mb2_header_length + header->mb2_checksum != 0) {
 183                         header = NULL;
 184                         continue;
 185                 }
 186                 /*
 187                  * Finally, the entire header must fit within MULTIBOOT_SEARCH.
 188                  */
 189                 if (i + header->mb2_header_length > MULTIBOOT_SEARCH) {
 190                         header = NULL;
 191                         continue;
 192                 }
 193                 break;
 194         }
 195 
 196         if (header == NULL)
 197                 goto out;
 198 

 199         for (tag = header->mb2_tags; tag->mbh_type != MULTIBOOT_TAG_TYPE_END;
 200             tag = (multiboot_header_tag_t *)((uintptr_t)tag +
 201             roundup2(tag->mbh_size, MULTIBOOT_TAG_ALIGN))) {
 202                 switch (tag->mbh_type) {
 203                 case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST:
 204                         if (is_info_request_valid((void*)tag) == false)
 205                                 goto out;
 206                         break;
 207                 case MULTIBOOT_HEADER_TAG_ADDRESS:
 208                         addr_tag = (multiboot_header_tag_address_t *)tag;
 209                         break;
 210                 case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS:
 211                         entry_tag =
 212                             (multiboot_header_tag_entry_address_t *)tag;
 213                         break;
 214                 case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
 215                         break;
 216                 case MULTIBOOT_HEADER_TAG_FRAMEBUFFER:
 217                         have_framebuffer = true;
 218                         break;


 580 int
 581 mb_kernel_cmdline(struct preloaded_file *fp, struct devdesc *rootdev,
 582     char **line)
 583 {
 584         const char *fs = getenv("fstype");
 585         char *cmdline;
 586         size_t len;
 587         bool zfs_root = false;
 588         bool mb2;
 589         int rv;
 590 
 591         /*
 592          * 64-bit kernel has aout header, 32-bit kernel is elf, and the
 593          * type strings are different. Lets just search for "multiboot2".
 594          */
 595         if (strstr(fp->f_type, "multiboot2") == NULL)
 596                 mb2 = false;
 597         else
 598                 mb2 = true;
 599 
 600         if (rootdev->d_type == DEVT_ZFS)
 601                 zfs_root = true;
 602 
 603         /* If we have fstype set in env, reset zfs_root if needed. */
 604         if (fs != NULL && strcmp(fs, "zfs") != 0)
 605                 zfs_root = false;
 606 
 607         /*
 608          * If we have fstype set on the command line,
 609          * reset zfs_root if needed.
 610          */
 611         rv = find_property_value(fp->f_args, "fstype", &fs, &len);
 612         if (rv != 0 && rv != ENOENT)
 613                 return (rv);
 614 
 615         if (fs != NULL && strncmp(fs, "zfs", len) != 0)
 616                 zfs_root = false;
 617 
 618         /* zfs_bootfs() will set the environment, it must be called. */
 619         if (zfs_root == true)
 620                 fs = zfs_bootfs(rootdev);


 715  */
 716 static size_t
 717 biossmap_size(struct preloaded_file *fp)
 718 {
 719         int num;
 720         struct file_metadata *md;
 721 
 722         md = file_findmetadata(fp, MODINFOMD_SMAP);
 723         if (md == NULL)
 724                 return (0);
 725 
 726         num = md->md_size / sizeof(struct bios_smap); /* number of entries */
 727         return (sizeof (multiboot_tag_mmap_t) +
 728             num * sizeof (multiboot_mmap_entry_t));
 729 }
 730 
 731 static size_t
 732 mbi_size(struct preloaded_file *fp, char *cmdline)
 733 {
 734         size_t size;



 735 
 736         size = sizeof (uint32_t) * 2; /* first 2 fields from MBI header */
 737         size += sizeof (multiboot_tag_string_t) + strlen(cmdline) + 1;
 738         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 739         size += sizeof (multiboot_tag_string_t) + strlen(bootprog_info) + 1;
 740         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 741 #if !defined (EFI)
 742         size += sizeof (multiboot_tag_basic_meminfo_t);
 743         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 744 #endif
 745         size += module_size(fp);
 746         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 747 #if defined (EFI)
 748         size += sizeof (multiboot_tag_efi64_t);
 749         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 750         size += efimemmap_size();
 751         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 752 
 753         if (have_framebuffer == true) {
 754                 size += sizeof (multiboot_tag_framebuffer_t);
 755                 size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 756         }
 757 #endif

 758         size += biossmap_size(fp);
 759         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 760 















 761         if (bootp_response != NULL) {
 762                 size += sizeof(multiboot_tag_network_t) + bootp_response_size;
 763                 size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 764         }
 765 
 766         if (rsdp != NULL) {
 767                 if (rsdp->Revision == 0) {
 768                         size += sizeof (multiboot_tag_old_acpi_t) +
 769                             sizeof(ACPI_RSDP_COMMON);
 770                 } else {
 771                         size += sizeof (multiboot_tag_new_acpi_t) +
 772                             rsdp->Length;
 773                 }
 774                 size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 775         }
 776         size += sizeof(multiboot_tag_t);
 777 
 778         return (size);
 779 }
 780 


 785         multiboot2_info_header_t *mbi;
 786         char *cmdline = NULL;
 787         struct devdesc *rootdev;
 788         struct file_metadata *md;
 789         int i, error, num;
 790         int rootfs = 0;
 791         size_t size;
 792         struct bios_smap *smap;
 793 #if defined (EFI)
 794         multiboot_tag_module_t *module, *mp;
 795         EFI_MEMORY_DESCRIPTOR *map;
 796         UINTN map_size, desc_size;
 797         struct relocator *relocator;
 798         struct chunk_head *head;
 799         struct chunk *chunk;
 800         vm_offset_t tmp;
 801 
 802         efi_getdev((void **)(&rootdev), NULL, NULL);
 803 #else
 804         i386_getdev((void **)(&rootdev), NULL, NULL);





 805 #endif
 806 
 807         error = EINVAL;
 808         if (rootdev == NULL) {
 809                 printf("can't determine root device\n");
 810                 goto error;
 811         }
 812 
 813         /*
 814          * Set the image command line.
 815          */
 816         if (fp->f_args == NULL) {
 817                 cmdline = getenv("boot-args");
 818                 if (cmdline != NULL) {
 819                         fp->f_args = strdup(cmdline);
 820                         if (fp->f_args == NULL) {
 821                                 error = ENOMEM;
 822                                 goto error;
 823                         }
 824                 }
 825         }
 826 
 827         error = mb_kernel_cmdline(fp, rootdev, &cmdline);
 828         if (error != 0)
 829                 goto error;
 830 
 831         /* mb_kernel_cmdline() updates the environment. */
 832         build_environment_module();
 833 





 834         size = mbi_size(fp, cmdline);   /* Get the size for MBI. */
 835 
 836         /* Set up the base for mb_malloc. */
 837         i = 0;
 838         for (mfp = fp; mfp->f_next != NULL; mfp = mfp->f_next)
 839                 i++;
 840 
 841 #if defined (EFI)
 842         /* We need space for kernel + MBI + # modules */
 843         num = (EFI_PAGE_SIZE - offsetof(struct relocator, rel_chunklist)) /
 844             sizeof (struct chunk);
 845         if (i + 2 >= num) {
 846                 printf("Too many modules, do not have space for relocator.\n");
 847                 error = ENOMEM;
 848                 goto error;
 849         }
 850 
 851         last_addr = efi_loadaddr(LOAD_MEM, &size, mfp->f_addr + mfp->f_size);
 852         mbi = (multiboot2_info_header_t *)last_addr;
 853         if (mbi == NULL) {


1000                 mmap_entry = (multiboot_mmap_entry_t *)tag->mb_entries;
1001 
1002                 for (i = 0; i < num; i++) {
1003                         mmap_entry[i].mmap_addr = smap[i].base;
1004                         mmap_entry[i].mmap_len = smap[i].length;
1005                         mmap_entry[i].mmap_type = smap[i].type;
1006                         mmap_entry[i].mmap_reserved = 0;
1007                 }
1008         }
1009 
1010         if (bootp_response != NULL) {
1011                 multiboot_tag_network_t *tag;
1012                 tag = (multiboot_tag_network_t *)
1013                     mb_malloc(sizeof(*tag) + bootp_response_size);
1014 
1015                 tag->mb_type = MULTIBOOT_TAG_TYPE_NETWORK;
1016                 tag->mb_size = sizeof(*tag) + bootp_response_size;
1017                 memcpy(tag->mb_dhcpack, bootp_response, bootp_response_size);
1018         }
1019 














1020         if (rsdp != NULL) {
1021                 multiboot_tag_new_acpi_t *ntag;
1022                 multiboot_tag_old_acpi_t *otag;
1023                 uint32_t tsize;
1024 
1025                 if (rsdp->Revision == 0) {
1026                         tsize = sizeof (*otag) + sizeof (ACPI_RSDP_COMMON);
1027                         otag = (multiboot_tag_old_acpi_t *)mb_malloc(tsize);
1028                         otag->mb_type = MULTIBOOT_TAG_TYPE_ACPI_OLD;
1029                         otag->mb_size = tsize;
1030                         memcpy(otag->mb_rsdp, rsdp, sizeof (ACPI_RSDP_COMMON));
1031                 } else {
1032                         tsize = sizeof (*ntag) + rsdp->Length;
1033                         ntag = (multiboot_tag_new_acpi_t *)mb_malloc(tsize);
1034                         ntag->mb_type = MULTIBOOT_TAG_TYPE_ACPI_NEW;
1035                         ntag->mb_size = tsize;
1036                         memcpy(ntag->mb_rsdp, rsdp, rsdp->Length);
1037                 }
1038         }
1039 
1040 #if defined (EFI)

1041         {
1042                 multiboot_tag_efi64_t *tag;
1043                 tag = (multiboot_tag_efi64_t *)
1044                     mb_malloc(sizeof (*tag));
1045 
1046                 tag->mb_type = MULTIBOOT_TAG_TYPE_EFI64;
1047                 tag->mb_size = sizeof (*tag);
1048                 tag->mb_pointer = (uint64_t)(uintptr_t)ST;
1049         }





1050 







1051         if (have_framebuffer == true) {
1052                 multiboot_tag_framebuffer_t *tag;
1053                 int bpp;
1054                 struct efi_fb fb;
1055                 extern int efi_find_framebuffer(struct efi_fb *efifb);
1056 
1057                 if (efi_find_framebuffer(&fb) == 0) {
1058                         tag = (multiboot_tag_framebuffer_t *)
1059                             mb_malloc(sizeof (*tag));





1060 
1061                         /*
1062                          * We assume contiguous color bitmap, and use
1063                          * the msb for bits per pixel calculation.
1064                          */
1065                         bpp = fls(fb.fb_mask_red | fb.fb_mask_green |
1066                             fb.fb_mask_blue | fb.fb_mask_reserved);




1067 



1068                         tag->framebuffer_common.mb_type =
1069                             MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
1070                         tag->framebuffer_common.mb_size =
1071                             sizeof (multiboot_tag_framebuffer_t);
1072                         tag->framebuffer_common.framebuffer_addr = fb.fb_addr;
1073                         tag->framebuffer_common.framebuffer_width = fb.fb_width;
1074                         tag->framebuffer_common.framebuffer_height =
1075                             fb.fb_height;
1076                         tag->framebuffer_common.framebuffer_bpp = bpp;
1077                         /*
1078                          * Pitch is stride * bytes per pixel.
1079                          * Stride is pixels per scanline.
1080                          */
1081                         tag->framebuffer_common.framebuffer_pitch =
1082                             fb.fb_stride * (bpp / 8);
1083                         tag->framebuffer_common.framebuffer_type =
1084                             MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
1085                         tag->framebuffer_common.mb_reserved = 0;
1086 
1087                         /*
1088                          * The RGB or BGR color ordering.
1089                          */
1090                         if (fb.fb_mask_red & 0x000000ff) {
1091                                 tag->u.fb2.framebuffer_red_field_position = 0;
1092                                 tag->u.fb2.framebuffer_blue_field_position = 16;
1093                         } else {
1094                                 tag->u.fb2.framebuffer_red_field_position = 16;
1095                                 tag->u.fb2.framebuffer_blue_field_position = 0;
1096                         }
1097                         tag->u.fb2.framebuffer_red_mask_size = 8;
1098                         tag->u.fb2.framebuffer_green_field_position = 8;
1099                         tag->u.fb2.framebuffer_green_mask_size = 8;
1100                         tag->u.fb2.framebuffer_blue_mask_size = 8;
1101                 }
1102         }
1103 

1104         /* Leave EFI memmap last as we will also switch off the BS. */
1105         {
1106                 multiboot_tag_efi_mmap_t *tag;
1107                 UINTN key;
1108                 EFI_STATUS status;
1109 
1110                 tag = (multiboot_tag_efi_mmap_t *)
1111                     mb_malloc(sizeof (*tag));
1112 
1113                 map_size = 0;
1114                 status = BS->GetMemoryMap(&map_size,
1115                     (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap, &key,
1116                     &desc_size, &tag->mb_descr_vers);
1117                 if (status != EFI_BUFFER_TOO_SMALL) {
1118                         error = EINVAL;
1119                         goto error;
1120                 }
1121                 status = BS->GetMemoryMap(&map_size,
1122                     (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap, &key,
1123                     &desc_size, &tag->mb_descr_vers);


1201                 chunk->chunk_vaddr = mfp->f_addr;
1202 
1203                 /*
1204                  * fix the mb_mod_start and mb_mod_end.
1205                  */
1206                 mp->mb_mod_start = efi_physaddr(module, tmp, map,
1207                     map_size / desc_size, desc_size, mp->mb_mod_end);
1208                 if (mp->mb_mod_start == 0)
1209                         panic("Could not find memory for module\n");
1210 
1211                 mp->mb_mod_end += mp->mb_mod_start;
1212                 chunk->chunk_paddr = mp->mb_mod_start;
1213                 chunk->chunk_size = mfp->f_size;
1214                 STAILQ_INSERT_TAIL(head, chunk, chunk_next);
1215 
1216                 mp = (multiboot_tag_module_t *)
1217                     roundup2((uintptr_t)mp + mp->mb_size,
1218                     MULTIBOOT_TAG_ALIGN);
1219         }
1220         chunk = &relocator->rel_chunklist[i++];
1221         chunk->chunk_vaddr = (EFI_VIRTUAL_ADDRESS)mbi;
1222         chunk->chunk_paddr = efi_physaddr(module, tmp, map,
1223                     map_size / desc_size, desc_size, mbi->mbi_total_size);
1224         chunk->chunk_size = mbi->mbi_total_size;
1225         STAILQ_INSERT_TAIL(head, chunk, chunk_next);
1226 
1227         trampoline = (void *)(uintptr_t)relocator + EFI_PAGE_SIZE;
1228         memmove(trampoline, multiboot_tramp, EFI_PAGE_SIZE);
1229 
1230         relocator->rel_copy = (uintptr_t)trampoline + EFI_PAGE_SIZE;
1231         memmove((void *)relocator->rel_copy, efi_copy_finish, EFI_PAGE_SIZE);
1232 
1233         relocator->rel_memmove = (uintptr_t)relocator->rel_copy + EFI_PAGE_SIZE;
1234         memmove((void *)relocator->rel_memmove, memmove, EFI_PAGE_SIZE);
1235         relocator->rel_stack = relocator->rel_memmove + EFI_PAGE_SIZE - 8;
1236 
1237         trampoline(MULTIBOOT2_BOOTLOADER_MAGIC, relocator, entry_addr);
1238 #else
1239         dev_cleanup();
1240         __exec((void *)VTOP(multiboot_tramp), MULTIBOOT2_BOOTLOADER_MAGIC,
1241             (void *)entry_addr, (void *)VTOP(mbi));
1242 #endif
1243         panic("exec returned");
1244 
1245 error:
1246         if (cmdline != NULL)
1247                 free(cmdline);
1248 #if defined (EFI)
1249         if (mbi != NULL)
1250                 efi_free_loadaddr((uint64_t)mbi, EFI_SIZE_TO_PAGES(size));
1251 #endif
1252         return (error);
1253 }


  17  * This module adds support for loading and booting illumos multiboot2
  18  * kernel. This code is only built to support the illumos kernel, it does
  19  * not support xen.
  20  */
  21 
  22 #include <sys/cdefs.h>
  23 #include <sys/stddef.h>
  24 
  25 #include <sys/param.h>
  26 #include <sys/exec.h>
  27 #include <sys/linker.h>
  28 #include <sys/module.h>
  29 #include <sys/stdint.h>
  30 #include <sys/multiboot2.h>
  31 #include <stand.h>
  32 #include <stdbool.h>
  33 #include <machine/elf.h>
  34 #include "libzfs.h"
  35 
  36 #include "bootstrap.h"
  37 #include <sys/consplat.h>
  38 
  39 #include <machine/metadata.h>
  40 #include <machine/pc/bios.h>
  41 
  42 #define SUPPORT_DHCP
  43 #include <bootp.h>
  44 
  45 #if !defined(EFI)

  46 #include "../i386/btx/lib/btxv86.h"
  47 #include "libi386.h"
  48 #include "vbe.h"
  49 
  50 #else
  51 #include <efi.h>
  52 #include <efilib.h>
  53 #include "loader_efi.h"
  54 
  55 static void (*trampoline)(uint32_t, struct relocator *, uint64_t);
  56 #endif
  57 
  58 #include "platform/acfreebsd.h"
  59 #include "acconfig.h"
  60 #define ACPI_SYSTEM_XFACE
  61 #include "actypes.h"
  62 #include "actbl.h"
  63 
  64 extern ACPI_TABLE_RSDP *rsdp;
  65 
  66 /* MB data heap pointer. */
  67 static vm_offset_t last_addr;
  68 extern char bootprog_info[];


 181                  * header_length + checksum must equal 0.
 182                  */
 183                 if (header->mb2_magic + header->mb2_architecture +
 184                     header->mb2_header_length + header->mb2_checksum != 0) {
 185                         header = NULL;
 186                         continue;
 187                 }
 188                 /*
 189                  * Finally, the entire header must fit within MULTIBOOT_SEARCH.
 190                  */
 191                 if (i + header->mb2_header_length > MULTIBOOT_SEARCH) {
 192                         header = NULL;
 193                         continue;
 194                 }
 195                 break;
 196         }
 197 
 198         if (header == NULL)
 199                 goto out;
 200 
 201         have_framebuffer = false;
 202         for (tag = header->mb2_tags; tag->mbh_type != MULTIBOOT_TAG_TYPE_END;
 203             tag = (multiboot_header_tag_t *)((uintptr_t)tag +
 204             roundup2(tag->mbh_size, MULTIBOOT_TAG_ALIGN))) {
 205                 switch (tag->mbh_type) {
 206                 case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST:
 207                         if (is_info_request_valid((void*)tag) == false)
 208                                 goto out;
 209                         break;
 210                 case MULTIBOOT_HEADER_TAG_ADDRESS:
 211                         addr_tag = (multiboot_header_tag_address_t *)tag;
 212                         break;
 213                 case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS:
 214                         entry_tag =
 215                             (multiboot_header_tag_entry_address_t *)tag;
 216                         break;
 217                 case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
 218                         break;
 219                 case MULTIBOOT_HEADER_TAG_FRAMEBUFFER:
 220                         have_framebuffer = true;
 221                         break;


 583 int
 584 mb_kernel_cmdline(struct preloaded_file *fp, struct devdesc *rootdev,
 585     char **line)
 586 {
 587         const char *fs = getenv("fstype");
 588         char *cmdline;
 589         size_t len;
 590         bool zfs_root = false;
 591         bool mb2;
 592         int rv;
 593 
 594         /*
 595          * 64-bit kernel has aout header, 32-bit kernel is elf, and the
 596          * type strings are different. Lets just search for "multiboot2".
 597          */
 598         if (strstr(fp->f_type, "multiboot2") == NULL)
 599                 mb2 = false;
 600         else
 601                 mb2 = true;
 602 
 603         if (rootdev->d_dev->dv_type == DEVT_ZFS)
 604                 zfs_root = true;
 605 
 606         /* If we have fstype set in env, reset zfs_root if needed. */
 607         if (fs != NULL && strcmp(fs, "zfs") != 0)
 608                 zfs_root = false;
 609 
 610         /*
 611          * If we have fstype set on the command line,
 612          * reset zfs_root if needed.
 613          */
 614         rv = find_property_value(fp->f_args, "fstype", &fs, &len);
 615         if (rv != 0 && rv != ENOENT)
 616                 return (rv);
 617 
 618         if (fs != NULL && strncmp(fs, "zfs", len) != 0)
 619                 zfs_root = false;
 620 
 621         /* zfs_bootfs() will set the environment, it must be called. */
 622         if (zfs_root == true)
 623                 fs = zfs_bootfs(rootdev);


 718  */
 719 static size_t
 720 biossmap_size(struct preloaded_file *fp)
 721 {
 722         int num;
 723         struct file_metadata *md;
 724 
 725         md = file_findmetadata(fp, MODINFOMD_SMAP);
 726         if (md == NULL)
 727                 return (0);
 728 
 729         num = md->md_size / sizeof(struct bios_smap); /* number of entries */
 730         return (sizeof (multiboot_tag_mmap_t) +
 731             num * sizeof (multiboot_mmap_entry_t));
 732 }
 733 
 734 static size_t
 735 mbi_size(struct preloaded_file *fp, char *cmdline)
 736 {
 737         size_t size;
 738 #if !defined (EFI)
 739         extern multiboot_tag_framebuffer_t gfx_fb;
 740 #endif
 741 
 742         size = sizeof (uint32_t) * 2; /* first 2 fields from MBI header */
 743         size += sizeof (multiboot_tag_string_t) + strlen(cmdline) + 1;
 744         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 745         size += sizeof (multiboot_tag_string_t) + strlen(bootprog_info) + 1;
 746         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 747 #if !defined (EFI)
 748         size += sizeof (multiboot_tag_basic_meminfo_t);
 749         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 750 #endif
 751         size += module_size(fp);
 752         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 753 #if defined (EFI)
 754         size += sizeof (multiboot_tag_efi64_t);
 755         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 756         size += efimemmap_size();
 757         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 758 
 759         if (have_framebuffer == true) {
 760                 size += sizeof (multiboot_tag_framebuffer_t);
 761                 size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 762         }
 763 #endif
 764 
 765         size += biossmap_size(fp);
 766         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 767 
 768 #if !defined (EFI)
 769         if (gfx_fb.framebuffer_common.framebuffer_type ==
 770             MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED) {
 771                 size += sizeof (struct multiboot_tag_framebuffer_common);
 772                 size += gfx_fb.u.fb1.framebuffer_palette_num_colors *
 773                     sizeof (multiboot_color_t);
 774         } else {
 775                 size += sizeof (multiboot_tag_framebuffer_t);
 776         }
 777         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 778 
 779         size += sizeof (multiboot_tag_vbe_t);
 780         size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 781 #endif
 782 
 783         if (bootp_response != NULL) {
 784                 size += sizeof(multiboot_tag_network_t) + bootp_response_size;
 785                 size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 786         }
 787 
 788         if (rsdp != NULL) {
 789                 if (rsdp->Revision == 0) {
 790                         size += sizeof (multiboot_tag_old_acpi_t) +
 791                             sizeof(ACPI_RSDP_COMMON);
 792                 } else {
 793                         size += sizeof (multiboot_tag_new_acpi_t) +
 794                             rsdp->Length;
 795                 }
 796                 size = roundup2(size, MULTIBOOT_TAG_ALIGN);
 797         }
 798         size += sizeof(multiboot_tag_t);
 799 
 800         return (size);
 801 }
 802 


 807         multiboot2_info_header_t *mbi;
 808         char *cmdline = NULL;
 809         struct devdesc *rootdev;
 810         struct file_metadata *md;
 811         int i, error, num;
 812         int rootfs = 0;
 813         size_t size;
 814         struct bios_smap *smap;
 815 #if defined (EFI)
 816         multiboot_tag_module_t *module, *mp;
 817         EFI_MEMORY_DESCRIPTOR *map;
 818         UINTN map_size, desc_size;
 819         struct relocator *relocator;
 820         struct chunk_head *head;
 821         struct chunk *chunk;
 822         vm_offset_t tmp;
 823 
 824         efi_getdev((void **)(&rootdev), NULL, NULL);
 825 #else
 826         i386_getdev((void **)(&rootdev), NULL, NULL);
 827 
 828         if (have_framebuffer == false) {
 829                 /* make sure we have text mode */
 830                 bios_set_text_mode(3);
 831         }
 832 #endif
 833 
 834         error = EINVAL;
 835         if (rootdev == NULL) {
 836                 printf("can't determine root device\n");
 837                 goto error;
 838         }
 839 
 840         /*
 841          * Set the image command line.
 842          */
 843         if (fp->f_args == NULL) {
 844                 cmdline = getenv("boot-args");
 845                 if (cmdline != NULL) {
 846                         fp->f_args = strdup(cmdline);
 847                         if (fp->f_args == NULL) {
 848                                 error = ENOMEM;
 849                                 goto error;
 850                         }
 851                 }
 852         }
 853 
 854         error = mb_kernel_cmdline(fp, rootdev, &cmdline);
 855         if (error != 0)
 856                 goto error;
 857 
 858         /* mb_kernel_cmdline() updates the environment. */
 859         build_environment_module();
 860 
 861         if (have_framebuffer == true) {
 862                 /* Pass the loaded console font for kernel. */
 863                 build_font_module();
 864         }
 865 
 866         size = mbi_size(fp, cmdline);   /* Get the size for MBI. */
 867 
 868         /* Set up the base for mb_malloc. */
 869         i = 0;
 870         for (mfp = fp; mfp->f_next != NULL; mfp = mfp->f_next)
 871                 i++;
 872 
 873 #if defined (EFI)
 874         /* We need space for kernel + MBI + # modules */
 875         num = (EFI_PAGE_SIZE - offsetof(struct relocator, rel_chunklist)) /
 876             sizeof (struct chunk);
 877         if (i + 2 >= num) {
 878                 printf("Too many modules, do not have space for relocator.\n");
 879                 error = ENOMEM;
 880                 goto error;
 881         }
 882 
 883         last_addr = efi_loadaddr(LOAD_MEM, &size, mfp->f_addr + mfp->f_size);
 884         mbi = (multiboot2_info_header_t *)last_addr;
 885         if (mbi == NULL) {


1032                 mmap_entry = (multiboot_mmap_entry_t *)tag->mb_entries;
1033 
1034                 for (i = 0; i < num; i++) {
1035                         mmap_entry[i].mmap_addr = smap[i].base;
1036                         mmap_entry[i].mmap_len = smap[i].length;
1037                         mmap_entry[i].mmap_type = smap[i].type;
1038                         mmap_entry[i].mmap_reserved = 0;
1039                 }
1040         }
1041 
1042         if (bootp_response != NULL) {
1043                 multiboot_tag_network_t *tag;
1044                 tag = (multiboot_tag_network_t *)
1045                     mb_malloc(sizeof(*tag) + bootp_response_size);
1046 
1047                 tag->mb_type = MULTIBOOT_TAG_TYPE_NETWORK;
1048                 tag->mb_size = sizeof(*tag) + bootp_response_size;
1049                 memcpy(tag->mb_dhcpack, bootp_response, bootp_response_size);
1050         }
1051 
1052 #if !defined (EFI)
1053         {
1054                 multiboot_tag_vbe_t *tag;
1055                 extern multiboot_tag_vbe_t vbestate;
1056 
1057                 if (vbestate.vbe_mode >= 0x100) {
1058                         tag = (multiboot_tag_vbe_t *)mb_malloc(sizeof(*tag));
1059                         memcpy(tag, &vbestate, sizeof(*tag));
1060                         tag->mb_type = MULTIBOOT_TAG_TYPE_VBE;
1061                         tag->mb_size = sizeof(*tag);
1062                 }
1063         }
1064 #endif
1065 
1066         if (rsdp != NULL) {
1067                 multiboot_tag_new_acpi_t *ntag;
1068                 multiboot_tag_old_acpi_t *otag;
1069                 uint32_t tsize;
1070 
1071                 if (rsdp->Revision == 0) {
1072                         tsize = sizeof (*otag) + sizeof (ACPI_RSDP_COMMON);
1073                         otag = (multiboot_tag_old_acpi_t *)mb_malloc(tsize);
1074                         otag->mb_type = MULTIBOOT_TAG_TYPE_ACPI_OLD;
1075                         otag->mb_size = tsize;
1076                         memcpy(otag->mb_rsdp, rsdp, sizeof (ACPI_RSDP_COMMON));
1077                 } else {
1078                         tsize = sizeof (*ntag) + rsdp->Length;
1079                         ntag = (multiboot_tag_new_acpi_t *)mb_malloc(tsize);
1080                         ntag->mb_type = MULTIBOOT_TAG_TYPE_ACPI_NEW;
1081                         ntag->mb_size = tsize;
1082                         memcpy(ntag->mb_rsdp, rsdp, rsdp->Length);
1083                 }
1084         }
1085 
1086 #if defined (EFI)
1087 #ifdef  __LP64__
1088         {
1089                 multiboot_tag_efi64_t *tag;
1090                 tag = (multiboot_tag_efi64_t *)
1091                     mb_malloc(sizeof (*tag));
1092 
1093                 tag->mb_type = MULTIBOOT_TAG_TYPE_EFI64;
1094                 tag->mb_size = sizeof (*tag);
1095                 tag->mb_pointer = (uint64_t)(uintptr_t)ST;
1096         }
1097 #else
1098         {
1099                 multiboot_tag_efi32_t *tag;
1100                 tag = (multiboot_tag_efi32_t *)
1101                     mb_malloc(sizeof (*tag));
1102 
1103                 tag->mb_type = MULTIBOOT_TAG_TYPE_EFI32;
1104                 tag->mb_size = sizeof (*tag);
1105                 tag->mb_pointer = (uint32_t)ST;
1106         }
1107 #endif /* __LP64__ */
1108 #endif
1109 
1110         if (have_framebuffer == true) {
1111                 multiboot_tag_framebuffer_t *tag;
1112                 extern multiboot_tag_framebuffer_t gfx_fb;
1113 #if defined (EFI)

1114 
1115                 tag = (multiboot_tag_framebuffer_t *) mb_malloc(sizeof (*tag));
1116                 memcpy(tag, &gfx_fb, sizeof (*tag));
1117                 tag->framebuffer_common.mb_type =
1118                     MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
1119                 tag->framebuffer_common.mb_size = sizeof (*tag);
1120 #else
1121                 extern multiboot_color_t *cmap;
1122                 uint32_t size;
1123 
1124                 if (gfx_fb.framebuffer_common.framebuffer_type ==
1125                     MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED) {
1126                         uint16_t nc;
1127                         nc = gfx_fb.u.fb1.framebuffer_palette_num_colors;
1128                         size = sizeof (struct multiboot_tag_framebuffer_common)
1129                             + sizeof (nc)
1130                             + nc * sizeof (multiboot_color_t);
1131                 } else {
1132                         size = sizeof (gfx_fb);
1133                 }
1134 
1135                 tag = (multiboot_tag_framebuffer_t *) mb_malloc(size);
1136                 memcpy(tag, &gfx_fb, sizeof (*tag));
1137 
1138                 tag->framebuffer_common.mb_type =
1139                     MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
1140                 tag->framebuffer_common.mb_size = size;















1141 
1142                 if (gfx_fb.framebuffer_common.framebuffer_type ==
1143                     MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED) {
1144                         memcpy(tag->u.fb1.framebuffer_palette, cmap,
1145                             sizeof (multiboot_color_t) *
1146                             gfx_fb.u.fb1.framebuffer_palette_num_colors);




1147                 }
1148 #endif



1149         }

1150 
1151 #if defined (EFI)
1152         /* Leave EFI memmap last as we will also switch off the BS. */
1153         {
1154                 multiboot_tag_efi_mmap_t *tag;
1155                 UINTN key;
1156                 EFI_STATUS status;
1157 
1158                 tag = (multiboot_tag_efi_mmap_t *)
1159                     mb_malloc(sizeof (*tag));
1160 
1161                 map_size = 0;
1162                 status = BS->GetMemoryMap(&map_size,
1163                     (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap, &key,
1164                     &desc_size, &tag->mb_descr_vers);
1165                 if (status != EFI_BUFFER_TOO_SMALL) {
1166                         error = EINVAL;
1167                         goto error;
1168                 }
1169                 status = BS->GetMemoryMap(&map_size,
1170                     (EFI_MEMORY_DESCRIPTOR *)tag->mb_efi_mmap, &key,
1171                     &desc_size, &tag->mb_descr_vers);


1249                 chunk->chunk_vaddr = mfp->f_addr;
1250 
1251                 /*
1252                  * fix the mb_mod_start and mb_mod_end.
1253                  */
1254                 mp->mb_mod_start = efi_physaddr(module, tmp, map,
1255                     map_size / desc_size, desc_size, mp->mb_mod_end);
1256                 if (mp->mb_mod_start == 0)
1257                         panic("Could not find memory for module\n");
1258 
1259                 mp->mb_mod_end += mp->mb_mod_start;
1260                 chunk->chunk_paddr = mp->mb_mod_start;
1261                 chunk->chunk_size = mfp->f_size;
1262                 STAILQ_INSERT_TAIL(head, chunk, chunk_next);
1263 
1264                 mp = (multiboot_tag_module_t *)
1265                     roundup2((uintptr_t)mp + mp->mb_size,
1266                     MULTIBOOT_TAG_ALIGN);
1267         }
1268         chunk = &relocator->rel_chunklist[i++];
1269         chunk->chunk_vaddr = (EFI_VIRTUAL_ADDRESS)(uintptr_t)mbi;
1270         chunk->chunk_paddr = efi_physaddr(module, tmp, map,
1271                     map_size / desc_size, desc_size, mbi->mbi_total_size);
1272         chunk->chunk_size = mbi->mbi_total_size;
1273         STAILQ_INSERT_TAIL(head, chunk, chunk_next);
1274 
1275         trampoline = (void *)(uintptr_t)relocator + EFI_PAGE_SIZE;
1276         memmove(trampoline, multiboot_tramp, EFI_PAGE_SIZE);
1277 
1278         relocator->rel_copy = (uintptr_t)trampoline + EFI_PAGE_SIZE;
1279         memmove((void *)relocator->rel_copy, efi_copy_finish, EFI_PAGE_SIZE);
1280 
1281         relocator->rel_memmove = (uintptr_t)relocator->rel_copy + EFI_PAGE_SIZE;
1282         memmove((void *)relocator->rel_memmove, memmove, EFI_PAGE_SIZE);
1283         relocator->rel_stack = relocator->rel_memmove + EFI_PAGE_SIZE - 8;
1284 
1285         trampoline(MULTIBOOT2_BOOTLOADER_MAGIC, relocator, entry_addr);
1286 #else
1287         dev_cleanup();
1288         __exec((void *)VTOP(multiboot_tramp), MULTIBOOT2_BOOTLOADER_MAGIC,
1289             (void *)entry_addr, (void *)VTOP(mbi));
1290 #endif
1291         panic("exec returned");
1292 
1293 error:
1294         if (cmdline != NULL)
1295                 free(cmdline);
1296 #if defined (EFI)
1297         if (mbi != NULL)
1298                 efi_free_loadaddr((vm_offset_t)mbi, EFI_SIZE_TO_PAGES(size));
1299 #endif
1300         return (error);
1301 }