aboutsummaryrefslogtreecommitdiff
path: root/src/bootstrap
diff options
context:
space:
mode:
authorMarin Ivanov <[email protected]>2024-05-02 17:48:15 +0300
committerMarin Ivanov <[email protected]>2024-05-02 17:48:15 +0300
commitddaeafc36ab692f6a1d3af4b08ca6ca0bf942d2b (patch)
treea3ba08d97f2f7008f0709e3c7acb42c14007ccd3 /src/bootstrap
parentd2315e49803fd4c982ccbaf0594d65da4842a701 (diff)
cleanup: extract bootstrap and multiboot2 header from main.zig
Diffstat (limited to 'src/bootstrap')
-rw-r--r--src/bootstrap/boot.zig28
-rw-r--r--src/bootstrap/boot32.s143
-rw-r--r--src/bootstrap/boot64.s16
3 files changed, 187 insertions, 0 deletions
diff --git a/src/bootstrap/boot.zig b/src/bootstrap/boot.zig
new file mode 100644
index 0000000..fcb60eb
--- /dev/null
+++ b/src/bootstrap/boot.zig
@@ -0,0 +1,28 @@
+comptime {
+ asm (@embedFile("boot64.s"));
+ asm (@embedFile("boot32.s"));
+}
+
+const MAGIC = 0xE85250D6;
+const ARCHITECTURE = 0;
+
+const MultibootHeader = extern struct {
+ magic: u32,
+ architecture: u32,
+ header_len: u32,
+ checksum: u32,
+
+ tag0: u16,
+ tag1: u16,
+ tag2: u32,
+};
+
+export const multiboot2 align(4) linksection(".multiboot") = MultibootHeader{
+ .magic = MAGIC,
+ .architecture = ARCHITECTURE,
+ .header_len = 24,
+ .checksum = 0x100000000 - (MAGIC + ARCHITECTURE + 24),
+ .tag0 = 0,
+ .tag1 = 0,
+ .tag2 = 8,
+};
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
diff --git a/src/bootstrap/boot64.s b/src/bootstrap/boot64.s
new file mode 100644
index 0000000..493912b
--- /dev/null
+++ b/src/bootstrap/boot64.s
@@ -0,0 +1,16 @@
+.global long_mode_start
+.extern kmain
+
+.section .text
+.code64
+long_mode_start:
+ // load null into all data segment registers
+ mov $0, %ax
+ mov %ax, %ss
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+
+ call kmain
+ hlt \ No newline at end of file