From 72a46bc7ce086420ae29298ddfa59f9e5717fd15 Mon Sep 17 00:00:00 2001 From: Jozef Nagy Date: Mon, 10 Mar 2025 17:10:35 +0100 Subject: [PATCH] I don't even know what to write at this point --- boot/arch/x86_64/common/mm/paging.c | 70 +++++++----- boot/arch/x86_64/common/proto/aurix_handoff.S | 11 ++ boot/common/init.c | 19 +--- boot/common/loader/elf.c | 102 +++++++++++------- boot/common/print.c | 2 +- boot/common/proto/aurix.c | 69 ++++++++++++ boot/include/arch/x86_64/arch/mm/paging.h | 11 ++ boot/include/loader/elf.h | 3 +- boot/include/mm/vmm.h | 10 +- boot/include/proto/aurix.h | 25 +++++ kernel/Makefile | 5 +- kernel/arch/x86_64/linker.ld | 4 +- 12 files changed, 235 insertions(+), 96 deletions(-) create mode 100644 boot/arch/x86_64/common/proto/aurix_handoff.S create mode 100644 boot/common/proto/aurix.c create mode 100644 boot/include/proto/aurix.h diff --git a/boot/arch/x86_64/common/mm/paging.c b/boot/arch/x86_64/common/mm/paging.c index 259623f..85080a3 100644 --- a/boot/arch/x86_64/common/mm/paging.c +++ b/boot/arch/x86_64/common/mm/paging.c @@ -21,48 +21,64 @@ #include #include #include +#include #include /* Trimmed down version of */ /* https://github.com/KevinAlavik/nekonix/blob/main/kernel/src/mm/vmm.c */ /* Thanks, Kevin <3 */ -void map_page(uintptr_t *pm, uintptr_t virt, uintptr_t phys, uint64_t flags) +void map_pages(pagetable *pm, uintptr_t virt, uintptr_t phys, size_t size, uint64_t flags) { - uint64_t pml1_idx = (virt & (uint64_t)0x1ff << 12) >> 12; - uint64_t pml2_idx = (virt & (uint64_t)0x1ff << 21) >> 21; - uint64_t pml3_idx = (virt & (uint64_t)0x1ff << 30) >> 30; - uint64_t pml4_idx = (virt & (uint64_t)0x1ff << 39) >> 39; - - if (!(pm[pml4_idx] & 1)) { - pm[pml4_idx] = (uint64_t)mem_alloc(PAGE_SIZE) | flags; + for (size_t i = 0; i < ROUND_UP(size, PAGE_SIZE); i += PAGE_SIZE) { + map_page(pm, virt + i, phys + i, flags); } - - uint64_t *pml3_table = (uint64_t *)(pm[pml4_idx] & 0x000FFFFFFFFFF000); - if (!(pml3_table[pml3_idx] & 1)) { - pml3_table[pml3_idx] = (uint64_t)mem_alloc(PAGE_SIZE) | flags; - } - - uint64_t *pml2_table = (uint64_t *)(pml3_table[pml3_idx] & 0x000FFFFFFFFFF000); - if (!(pml2_table[pml2_idx] & 1)) { - pml2_table[pml2_idx] = (uint64_t)mem_alloc(PAGE_SIZE) | flags; - } - - uint64_t *pml1_table = (uint64_t *)(pml2_table[pml2_idx] & 0x000FFFFFFFFFF000); - pml1_table[pml1_idx] = phys | flags; - - debug("map_page(): Mapped 0x%lx -> 0x%lx\n", phys, virt); } -uintptr_t *create_pagemap() +void map_page(pagetable *pm, uintptr_t virt, uintptr_t phys, uint64_t flags) { - uint64_t *pm = (uint64_t *)mem_alloc(PAGE_SIZE); + uint64_t pml1_idx = (virt >> 12) & 0x1ff; + uint64_t pml2_idx = (virt >> 21) & 0x1ff; + uint64_t pml3_idx = (virt >> 30) & 0x1ff; + uint64_t pml4_idx = (virt >> 39) & 0x1ff; + + if (!(pm->entries[pml4_idx] & 1)) { + void *pml4 = mem_alloc(PAGE_SIZE); + memset(pml4, 0, sizeof(pagetable)); + pm->entries[pml4_idx] = (uint64_t)pml4 | VMM_PRESENT | VMM_WRITABLE | VMM_USER; + } + + pagetable *pml3_table = (pagetable *)(pm->entries[pml4_idx] & 0x000FFFFFFFFFF000); + if (!(pml3_table->entries[pml3_idx] & 1)) { + void *pml3 = mem_alloc(PAGE_SIZE); + memset(pml3, 0, sizeof(pagetable)); + pml3_table->entries[pml3_idx] = (uint64_t)pml3 | VMM_PRESENT | VMM_WRITABLE | VMM_USER; + } + + pagetable *pml2_table = (pagetable *)(pml3_table->entries[pml3_idx] & 0x000FFFFFFFFFF000); + if (!(pml2_table->entries[pml2_idx] & 1)) { + void *pml2 = mem_alloc(PAGE_SIZE); + memset(pml2, 0, sizeof(pagetable)); + pml2_table->entries[pml2_idx] = (uint64_t)pml2 | VMM_PRESENT | VMM_WRITABLE | VMM_USER; + } + + pagetable *pml1_table = (pagetable *)(pml2_table->entries[pml2_idx] & 0x000FFFFFFFFFF000); + if (!(pml1_table->entries[pml1_idx] & 1)) { + pml1_table->entries[pml1_idx] = (phys | 0x000FFFFFFFFFF000) | flags; + } + + debug("map_page(): Mapped 0x%llx -> 0x%llx\n", phys, virt); +} + +pagetable *create_pagemap() +{ + pagetable *pm = (pagetable *)mem_alloc(PAGE_SIZE); if (!pm) { debug("create_pagemap(): Failed to allocate memory for a new pm.\n"); return NULL; } - memset(pm, 0, PAGE_SIZE); + memset(pm, 0, sizeof(pagetable)); - debug("create_pagemap(): Created new pm at 0x%lx\n", (uint64_t)pm); + debug("create_pagemap(): Created new pm at 0x%llx\n", (uint64_t)pm); return pm; } diff --git a/boot/arch/x86_64/common/proto/aurix_handoff.S b/boot/arch/x86_64/common/proto/aurix_handoff.S new file mode 100644 index 0000000..9d7e12b --- /dev/null +++ b/boot/arch/x86_64/common/proto/aurix_handoff.S @@ -0,0 +1,11 @@ +.globl _aurix_handoff_start +.globl _aurix_handoff_end +.globl aurix_handoff + +aurix_handoff: + cli + movq %rsi, %rsp +_aurix_handoff_start: + movq %rdi, %cr3 + jmpq *%rdx +_aurix_handoff_end: \ No newline at end of file diff --git a/boot/common/init.c b/boot/common/init.c index 53c368d..6ef4552 100644 --- a/boot/common/init.c +++ b/boot/common/init.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include void axboot_init() @@ -31,22 +31,7 @@ void axboot_init() while (1); } - // read kernel -> test read - char *kbuf = NULL; - vfs_read("\\System\\axkrnl", &kbuf); - - // TODO: Do something with the kernel :p - uintptr_t *pm = create_pagemap(); - if (!pm) { - debug("axboot_init(): Failed to create kernel pagemap! Halting...\n"); - // TODO: Halt - while (1); - } - - void *kernel_entry = (void *)elf_load(kbuf, pm); - (void)kernel_entry; - - mem_free(kbuf); + aurix_load("\\System\\axkrnl"); while (1); } \ No newline at end of file diff --git a/boot/common/loader/elf.c b/boot/common/loader/elf.c index 537f9ab..77ce003 100644 --- a/boot/common/loader/elf.c +++ b/boot/common/loader/elf.c @@ -28,7 +28,61 @@ /* https://github.com/KevinAlavik/nekonix/blob/main/kernel/src/proc/elf.c */ /* Thanks, Kevin <3 */ -uint64_t elf_load(char *data, uintptr_t *pagemap) +uintptr_t elf32_load(char *data, pagetable *pagemap) +{ + (void)data; + (void)pagemap; + return 0; +} + +uintptr_t elf64_load(char *data, pagetable *pagemap) +{ + struct elf_header *header = (struct elf_header *)data; + struct elf_program_header *ph = (struct elf_program_header *)((uint8_t *)data + header->e_phoff); + + uint64_t lowest = UINT64_MAX; + uint64_t max_align = 0; + + for (uint16_t i = 0; i < header->e_phnum; i++) { + if (ph[i].p_type != PT_LOAD) + continue; + + if (ph[i].p_align > max_align) { + max_align = ph[i].p_align; + } + } + + for (uint16_t i = 0; i < header->e_phnum; i++) { + if (ph[i].p_type != PT_LOAD) + continue; + + if ((ph[i].p_vaddr & (~(max_align - 1))) < lowest) { + lowest = ph[i].p_vaddr & ~(max_align - 1); + } + + uint64_t flags = VMM_PRESENT; + if (ph[i].p_flags & PF_W) + flags |= VMM_WRITABLE; + if (!(ph[i].p_flags & PF_X)) + flags |= VMM_NX; + + debug("elf64_load(): phys=0x%llx, virt=0x%llx, size=%lu\n", ph[i].p_paddr, ph[i].p_vaddr, ph[i].p_filesz); + + uint64_t phys = (uint64_t)mem_alloc(ph[i].p_memsz); + if (!phys) { + debug("elf64_load(): Out of memory\n"); + return 0; + } + + map_page(pagemap, ph[i].p_vaddr, phys, flags); + memcpy((void*)ph[i].p_vaddr - lowest, data + ph[i].p_offset, ph[i].p_filesz); + } + + debug("elf64_load(): ELF loaded successfully, entry: 0x%llx\n", header->e_entry); + return (uintptr_t)((uint8_t *)data + (header->e_entry - lowest)); +} + +uintptr_t elf_load(char *data, pagetable *pagemap) { struct elf_header *header = (struct elf_header *)data; @@ -42,44 +96,14 @@ uint64_t elf_load(char *data, uintptr_t *pagemap) return 0; } - struct elf_program_header *ph = (struct elf_program_header *)(data + header->e_phoff); - - for (uint16_t i = 0; i < header->e_phnum; i++) { - if (ph[i].p_type != PT_LOAD) - continue; - - uint64_t vaddr_start = ALIGN_DOWN(ph[i].p_vaddr, PAGE_SIZE); - uint64_t vaddr_end = ALIGN_UP(ph[i].p_vaddr + ph[i].p_memsz, PAGE_SIZE); - uint64_t offset = ph[i].p_offset; - - uint64_t flags = VMM_PRESENT; - if (ph[i].p_flags & PF_W) - flags |= VMM_WRITABLE; - if (!(ph[i].p_flags & PF_X)) - flags |= VMM_NX; - - for (uint64_t addr = vaddr_start; addr < vaddr_end; addr += PAGE_SIZE) { - uint64_t phys = (uint64_t)mem_alloc(PAGE_SIZE); - if (!phys) { - debug("Out of physical memory"); - return 0; - } - - map_page(pagemap, addr, phys, flags); - - uint64_t file_offset = offset + (addr - vaddr_start); - if (file_offset < offset + ph[i].p_filesz) { - uint64_t to_copy = PAGE_SIZE; - if (file_offset + PAGE_SIZE > offset + ph[i].p_filesz) - to_copy = offset + ph[i].p_filesz - file_offset; - - memcpy((void *)phys, data + file_offset, to_copy); - } else { - memset((void *)phys, 0, PAGE_SIZE); - } - } + if (header->e_machine == 20 || + header->e_machine == 3 || + header->e_machine == 40) { + return elf32_load(data, pagemap); + } else if (header->e_machine == 62) { + return elf64_load(data, pagemap); } - debug("ELF loaded successfully, entry: 0x%lx", header->e_entry); - return header->e_entry; + debug("Unsupported ELF machine: %u", header->e_machine); + return 0; } diff --git a/boot/common/print.c b/boot/common/print.c index 359b4e5..93553c7 100644 --- a/boot/common/print.c +++ b/boot/common/print.c @@ -21,7 +21,7 @@ #define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 1 #define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 0 #define NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS 0 -#define NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS 0 +#define NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS 1 #define NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS 0 #define NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS 0 #include diff --git a/boot/common/proto/aurix.c b/boot/common/proto/aurix.c new file mode 100644 index 0000000..049c5e1 --- /dev/null +++ b/boot/common/proto/aurix.c @@ -0,0 +1,69 @@ +/*********************************************************************************/ +/* Module Name: aurix.c */ +/* Project: AurixOS */ +/* */ +/* Copyright (c) 2024-2025 Jozef Nagy */ +/* */ +/* This source is subject to the MIT License. */ +/* See License.txt in the root of this repository. */ +/* All other rights reserved. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/*********************************************************************************/ + +#include +#include +#include +#include +#include +#include + +extern __attribute__((noreturn)) void aurix_handoff(void *pagemap, void *stack, uint64_t entry, void *params); +extern char _aurix_handoff_start[], _aurix_handoff_end[]; + +void aurix_load(char *kernel) +{ + // read kernel -> test read + char *kbuf = NULL; + vfs_read(kernel, &kbuf); + + // TODO: Do something with the kernel :p + pagetable *pm = create_pagemap(); + if (!pm) { + debug("aurix_load(): Failed to create kernel pagemap! Halting...\n"); + // TODO: Halt + while (1); + } + + map_pages(pm, (uintptr_t)_aurix_handoff_start, (uintptr_t)_aurix_handoff_start, (uint64_t)_aurix_handoff_end - (uint64_t)_aurix_handoff_start, VMM_PRESENT | VMM_USER | VMM_WRITABLE); + + void *stack = mem_alloc(16*1024); // 16 KiB stack should be well more than enough + if (!stack) { + debug("aurix_load(): Failed to allocate stack! Halting...\n"); + while (1); + } + + void *kernel_entry = (void *)elf_load(kbuf, pm); + if (!kernel_entry) { + debug("aurix_load(): Failed to load '%s'! Halting...\n", kernel); + mem_free(kbuf); + while (1); + } + + void *parameters = NULL; + + debug("aurix_load(): Handoff state: pm=0x%llx, stack=0x%llx, kernel_entry=0x%llx\n", pm, stack, kernel_entry); + + aurix_handoff(pm, (void *)((uint8_t)stack - 16*1024), (uint64_t)kernel_entry, (void *)parameters); + + // __asm__ volatile("movq %[pml4], %%cr3\n" :: [pml4]"r"(pm) : "memory"); + // __asm__ volatile("callq *%[entry]\n" + // :: [entry]"r"(kernel_entry)); + +} \ No newline at end of file diff --git a/boot/include/arch/x86_64/arch/mm/paging.h b/boot/include/arch/x86_64/arch/mm/paging.h index d9c8698..85bb448 100644 --- a/boot/include/arch/x86_64/arch/mm/paging.h +++ b/boot/include/arch/x86_64/arch/mm/paging.h @@ -20,6 +20,17 @@ #ifndef _MM_PAGING_H #define _MM_PAGING_H +#include + #define PAGE_SIZE 0x1000 +#define VMM_PRESENT 1 +#define VMM_WRITABLE 2 +#define VMM_NX (1ull << 63) +#define VMM_USER 4 + +typedef struct { + uint64_t entries[512]; +} pagetable; + #endif /* _MM_PAGING_H */ \ No newline at end of file diff --git a/boot/include/loader/elf.h b/boot/include/loader/elf.h index c1b8931..0613173 100644 --- a/boot/include/loader/elf.h +++ b/boot/include/loader/elf.h @@ -20,6 +20,7 @@ #ifndef _LOADER_ELF_H #define _LOADER_ELF_H +#include #include //#include @@ -72,6 +73,6 @@ struct elf_program_header { #define PF_W 0x2 #define PF_R 0x4 -uint64_t elf_load(char *kernel, uintptr_t *pagemap); +uintptr_t elf_load(char *kernel, pagetable *pagemap); #endif /* _LOADER_ELF_H */ diff --git a/boot/include/mm/vmm.h b/boot/include/mm/vmm.h index 6ea50c0..0f04442 100644 --- a/boot/include/mm/vmm.h +++ b/boot/include/mm/vmm.h @@ -23,13 +23,9 @@ #include #include -#define VMM_PRESENT 1 -#define VMM_WRITABLE 2 -#define VMM_NX (1ull << 63) -#define VMM_USER 4 +pagetable *create_pagemap(void); -uintptr_t *create_pagemap(void); - -void map_page(uintptr_t *pm, uintptr_t virt, uintptr_t phys, uint64_t flags); +void map_page(pagetable *pm, uintptr_t virt, uintptr_t phys, uint64_t flags); +void map_pages(pagetable *pm, uintptr_t virt, uintptr_t phys, size_t size, uint64_t flags); #endif /* _MM_VMM_H */ \ No newline at end of file diff --git a/boot/include/proto/aurix.h b/boot/include/proto/aurix.h new file mode 100644 index 0000000..8863e29 --- /dev/null +++ b/boot/include/proto/aurix.h @@ -0,0 +1,25 @@ +/*********************************************************************************/ +/* Module Name: aurix.h */ +/* Project: AurixOS */ +/* */ +/* Copyright (c) 2024-2025 Jozef Nagy */ +/* */ +/* This source is subject to the MIT License. */ +/* See License.txt in the root of this repository. */ +/* All other rights reserved. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/*********************************************************************************/ + +#ifndef _PROTO_AURIX_H +#define _PROTO_AURIX_H + +void aurix_load(char *kernel); + +#endif /* _PROTO_AURIX_H */ diff --git a/kernel/Makefile b/kernel/Makefile index e43d71c..54da7de 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -47,14 +47,15 @@ KERNEL_CFLAGS := $(foreach d, $(INCLUDE_DIRS), -I$d) \ -fno-omit-frame-pointer \ -fno-stack-protector \ -fno-stack-check \ - -fno-pie \ + -fpic \ + -fpie \ -MMD \ -MP KERNEL_LDFLAGS := -Tarch/$(ARCH)/linker.ld \ -nostdlib \ -static \ - -no-pie + #-no-pie ifeq ($(BUILD_TYPE),debug) KERNEL_CFLAGS += -O0 -g3 diff --git a/kernel/arch/x86_64/linker.ld b/kernel/arch/x86_64/linker.ld index 4660482..95a8a7a 100644 --- a/kernel/arch/x86_64/linker.ld +++ b/kernel/arch/x86_64/linker.ld @@ -31,8 +31,8 @@ PHDRS SECTIONS { - /* AxBoot remaps this to 0xffffffff80000000 for us */ - . = 0x1000; + /* TODO: 0xffffffff80000000 */ + . = 0xffffffff80000000; _linker_start_text = .;