summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/boot.S138
-rw-r--r--kernel/boot64.S17
-rw-r--r--kernel/grub.cfg7
-rw-r--r--kernel/header.S17
-rw-r--r--kernel/kernel.ld38
-rw-r--r--kernel/main.c12
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;
+}