diff options
| -rw-r--r-- | api/kernel/entry.h | 4 | ||||
| -rw-r--r-- | loader/Makefile | 2 | ||||
| -rw-r--r-- | loader/entry_efi.c | 2 | ||||
| -rw-r--r-- | loader/loader_efi.c | 147 | ||||
| -rw-r--r-- | loader/loader_efi.h | 19 | ||||
| -rw-r--r-- | loader/memory_efi.c | 2 | ||||
| -rw-r--r-- | loader/paging_efi.c | 155 |
7 files changed, 201 insertions, 130 deletions
diff --git a/api/kernel/entry.h b/api/kernel/entry.h index 0dae45d..8a26125 100644 --- a/api/kernel/entry.h +++ b/api/kernel/entry.h @@ -1,7 +1,7 @@ #pragma once #define KERNEL_ENTRY_STACK_SIZE 0x4000 -#define KERNEL_ENTRY_STACK_HEAD 0xffffffffff000000 -#define KERNEL_ENTRY_STACK_BASE (KERNEL_ENTRY_STACK_HEAD - KERNEL_ENTRY_STACK_SIZE) +#define KERNEL_ENTRY_STACK_HEAD (void *)0xffffffffff000000 +#define KERNEL_ENTRY_STACK_BASE ((char *)KERNEL_ENTRY_STACK_HEAD - KERNEL_ENTRY_STACK_SIZE) typedef void (*kernel_entry_func)(void *data); diff --git a/loader/Makefile b/loader/Makefile index 582daf3..f552d9a 100644 --- a/loader/Makefile +++ b/loader/Makefile @@ -10,7 +10,7 @@ CPPFLAGS += -I../api all: $(BUILD) -OBJS := entry_efi.o loader_efi.o memory_efi.o memcmp.o memmove.o +OBJS := entry_efi.o loader_efi.o paging_efi.o memory_efi.o memcmp.o memmove.o DEPS := $(OBJS:.o=.d) IMAGE_SO := $(IMAGE:.efi=_efi.so) diff --git a/loader/entry_efi.c b/loader/entry_efi.c index fa27c02..070cc16 100644 --- a/loader/entry_efi.c +++ b/loader/entry_efi.c @@ -34,6 +34,8 @@ EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) e_system_partition = open_system_partition(); e_graphics_output = open_graphics_output(); + WaitForSingleEvent(e_st->ConIn->WaitForKey, 0); + loader_main(); efi_exit(EFI_ABORTED); diff --git a/loader/loader_efi.c b/loader/loader_efi.c index 08da215..724e8ec 100644 --- a/loader/loader_efi.c +++ b/loader/loader_efi.c @@ -3,12 +3,12 @@ #include <loader/data_efi.h> #include <kernel/entry.h> -#include <kernel/memory/paging.h> #include <elf/elf64.h> #include <stdbool.h> #include <stddef.h> +#include <stdnoreturn.h> struct system_image { @@ -20,7 +20,6 @@ struct system_image static CHAR16 *kernel_path = L"\\adasoft\\sophia\\kernel.os"; static struct system_image *kernel_image = NULL; -static uint64_t *system_page_map = NULL; static struct system_image *open_system_image(CHAR16 *path); static bool load_system_image(struct system_image *image); @@ -28,74 +27,6 @@ static struct efi_memory_map_data *get_memory_map_data(void); static struct efi_framebuffer_data *get_framebuffer_data(void); static void *get_acpi_rsdp(void); -enum page_type -{ - INVALID_PAGE_TYPE = 0x0, - CODE_PAGE_TYPE = PAGE_PR, - RODATA_PAGE_TYPE = PAGE_PR|PAGE_NX, - DATA_PAGE_TYPE = PAGE_PR|PAGE_WR|PAGE_NX -}; - -static uint64_t *new_page_table(void) -{ - struct memory_range table = system_allocate(page_size(1)); - e_bs->SetMem((void *)table.base, table.size, 0); - - return (uint64_t *)table.base; -} - -static uint64_t *get_page_map(void) -{ - uint64_t map; - __asm__("mov %%cr3, %0" : "=r"(map)); - return (uint64_t *)(page_address(map, 1)); -} - -void set_page_map(uint64_t *map) -{ - __asm__("cli"); - __asm__("mov %0, %%cr3" :: "r"(map)); -} - -static uint64_t *get_page_table(uint64_t *map, uint64_t virt, int level) -{ - if ((level < 1) || (level > PAGE_MAP_LEVELS)) - { - return NULL; - } - - for (int i = PAGE_MAP_LEVELS; i > level; i--) - { - if (!map[pte_index(virt, i)]) - { - uint64_t *next_map = new_page_table(); - map[pte_index(virt, i)] = (uint64_t)next_map|PAGE_PR|PAGE_WR; - map = next_map; - } - else - { - map = (uint64_t *)page_address(map[pte_index(virt, i)], 1); - } - } - - return map; -} - -static uint64_t *get_page_entry(uint64_t *map, uint64_t virt) -{ - int level = 1; - uint64_t *table = get_page_table(map, virt, level); - return &table[pte_index(virt, level)]; -} - -static void map_page(void *map, - uint64_t virt, - uint64_t phys, - enum page_type type) -{ - *get_page_entry(map, virt) = phys | type; -} - enum page_type get_page_type(Elf64_Phdr *phdr) { switch (phdr->p_flags) @@ -111,19 +42,6 @@ enum page_type get_page_type(Elf64_Phdr *phdr) return INVALID_PAGE_TYPE; } -static void map_pages(void *map, - uint64_t virt, - uint64_t phys, - enum page_type type, - size_t size) -{ - for (size_t offset = 0; offset < size; offset += page_size(1)) - { - Print(L"mapping page %16.0lx to %16.0lx\r\n", virt + offset, phys + offset); - map_page(map, virt + offset, phys + offset, type); - } -} - static void create_image_maps(struct system_image *image) { Elf64_Ehdr *ehdr = &image->ehdr; @@ -133,23 +51,23 @@ static void create_image_maps(struct system_image *image) { if (phdrs[i].p_type == PT_LOAD) { - uint64_t virt_begin = phdrs[i].p_vaddr; + void *virt_begin = (void *)phdrs[i].p_vaddr; uint64_t phys_begin = image->buffer.base + phdrs[i].p_paddr; size_t size = phdrs[i].p_memsz; Print(L"mapping segment %16.0lx to %16.0lx %d bytes\r\n", virt_begin, phys_begin, size); - map_pages(system_page_map, - virt_begin, - phys_begin, - get_page_type(&phdrs[i]), - size); + + paging_map_pages(virt_begin, + phys_begin, + get_page_type(&phdrs[i]), + size); } } } -static void enter_kernel() +noreturn static void enter_kernel() { struct efi_boot_data data; kernel_entry_func kernel_entry; @@ -159,12 +77,9 @@ static void enter_kernel() system_allocate(KERNEL_ENTRY_STACK_SIZE); // get a stack here for now idfk - map_pages(system_page_map, - KERNEL_ENTRY_STACK_BASE, - kernel_entry_stack.base, - DATA_PAGE_TYPE, - kernel_entry_stack.size); - + paging_map_range(KERNEL_ENTRY_STACK_BASE, + &kernel_entry_stack, + DATA_PAGE_TYPE); data.system_table = e_st; data.framebuffer = get_framebuffer_data(); @@ -180,12 +95,10 @@ static void enter_kernel() efi_exit(status); } - // parasitic map of uefi page tables is this ok??????? - uint64_t *efi_map = get_page_map(); - system_page_map[0] = efi_map[0]; - - set_page_map(system_page_map); - + // enter the kernel address environment + paging_enter(); + + // set the kernel entry stack. __asm__ ( "mov %0, %%rsp" @@ -194,27 +107,8 @@ static void enter_kernel() ); kernel_entry(&data); -} - -#define KERNEL_SPACE_LOWER 0xffffffff80000000 -#define KERNEL_SPACE_UPPER 0xffffffffc0000000 - -static void create_system_maps() -{ - system_page_map = new_page_table(); - - // Create fractal mappings - uint64_t *lower_page_dir = get_page_table(system_page_map, - KERNEL_SPACE_LOWER, - 2); - uint64_t *upper_page_dir = get_page_table(system_page_map, - KERNEL_SPACE_UPPER, - 2); - - upper_page_dir[PAGE_TABLE_INDEX_MASK] = - (uint64_t)upper_page_dir|DATA_PAGE_TYPE; - upper_page_dir[PAGE_TABLE_INDEX_MASK - 1] = - (uint64_t)lower_page_dir|DATA_PAGE_TYPE; + + while(true); } void loader_main(void) @@ -235,8 +129,7 @@ void loader_main(void) efi_exit(EFI_ABORTED); } - create_system_maps(); - Print(L"kernel pml4 %16.0lx\r\n", system_page_map); + paging_init(); create_image_maps(kernel_image); Print(L"kernel maps created. entering kernel\r\n"); enter_kernel(); @@ -352,7 +245,9 @@ static UINTN get_image_size(struct system_image *image) { size = phdrs[i].p_paddr + phdrs[i].p_memsz; if (phdrs[i].p_align > 1) - size = (size + phdrs[i].p_align - 1) & ~(phdrs[i].p_align - 1); + { + size = (size + phdrs[i].p_align - 1) & ~(phdrs[i].p_align - 1); + } } } diff --git a/loader/loader_efi.h b/loader/loader_efi.h index a1ba360..17c58cf 100644 --- a/loader/loader_efi.h +++ b/loader/loader_efi.h @@ -7,6 +7,15 @@ #include <stdnoreturn.h> #include <kernel/memory/range.h> +#include <kernel/memory/paging.h> + +enum page_type +{ + INVALID_PAGE_TYPE = 0x0, + CODE_PAGE_TYPE = PAGE_PR, + RODATA_PAGE_TYPE = PAGE_PR|PAGE_NX, + DATA_PAGE_TYPE = PAGE_PR|PAGE_WR|PAGE_NX +}; extern EFI_SYSTEM_TABLE *e_st; extern EFI_BOOT_SERVICES *e_bs; @@ -25,5 +34,15 @@ struct memory_range system_allocate(size_t size); void *efi_allocate(size_t size); void efi_free(void *buffer); +void paging_init(void); +void paging_enter(void); +void *paging_map_page(void *vaddr, phys_addr_t paddr, enum page_type type); +void *paging_map_pages(void *vaddr, + phys_addr_t paddr, + enum page_type type, + size_t size); +void *paging_map_range(void *vaddr, + struct memory_range *range, + enum page_type type); void loader_main(void); diff --git a/loader/memory_efi.c b/loader/memory_efi.c index b2d38ee..2fab6b7 100644 --- a/loader/memory_efi.c +++ b/loader/memory_efi.c @@ -18,6 +18,7 @@ struct memory_range system_allocate(size_t size) if (EFI_ERROR(status)) { + Print(L"error allocating range: %r\r\n", status); e_last_error = status; buffer.type = UNUSABLE_MEMORY; } @@ -52,4 +53,3 @@ void efi_free(void *buffer) e_last_error = status; } } - diff --git a/loader/paging_efi.c b/loader/paging_efi.c new file mode 100644 index 0000000..5f65213 --- /dev/null +++ b/loader/paging_efi.c @@ -0,0 +1,155 @@ +#include "loader_efi.h" + +#include <kernel/memory/paging.h> + +#define KERNEL_SPACE_LOWER (void *)0xffffffff80000000 +#define KERNEL_SPACE_UPPER (void *)0xffffffffc0000000 + +static uint64_t *new_page_table(void); +static uint64_t *get_page_table(void *vaddr, int level); +static uint64_t *get_page_entry(void *vaddr); + +static uint64_t *get_page_map(void); +static void set_page_map(uint64_t *map); + +static uint64_t *efi_page_map = NULL; +static uint64_t *system_page_map = NULL; + +void paging_init(void) +{ + efi_page_map = get_page_map(); + system_page_map = new_page_table(); + + if (!system_page_map) + { + Print(L"error creating page map: %r\r\n", e_last_error); + efi_exit(e_last_error); + } + + // copy the identity mappings from the EFI PML4. + system_page_map[0] = efi_page_map[0]; + + // create kernel fractal mappings + // TODO: move this into the kernel instead? + uint64_t *lower_pm2 = get_page_table(KERNEL_SPACE_LOWER, 2); + uint64_t *upper_pm2 = get_page_table(KERNEL_SPACE_UPPER, 2); + + upper_pm2[PAGE_TABLE_INDEX_MASK - 1] = (phys_addr_t)lower_pm2|DATA_PAGE_TYPE; + upper_pm2[PAGE_TABLE_INDEX_MASK] = (phys_addr_t)upper_pm2|DATA_PAGE_TYPE; +} + +void paging_enter(void) +{ + // use the system_page_map instead of efi_page_map + set_page_map(system_page_map); +} + +void *paging_map_page(void *vaddr, phys_addr_t paddr, enum page_type type) +{ + uint64_t *entry = get_page_entry(vaddr); + + if (entry) + { + *entry = paddr | type; + return vaddr; + } + + return NULL; +} + +void *paging_map_pages(void *vaddr, + phys_addr_t paddr, + enum page_type type, + size_t size) +{ + for (size_t offset = 0; offset < size; offset += page_size(1)) + { + if (!paging_map_page((char *)vaddr + offset, paddr + offset, type)) + { + return NULL; + } + } + + return vaddr; +} + +void *paging_map_range(void *vaddr, + struct memory_range *range, + enum page_type type) +{ + return paging_map_pages(vaddr, range->base, type, range->size); +} + +static uint64_t *new_page_table(void) +{ + struct memory_range table = system_allocate(page_size(1)); + + if (table.type == SYSTEM_MEMORY) + { + e_bs->SetMem((void *)table.base, table.size, 0); + return (uint64_t *)table.base; + } + + return NULL; +} + +static uint64_t *get_page_table(void *vaddr, int level) +{ + // don't try to do anything if there's no page map. + if (!system_page_map) + { + return NULL; + } + + // don't try to do anything outside of the page map + if ((level < 1) || (level > PAGE_MAP_LEVELS)) + { + return NULL; + } + + // don't use a non-canonical address + + uint64_t *map = system_page_map; + + for (int i = PAGE_MAP_LEVELS; i > level; i--) + { + if (!map[pte_index(vaddr, i)]) + { + uint64_t *next_map = new_page_table(); + map[pte_index(vaddr, i)] = (phys_addr_t)next_map|PAGE_PR|PAGE_WR; + map = next_map; + } + else + { + map = (uint64_t *)page_address(map[pte_index(vaddr, i)], 1); + } + } + + return map; +} + +static uint64_t *get_page_entry(void *vaddr) +{ + uint64_t *table = get_page_table(vaddr, 1); + return &table[pte_index(vaddr, 1)]; +} + +static uint64_t *get_page_map(void) +{ + uint64_t map; + __asm__("mov %%cr3, %0" : "=r"(map)); + return (uint64_t *)(page_address(map, 1)); +} + +static void set_page_map(uint64_t *map) +{ + __asm__ + ( + "pushf\r\n" + "cli\r\n" + "mov %0, %%cr3\r\n" + "popf" + : + : "r"(map) + ); +} |
