aboutsummaryrefslogtreecommitdiff
path: root/src/boot/boot32.s
diff options
context:
space:
mode:
Diffstat (limited to 'src/boot/boot32.s')
-rw-r--r--src/boot/boot32.s137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/boot/boot32.s b/src/boot/boot32.s
new file mode 100644
index 0000000..5650422
--- /dev/null
+++ b/src/boot/boot32.s
@@ -0,0 +1,137 @@
+.global _start
+.extern long_mode_start
+
+.section .text
+.code32
+
+/* Entry point. It puts the machine into a consistent state and starts long mode. */
+_start:
+ mov $0x80000, %esp // Setup the stack.
+
+ call boot_check_multiboot
+ call boot_check_cpuid
+ call boot_check_long_mode
+
+ call boot_setup_page_tables
+ call boot_enable_paging
+
+ lgdt (boot_gdtdesc)
+ jmpl $0x8, $boot_long_mode_start
+ hlt
+
+boot_check_multiboot:
+ cmp $0x36d76289, %eax
+ jne .boot_no_multiboot
+ ret
+.boot_no_multiboot:
+ mov $'M', %al
+ jmp boot_error
+
+boot_check_cpuid:
+ pushfd
+ pop %eax
+ mov %eax, %ecx
+ xor $(1 << 21), %eax
+ push %eax
+ popfd
+ pushfd
+ pop %eax
+ push %ecx
+ popfd
+ cmp %eax, %ecx
+ je .boot_no_cpuid
+ ret
+.boot_no_cpuid:
+ mov $'C', %al
+ jmp boot_error
+
+boot_check_long_mode:
+ mov $0x80000000, %eax
+ cpuid
+ cmp $0x80000001, %eax
+ jb .boot_no_long_mode
+
+ mov $0x80000001, %eax
+ cpuid
+ test $(1 << 29), %edx
+ jz .boot_no_long_mode
+
+ ret
+.boot_no_long_mode:
+ mov $'L', %al
+ jmp boot_error
+
+boot_setup_page_tables:
+ mov $page_table_l3, %eax
+ or $0b11 , %eax /* present, writable */
+ mov %eax, (page_table_l4)
+
+ mov $page_table_l2, %eax
+ or $0b11, %eax /* present, writable */
+ mov %eax, (page_table_l3)
+
+ mov $0, %ecx /* counter */
+.boot_pages_loop:
+
+ mov $0x200000, %eax /* 2MiB */
+ mul %ecx
+ or $0b10000011, %eax /* present, writable, huge page */
+ mov %eax, +page_table_l2(,%ecx,8)
+
+ inc %ecx /* increment counter */
+ cmp $512, %ecx /* checks if the whole table is mapped */
+ jne .boot_pages_loop /* if not, continue */
+
+ ret
+
+boot_enable_paging:
+ /* pass page table location to cpu */
+ mov $page_table_l4, %eax
+ mov %eax, %cr3
+
+ /* enable PAE */
+ mov %cr4, %eax
+ or $(1 << 5), %eax
+ mov %eax, %cr4
+
+ /* enable long mode */
+ mov $0xC0000080, %ecx
+ rdmsr
+ or $(1 << 8), %eax
+ wrmsr
+
+ /* enable paging */
+ mov %cr0, %eax
+ or $(1 << 31), %eax
+ mov %eax, %cr0
+
+ ret
+
+boot_error:
+ /* print in VGA "ERR: X" where X is the error code */
+ movl $0x4f524f45, 0xb8000
+ movl $0x4f3a4f52, 0xb8004
+ movl $0x4f204f20, 0xb8008
+ movb %al, 0xb800a
+ hlt
+
+.section .bss
+.align 4096
+page_table_l4:
+ .skip 4096
+page_table_l3:
+ .skip 4096
+page_table_l2:
+ .skip 4096
+stack_bottom:
+ .skip 4096 * 4
+stack_top:
+
+.section .rodata
+.p2align 2 /* force 4 byte alignment */
+boot_gdt64:
+ .quad 0 /* zero entry */
+ .quad (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53) /* code segment */
+boot_gdtdesc:
+ .word (boot_gdtdesc - boot_gdt64 - 1) /* sizeof(gdt) - 1 */
+ .long boot_gdt64 /* address gdt */ \ No newline at end of file