From: Duje Mihanović Date: Tue, 21 Jun 2022 13:30:41 +0000 (+0200) Subject: Add C code for enabling paging in bootloader X-Git-Tag: 0.1.1~5 X-Git-Url: http://git.dujemihanovic.xyz/img/sics.gif?a=commitdiff_plain;h=485fd9b6752dd8590ac786397e9a0a4487860290;p=nameless-os.git Add C code for enabling paging in bootloader Also compile the bootloader as ELF as well for easier debugging. --- diff --git a/Makefile b/Makefile index bff97e5..2eedce2 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ CFLAGS = -g -fgnu89-inline -Iinclude/arch/x86 -ffreestanding -DGIT_COMMIT=\"$(GI KERNEL_OBJ = kernel/entry.o kernel/arch/x86/tty/tty.o kernel/drivers/irq/i8259a.o kernel/arch/x86/irq/idt.o kernel/arch/x86/irq/sample_handler.o kernel/kernel.o -BOOTLOADER_OBJ = boot/x86/mbr boot/x86/vbr-fat32 boot/x86/stage3/LOADER.BIN +BOOTLOADER_OBJ = boot/x86/mbr boot/x86/vbr-fat32 boot/x86/stage3/LOADER.BIN boot/x86/stage3/loader.elf default: kernel/kernel.elf bootloader @@ -21,7 +21,8 @@ run: all boot/x86/mbr: boot/x86/mbr.s boot/x86/vbr-fat32: boot/x86/vbr-fat32.s boot/x86/fat32/*.s -boot/x86/stage3/LOADER.BIN: boot/x86/stage3/*.s boot/x86/fat32/*.s +boot/x86/stage3/LOADER.BIN: boot/x86/stage3/*.s boot/x86/stage3/*.c boot/x86/fat32/*.s +boot/x86/stage3/loader.elf: boot/x86/stage3/*.s boot/x86/stage3/*.c boot/x86/fat32/*.s $(BOOTLOADER_OBJ): $(MAKE) -C boot/x86 diff --git a/boot/x86/Makefile b/boot/x86/Makefile index 0e5ac00..202d839 100644 --- a/boot/x86/Makefile +++ b/boot/x86/Makefile @@ -1,9 +1,10 @@ -default: mbr vbr-fat32 stage3/LOADER.BIN +default: mbr vbr-fat32 stage3/LOADER.BIN stage3/loader.elf +CFLAGS=-g -ffreestanding LD=i686-elf-gcc -LDFLAGS=-T stage3/stage3.ld -nostdlib +LDFLAGS=-T stage3/stage3.ld -nostdlib -g -STAGE3_OBJ=stage3/loader.o +STAGE3_OBJ=stage3/loader.o stage3/paging.o mbr: mbr.s $(AS) $(ASFLAGS) -w-zeroing -o $@ $< @@ -11,8 +12,11 @@ mbr: mbr.s vbr-fat32: vbr-fat32.s fat32/*.s $(AS) $(ASFLAGS) -o $@ $< +stage3/loader.elf: $(STAGE3_OBJ) + $(CC) $(LDFLAGS) -o $@ $^ -Wl,--oformat=elf32-i386 + stage3/LOADER.BIN: $(STAGE3_OBJ) - $(LD) $(LDFLAGS) -o $@ $< + $(CC) $(LDFLAGS) -o $@ $^ stage3/loader.o: stage3/loader.s stage3/*.s $(AS) $(ASFLAGS) -f elf -g dwarf2 -DGIT_REVISION=\"$(GIT_REV)\" -o $@ $< diff --git a/boot/x86/stage3/loader.s b/boot/x86/stage3/loader.s index cdecbaa..9ed7102 100644 --- a/boot/x86/stage3/loader.s +++ b/boot/x86/stage3/loader.s @@ -1,6 +1,10 @@ bits 16 cpu 686 +extern enable_paging +extern map_range +extern set_up_page_directory + section .text %include "../fat32/fat32-structs.s" @@ -69,6 +73,11 @@ _start: print kernel_loaded call get_e820_map + mov ebx, ecx + mov eax, 24 + mul ecx + add eax, 20 + sub sp, ax cli lgdt [gdt] @@ -168,13 +177,43 @@ in_protected: mov fs, ax mov gs, ax - call load_paging_structs + push dword 0 + push 0xc0003000 + push 0xc0000000 + push 0x103000 + push 0x100000 + call map_range + cmp eax, 0 + jne .error + add esp, 20 + push dword 2 + push 0xc0009000 + push 0xc0003000 + push 0x109000 + push 0x103000 + call map_range + cmp eax, 0 + jne .error + add esp, 20 + push dword 2 + push 0x100000 + push dword 0 + push 0x100000 + push dword 0 + call map_range + cmp eax, 0 + jne .error + add esp, 20 + + call set_up_page_directory call enable_paging - jmp 0x8:0xc0000000 + jmp 0xc0000000 nop - -%include "paging.s" +.error: + mov dword [0xb8000], 0xcf28cf3a + hlt + jmp $-1 section .rodata diff --git a/boot/x86/stage3/paging.c b/boot/x86/stage3/paging.c new file mode 100644 index 0000000..0482ded --- /dev/null +++ b/boot/x86/stage3/paging.c @@ -0,0 +1,70 @@ +/* Code for enabling paging */ + +#include + +#define ADDRESS_NOT_ALIGNED 1 +#define INVL_ADDRESS 2 +#define ADDRESS_ALREADY_MAPPED 3 +#define ADDRESS_RANGE_MISMATCHED 4 + +static uint32_t page_directory[1024] __attribute__((aligned(4096))) __attribute__((section(".data"))); +static uint32_t page_table_firstmb[1024] __attribute__((aligned(4096))) __attribute__((section(".data"))); +static uint32_t page_table_kernel[1024] __attribute__((aligned(4096))) __attribute__((section(".data"))); + +void enable_paging() +{ + int cr3; + asm ("mov %0, %%cr3": : "a" (page_directory)); + asm ("mov %%cr0, %0": "=a" (cr3)); + cr3 |= 0x80000000; + asm ("mov %0, %%cr0": : "a" (cr3)); +} + +int map_address(void *physical, void *virtual, int flags) +{ + if ((uint32_t) physical & 0xfff || (uint32_t) virtual & 0xfff) + return ADDRESS_NOT_ALIGNED; + + uint32_t pdir_index = (uint32_t) virtual >> 22; + if (pdir_index != 0 && pdir_index != 0x300) + return INVL_ADDRESS; + + uint32_t ptbl_index = ((uint32_t) virtual >> 12) & 0x3ff; + switch (pdir_index) { + case 0: + if (page_table_firstmb[ptbl_index] & 1 == 1) + return ADDRESS_ALREADY_MAPPED; + page_table_firstmb[ptbl_index] = ((uint32_t) physical & ~0xfff) | (flags & 0xfff) | 1; + break; + case 0x300: + if (page_table_kernel[ptbl_index] & 1 == 1) + return ADDRESS_ALREADY_MAPPED; + page_table_kernel[ptbl_index] = ((uint32_t) physical & ~0xfff) | (flags & 0xfff) | 1; + } + + return 0; +} + +int map_range(void *phys_start, void *phys_end, void *virt_start, void *virt_end, int flags) +{ + if ((uint32_t) phys_start & 0xfff || (uint32_t) phys_end & 0xfff || + (uint32_t) virt_start & 0xfff || (uint32_t) virt_end & 0xfff) + return ADDRESS_NOT_ALIGNED; + + if ((uint32_t) phys_end - (uint32_t) phys_start != (uint32_t) virt_end - (uint32_t) virt_start) + return ADDRESS_RANGE_MISMATCHED; + + int loops = ((uint32_t) phys_end - (uint32_t) phys_start) / 4096; + for (int i=0; i