From e36a61a85d91f49a0230e05afd15aa7f1d1c9725 Mon Sep 17 00:00:00 2001 From: Zhang Chen Date: Mon, 31 Jul 2023 18:12:00 +0800 Subject: [PATCH] HV: elf_loader: Prepare to extend elf loader for multiboot protocol For the TEE and android kernelflinger boot requirements, elf_loader need to support the multiboot protocol. This patch define a memory block to store ELF format VM load params in guest address space. At the same time, prepare the elf cmdline field and memory map for the guest kernel. Tracked-On: #8642 Signed-off-by: Victor Sun Signed-off-by: Zhang Chen Reviewed-by: Junjie Mao --- hypervisor/boot/guest/elf_loader.c | 58 ++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/hypervisor/boot/guest/elf_loader.c b/hypervisor/boot/guest/elf_loader.c index 71d4993061..ebb7bca7c6 100644 --- a/hypervisor/boot/guest/elf_loader.c +++ b/hypervisor/boot/guest/elf_loader.c @@ -5,9 +5,39 @@ */ #include +#include +#include #include #include #include +#include + +/* Define a memory block to store ELF format VM load params in guest address space + * The params including: + * MISC info: 1KB + * including: Init GDT(40 bytes),ACRN ELF loader name(20 bytes), ACPI RSDP table(36 bytes). + * Multiboot info : 4KB + * Boot cmdline : 2KB + * memory map : 20KB (enough to put memory entries for multiboot 0.6.96 or multiboot 2.0) + * Each param should keep 8byte aligned and the total region should be able to put below MEM_1M. + * The total params size is: + * (MEM_1K + MEM_4K + MEM_2K + 20K) = 27KB + */ + +struct elf_boot_para { + char init_gdt[40]; + char loader_name[20]; + struct acpi_table_rsdp rsdp; + struct multiboot_info mb_info; + char cmdline[MEM_2K]; + char mmap[MEM_4K * 5U]; +} __aligned(8); + +int32_t prepare_elf_cmdline(struct acrn_vm *vm, uint64_t param_cmd_gpa) +{ + return copy_to_gpa(vm, vm->sw.bootargs_info.src_addr, param_cmd_gpa, + vm->sw.bootargs_info.size); +} /** * @pre vm != NULL @@ -176,17 +206,25 @@ static int32_t load_elf(struct acrn_vm *vm) int32_t elf_loader(struct acrn_vm *vm) { - uint64_t vgdt_gpa = 0x800; - + int32_t ret = -ENOMEM; + /* Get primary vcpu */ + struct acrn_vcpu *vcpu = vcpu_from_vid(vm, BSP_CPU_ID); /* - * TODO: - * - We need to initialize the guest BSP(boot strap processor) registers according to - * guest boot mode (real mode vs protect mode) - * - The memory layout usage is unclear, only GDT might be needed as its boot param. - * currently we only support Zephyr which has no needs on cmdline/e820/efimmap/etc. - * hardcode the vGDT GPA to 0x800 where is not used by Zephyr so far; + * Assuming the guest elf would not load content to GPA space under + * VIRT_RSDP_ADDR, and guest gpa load space is sure under address + * we prepared in ve820.c. In the future, need to check each + * ELF load entry according to ve820 if relocation is not supported. */ - init_vcpu_protect_mode_regs(vcpu_from_vid(vm, BSP_CPU_ID), vgdt_gpa); + uint64_t load_params_gpa = find_space_from_ve820(vm, sizeof(struct elf_boot_para), + MEM_4K, VIRT_RSDP_ADDR); + + if (load_params_gpa != INVALID_GPA) { + /* We boot ELF Image from protected mode directly */ + init_vcpu_protect_mode_regs(vcpu, load_params_gpa + + offsetof(struct elf_boot_para, init_gdt)); - return load_elf(vm); + ret = load_elf(vm); + } + + return ret; }