Skip to content

Commit

Permalink
HV: elf_loader: enable guest multiboot support
Browse files Browse the repository at this point in the history
This patch enable guest multiboot support. Try to find
the multiboot header in normal elf guest image.
Introduce the multiboot related basic functions to
initialize multiboot structure. Including
prepare_multiboot_mmap, prepare_loader_name and
find_img_multiboot_header.

Tracked-On: projectacrn#8642

Signed-off-by: Victor Sun <[email protected]>
Signed-off-by: Zhang Chen <[email protected]>
Reviewed-by: Junjie Mao <[email protected]>
  • Loading branch information
zhangckid committed Jul 3, 2024
1 parent 2f400ba commit 3b6e4b3
Showing 1 changed file with 121 additions and 3 deletions.
124 changes: 121 additions & 3 deletions hypervisor/boot/guest/elf_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,41 @@ int32_t prepare_elf_cmdline(struct acrn_vm *vm, uint64_t param_cmd_gpa)
vm->sw.bootargs_info.size);
}

uint32_t prepare_multiboot_mmap(struct acrn_vm *vm, uint64_t param_mmap_gpa)
{
uint32_t i, mmap_length = 0U;
struct multiboot_mmap mmap_entry;
uint64_t mmap_gpa = param_mmap_gpa;

for (i = 0U; i < vm->e820_entry_num; i++) {
mmap_entry.size = 20U;
mmap_entry.baseaddr = vm->e820_entries[i].baseaddr;
mmap_entry.length = vm->e820_entries[i].length;
mmap_entry.type = vm->e820_entries[i].type;
if (mmap_entry.type > MULTIBOOT_MEMORY_BADRAM) {
mmap_entry.type = MULTIBOOT_MEMORY_RESERVED;
}

if (copy_to_gpa(vm, &mmap_entry, mmap_gpa,
sizeof(struct multiboot_mmap)) != 0U) {
mmap_length = 0U;
break;
}
mmap_gpa += sizeof(struct multiboot_mmap);
mmap_length += sizeof(struct multiboot_mmap);
}

return mmap_length;
}

uint32_t prepare_loader_name(struct acrn_vm *vm, uint64_t param_ldrname_gpa)
{
char loader_name[MAX_LOADER_NAME_SIZE] = "ACRN ELF LOADER";

return (copy_to_gpa(vm, (void *)loader_name, param_ldrname_gpa,
MAX_LOADER_NAME_SIZE));
}

/**
* @pre vm != NULL
* must run in stac/clac context
Expand Down Expand Up @@ -204,9 +239,42 @@ static int32_t load_elf(struct acrn_vm *vm)
return ret;
}

struct multiboot_header *find_img_multiboot_header(struct acrn_vm *vm)
{
uint16_t i, j;
struct multiboot_header *ret = NULL;
uint32_t *p = (uint32_t *)vm->sw.kernel_info.kernel_src_addr;

/* Scan the first 8k to detect whether the elf needs multboot info prepared. */
for (i = 0U; i <= (((MEM_4K * 2U) / sizeof(uint32_t)) - 3U); i++) {
if (p[i] == MULTIBOOT_HEADER_MAGIC) {
uint32_t sum = 0U;

/* According to multiboot spec 0.6.96 sec 3.1.2.
* There are three u32:
* offset field
* 0 multiboot_header_magic
* 4 flags
* 8 checksum
* The sum of these three u32 should be u32 zero.
*/
for (j = 0U; j < 3U; j++) {
sum += p[j + i];
}

if (0U == sum) {
ret = (struct multiboot_header *)(p + i);
break;
}
}
}
return ret;
}

int32_t elf_loader(struct acrn_vm *vm)
{
int32_t ret = -ENOMEM;
int32_t ret = 0;
struct multiboot_header *mb_hdr;
/* Get primary vcpu */
struct acrn_vcpu *vcpu = vcpu_from_vid(vm, BSP_CPU_ID);
/*
Expand All @@ -222,9 +290,59 @@ int32_t elf_loader(struct acrn_vm *vm)
/* We boot ELF Image from protected mode directly */
init_vcpu_protect_mode_regs(vcpu, load_params_gpa +
offsetof(struct elf_boot_para, init_gdt));
stac();
mb_hdr = find_img_multiboot_header(vm);
clac();
if (mb_hdr != NULL) {
uint32_t mmap_length = 0U;
struct multiboot_info mb_info;

ret = load_elf(vm);
}
stac();
if ((mb_hdr->flags & MULTIBOOT_HEADER_NEED_MEMINFO) != 0U) {
mmap_length = prepare_multiboot_mmap(vm, load_params_gpa +
offsetof(struct elf_boot_para, mmap));
}

if (mmap_length != 0U) {
mb_info.mi_flags |= MULTIBOOT_INFO_HAS_MMAP;
mb_info.mi_mmap_addr = (uint32_t)(load_params_gpa +
offsetof(struct elf_boot_para, mmap));
mb_info.mi_mmap_length = mmap_length;
}
ret = prepare_elf_cmdline(vm, load_params_gpa +
offsetof(struct elf_boot_para, cmdline));
if (ret == 0) {
mb_info.mi_flags |= MULTIBOOT_INFO_HAS_CMDLINE;
mb_info.mi_cmdline = load_params_gpa +
offsetof(struct elf_boot_para, cmdline);
ret = prepare_loader_name(vm, load_params_gpa +
offsetof(struct elf_boot_para, loader_name));
}

if (ret == 0) {
mb_info.mi_flags |= MULTIBOOT_INFO_HAS_LOADER_NAME;
mb_info.mi_loader_name = load_params_gpa +
offsetof(struct elf_boot_para, loader_name);
ret = copy_to_gpa(vm, (void *)&mb_info, load_params_gpa +
offsetof(struct elf_boot_para, mb_info),
sizeof(struct multiboot_info));
}

if (ret == 0) {
vcpu_set_gpreg(vcpu, CPU_REG_RAX, MULTIBOOT_INFO_MAGIC);
vcpu_set_gpreg(vcpu, CPU_REG_RBX, load_params_gpa +
offsetof(struct elf_boot_para, mb_info));
/* other vcpu regs should have satisfied multiboot requirement already. */
}
clac();
}
/*
* elf_loader need support non-multiboot header image
* at the same time.
*/
if (ret == 0) {
ret = load_elf(vm);
}
}
return ret;
}

0 comments on commit 3b6e4b3

Please sign in to comment.