Skip to content

Commit b669a71

Browse files
jsun26intelwenlingz
authored andcommitted
HV: init mmap info with multiboot2
Initialize mmap info of acrn mbi when boot from multiboot2 protocol, with this patch acrn hv could boot from multiboot2; Tracked-On: #4419 Signed-off-by: Victor Sun <victor.sun@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent d008b72 commit b669a71

File tree

4 files changed

+99
-1
lines changed

4 files changed

+99
-1
lines changed

hypervisor/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ BOOT_S_SRCS += arch/x86/boot/cpu_primary.S
197197
BOOT_S_SRCS += arch/x86/boot/cpu_save_boot_ctx.S
198198
BOOT_S_SRCS += arch/x86/boot/trampoline.S
199199
BOOT_C_SRCS += boot/multiboot.c
200+
ifeq ($(CONFIG_MULTIBOOT2),y)
201+
BOOT_C_SRCS += boot/multiboot2.c
202+
endif
200203
BOOT_C_SRCS += boot/reloc.c
201204

202205
# hardware management component

hypervisor/boot/include/boot.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#define BOOT_H_
99

1010
#include <multiboot.h>
11+
#ifdef CONFIG_MULTIBOOT2
12+
#include <multiboot2.h>
13+
#endif
1114
#include <e820.h>
1215

1316
#define MAX_BOOTARGS_SIZE 2048U
@@ -37,6 +40,15 @@ static inline bool boot_from_multiboot1(void)
3740
return ((boot_regs[0] == MULTIBOOT_INFO_MAGIC) && (boot_regs[1] != 0U));
3841
}
3942

43+
#ifdef CONFIG_MULTIBOOT2
44+
static inline bool boot_from_multiboot2(void)
45+
{
46+
return ((boot_regs[0] == MULTIBOOT2_INFO_MAGIC) && (boot_regs[1] != 0U));
47+
}
48+
49+
int32_t multiboot2_to_acrn_mbi(struct acrn_multiboot_info *mbi, void *mb2_info);
50+
#endif
51+
4052
struct acrn_multiboot_info *get_multiboot_info(void);
4153
int32_t sanitize_multiboot_info(void);
4254
void parse_hv_cmdline(void);

hypervisor/boot/multiboot.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ int32_t sanitize_multiboot_info(void)
5454
} else {
5555
acrn_mbi.mi_flags &= ~MULTIBOOT_INFO_HAS_MODS;
5656
}
57-
57+
#ifdef CONFIG_MULTIBOOT2
58+
} else if (boot_from_multiboot2()) {
59+
ret = multiboot2_to_acrn_mbi(&acrn_mbi, hpa2hva_early((uint64_t)boot_regs[1]));
60+
#endif
5861
} else {
5962
pr_err("no multiboot info found!");
6063
ret = -ENODEV;

hypervisor/boot/multiboot2.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright (C) 2020 Intel Corporation. All rights reserved.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#include <types.h>
8+
#include <errno.h>
9+
#include <boot.h>
10+
#include <pgtable.h>
11+
#include <util.h>
12+
#include <logmsg.h>
13+
14+
/**
15+
* @pre mbi != NULL && mb2_tag_mmap != NULL
16+
*/
17+
static void mb2_mmap_to_mbi(struct acrn_multiboot_info *mbi, struct multiboot2_tag_mmap *mb2_tag_mmap)
18+
{
19+
uint32_t i;
20+
21+
/* multiboot2 mmap tag header occupied 16 bytes */
22+
mbi->mi_mmap_entries = (mb2_tag_mmap->size - 16U) / sizeof(struct multiboot2_mmap_entry);
23+
if (mbi->mi_mmap_entries > E820_MAX_ENTRIES) {
24+
pr_err("Too many E820 entries %d\n", mbi->mi_mmap_entries);
25+
mbi->mi_mmap_entries = E820_MAX_ENTRIES;
26+
}
27+
for (i = 0U; i < mbi->mi_mmap_entries; i++) {
28+
mbi->mi_mmap_entry[i].baseaddr = mb2_tag_mmap->entries[i].addr;
29+
mbi->mi_mmap_entry[i].length = mb2_tag_mmap->entries[i].len;
30+
mbi->mi_mmap_entry[i].type = mb2_tag_mmap->entries[i].type;
31+
}
32+
mbi->mi_flags |= MULTIBOOT_INFO_HAS_MMAP;
33+
}
34+
35+
/**
36+
* @pre mbi != NULL && mb2_info != NULL
37+
*/
38+
int32_t multiboot2_to_acrn_mbi(struct acrn_multiboot_info *mbi, void *mb2_info)
39+
{
40+
int32_t ret = 0;
41+
struct multiboot2_tag *mb2_tag, *mb2_tag_end;
42+
uint32_t mb2_info_size = *(uint32_t *)mb2_info;
43+
44+
/* The start part of multiboot2 info: total mbi size (4 bytes), reserved (4 bytes) */
45+
mb2_tag = (struct multiboot2_tag *)((uint8_t *)mb2_info + 8U);
46+
mb2_tag_end = (struct multiboot2_tag *)((uint8_t *)mb2_info + mb2_info_size);
47+
48+
while ((mb2_tag->type != MULTIBOOT2_TAG_TYPE_END) && (mb2_tag < mb2_tag_end)) {
49+
if (mb2_tag->size == 0U) {
50+
pr_err("the multiboot2 tag size should not be 0!");
51+
ret = -EINVAL;
52+
break;
53+
}
54+
55+
switch (mb2_tag->type) {
56+
case MULTIBOOT2_TAG_TYPE_MMAP:
57+
mb2_mmap_to_mbi(mbi, (struct multiboot2_tag_mmap *)mb2_tag);
58+
break;
59+
default:
60+
if (mb2_tag->type <= MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR) {
61+
pr_warn("unhandled multiboot2 tag type: %d", mb2_tag->type);
62+
} else {
63+
pr_err("unknown multiboot2 tag type: %d", mb2_tag->type);
64+
ret = -EINVAL;
65+
}
66+
break;
67+
}
68+
if (ret != 0) {
69+
pr_err("multiboot2 info format error!");
70+
break;
71+
}
72+
/*
73+
* tag->size is not including padding whearas each tag
74+
* start at 8-bytes aligned address.
75+
*/
76+
mb2_tag = (struct multiboot2_tag *)((uint8_t *)mb2_tag
77+
+ ((mb2_tag->size + (MULTIBOOT2_INFO_ALIGN - 1U)) & ~(MULTIBOOT2_INFO_ALIGN - 1U)));
78+
}
79+
return ret;
80+
}

0 commit comments

Comments
 (0)