diff options
| author | Marin Ivanov <[email protected]> | 2024-05-02 17:48:15 +0300 |
|---|---|---|
| committer | Marin Ivanov <[email protected]> | 2024-05-02 17:48:15 +0300 |
| commit | ddaeafc36ab692f6a1d3af4b08ca6ca0bf942d2b (patch) | |
| tree | a3ba08d97f2f7008f0709e3c7acb42c14007ccd3 /src/bootstrap | |
| parent | d2315e49803fd4c982ccbaf0594d65da4842a701 (diff) | |
cleanup: extract bootstrap and multiboot2 header from main.zig
Diffstat (limited to 'src/bootstrap')
| -rw-r--r-- | src/bootstrap/boot.zig | 28 | ||||
| -rw-r--r-- | src/bootstrap/boot32.s | 143 | ||||
| -rw-r--r-- | src/bootstrap/boot64.s | 16 |
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 |
