diff --git a/hypervisor/arch/x86/boot/cpu_primary.S b/hypervisor/arch/x86/boot/cpu_primary.S index eacadda2e..09e0ae69e 100644 --- a/hypervisor/arch/x86/boot/cpu_primary.S +++ b/hypervisor/arch/x86/boot/cpu_primary.S @@ -63,6 +63,8 @@ info_req_tag_start: .long MULTIBOOT2_TAG_TYPE_MMAP .long MULTIBOOT2_TAG_TYPE_MODULE .long MULTIBOOT2_TAG_TYPE_ACPI_NEW + .long MULTIBOOT2_TAG_TYPE_EFI64 + .long MULTIBOOT2_TAG_TYPE_EFI_MMAP info_req_tag_end: .align MULTIBOOT2_TAG_ALIGN @@ -246,3 +248,9 @@ cpu_primary32_pdt_addr: .quad address + 0x83 address = address + 0x200000 .endr + +#ifdef CONFIG_MULTIBOOT2 + .global efiloader_sig +efiloader_sig: + .asciz "EL64" +#endif diff --git a/hypervisor/boot/include/boot.h b/hypervisor/boot/include/boot.h index 0c079464d..ac7e7133d 100644 --- a/hypervisor/boot/include/boot.h +++ b/hypervisor/boot/include/boot.h @@ -12,10 +12,15 @@ #include #endif #include +#include #define MAX_BOOTARGS_SIZE 2048U #define MAX_MODULE_COUNT 4U +/* extended flags for acrn multiboot info from multiboot2 */ +#define MULTIBOOT_INFO_HAS_EFI_MMAP 0x00010000U +#define MULTIBOOT_INFO_HAS_EFI64 0x00020000U + struct acrn_multiboot_info { uint32_t mi_flags; /* the flags is back-compatible with multiboot1 */ @@ -32,11 +37,14 @@ struct acrn_multiboot_info { struct multiboot_mmap mi_mmap_entry[E820_MAX_ENTRIES]; void *mi_acpi_rsdp; + struct efi_info mi_efi_info; }; /* boot_regs store the multiboot info magic and address */ extern uint32_t boot_regs[2]; +extern char *efiloader_sig; + static inline bool boot_from_multiboot1(void) { return ((boot_regs[0] == MULTIBOOT_INFO_MAGIC) && (boot_regs[1] != 0U)); diff --git a/hypervisor/boot/include/multiboot2.h b/hypervisor/boot/include/multiboot2.h index 402bf7a3a..dbddec1d3 100644 --- a/hypervisor/boot/include/multiboot2.h +++ b/hypervisor/boot/include/multiboot2.h @@ -126,6 +126,22 @@ struct multiboot2_tag_new_acpi uint8_t rsdp[0]; }; +struct multiboot2_tag_efi64 +{ + uint32_t type; + uint32_t size; + uint64_t pointer; +}; + +struct multiboot2_tag_efi_mmap +{ + uint32_t type; + uint32_t size; + uint32_t descr_size; + uint32_t descr_vers; + uint8_t efi_mmap[0]; +}; + #endif /* ASSEMBLER */ #endif /* MULTIBOOT2_H */ diff --git a/hypervisor/boot/multiboot2.c b/hypervisor/boot/multiboot2.c index 5daf1d352..0136ad68b 100644 --- a/hypervisor/boot/multiboot2.c +++ b/hypervisor/boot/multiboot2.c @@ -49,6 +49,37 @@ static void mb2_mods_to_mbi(struct acrn_multiboot_info *mbi, mbi->mi_flags |= MULTIBOOT_INFO_HAS_MODS; } +/** + * @pre mbi != NULL && mb2_tag_efi64 != 0 + */ +static void mb2_efi64_to_mbi(struct acrn_multiboot_info *mbi, struct multiboot2_tag_efi64 *mb2_tag_efi64) +{ + mbi->mi_efi_info.efi_systab = (uint32_t)(uint64_t)mb2_tag_efi64->pointer; + mbi->mi_efi_info.efi_loader_signature = (uint32_t)(uint64_t)efiloader_sig; + mbi->mi_flags |= MULTIBOOT_INFO_HAS_EFI64; +} + +/** + * @pre mbi != NULL && mb2_tag_efimmap != 0 + */ +static int32_t mb2_efimmap_to_mbi(struct acrn_multiboot_info *mbi, struct multiboot2_tag_efi_mmap *mb2_tag_efimmap) +{ + int32_t ret = 0; + + mbi->mi_efi_info.efi_memdesc_size = mb2_tag_efimmap->descr_size; + mbi->mi_efi_info.efi_memdesc_version = mb2_tag_efimmap->descr_vers; + mbi->mi_efi_info.efi_memmap = (uint32_t)(uint64_t)mb2_tag_efimmap->efi_mmap; + mbi->mi_efi_info.efi_memmap_size = mb2_tag_efimmap->size - 16U; + mbi->mi_efi_info.efi_memmap_hi = (uint32_t)(((uint64_t)mb2_tag_efimmap->efi_mmap) >> 32U); + if (mbi->mi_efi_info.efi_memmap_hi != 0U) { + pr_err("the efi mmap address should be less than 4G!"); + ret = -EINVAL; + } else { + mbi->mi_flags |= MULTIBOOT_INFO_HAS_EFI64; + } + return ret; +} + /** * @pre mbi != NULL && mb2_info != NULL */ @@ -84,6 +115,12 @@ int32_t multiboot2_to_acrn_mbi(struct acrn_multiboot_info *mbi, void *mb2_info) case MULTIBOOT2_TAG_TYPE_ACPI_NEW: mbi->mi_acpi_rsdp = ((struct multiboot2_tag_new_acpi *)mb2_tag)->rsdp; break; + case MULTIBOOT2_TAG_TYPE_EFI64: + mb2_efi64_to_mbi(mbi, (struct multiboot2_tag_efi64 *)mb2_tag); + break; + case MULTIBOOT2_TAG_TYPE_EFI_MMAP: + ret = mb2_efimmap_to_mbi(mbi, (struct multiboot2_tag_efi_mmap *)mb2_tag); + break; default: if (mb2_tag->type <= MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR) { pr_warn("unhandled multiboot2 tag type: %d", mb2_tag->type); @@ -104,5 +141,8 @@ int32_t multiboot2_to_acrn_mbi(struct acrn_multiboot_info *mbi, void *mb2_info) mb2_tag = (struct multiboot2_tag *)((uint8_t *)mb2_tag + ((mb2_tag->size + (MULTIBOOT2_INFO_ALIGN - 1U)) & ~(MULTIBOOT2_INFO_ALIGN - 1U))); } + if ((mbi->mi_flags & (MULTIBOOT_INFO_HAS_EFI64 | MULTIBOOT_INFO_HAS_EFI_MMAP)) == 0U) { + pr_err("no multiboot2 uefi info found!"); + } return ret; } diff --git a/hypervisor/common/vm_load.c b/hypervisor/common/vm_load.c index a0b8629b8..29258d3ec 100644 --- a/hypervisor/common/vm_load.c +++ b/hypervisor/common/vm_load.c @@ -58,11 +58,10 @@ static uint32_t create_zeropage_e820(struct zero_page *zp, const struct acrn_vm */ static uint64_t create_zero_page(struct acrn_vm *vm) { - struct zero_page *zeropage; + struct zero_page *zeropage, *hva; struct sw_kernel_info *sw_kernel = &(vm->sw.kernel_info); struct sw_module_info *bootargs_info = &(vm->sw.bootargs_info); struct sw_module_info *ramdisk_info = &(vm->sw.ramdisk_info); - struct zero_page *hva; uint64_t gpa, addr; /* Set zeropage in Linux Guest RAM region just past boot args */ @@ -74,6 +73,14 @@ static uint64_t create_zero_page(struct acrn_vm *vm) /* clear the zeropage */ (void)memset(zeropage, 0U, MEM_2K); +#ifdef CONFIG_MULTIBOOT2 + if (is_sos_vm(vm)) { + struct acrn_multiboot_info *mbi = get_multiboot_info(); + + (void)memcpy_s(&(zeropage->boot_efi_info), sizeof(zeropage->boot_efi_info), + &(mbi->mi_efi_info), sizeof(mbi->mi_efi_info)); + } +#endif /* copy part of the header into the zero page */ hva = (struct zero_page *)gpa2hva(vm, (uint64_t)sw_kernel->kernel_load_addr); (void)memcpy_s(&(zeropage->hdr), sizeof(zeropage->hdr), diff --git a/hypervisor/include/arch/x86/zeropage.h b/hypervisor/include/arch/x86/zeropage.h index 5cad176ae..935407754 100644 --- a/hypervisor/include/arch/x86/zeropage.h +++ b/hypervisor/include/arch/x86/zeropage.h @@ -8,8 +8,23 @@ #define ZEROPAGE_H #include +struct efi_info { + uint32_t efi_loader_signature; /* 0x1d0 */ + uint32_t efi_systab; /* 0x1c4 */ + uint32_t efi_memdesc_size; /* 0x1c8 */ + uint32_t efi_memdesc_version; /* 0x1cc */ + uint32_t efi_memmap; /* 0x1d0 */ + uint32_t efi_memmap_size; /* 0x1d4 */ + uint32_t efi_systab_hi; /* 0x1d8 */ + uint32_t efi_memmap_hi; /* 0x1dc */ +} __packed; + struct zero_page { - uint8_t pad1[0x1e8]; /* 0x000 */ + uint8_t pad0[0x1c0]; /* 0x000 */ + + struct efi_info boot_efi_info; + + uint8_t pad1[0x8]; /* 0x1e0 */ uint8_t e820_nentries; /* 0x1e8 */ uint8_t pad2[0x8]; /* 0x1e9 */