HV: modularization: add boot.c to wrap multiboot module

Add a wrapper API init_acrn_boot_info() so that it could be used to boot
ACRN with any boot protocol;

Another change is change term of multiboot1 to multiboot because there is
no such term officially;

Tracked-On: #5661

Signed-off-by: Victor Sun <victor.sun@intel.com>
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
This commit is contained in:
Victor Sun 2021-05-21 15:28:49 +08:00 committed by wenlingz
parent c9841d7618
commit fd75fcdef0
7 changed files with 177 additions and 132 deletions

View File

@ -194,6 +194,7 @@ endif
# platform boot component
BOOT_S_SRCS += arch/x86/boot/cpu_primary.S
BOOT_S_SRCS += arch/x86/boot/trampoline.S
BOOT_C_SRCS += boot/boot.c
BOOT_C_SRCS += boot/multiboot/multiboot.c
ifeq ($(CONFIG_MULTIBOOT2),y)
BOOT_C_SRCS += boot/multiboot/multiboot2.c

View File

@ -91,12 +91,12 @@ void init_primary_pcpu(void)
/* Clear BSS */
(void)memset(&ld_bss_start, 0U, (size_t)(&ld_bss_end - &ld_bss_start));
init_acrn_boot_info(boot_regs[0], boot_regs[1]);
init_acrn_boot_info(boot_regs);
init_debug_pre();
if (sanitize_acrn_boot_info(boot_regs[0], boot_regs[1]) != 0) {
panic("Multiboot info error!");
if (sanitize_acrn_boot_info(get_acrn_boot_info()) != 0) {
panic("Sanitize boot info failed!");
}
init_pcpu_pre(true);

79
hypervisor/boot/boot.c Normal file
View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2021 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <types.h>
#include <errno.h>
#include <asm/pgtable.h>
#include <multiboot.h>
#include <rtl.h>
#include <logmsg.h>
#include "multiboot/multiboot_priv.h"
static struct acrn_boot_info acrn_bi = { 0U };
static char boot_protocol_name[16U] = { 0 };
void init_acrn_boot_info(uint32_t *registers)
{
if (init_multiboot_info(registers) == 0) {
strncpy_s(boot_protocol_name, 16U, "Multiboot", 16U);
#ifdef CONFIG_MULTIBOOT2
} else if (init_multiboot2_info(registers) == 0) {
strncpy_s(boot_protocol_name, 16U, "Multiboot2", 16U);
#endif
}
}
int32_t sanitize_acrn_boot_info(struct acrn_boot_info *abi)
{
int32_t abi_status = 0;
if (abi->mi_mmap_entries != 0U) {
abi->mi_flags |= MULTIBOOT_INFO_HAS_MMAP;
} else {
abi->mi_flags &= ~MULTIBOOT_INFO_HAS_MMAP;
}
if (abi->mi_mods_count != 0U) {
abi->mi_flags |= MULTIBOOT_INFO_HAS_MODS;
} else {
abi->mi_flags &= ~MULTIBOOT_INFO_HAS_MODS;
}
if ((abi->mi_flags & MULTIBOOT_INFO_HAS_MODS) == 0U) {
pr_err("no multiboot module info found");
abi_status = -EINVAL;
}
if ((abi->mi_flags & MULTIBOOT_INFO_HAS_MMAP) == 0U) {
pr_err("wrong multiboot flags: 0x%08x", abi->mi_flags);
abi_status = -EINVAL;
}
#ifdef CONFIG_MULTIBOOT2
if ((abi->mi_flags & (MULTIBOOT_INFO_HAS_EFI64 | MULTIBOOT_INFO_HAS_EFI_MMAP)) == 0U) {
pr_err("no multiboot2 uefi info found!");
}
#endif
if (abi->mi_loader_name[0] == '\0') {
pr_err("no bootloader name found!");
abi_status = -EINVAL;
} else {
printf("%s Bootloader: %s\n", boot_protocol_name, abi->mi_loader_name);
}
return abi_status;
}
/*
* @post retval != NULL
* @post retval->mi_flags & MULTIBOOT_INFO_HAS_MMAP != 0U
* @post (retval->mi_mmap_entries > 0U) && (retval->mi_mmap_entries <= MAX_MMAP_ENTRIES)
*/
struct acrn_boot_info *get_acrn_boot_info(void)
{
return &acrn_bi;
}

View File

@ -32,22 +32,23 @@ struct acrn_boot_info {
const char *mi_loader_name;
uint32_t mi_mods_count;
const void *mi_mods_va;
struct multiboot_module mi_mods[MAX_MODULE_NUM];
uint32_t mi_drives_length;
uint32_t mi_drives_addr;
uint32_t mi_mmap_entries;
const void *mi_mmap_va;
struct multiboot_mmap mi_mmap_entry[MAX_MMAP_ENTRIES];
const void *mi_acpi_rsdp_va;
struct efi_info mi_efi_info;
};
void init_acrn_boot_info(uint32_t magic, uint32_t info);
int32_t sanitize_acrn_boot_info(uint32_t magic, uint32_t info);
int32_t init_multiboot_info(uint32_t *registers);
int32_t init_multiboot2_info(uint32_t *registers);
void init_acrn_boot_info(uint32_t *registers);
int32_t sanitize_acrn_boot_info(struct acrn_boot_info *abi);
struct acrn_boot_info *get_acrn_boot_info(void);
#endif /* ASSEMBLER */

View File

@ -8,126 +8,62 @@
#include <errno.h>
#include <asm/pgtable.h>
#include <multiboot.h>
#include <rtl.h>
#include <logmsg.h>
#include "multiboot_priv.h"
static struct acrn_boot_info acrn_bi = { 0U };
static int32_t abi_status;
void init_acrn_boot_info(uint32_t magic, uint32_t info)
{
if (boot_from_multiboot1(magic, info)) {
struct multiboot_info *mbi = (struct multiboot_info *)(hpa2hva_early((uint64_t)info));
acrn_bi.mi_flags = mbi->mi_flags;
acrn_bi.mi_drives_addr = mbi->mi_drives_addr;
acrn_bi.mi_drives_length = mbi->mi_drives_length;
acrn_bi.mi_cmdline = (char *)hpa2hva_early((uint64_t)mbi->mi_cmdline);
acrn_bi.mi_loader_name = (char *)hpa2hva_early((uint64_t)mbi->mi_loader_name);
acrn_bi.mi_mmap_entries = mbi->mi_mmap_length / sizeof(struct multiboot_mmap);
acrn_bi.mi_mmap_va = (struct multiboot_mmap *)hpa2hva_early((uint64_t)mbi->mi_mmap_addr);
acrn_bi.mi_mods_count = mbi->mi_mods_count;
acrn_bi.mi_mods_va = (struct multiboot_module *)hpa2hva_early((uint64_t)mbi->mi_mods_addr);
abi_status = 0;
#ifdef CONFIG_MULTIBOOT2
} else if (boot_from_multiboot2(magic)) {
abi_status = multiboot2_to_acrn_bi(&acrn_bi, hpa2hva_early((uint64_t)info));
#endif
} else {
abi_status = -ENODEV;
}
}
int32_t sanitize_acrn_boot_info(uint32_t magic, uint32_t info)
{
if ((acrn_bi.mi_mmap_entries != 0U) && (acrn_bi.mi_mmap_va != NULL)) {
if (acrn_bi.mi_mmap_entries > MAX_MMAP_ENTRIES) {
pr_err("Too many E820 entries %d\n", acrn_bi.mi_mmap_entries);
acrn_bi.mi_mmap_entries = MAX_MMAP_ENTRIES;
}
if (boot_from_multiboot1(magic, info)) {
uint32_t mmap_entry_size = sizeof(struct multiboot_mmap);
(void)memcpy_s((void *)(&acrn_bi.mi_mmap_entry[0]),
(acrn_bi.mi_mmap_entries * mmap_entry_size),
(const void *)acrn_bi.mi_mmap_va,
(acrn_bi.mi_mmap_entries * mmap_entry_size));
}
#ifdef CONFIG_MULTIBOOT2
if (boot_from_multiboot2(magic)) {
uint32_t i;
struct multiboot2_mmap_entry *mb2_mmap = (struct multiboot2_mmap_entry *)acrn_bi.mi_mmap_va;
for (i = 0U; i < acrn_bi.mi_mmap_entries; i++) {
acrn_bi.mi_mmap_entry[i].baseaddr = (mb2_mmap + i)->addr;
acrn_bi.mi_mmap_entry[i].length = (mb2_mmap + i)->len;
acrn_bi.mi_mmap_entry[i].type = (mb2_mmap + i)->type;
}
}
#endif
acrn_bi.mi_flags |= MULTIBOOT_INFO_HAS_MMAP;
} else {
acrn_bi.mi_flags &= ~MULTIBOOT_INFO_HAS_MMAP;
}
if (acrn_bi.mi_mods_count > MAX_MODULE_NUM) {
pr_err("Too many multiboot modules %d\n", acrn_bi.mi_mods_count);
acrn_bi.mi_mods_count = MAX_MODULE_NUM;
}
if (acrn_bi.mi_mods_count != 0U) {
if (boot_from_multiboot1(magic, info) && (acrn_bi.mi_mods_va != NULL)) {
(void)memcpy_s((void *)(&acrn_bi.mi_mods[0]),
(acrn_bi.mi_mods_count * sizeof(struct multiboot_module)),
(const void *)acrn_bi.mi_mods_va,
(acrn_bi.mi_mods_count * sizeof(struct multiboot_module)));
}
acrn_bi.mi_flags |= MULTIBOOT_INFO_HAS_MODS;
} else {
acrn_bi.mi_flags &= ~MULTIBOOT_INFO_HAS_MODS;
}
if ((acrn_bi.mi_flags & MULTIBOOT_INFO_HAS_MODS) == 0U) {
pr_err("no multiboot module info found");
abi_status = -EINVAL;
}
if ((acrn_bi.mi_flags & MULTIBOOT_INFO_HAS_MMAP) == 0U) {
pr_err("wrong multiboot flags: 0x%08x", acrn_bi.mi_flags);
abi_status = -EINVAL;
}
#ifdef CONFIG_MULTIBOOT2
if (boot_from_multiboot2(magic)) {
if (acrn_bi.mi_efi_info.efi_memmap_hi != 0U) {
pr_err("the EFI mmap address should be less than 4G!");
acrn_bi.mi_flags &= ~MULTIBOOT_INFO_HAS_EFI_MMAP;
abi_status = -EINVAL;
}
if ((acrn_bi.mi_flags & (MULTIBOOT_INFO_HAS_EFI64 | MULTIBOOT_INFO_HAS_EFI_MMAP)) == 0U) {
pr_err("no multiboot2 uefi info found!");
}
}
#endif
if (acrn_bi.mi_loader_name[0] == '\0') {
pr_err("no bootloader name found!");
abi_status = -EINVAL;
} else {
printf("Multiboot%s Bootloader: %s\n", boot_from_multiboot1(magic, info) ? "" : "2", acrn_bi.mi_loader_name);
}
return abi_status;
}
/*
* @post retval != NULL
* @post retval->mi_flags & MULTIBOOT_INFO_HAS_MMAP != 0U
* @post (retval->mi_mmap_entries > 0U) && (retval->mi_mmap_entries <= MAX_MMAP_ENTRIES)
/**
* @pre abi != NULL
*/
struct acrn_boot_info *get_acrn_boot_info(void)
{
return &acrn_bi;
int32_t multiboot_to_acrn_bi(struct acrn_boot_info *abi, void *mb_info) {
struct multiboot_info *mbi = (struct multiboot_info *)(hpa2hva_early((uint64_t)mb_info));
struct multiboot_mmap *mmap = (struct multiboot_mmap *)hpa2hva_early((uint64_t)mbi->mi_mmap_addr);
struct multiboot_module *mods = (struct multiboot_module *)hpa2hva_early((uint64_t)mbi->mi_mods_addr);
abi->mi_flags = mbi->mi_flags;
abi->mi_cmdline = (char *)hpa2hva_early((uint64_t)mbi->mi_cmdline);
abi->mi_loader_name = (char *)hpa2hva_early((uint64_t)mbi->mi_loader_name);
abi->mi_mmap_entries = mbi->mi_mmap_length / sizeof(struct multiboot_mmap);
abi->mi_mods_count = mbi->mi_mods_count;
if (((mbi->mi_flags & MULTIBOOT_INFO_HAS_MMAP) != 0U) && (abi->mi_mmap_entries != 0U) && (mmap != NULL)) {
if (abi->mi_mmap_entries > MAX_MMAP_ENTRIES) {
abi->mi_mmap_entries = MAX_MMAP_ENTRIES;
}
(void)memcpy_s((void *)(&abi->mi_mmap_entry[0]),
(abi->mi_mmap_entries * sizeof(struct multiboot_mmap)),
mmap, (abi->mi_mmap_entries * sizeof(struct multiboot_mmap)));
} else {
abi->mi_mmap_entries = 0U;
}
if (((mbi->mi_flags & MULTIBOOT_INFO_HAS_MODS) != 0U) && (abi->mi_mods_count != 0U) && (mods != NULL)) {
if (abi->mi_mods_count > MAX_MODULE_NUM) {
abi->mi_mods_count = MAX_MODULE_NUM;
}
(void)memcpy_s((void *)(&abi->mi_mods[0]),
(abi->mi_mods_count * sizeof(struct multiboot_module)),
mods, (abi->mi_mods_count * sizeof(struct multiboot_module)));
} else {
abi->mi_mods_count = 0U;
}
return 0;
}
int32_t init_multiboot_info(uint32_t *registers)
{
int32_t ret = -ENODEV;
uint32_t magic = registers[0];
uint32_t info = registers[1];
struct acrn_boot_info *abi = get_acrn_boot_info();
if (boot_from_multiboot(magic, info)) {
if (multiboot_to_acrn_bi(abi, hpa2hva_early((uint64_t)info)) == 0) {
ret = 0;
}
}
return ret;
}

View File

@ -15,9 +15,20 @@
*/
static void mb2_mmap_to_abi(struct acrn_boot_info *abi, const struct multiboot2_tag_mmap *mb2_tag_mmap)
{
uint32_t i;
struct multiboot2_mmap_entry *mb2_mmap = (struct multiboot2_mmap_entry *)mb2_tag_mmap->entries;
/* multiboot2 mmap tag header occupied 16 bytes */
abi->mi_mmap_entries = (mb2_tag_mmap->size - 16U) / sizeof(struct multiboot2_mmap_entry);
abi->mi_mmap_va = (struct multiboot2_mmap_entry *)mb2_tag_mmap->entries;
if (abi->mi_mmap_entries > MAX_MMAP_ENTRIES) {
abi->mi_mmap_entries = MAX_MMAP_ENTRIES;
}
for (i = 0U; i < abi->mi_mmap_entries; i++) {
abi->mi_mmap_entry[i].baseaddr = (mb2_mmap + i)->addr;
abi->mi_mmap_entry[i].length = (mb2_mmap + i)->len;
abi->mi_mmap_entry[i].type = (mb2_mmap + i)->type;
}
}
/**
@ -122,3 +133,18 @@ int32_t multiboot2_to_acrn_bi(struct acrn_boot_info *abi, void *mb2_info)
return ret;
}
int32_t init_multiboot2_info(uint32_t *registers)
{
int32_t ret = -ENODEV;
uint32_t magic = registers[0];
uint32_t info = registers[1];
struct acrn_boot_info *abi = get_acrn_boot_info();
if (boot_from_multiboot2(magic)) {
if (multiboot2_to_acrn_bi(abi, hpa2hva_early((uint64_t)info)) == 0) {
ret = 0;
}
}
return ret;
}

View File

@ -11,6 +11,13 @@
#define MULTIBOOT_INFO_HAS_EFI_MMAP 0x00010000U
#define MULTIBOOT_INFO_HAS_EFI64 0x00020000U
static inline bool boot_from_multiboot(uint32_t magic, uint32_t info)
{
return ((magic == MULTIBOOT_INFO_MAGIC) && (info != 0U));
}
int32_t multiboot_to_acrn_bi(struct acrn_boot_info *abi, void *mb_info);
#ifdef CONFIG_MULTIBOOT2
/*
* @post boot_regs[1] stores the address pointer that point to a valid multiboot2 info
@ -32,9 +39,4 @@ static inline bool boot_from_multiboot2(uint32_t magic)
int32_t multiboot2_to_acrn_bi(struct acrn_boot_info *abi, void *mb2_info);
#endif
static inline bool boot_from_multiboot1(uint32_t magic, uint32_t info)
{
return ((magic == MULTIBOOT_INFO_MAGIC) && (info != 0U));
}
#endif /* MULTIBOOT_PRIV_H */