Skip to content

Commit

Permalink
Support UEFI booting from alternate load addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
fintelia committed Apr 25, 2021
1 parent a1aca82 commit 4e6c320
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 8 deletions.
14 changes: 13 additions & 1 deletion include/uefi.hh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ struct efi_guid {
u16 data2;
u16 data3;
u8 data4[8];

bool operator==(const efi_guid &b) const {
for (int i = 0; i < 8; i++)
if (data4[i] != b.data4[i])
return false;
return data1 == b.data1 && data2 == b.data2 && data3 == b.data3;
}
};
enum efi_locate_search_type { AllHandles, ByRegisterNotify, ByProtocol};

Expand Down Expand Up @@ -108,6 +115,11 @@ struct efi_runtime_services {
void* reset_system;
};

struct efi_configuration_table {
efi_guid guid;
void* table;
};

struct efi_system_table {
struct {
u64 signature;
Expand All @@ -127,7 +139,7 @@ struct efi_system_table {
efi_runtime_services* runtime_services;
efi_boot_services* boot_services;
u64 num_table_entries;
void* configuration_table;
efi_configuration_table* configuration_table;
};

struct efi_memory_descriptor {
Expand Down
5 changes: 4 additions & 1 deletion kernel/boot.S
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,10 @@ relocate64:
efi_main:
movl %eax, %edi
movl %ebx, %esi
movq $PADDR(stack+STACK), %rsp

call 1f
1: pop %rsp
addq $(PADDR(stack+STACK)-PADDR(1b)), %rsp
call efi_cmain

.code32
Expand Down
81 changes: 75 additions & 6 deletions kernel/uefi.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,35 @@
#include "cmdline.hh"
#include "amd64.h"

efi_guid efi_acpi20_table_guid = {0x8868e871,0xe4f1,0x11d3, {0xbc,0x22,0x00,0x80,0xc7,0x3c,0x88,0x81}};
efi_guid efi_acpi10_table_guid = {0xeb9d2d30,0x2d88,0x11d3, {0x9a,0x16,0x00,0x90,0x27,0x3f,0xc1,0x4d}};

void multiboot2_early(u64 mbaddr, multiboot_saved* mb);

extern u64 kpml4[];
extern u64 physical_address_offset;

extern "C" u64 efi_cmain (u64 mbmagic, u64 mbaddr, void* boot_system_table, void* boot_image_table)
extern "C" u64 efi_cmain (u64 mbmagic, u64 mbaddr)
{
u64 offset;
__asm volatile("call 1f; 1: pop %0; sub $(1b-%a1), %0" : "=r" (offset) : "i"(KCODE));
physical_address_offset = offset;

multiboot_saved* mb = (multiboot_saved*)v2p(&multiboot);
multiboot2_early(mbaddr, mb);
efi_system_table* system_table = (efi_system_table*)mb->efi_system_table;

auto get_memory_map = system_table->boot_services->get_memory_map;
auto exit_boot_services = system_table->boot_services->exit_boot_services;

for (int i = 0; i < system_table->num_table_entries; i++) {
if (system_table->configuration_table[i].guid == efi_acpi10_table_guid) {
memcpy(mb->acpi_rsdpv1, system_table->configuration_table[i].table, 20);
mb->flags |= MULTIBOOT2_FLAG_ACPI_RSDP_V1;
} else if (system_table->configuration_table[i].guid == efi_acpi20_table_guid) {
memcpy(mb->acpi_rsdpv2, system_table->configuration_table[i].table, 36);
mb->flags |= MULTIBOOT2_FLAG_ACPI_RSDP_V2;
}
}

u64 key;
auto mem_descs = (efi_memory_descriptor*)&mb->efi_mmap[0];
Expand Down Expand Up @@ -51,10 +67,63 @@ extern "C" u64 efi_cmain (u64 mbmagic, u64 mbaddr, void* boot_system_table, void
dtr.base = (u64)bootgdt;
lgdt((void*)&dtr.limit);

// TODO: use trampoline_pml4
__asm volatile("movabs $(kpml4-%a1), %%rax; mov %%rax, %%cr3; add %0, %%rsp; movabs $1f, %%rax; jmp *%%rax; 1:"
:: "r"(KBASE), "i"(KCODE) : "rax", "memory");
cmain(mbmagic, mbaddr);
__asm volatile(
"call 1f; 1: pop %%rax; sub $(1b-%a0), %%rax;"

"movq $(physical_address_offset-%a0), %%rbx;"
"addq %%rax, %%rbx;"
"movq %%rax, (%%rbx);"

"movl %%eax, %%ebx;"
"addl $(kpml4-%a0), %%ebx;"
"addl %%eax, 0xff0(%%ebx);"
"addl %%eax, 0xff8(%%ebx);"

"movl %%eax, %%ebx;"
"addl $(trampoline_pml4-%a0), %%ebx;"
"addl %%eax, (%%ebx);"
"addl %%eax, 0xff0(%%ebx);"
"addl %%eax, 0xff8(%%ebx);"

"movl %%eax, %%ebx;"
"addl $(pdpt0-%a0), %%ebx;"
"addl %%eax, (%%ebx);"

"movl %%eax, %%ebx;"
"addl $(pdptbase-%a0), %%ebx;"
"addl %%eax, 0x00(%%ebx);"
"addl %%eax, 0x08(%%ebx);"
"addl %%eax, 0x10(%%ebx);"
"addl %%eax, 0x18(%%ebx);"

"movl %%eax, %%ebx;"
"addl $(pdptcode-%a0), %%ebx;"
"addl %%eax, 0xff8(%%ebx);"

"movl 0xff8(%%ebx), %%ebx;"
"and $0xfffff000, %%ebx;"
"mov $0x1000, %%ecx;"
"1: sub $8, %%ecx;"
"addl %%eax, (%%ebx,%%ecx);"
"cmp $0, %%ecx;"
"jnz 1b;" :: "i"(KCODE) : "rax", "rbx", "rcx");

__asm volatile(
"call 1f; 1: pop %%rbx; sub $(1b-%a1), %%rbx;"
"movabs $(trampoline_pml4-%a1), %%rax;"
"addq %%rbx, %%rax;"
"mov %%rax, %%cr3;"

"add %0, %%rsp;"
"movabs $1f, %%rax;"
"jmp *%%rax; 1:"

"movabs $(kpml4-%a1), %%rax;"
"addq %%rbx, %%rax;"
"mov %%rax, %%cr3;"
"call cmain;"
:: "r"(KBASE), "i"(KCODE), "rdi"(mbmagic), "rsi"(mbaddr) : "rax", "rbx", "memory");

panic("cmain should not return?");

return 1;
Expand Down

0 comments on commit 4e6c320

Please sign in to comment.