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 }
|