diff --git a/src/gdt.s b/src/gdt.s new file mode 100644 index 0000000..5f93f15 --- /dev/null +++ b/src/gdt.s @@ -0,0 +1,56 @@ +global gdtr + +section .gdt_sect + gdt: + ;Null descriptor + dd 0x00000000 + dd 0x00000000 + ;Kernel code segment. + ;Limit: in 4kib pages. 0xFFFFF * 4K = full address space. + dw 0xFFFF + ;Base: Start at 0. We want the whole thing. + dw 0 + ;ALSO BASE: bits 16-23. All zeroes, still. + db 0 + ;Access byte. Defines flags for access permissions to the segment. This segment is: + ;RX, and code/data segment + db 0b10011010 + ;Next two segments are nibbles so I put them together (cant db only a nibble at once). + ;Upper limit bits (right hand nibble) is all ones to fill out the full 4gib in pages + ;Flags (left hand nibble) are set to say that the limit is meant to be read as pages, and we're working in 32bit. + db 0b11001111 + ;Final upper base bits. Still zero lol. + db 0 + ;Done! Now we move onto our next table entries, they are back to back. + ;Kernel Data Segment + dw 0xFFFF + dw 0 + db 0 + db 0b10010010 + db 0b11001111 + db 0 + ;User Code Segment + dw 0xFFFF + dw 0 + db 0 + db 0b11111010 + db 0b11001111 + db 0 + ;User Data Segment + dw 0xFFFF + dw 0 + db 0 + db 0b11110010 + db 0b11001111 + db 0 + ;Task State Segment + ;For a lot of this it's going to be zeroes so we can do it dynamically later (such as finding &tss). + ;Really, we just want to set the access bytes correctly. + dd 0 + db 0 + db 0b10001001 + dw 0 + gdtr: + dw gdtr - gdt - 1 + dd gdt + diff --git a/src/main.c b/src/main.c index 6d094d2..eb46240 100644 --- a/src/main.c +++ b/src/main.c @@ -8,6 +8,11 @@ //finally, main. 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. + //First interrupts. + + + //wipe the screen vga_clear(); //We're going to use this buffer as our 8char hex representation for reading mem diff --git a/src/multiboot.s b/src/multiboot.s new file mode 100644 index 0000000..e05ef8a --- /dev/null +++ b/src/multiboot.s @@ -0,0 +1,13 @@ +;multiboot for GRUB to boot it. Ideally stage01_bootloader will be able to support the multiboot standard. +;regardless of who's doing it, we have to set the required stuff +MB_MAGIC equ 0x1BADB002 ; bytes that bootloader will use to find this place +MB_FLAGS equ (1 << 0) | (1 << 1) ; flags request the following from the bootloader: maintain page boundaries + provide a memory map +MB_CHECKSUM equ (0 - (MB_MAGIC + MB_FLAGS)) ; Fails if checksum doesn't pass. Kind of arbitrary, but required. + + +;Now we actually place the multiboot stuff into the resulting executable... +section .multiboot align=4 + dd MB_MAGIC + dd MB_FLAGS + dd MB_CHECKSUM + diff --git a/src/start.s b/src/start.s index 8823c6e..d877dd8 100644 --- a/src/start.s +++ b/src/start.s @@ -1,24 +1,12 @@ -;C main function for our kernel -;See: kernel.c +; Bootloader places us in 32 bit mode :) bits 32 +;Some symbols we'll need from other files... extern kern_main +extern gdtr ;This will be our entrypoint function name - gotta initialize it now as global so the linker knows later. global start -;multiboot for GRUB to boot it. Ideally stage01_bootloader will be able to support the multiboot standard. -;regardless of who's doing it, we have to set the required stuff -MB_MAGIC equ 0x1BADB002 ; bytes that bootloader will use to find this place -MB_FLAGS equ (1 << 0) | (1 << 1) ; flags request the following from the bootloader: maintain page boundaries + provide a memory map -MB_CHECKSUM equ (0 - (MB_MAGIC + MB_FLAGS)) ; Fails if checksum doesn't pass. Kind of arbitrary, but required. - - -;Now we actually place the multiboot stuff into the resulting executable... -section .multiboot align=4 - dd MB_MAGIC - dd MB_FLAGS - dd MB_CHECKSUM - ; Set up for C code. Practically the only requirement for C-generated assembly to work properly is alignment and the presence of a stack. section .bss align=16 stack_bottom: @@ -26,65 +14,11 @@ section .bss align=16 ;Remember, stack grows DOWNWARD! So the last thing in the section -> the highest memory address -> the very first thing on the stack! ;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. tss: resb 104 - ;We're putting the GDT here. I'll be thoroughly commenting the first entry for my own understanding. Rest will be minimal. -section .gdt_sect - gdt: - ;Null descriptor - dd 0x00000000 - dd 0x00000000 - ;Kernel code segment. - ;Limit: in 4kib pages. 0xFFFFF * 4K = full address space. - dw 0xFFFF - ;Base: Start at 0. We want the whole thing. - dw 0 - ;ALSO BASE: bits 16-23. All zeroes, still. - db 0 - ;Access byte. Defines flags for access permissions to the segment. This segment is: - ;RX, and code/data segment - db 0b10011010 - ;Next two segments are nibbles so I put them together (cant db only a nibble at once). - ;Upper limit bits (right hand nibble) is all ones to fill out the full 4gib in pages - ;Flags (left hand nibble) are set to say that the limit is meant to be read as pages, and we're working in 32bit. - db 0b11001111 - ;Final upper base bits. Still zero lol. - db 0 - ;Done! Now we move onto our next table entries, they are back to back. - ;Kernel Data Segment - dw 0xFFFF - dw 0 - db 0 - db 0b10010010 - db 0b11001111 - db 0 - ;User Code Segment - dw 0xFFFF - dw 0 - db 0 - db 0b11111010 - db 0b11001111 - db 0 - ;User Data Segment - dw 0xFFFF - dw 0 - db 0 - db 0b11110010 - db 0b11001111 - db 0 - ;Task State Segment - ;For a lot of this it's going to be zeroes so we can do it dynamically later (such as finding &tss). - ;Really, we just want to set the access bytes correctly. - dd 0 - db 0 - db 0b10001001 - dw 0 - gdtr: - dw gdtr - gdt - 1 - dd gdt - ;Actual code. Entry point goes here! section .text ;Here it is!