aboutsummaryrefslogtreecommitdiff
path: root/src/bootstrap/boot32.s
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootstrap/boot32.s')
-rw-r--r--src/bootstrap/boot32.s143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/bootstrap/boot32.s b/src/bootstrap/boot32.s
new file mode 100644
index 0000000..dc02102
--- /dev/null
+++ b/src/bootstrap/boot32.s
@@ -0,0 +1,143 @@
+.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.
+ push %ebx // Pass multiboot info structure.
+ push %eax // Pass multiboot magic code.
+
+ call check_multiboot
+ call check_cpuid
+ call check_long_mode
+
+ call setup_page_tables
+ call enable_paging
+
+ lgdt (gdtdesc)
+ jmpl $0x8, $long_mode_start
+
+ call halt
+halt:
+ hlt
+
+check_multiboot:
+ cmp $0x36d76289, %eax
+ jne .no_multiboot
+ ret
+.no_multiboot:
+ mov $'M', %al
+ jmp error
+
+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 .no_cpuid
+ ret
+.no_cpuid:
+ mov $'C', %al
+ jmp error
+
+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
+.no_long_mode:
+ mov $'L', %al
+ jmp error
+
+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 */
+.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 .loop /* if not, continue */
+
+ ret
+
+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
+
+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 */
+gdt64:
+ .quad 0 /* zero entry */
+.code_segment:
+ .quad (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53) /* code segment */
+gdtdesc:
+ .word (gdtdesc - gdt64 - 1) /* sizeof(gdt) - 1 */
+ .long gdt64 /* address gdt */ \ No newline at end of file