diff --git a/Makefile b/Makefile index a5eeab3..ef4a381 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ CFLAGS = -fno-pic -ffreestanding -static -fno-builtin -fno-strict-aliasing \ -mno-sse \ -Wall -ggdb -m32 -Werror -fno-omit-frame-pointer CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector) -ASMFLAGS = -m32 -ffreestanding -c -g +ASMFLAGS = -m32 -ffreestanding -c -g -I. ifeq ($(LLVM),on) #AS=llvm-as @@ -24,7 +24,7 @@ ASMFLAGS = -target elf-i386 -ffreestanding -c -g LDKERNELFLAGS = --script=script.ld endif -OBJECTS = kernel.o console.o drivers/vga.o drivers/uart.o drivers/keyboard.o \ +OBJECTS = kernel/kstart.o kernel.o console.o drivers/vga.o drivers/uart.o drivers/keyboard.o \ cpu/idt.o cpu/gdt.o cpu/swtch.o cpu/vectors.o lib/mem.o proc.o lib/string.o \ fs/fs.o drivers/ata.o lib/mem.o lib/string.o proc.o drivers/pit.o @@ -91,13 +91,13 @@ fs.img: kernel.bin tools/mkfs user/false user/greet user/div0 user/shout LDFLAGS=-m elf_i386 user/%: user/%.o user/crt.o - $(LD) $(LDFLAGS) -o $@ -Ttext 0x1000 $^ + $(LD) $(LDFLAGS) -o $@ -Ttext 0x10000 $^ image.bin: mbr.bin fs.img cat $^ >$@ kernel.bin: $(OBJECTS) - $(LD) $(LDFLAGS) $(LDKERNELFLAGS) -o $@ -Ttext 0x9000 $^ + $(LD) $(LDFLAGS) $(LDKERNELFLAGS) -o $@ -Ttext 0xf0009000 $^ bootmain.o: bootmain.c $(CC) $(CFLAGS) -Os -c $< -o $@ diff --git a/bootmain.c b/bootmain.c index 95a10fd..77d3263 100644 --- a/bootmain.c +++ b/bootmain.c @@ -40,7 +40,7 @@ bootmain(void) ph = (Elf32_Phdr*)((uchar*)elf + elf->e_phoff); eph = ph + elf->e_phnum; for(; ph < eph; ph++) { - pa = (uchar*)ph->p_paddr; + pa = (uchar*)(ph->p_paddr & 0x0fffffff); readseg(pa, ph->p_filesz, ph->p_offset); if(ph->p_memsz > ph->p_filesz) stosb(pa + ph->p_filesz, 0, ph->p_memsz - ph->p_filesz); @@ -48,7 +48,7 @@ bootmain(void) // Call the entry point from the ELF header. // Does not return! - entry = (void(*)(void))(elf->e_entry); + entry = (void(*)(void))(elf->e_entry & 0x0fffffff); entry(); } diff --git a/cpu/memlayout.h b/cpu/memlayout.h new file mode 100644 index 0000000..0702d52 --- /dev/null +++ b/cpu/memlayout.h @@ -0,0 +1,3 @@ +#pragma once + +#define KERNBASE 0xf0000000 \ No newline at end of file diff --git a/kernel.c b/kernel.c index e502a2c..fa83a72 100644 --- a/kernel.c +++ b/kernel.c @@ -14,7 +14,7 @@ asm(".asciz \"kernel start\\n\""); #include "proc.h" -void _start() { +void kmain() { load_gdt(); init_keyboard(); init_pit(); diff --git a/kernel/kstart.S b/kernel/kstart.S new file mode 100644 index 0000000..73f49fb --- /dev/null +++ b/kernel/kstart.S @@ -0,0 +1,71 @@ +#include "cpu/memlayout.h" + +/* + Memory layout at this point (see https://wiki.osdev.org/Memory_Map_(x86) for more details): + 0x00500 - 0x08fff: usable memory + 0x09000 – 0x14fff: kernel code and global data + 0x15000 - 0x7ffff: usable memory + 0x80000 - 0xfffff: BDA and upper memory + 0x100000 - 0x8000000 (1 MiB - 128 MiB): usable memory +*/ + .intel_syntax noprefix + .global _start + .asciz "kernel start\n" +_start: +.code32 + mov dword ptr [patch_addr - KERNBASE], offset gdt32_begin - KERNBASE + lgdt gdtr32 - KERNBASE + + // zero our PD at 0x1000 and PT at 0x2000 + xor eax, eax + mov ecx, 2048 + rep stosd + + // Set up the page table for the lowest 4 MiB: PD[0] -> PT + mov dword ptr [0x1000], 0x2000 | 0x3 + + // KERNBASE = 0xF000_0000 + // Use the same page table for the first 4 MiB after KERNBASE: PD[0x3c0] -> PT + mov dword ptr [0x1000 + (0x3c0 * 4)], 0x2000 | 0x3 + + // Identity map the first 2 MiB + mov edi, 0x2000 // Start of the PT + mov ebx, 0x00000003 // Present, R/W + mov ecx, 512 // 2 MiB / 4 KiB = 512 +SetEntry: + mov dword ptr [edi], ebx + add ebx, 0x1000 + add edi, 4 + loop SetEntry + + // Load physical address of PD into CR3 + mov edi, 0x1000 + mov cr3, edi + + // Enable paging + mov eax, cr0 + or eax, 1 << 31 // Set the PG bit + mov cr0, eax + + .att_syntax + jmp $0x8, $loadseg - KERNBASE + .intel_syntax noprefix + +loadseg: + // jump to the high half + add esp, KERNBASE + lea eax, kmain + jmp eax + +.align 16 +gdtr32: + .word gdt32_end - gdt32_begin - 1 +patch_addr: + .long gdt32_begin - KERNBASE + +.align 16 +gdt32_begin: + .long 0x00000000, 0x00000000 # Null descriptor + .long 0x0000ffff, 0x00cf9a00 # Code segment + .long 0x0000ffff, 0x00cf9200 # Data segment +gdt32_end: