aboutsummaryrefslogtreecommitdiff
path: root/src/boot
diff options
context:
space:
mode:
authorMarin Ivanov <[email protected]>2024-05-02 19:02:42 +0300
committerMarin Ivanov <[email protected]>2024-05-02 19:02:42 +0300
commita98393d68bb76c21015d2d41d4092f9552016bad (patch)
tree2ab78c97142ca18ec360fe3d7938a1647746353c /src/boot
parent73aa1c6db67924c073d05cd167d4c70f4b7ae09f (diff)
cleanup: prefix boot labels
Diffstat (limited to 'src/boot')
-rw-r--r--src/boot/boot.zig29
-rw-r--r--src/boot/boot32.s137
-rw-r--r--src/boot/boot64.s15
3 files changed, 181 insertions, 0 deletions
diff --git a/src/boot/boot.zig b/src/boot/boot.zig
new file mode 100644
index 0000000..998e1e5
--- /dev/null
+++ b/src/boot/boot.zig
@@ -0,0 +1,29 @@
+comptime {
+ asm (@embedFile("boot64.s"));
+ asm (@embedFile("boot32.s"));
+}
+
+const MAGIC = 0xE85250D6;
+const ARCHITECTURE = 0;
+
+const EndTag = packed struct {
+ type: u16 = 0,
+ flags: u16 = 0,
+ size: u32 = 8,
+};
+
+const MultibootHeader = extern struct {
+ magic: u32,
+ architecture: u32,
+ header_len: u32,
+ checksum: u32,
+ endtag: EndTag,
+};
+
+export const multiboot2 align(4) linksection(".multiboot") = MultibootHeader{
+ .magic = MAGIC,
+ .architecture = ARCHITECTURE,
+ .header_len = 24,
+ .checksum = 0x100000000 - (MAGIC + ARCHITECTURE + 24),
+ .endtag = EndTag{},
+};
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
diff --git a/src/boot/boot64.s b/src/boot/boot64.s
new file mode 100644
index 0000000..e851388
--- /dev/null
+++ b/src/boot/boot64.s
@@ -0,0 +1,15 @@
+.global boot_long_mode_start
+.extern kmain
+
+.section .text
+.code64
+boot_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
+
+ jmp kmain \ No newline at end of file