diff --git a/hypervisor/Makefile b/hypervisor/Makefile index 0f3351857..5acaa9177 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -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 diff --git a/hypervisor/arch/x86/init.c b/hypervisor/arch/x86/init.c index 30f6bdf3a..36c1fcede 100644 --- a/hypervisor/arch/x86/init.c +++ b/hypervisor/arch/x86/init.c @@ -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); diff --git a/hypervisor/boot/boot.c b/hypervisor/boot/boot.c new file mode 100644 index 000000000..c3b8ef93d --- /dev/null +++ b/hypervisor/boot/boot.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021 Intel Corporation. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +static struct acrn_boot_info acrn_bi = { 0U }; + +void init_acrn_boot_info(uint32_t *registers) +{ + (void)init_multiboot_info(registers); + /* TODO: add more boot protocol support here */ +} + +int32_t sanitize_acrn_boot_info(struct acrn_boot_info *abi) +{ + int32_t abi_status = 0; + + if (abi->mi_mods_count == 0U) { + pr_err("no boot module info found"); + abi_status = -EINVAL; + } + + if (abi->mi_mmap_entries == 0U) { + pr_err("no boot mmap info found"); + abi_status = -EINVAL; + } + + if ((abi->mi_efi_info.efi_systab == 0U) && (abi->mi_efi_info.efi_systab_hi == 0U)) { + pr_err("no uefi info found!"); + } + + if (abi->mi_loader_name[0] == '\0') { + pr_err("no bootloader name found!"); + abi_status = -EINVAL; + } else { + printf("%s Bootloader: %s\n", abi->protocol_name, abi->mi_loader_name); + } + + return abi_status; +} + +/* + * @post retval != NULL + */ +struct acrn_boot_info *get_acrn_boot_info(void) +{ + return &acrn_bi; +} diff --git a/hypervisor/boot/include/boot.h b/hypervisor/boot/include/boot.h index b39f3ae89..71ab74f84 100644 --- a/hypervisor/boot/include/boot.h +++ b/hypervisor/boot/include/boot.h @@ -16,6 +16,8 @@ #define MAX_BOOTARGS_SIZE 2048U +#define MAX_PROTOCOL_NAME_SIZE 16U + /* The modules in multiboot are: Pre-launched VM: kernel/ramdisk/acpi; SOS VM: kernel/ramdisk */ #define MAX_MODULE_NUM (3U * PRE_VM_NUM + 2U * SOS_VM_NUM) @@ -24,26 +26,28 @@ struct acrn_boot_info { + char protocol_name[MAX_PROTOCOL_NAME_SIZE]; + const char *mi_cmdline; 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); + +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 /* BOOT_H */ diff --git a/hypervisor/boot/multiboot/multiboot.c b/hypervisor/boot/multiboot/multiboot.c index b940775bb..21173898f 100644 --- a/hypervisor/boot/multiboot/multiboot.c +++ b/hypervisor/boot/multiboot/multiboot.c @@ -8,108 +8,71 @@ #include #include #include -#include -#include #include "multiboot_priv.h" -static struct acrn_boot_info acrn_bi = { 0U }; +/** + * @pre abi != NULL + */ +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); -static int32_t abi_status; + 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; -void init_acrn_boot_info(uint32_t magic, uint32_t info) + 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) { - if (boot_from_multiboot1(magic, info)) { - struct multiboot_info *mbi = (struct multiboot_info *)(hpa2hva_early((uint64_t)info)); + int32_t ret = -ENODEV; + uint32_t magic = registers[0]; + uint32_t info = registers[1]; + struct acrn_boot_info *abi = get_acrn_boot_info(); - 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; + if (boot_from_multiboot(magic, info)) { + if (multiboot_to_acrn_bi(abi, hpa2hva_early((uint64_t)info)) == 0) { + strncpy_s(abi->protocol_name, MAX_PROTOCOL_NAME_SIZE, + "Multiboot", (MAX_PROTOCOL_NAME_SIZE - 1U)); + ret = 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; - } + if (multiboot2_to_acrn_bi(abi, hpa2hva_early((uint64_t)info)) == 0) { + strncpy_s(abi->protocol_name, MAX_PROTOCOL_NAME_SIZE, + "Multiboot2", (MAX_PROTOCOL_NAME_SIZE - 1U)); + ret = 0; } #endif - } else { - abi_status = -EINVAL; } - - 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))); - } - } else { - pr_err("no multiboot module info found"); - 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!"); - abi_status = -EINVAL; - } - } -#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_mmap_entries > 0U) && (retval->mi_mmap_entries <= MAX_MMAP_ENTRIES) - */ -struct acrn_boot_info *get_acrn_boot_info(void) -{ - return &acrn_bi; + return ret; } diff --git a/hypervisor/boot/multiboot/multiboot2.c b/hypervisor/boot/multiboot/multiboot2.c index 7ca61faaf..83882f1a3 100644 --- a/hypervisor/boot/multiboot/multiboot2.c +++ b/hypervisor/boot/multiboot/multiboot2.c @@ -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; + } } /** diff --git a/hypervisor/boot/multiboot/multiboot_priv.h b/hypervisor/boot/multiboot/multiboot_priv.h index e5427dc39..ede6b669a 100644 --- a/hypervisor/boot/multiboot/multiboot_priv.h +++ b/hypervisor/boot/multiboot/multiboot_priv.h @@ -28,7 +28,7 @@ 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) +static inline bool boot_from_multiboot(uint32_t magic, uint32_t info) { return ((magic == MULTIBOOT_INFO_MAGIC) && (info != 0U)); }