summaryrefslogtreecommitdiff
path: root/kernel/arch/i386/boot.s
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2023-10-30 22:12:14 +0100
committerAnton Kling <anton@kling.gg>2023-10-31 00:18:38 +0100
commit8a9208612eec8ddae4c418485d848ecfa0613699 (patch)
tree2f4b29200c2f0c19ae52f45bdb9b38a41b356e30 /kernel/arch/i386/boot.s
parentca76600acc8bf7a02346efa5bd8f17072210ec01 (diff)
Meta: Move kernel and userland to their own folders.
This is to allow both the kernel and the userland to share certain header files and to make the folder structure a bit more clear.
Diffstat (limited to 'kernel/arch/i386/boot.s')
-rw-r--r--kernel/arch/i386/boot.s128
1 files changed, 128 insertions, 0 deletions
diff --git a/kernel/arch/i386/boot.s b/kernel/arch/i386/boot.s
new file mode 100644
index 0000000..61bbfbb
--- /dev/null
+++ b/kernel/arch/i386/boot.s
@@ -0,0 +1,128 @@
+.set ALIGN, 1<<0
+.set MEMINFO, 1<<1
+.set VIDEO_MODE, 1<<2
+.set FLAGS, VIDEO_MODE|ALIGN | MEMINFO
+.set MAGIC, 0x1BADB002
+.set CHECKSUM, -(MAGIC + FLAGS)
+
+#.section .multiboot
+.align 16, 0
+.section .multiboot.data, "aw"
+ .align 4
+ .long MAGIC
+ .long FLAGS
+ .long CHECKSUM
+ # unused(padding)
+ .long 0,0,0,0,0
+ # Video mode
+ .long 0 # Linear graphics
+ .long 0 # Preferred width
+ .long 0 # Preferred height
+ .long 32 # Preferred pixel depth
+
+# Allocate the initial stack.
+.section .bootstrap_stack, "aw", @nobits
+stack_bottom:
+.skip 16384 # 16 KiB
+stack_top:
+
+.global boot_page_directory
+.global boot_page_table1
+.section .bss, "aw", @nobits
+ .align 4096
+boot_page_directory:
+ .skip 4096
+boot_page_table1:
+ .skip 4096
+
+.section .multiboot.text, "a"
+.global _start
+.extern _kernel_end
+.type _start, @function
+# Kernel entry
+_start:
+ # edi contains the buffer we wish to modify
+ movl $(boot_page_table1 - 0xC0000000), %edi
+
+ # for loop
+ movl $0, %esi
+ movl $1024, %ecx
+1:
+ # esi = address
+ # If we are in kernel range jump to "label 2"
+ cmpl $_kernel_start, %esi
+ jl 2f
+
+ # If we are past the kernel jump to the final stage
+ # "label 3"
+ cmpl $(_kernel_end - 0xC0000000), %esi
+ jge 3f
+
+2:
+ # Add permission to the pages
+ movl %esi, %edx
+ orl $0x003, %edx
+ movl %edx, (%edi)
+
+ # Size of page is 4096 bytes.
+ addl $4096, %esi
+ # Size of entries in boot_page_table1 is 4 bytes.
+ addl $4, %edi
+ # Loop to the next entry if we haven't finished.
+ loop 1b
+
+3:
+ # Map the page table to both virtual addresses 0x00000000 and 0xC0000000.
+ movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 0
+ movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4
+
+ # Set cr3 to the address of the boot_page_directory.
+ movl $(boot_page_directory - 0xC0000000), %ecx
+ movl %ecx, %cr3
+
+ # Enable paging
+ movl %cr0, %ecx
+ orl $0x80000000, %ecx
+ movl %ecx, %cr0
+
+ # Jump to higher half with an absolute jump.
+ lea 4f, %ecx
+ jmp *%ecx
+
+.size _start, . - _start
+
+.section .text
+
+4:
+ # At this point, paging is fully set up and enabled.
+
+ # Unmap the identity mapping as it is now unnecessary.
+ movl $0, boot_page_directory + 0
+
+ # Reload crc3 to force a TLB flush so the changes to take effect.
+ movl %cr3, %ecx
+ movl %ecx, %cr3
+
+ # Set up the stack.
+ mov $stack_top, %esp
+
+ # Reset EFLAGS.
+ pushl $0
+ popf
+
+ pushl %esp
+
+ /* Push the pointer to the Multiboot information structure. */
+ pushl %ebx
+ /* Push the magic value. */
+ pushl %eax
+
+ mov $_kernel_end, %eax
+ pushl %eax
+ # Enter the high-level kernel.
+ call kernel_main
+
+ # Infinite loop if the system has nothing more to do.
+ cli
+1: hlt
+ jmp 1b