Skip to content

Commit da3d181

Browse files
jsun26intelwenlingz
authored andcommitted
HV: init efi info with multiboot2
Initialize efi info of acrn mbi when boot from multiboot2 protocol, with this patch hypervisor could get host efi info and pass it to Linux zeropage, then make guest Linux possible to boot with efi environment; Tracked-On: #4419 Signed-off-by: Victor Sun <victor.sun@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent 69da024 commit da3d181

File tree

6 files changed

+97
-3
lines changed

6 files changed

+97
-3
lines changed

hypervisor/arch/x86/boot/cpu_primary.S

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ info_req_tag_start:
6363
.long MULTIBOOT2_TAG_TYPE_MMAP
6464
.long MULTIBOOT2_TAG_TYPE_MODULE
6565
.long MULTIBOOT2_TAG_TYPE_ACPI_NEW
66+
.long MULTIBOOT2_TAG_TYPE_EFI64
67+
.long MULTIBOOT2_TAG_TYPE_EFI_MMAP
6668
info_req_tag_end:
6769

6870
.align MULTIBOOT2_TAG_ALIGN
@@ -246,3 +248,9 @@ cpu_primary32_pdt_addr:
246248
.quad address + 0x83
247249
address = address + 0x200000
248250
.endr
251+
252+
#ifdef CONFIG_MULTIBOOT2
253+
.global efiloader_sig
254+
efiloader_sig:
255+
.asciz "EL64"
256+
#endif

hypervisor/boot/include/boot.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,15 @@
1212
#include <multiboot2.h>
1313
#endif
1414
#include <e820.h>
15+
#include <zeropage.h>
1516

1617
#define MAX_BOOTARGS_SIZE 2048U
1718
#define MAX_MODULE_COUNT 4U
1819

20+
/* extended flags for acrn multiboot info from multiboot2 */
21+
#define MULTIBOOT_INFO_HAS_EFI_MMAP 0x00010000U
22+
#define MULTIBOOT_INFO_HAS_EFI64 0x00020000U
23+
1924
struct acrn_multiboot_info {
2025
uint32_t mi_flags; /* the flags is back-compatible with multiboot1 */
2126

@@ -32,11 +37,14 @@ struct acrn_multiboot_info {
3237
struct multiboot_mmap mi_mmap_entry[E820_MAX_ENTRIES];
3338

3439
void *mi_acpi_rsdp;
40+
struct efi_info mi_efi_info;
3541
};
3642

3743
/* boot_regs store the multiboot info magic and address */
3844
extern uint32_t boot_regs[2];
3945

46+
extern char *efiloader_sig;
47+
4048
static inline bool boot_from_multiboot1(void)
4149
{
4250
return ((boot_regs[0] == MULTIBOOT_INFO_MAGIC) && (boot_regs[1] != 0U));

hypervisor/boot/include/multiboot2.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,22 @@ struct multiboot2_tag_new_acpi
126126
uint8_t rsdp[0];
127127
};
128128

129+
struct multiboot2_tag_efi64
130+
{
131+
uint32_t type;
132+
uint32_t size;
133+
uint64_t pointer;
134+
};
135+
136+
struct multiboot2_tag_efi_mmap
137+
{
138+
uint32_t type;
139+
uint32_t size;
140+
uint32_t descr_size;
141+
uint32_t descr_vers;
142+
uint8_t efi_mmap[0];
143+
};
144+
129145
#endif /* ASSEMBLER */
130146

131147
#endif /* MULTIBOOT2_H */

hypervisor/boot/multiboot2.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,37 @@ static void mb2_mods_to_mbi(struct acrn_multiboot_info *mbi,
4949
mbi->mi_flags |= MULTIBOOT_INFO_HAS_MODS;
5050
}
5151

52+
/**
53+
* @pre mbi != NULL && mb2_tag_efi64 != 0
54+
*/
55+
static void mb2_efi64_to_mbi(struct acrn_multiboot_info *mbi, struct multiboot2_tag_efi64 *mb2_tag_efi64)
56+
{
57+
mbi->mi_efi_info.efi_systab = (uint32_t)(uint64_t)mb2_tag_efi64->pointer;
58+
mbi->mi_efi_info.efi_loader_signature = (uint32_t)(uint64_t)efiloader_sig;
59+
mbi->mi_flags |= MULTIBOOT_INFO_HAS_EFI64;
60+
}
61+
62+
/**
63+
* @pre mbi != NULL && mb2_tag_efimmap != 0
64+
*/
65+
static int32_t mb2_efimmap_to_mbi(struct acrn_multiboot_info *mbi, struct multiboot2_tag_efi_mmap *mb2_tag_efimmap)
66+
{
67+
int32_t ret = 0;
68+
69+
mbi->mi_efi_info.efi_memdesc_size = mb2_tag_efimmap->descr_size;
70+
mbi->mi_efi_info.efi_memdesc_version = mb2_tag_efimmap->descr_vers;
71+
mbi->mi_efi_info.efi_memmap = (uint32_t)(uint64_t)mb2_tag_efimmap->efi_mmap;
72+
mbi->mi_efi_info.efi_memmap_size = mb2_tag_efimmap->size - 16U;
73+
mbi->mi_efi_info.efi_memmap_hi = (uint32_t)(((uint64_t)mb2_tag_efimmap->efi_mmap) >> 32U);
74+
if (mbi->mi_efi_info.efi_memmap_hi != 0U) {
75+
pr_err("the efi mmap address should be less than 4G!");
76+
ret = -EINVAL;
77+
} else {
78+
mbi->mi_flags |= MULTIBOOT_INFO_HAS_EFI64;
79+
}
80+
return ret;
81+
}
82+
5283
/**
5384
* @pre mbi != NULL && mb2_info != NULL
5485
*/
@@ -84,6 +115,12 @@ int32_t multiboot2_to_acrn_mbi(struct acrn_multiboot_info *mbi, void *mb2_info)
84115
case MULTIBOOT2_TAG_TYPE_ACPI_NEW:
85116
mbi->mi_acpi_rsdp = ((struct multiboot2_tag_new_acpi *)mb2_tag)->rsdp;
86117
break;
118+
case MULTIBOOT2_TAG_TYPE_EFI64:
119+
mb2_efi64_to_mbi(mbi, (struct multiboot2_tag_efi64 *)mb2_tag);
120+
break;
121+
case MULTIBOOT2_TAG_TYPE_EFI_MMAP:
122+
ret = mb2_efimmap_to_mbi(mbi, (struct multiboot2_tag_efi_mmap *)mb2_tag);
123+
break;
87124
default:
88125
if (mb2_tag->type <= MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR) {
89126
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)
104141
mb2_tag = (struct multiboot2_tag *)((uint8_t *)mb2_tag
105142
+ ((mb2_tag->size + (MULTIBOOT2_INFO_ALIGN - 1U)) & ~(MULTIBOOT2_INFO_ALIGN - 1U)));
106143
}
144+
if ((mbi->mi_flags & (MULTIBOOT_INFO_HAS_EFI64 | MULTIBOOT_INFO_HAS_EFI_MMAP)) == 0U) {
145+
pr_err("no multiboot2 uefi info found!");
146+
}
107147
return ret;
108148
}

hypervisor/common/vm_load.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,10 @@ static uint32_t create_zeropage_e820(struct zero_page *zp, const struct acrn_vm
5858
*/
5959
static uint64_t create_zero_page(struct acrn_vm *vm)
6060
{
61-
struct zero_page *zeropage;
61+
struct zero_page *zeropage, *hva;
6262
struct sw_kernel_info *sw_kernel = &(vm->sw.kernel_info);
6363
struct sw_module_info *bootargs_info = &(vm->sw.bootargs_info);
6464
struct sw_module_info *ramdisk_info = &(vm->sw.ramdisk_info);
65-
struct zero_page *hva;
6665
uint64_t gpa, addr;
6766

6867
/* 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)
7473
/* clear the zeropage */
7574
(void)memset(zeropage, 0U, MEM_2K);
7675

76+
#ifdef CONFIG_MULTIBOOT2
77+
if (is_sos_vm(vm)) {
78+
struct acrn_multiboot_info *mbi = get_multiboot_info();
79+
80+
(void)memcpy_s(&(zeropage->boot_efi_info), sizeof(zeropage->boot_efi_info),
81+
&(mbi->mi_efi_info), sizeof(mbi->mi_efi_info));
82+
}
83+
#endif
7784
/* copy part of the header into the zero page */
7885
hva = (struct zero_page *)gpa2hva(vm, (uint64_t)sw_kernel->kernel_load_addr);
7986
(void)memcpy_s(&(zeropage->hdr), sizeof(zeropage->hdr),

hypervisor/include/arch/x86/zeropage.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,23 @@
88
#define ZEROPAGE_H
99
#include <e820.h>
1010

11+
struct efi_info {
12+
uint32_t efi_loader_signature; /* 0x1d0 */
13+
uint32_t efi_systab; /* 0x1c4 */
14+
uint32_t efi_memdesc_size; /* 0x1c8 */
15+
uint32_t efi_memdesc_version; /* 0x1cc */
16+
uint32_t efi_memmap; /* 0x1d0 */
17+
uint32_t efi_memmap_size; /* 0x1d4 */
18+
uint32_t efi_systab_hi; /* 0x1d8 */
19+
uint32_t efi_memmap_hi; /* 0x1dc */
20+
} __packed;
21+
1122
struct zero_page {
12-
uint8_t pad1[0x1e8]; /* 0x000 */
23+
uint8_t pad0[0x1c0]; /* 0x000 */
24+
25+
struct efi_info boot_efi_info;
26+
27+
uint8_t pad1[0x8]; /* 0x1e0 */
1328
uint8_t e820_nentries; /* 0x1e8 */
1429
uint8_t pad2[0x8]; /* 0x1e9 */
1530

0 commit comments

Comments
 (0)