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 18fcf7267..1653a024c 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..e71b3160b --- /dev/null +++ b/hypervisor/boot/boot.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2021 Intel Corporation. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/hypervisor/boot/include/multiboot.h b/hypervisor/boot/include/multiboot.h index c6b56b118..91d147f4d 100644 --- a/hypervisor/boot/include/multiboot.h +++ b/hypervisor/boot/include/multiboot.h @@ -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 */ diff --git a/hypervisor/boot/multiboot/multiboot.c b/hypervisor/boot/multiboot/multiboot.c index ea5a2b826..95298affa 100644 --- a/hypervisor/boot/multiboot/multiboot.c +++ b/hypervisor/boot/multiboot/multiboot.c @@ -8,126 +8,62 @@ #include #include #include -#include -#include #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; } diff --git a/hypervisor/boot/multiboot/multiboot2.c b/hypervisor/boot/multiboot/multiboot2.c index 8e73a0a80..d09468c03 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; + } } /** @@ -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; +} diff --git a/hypervisor/boot/multiboot/multiboot_priv.h b/hypervisor/boot/multiboot/multiboot_priv.h index e348b23ef..4edfbbb1d 100644 --- a/hypervisor/boot/multiboot/multiboot_priv.h +++ b/hypervisor/boot/multiboot/multiboot_priv.h @@ -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 */