diff options
| author | Aleksa Vuckovic <aleksav013@gmail.com> | 2022-07-31 03:55:45 +0200 |
|---|---|---|
| committer | Aleksa Vuckovic <aleksav013@gmail.com> | 2022-08-02 19:39:04 +0200 |
| commit | 132510156e1b907498dd83724f12ca101ae32f88 (patch) | |
| tree | e91a8b79fd3f090db0523fc78f308d81652693e8 /kernel | |
long mode multiboot2
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/boot.S | 138 | ||||
| -rw-r--r-- | kernel/boot64.S | 17 | ||||
| -rw-r--r-- | kernel/grub.cfg | 7 | ||||
| -rw-r--r-- | kernel/header.S | 17 | ||||
| -rw-r--r-- | kernel/kernel.ld | 38 | ||||
| -rw-r--r-- | kernel/main.c | 12 |
6 files changed, 229 insertions, 0 deletions
diff --git a/kernel/boot.S b/kernel/boot.S new file mode 100644 index 0000000..4276c98 --- /dev/null +++ b/kernel/boot.S @@ -0,0 +1,138 @@ +.global _start +.extern begin_long_mode + +.section .text +.code32 + +_start: + mov $stack_top, %esp + + call check_multiboot + call check_cpuid + call check_long_mode + + call setup_page_tables + call enable_paging + + lgdt gdt64_pointer + ljmp $gdt64_code_segment, $begin_long_mode + + +check_multiboot: + cmp $0x36d76289, %eax + jne no_multiboot + + ret + +check_cpuid: + pushfl + pop %eax + mov %eax, %ecx + xor $1<<21, %eax + push %eax + popfl + pushfl + pop %eax + push %ecx + popfl + cmp %eax, %ecx + je no_cpuid + + ret + +check_long_mode: + mov $0x80000000, %eax + cpuid + cmp $0x80000001, %eax + jb no_long_mode + + mov $0x80000001, %eax + cpuid + test $1<<29, %edx + jz no_long_mode + + ret + +setup_page_tables: + mov $page_table_lvl3, %eax + or $0x3, %eax + mov %eax, page_table_lvl4 + + mov $page_table_lvl2, %eax + or $0x3, %eax + mov %eax, page_table_lvl3 + + movl $0, %ecx +1: + movl $0x200000, %eax + mul %ecx + or $0b10000011, %eax + movl $page_table_lvl2, %edx + leal (%edx, %ecx, 8), %edx + movl %eax, (%edx) + inc %ecx + cmp $512, %ecx + jne 1b + + ret + +enable_paging: + // enable PAE + mov %cr4, %edx + or $1<<5 ,%edx + mov %edx, %cr4 + + // set LME (long mode enable) + mov $0xC0000080, %ecx + rdmsr + or $1<<8, %eax + wrmsr + + // page_table_lvl4 + mov $page_table_lvl4, %eax + mov %eax, %cr3 + + // enable paging (+ protected mode if not already enabled) + mov %cr0, %eax + or $1<<31 + 1<<0, %eax + mov %eax, %cr0 + + ret + +no_multiboot: + movl $0x4f4d, 0xb8000 + hlt + +no_cpuid: + movl $0x4f43, 0xb8000 + hlt + +no_long_mode: + movl $0x4f4c, 0xb8000 + hlt + + +.section .bss +.align 4096 + +// stack +stack_bottom: + .skip 4096*4 +stack_top: + +// page tables +page_table_lvl4: + .skip 4096 +page_table_lvl3: + .skip 4096 +page_table_lvl2: + .skip 4096 + +.section .rodata +gdt64: + .quad 0 +gdt64_code_segment = . - gdt64 + .quad 1<<43 + 1<<44 + 1<<47 + 1<<53 +gdt64_pointer: + .word . - gdt64 - 1 + .quad gdt64 diff --git a/kernel/boot64.S b/kernel/boot64.S new file mode 100644 index 0000000..e46bbef --- /dev/null +++ b/kernel/boot64.S @@ -0,0 +1,17 @@ +.global begin_long_mode + +.section .text +.code64 + +begin_long_mode: + + // reload segment registers + mov $0, %eax + mov %eax, %ss + mov %eax, %ds + mov %eax, %es + mov %eax, %fs + mov %eax, %gs + + call main + hlt diff --git a/kernel/grub.cfg b/kernel/grub.cfg new file mode 100644 index 0000000..535022a --- /dev/null +++ b/kernel/grub.cfg @@ -0,0 +1,7 @@ +set timeout=0 +set default=0 + +menuentry "mykernel64" { + multiboot2 /boot/kernel.bin + boot +} diff --git a/kernel/header.S b/kernel/header.S new file mode 100644 index 0000000..5a57741 --- /dev/null +++ b/kernel/header.S @@ -0,0 +1,17 @@ +.section .multiboot_header, "a" +.align 4 +header_start: + # magic number + .long 0xe85250d6 # multiboot2 + # architecture + .long 0 # protected mode i386 + # header length + .long (header_end - header_start) + # checksum + .long 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)) + + # end tag + .word 0 + .word 0 + .long 8 +header_end: diff --git a/kernel/kernel.ld b/kernel/kernel.ld new file mode 100644 index 0000000..bccea62 --- /dev/null +++ b/kernel/kernel.ld @@ -0,0 +1,38 @@ +ENTRY(_start) + +SECTIONS +{ + . = 1M; + + .boot BLOCK(4K) : ALIGN(4K) + { + KEEP(*(.multiboot_header)) + } + + .text BLOCK(4K) : ALIGN(4K) + { + *(.text) + } + + .rodata BLOCK(4K) : ALIGN(4K) + { + *(.rodata) + } + + .data BLOCK(4K) : ALIGN(4K) + { + *(.data) + } + + .bss BLOCK(4K) : ALIGN(4K) + { + *(COMMON) + *(.bss) + } + + /DISCARD/ : + { + *(.comment.*) + /* *(.note.*) */ + } +} diff --git a/kernel/main.c b/kernel/main.c new file mode 100644 index 0000000..ec40737 --- /dev/null +++ b/kernel/main.c @@ -0,0 +1,12 @@ +#include <stdint.h> + +int main(void) +{ + uint16_t* ct_buffer = (uint16_t*)0xb8000; + ct_buffer[0] = 0x2f4c; + ct_buffer[1] = 0x2f4f; + ct_buffer[2] = 0x2f4e; + ct_buffer[3] = 0x2f47; + + return 0; +} |
