feat(arm64): higher-half kernel, early MMU in boot, and VMM
This commit is contained in:
@@ -129,20 +129,18 @@ static efi_status_t parse_elf_headers(efi_physical_address_t kernel_addr) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static efi_status_t load_elf_segments(efi_physical_address_t kernel_addr, efi_file_handle_t* kernel_file) {
|
||||
static efi_status_t load_elf_segments(efi_physical_address_t kernel_addr, efi_file_handle_t* kernel_file, efi_physical_address_t* out_phys_entry) {
|
||||
Elf64_Ehdr* elf_header = (Elf64_Ehdr*)kernel_addr;
|
||||
*out_phys_entry = 0;
|
||||
|
||||
for (int i = 0; i < elf_header->e_phnum; i++) {
|
||||
Elf64_Phdr* phdr = (Elf64_Phdr*)(kernel_addr + elf_header->e_phoff + i * elf_header->e_phentsize);
|
||||
|
||||
if (phdr->p_type != PT_LOAD) continue;
|
||||
if (phdr->p_vaddr < 0x40000000) {
|
||||
print(WSTR("Skipping low/weird segment\r\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
uintn_t pages = (phdr->p_memsz + 0xFFF) / 0x1000;
|
||||
efi_physical_address_t segment_addr = phdr->p_vaddr;
|
||||
|
||||
efi_physical_address_t segment_addr = phdr->p_paddr;
|
||||
|
||||
efi_status_t status = gBS->AllocatePages(AllocateAddress, EfiLoaderData, pages, &segment_addr);
|
||||
if (EFI_ERROR(status)) {
|
||||
@@ -159,6 +157,15 @@ static efi_status_t load_elf_segments(efi_physical_address_t kernel_addr, efi_fi
|
||||
if (EFI_ERROR(status) || size_to_read != phdr->p_filesz) {
|
||||
return fail(WSTR("File read error\r\n"));
|
||||
}
|
||||
|
||||
if (elf_header->e_entry >= phdr->p_vaddr && elf_header->e_entry < phdr->p_vaddr + phdr->p_memsz) {
|
||||
uint64_t entry_offset = elf_header->e_entry - phdr->p_vaddr;
|
||||
*out_phys_entry = segment_addr + entry_offset;
|
||||
}
|
||||
}
|
||||
|
||||
if (*out_phys_entry == 0) {
|
||||
return fail(WSTR("Entry point not found in PT_LOAD segments\r\n"));
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
@@ -235,7 +242,8 @@ efi_status_t bootloader_main(void) {
|
||||
status = parse_elf_headers(kernel_addr);
|
||||
if (EFI_ERROR(status)) return status;
|
||||
|
||||
status = load_elf_segments(kernel_addr, kernel_file);
|
||||
efi_physical_address_t phys_entry = 0;
|
||||
status = load_elf_segments(kernel_addr, kernel_file, &phys_entry);
|
||||
if (EFI_ERROR(status)) return status;
|
||||
|
||||
Bootinfo* boot_info = NULL;
|
||||
@@ -261,7 +269,7 @@ efi_status_t bootloader_main(void) {
|
||||
}
|
||||
|
||||
typedef void (*kernel_entry_t)(Bootinfo*);
|
||||
kernel_entry_t kernel_main = (kernel_entry_t)elf_header->e_entry;
|
||||
kernel_entry_t kernel_main = (kernel_entry_t)phys_entry;
|
||||
kernel_main(boot_info);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
Reference in New Issue
Block a user