diff --git a/connect_gdb.sh b/connect_gdb.sh index 29fa887..7d72346 100755 --- a/connect_gdb.sh +++ b/connect_gdb.sh @@ -3,4 +3,3 @@ i686-elf-gdb build/ukern.elf \ -ex "target remote localhost:1234" \ -ex "break start" \ - -ex "continue" diff --git a/include/asm.h b/include/asm.h index 7ff4bfc..890aabe 100644 --- a/include/asm.h +++ b/include/asm.h @@ -7,8 +7,6 @@ #define ASM_H #include -#define COM1 0x3F8 -#define COM2 0x2F8 void outb(uint16_t port, uint8_t data); uint8_t inb(uint16_t port); diff --git a/include/serial.h b/include/serial.h index f85526e..d3a39f2 100644 --- a/include/serial.h +++ b/include/serial.h @@ -9,6 +9,11 @@ #include "io.h" #include + + +#define COM1 0x3F8 +#define COM2 0x2F8 + typedef struct serial_ctx_s { uint16_t port; } serial_ctx_t; diff --git a/linker.ld b/linker.ld index b4a188e..9c981fc 100644 --- a/linker.ld +++ b/linker.ld @@ -6,19 +6,31 @@ SECTIONS /*start me at 1Mb because below that is x86 essential stuff, which we dont want to be written on top of.*/ . = 1M; - _kernel_start = .; /* we're going to maintain 4K alignment - apparently useful for paging, and i'm not complaining about the lost space anyway. */ /*our multiboot header from start.s - has to go at the beginning of the executable so the bootloader knows we're loadable.*/ /*executable section*/ - .text BLOCK(4K) : ALIGN(4K) - { + .mb_sect : + { *(.multiboot) + } + + .lower_text : + { + *(.lower_text) + } + + /* Higher half addressing! We'll have to also specify that we want to be physically placed at 1MB.*/ + . += 0xC0000000; + + _kernel_start = .; + .text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000) + { *(.text) } /*general read only data*/ - .rodata BLOCK(4K) : ALIGN(4K) + .rodata ALIGN (4K) : AT(ADDR(.rodata) - 0xC0000000) { *(.rodata*) *(.gdt_sect) @@ -26,16 +38,18 @@ SECTIONS } /*initialized rw data. */ - .data BLOCK(4K) : ALIGN(4K) + .data ALIGN (4K) : AT(ADDR(.data) - 0xC0000000) { *(.data) } /*uninitialized data, and our stack as defined in start.s*/ - .bss BLOCK(4K) : ALIGN(4K) + .bss ALIGN(4K) : AT(ADDR(.bss) - 0xC0000000) { *(COMMON) *(.bss) + *(.bootstrap_tables) + *(.tss) *(.idt) } diff --git a/src/gdt.s b/src/gdt.s index ccd8bcf..7406b48 100644 --- a/src/gdt.s +++ b/src/gdt.s @@ -55,5 +55,5 @@ section .gdt_sect ;size of the gdt dw gdt_end - gdt - 1 ;location of the gdt - dd gdt + dd gdt - 0xC0000000 diff --git a/src/main.c b/src/main.c index bd24d37..5f48a81 100644 --- a/src/main.c +++ b/src/main.c @@ -7,6 +7,8 @@ #include "idt.h" #include "serial.h" #include "physmem.h" + + void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info) { //Hello C! Let's get to work in cleaning up our environment a bit and creating some safety. @@ -56,10 +58,10 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info) return; } - + /* This is broken while i implement virtual memory/paging unsigned int pages_allocated = build_bitmap((mb_mmap_entry_t*)multiboot_info->mmap_addr, multiboot_info->mmap_length); printf(default_output, "Available mem:%d Pages | %dK", pages_allocated, pages_allocated * 4); - + */ } diff --git a/src/start.s b/src/start.s index a48d4c5..009bce3 100644 --- a/src/start.s +++ b/src/start.s @@ -5,6 +5,8 @@ bits 32 ;Some symbols we'll need from other files... extern kern_main extern gdtr +extern _kernel_start +extern _kernel_end ;This will be our entrypoint function name - gotta initialize it now as global so the linker knows later. global start @@ -17,21 +19,28 @@ section .bss align=16 ;Therefore, we put a label here to represent the top of our stack for later. stack_top: ;We're gonna throw the TSS here too. + +section .tss align=16 nobits tss: resb 104 - + +section .bootstrap_tables nobits align=4096 + bootstrap_PD: + resb 4096 + bootstrap_PT: + resb 4096 ;Actual code. Entry point goes here! -section .text +section .lower_text exec ;Here it is! start: ;We made a GDT! Let's use it! - lgdt [gdtr] + lgdt [gdtr - 0xC0000000] ;Now we start by setting the code segment (CS) with a far jump... - jmp 0x08:segment_be_gone + jmp 0x08:gdt_load - segment_be_gone: + gdt_load: ;Now we go ahead and dump our kernel mode data segment (0x10) into the rest of our segments. ;Also preserving eax because it has the bootloader's multiboot magic in it and I want to check it in main. mov cx, 0x10 @@ -40,7 +49,67 @@ section .text mov ss, cx mov fs, cx mov gs, cx - ;Lets set up the stack. Stack grows downward on x86. We did the work earlier of defining where the top of the stack is, so just tell esp. + + ;So, we want to set up a page table and page directory. Let's take inventory. + ;eax - preserve, mb_magic + ;ebx - preserve, mb_info + ;ecx,edx,esi - can use + ;Can technically use esp as the stack is set to stack_top later. + + ;ecx = our current indexing for pages, this is a 4K-aligned address + mov ecx, 0x0 + ;edi = our pointer to the current page table entry. Array of 4byte entries. It's at, of course, where we put it earlier. + ;Worth noting that it's actually physically at ~1M with the kernel. The pointer, however, is virtually inclined. So we need to adjust. + mov edi, bootstrap_PT - 0xC0000000 + + page_alloc_loop: + ;If we're lower than our kernel, skip this page. If we've passed our kernel, we're done mapping. + cmp ecx, _kernel_start + jl next_page + cmp ecx, _kernel_end - 0xC0000000 + jge page_alloc_done + + ;Okay, we're in kernel zone. Let's map this one. + ;Let's make a page table entry in edx. + ;The top bits for the page table entry are just the upper bits of the address, so we dont need to touch it. + mov edx, ecx + ;Set last two bits, "present" and "writeable". Later on we'll make a proper page table with proper permissions, but we're bootstrapping here. + or edx, 0x003 + ;edi holds a pointer to the page table entry, so dereference it and throw our new entry (in edx) to it. Done! + mov [edi], edx + + next_page: + ;address page + 1 + add ecx, 0x1000 + ;page table entry + 1 + add edi, 4 + jmp page_alloc_loop + + page_alloc_done: + ;By now we've mapped the kernel in a page table! Let's map VGA too, we'll need that address later. + mov dword [bootstrap_PT - 0xC0000000 + 1023 * 4], 0x000B8000 | 0x27 + + ;We have our page tables mapped to the phys addr of kernel + VGA. Time to add them to our page directory! + ;First identity maps, second maps to higher half. + mov dword [bootstrap_PD - 0xC0000000], bootstrap_PT - 0xC0000000 + 0x003 + mov dword [bootstrap_PD - 0xC0000000 + 4 * (0xC0000000 >> 22)], bootstrap_PT - 0xC0000000 + 0x003 + + ;Let's set it! You do this with cr3. + mov ecx, bootstrap_PD - 0xC0000000 + mov cr3, ecx + + ;Enable paging in cr0 + mov ecx, cr0 + or ecx, 0x80010000 + mov cr0, ecx + ;Done! Leave to the higher half! + lea ecx, setup_c_env + jmp ecx + +section .text + + setup_c_env: + ;set up the stack. Stack grows downward on x86. We did the work earlier of defining where the top of the stack is, so just tell esp. mov esp, stack_top ;set the stack pointer push ebx push eax diff --git a/src/vga.c b/src/vga.c index 247a872..679d218 100644 --- a/src/vga.c +++ b/src/vga.c @@ -5,7 +5,7 @@ * VARS */ -volatile uint16_t* const vga_buffer = (uint16_t*)0xB8000; +volatile uint16_t* const vga_buffer = (uint16_t*)0xC03FF000; char_writer_t* default_vga = 0; /*