summaryrefslogtreecommitdiff
path: root/Kernel/Prekernel/boot.S
diff options
context:
space:
mode:
authorNico Weber <thakis@chromium.org>2021-08-28 13:39:34 -0400
committerLinus Groh <mail@linusgroh.de>2021-08-28 21:51:30 +0100
commitda785bd4bd6e63624954c6ebb90e017c6fe61099 (patch)
tree16bfe26b2c12ff375ef728076bc0e03d5bb10064 /Kernel/Prekernel/boot.S
parentce98aa567c5a2b67ca62ae2ba1fd450bb479943e (diff)
downloadserenity-da785bd4bd6e63624954c6ebb90e017c6fe61099.zip
Prekernel: Move boot.S and multiboot.S into an Arch/x86 subfolder
Diffstat (limited to 'Kernel/Prekernel/boot.S')
-rw-r--r--Kernel/Prekernel/boot.S512
1 files changed, 0 insertions, 512 deletions
diff --git a/Kernel/Prekernel/boot.S b/Kernel/Prekernel/boot.S
deleted file mode 100644
index 28da45d577..0000000000
--- a/Kernel/Prekernel/boot.S
+++ /dev/null
@@ -1,512 +0,0 @@
-#include <AK/Platform.h>
-#include <Kernel/Prekernel/Prekernel.h>
-
-.code32
-
-.section .stack, "aw", @nobits
-stack_bottom:
-.skip 32768
-stack_top:
-
-.global kernel_cmdline
-kernel_cmdline:
-.skip 4096
-
-.section .page_tables, "aw", @nobits
-.align 4096
-#if ARCH(X86_64)
-.global boot_pml4t
-boot_pml4t:
-.skip 4096
-#endif
-.global boot_pdpt
-boot_pdpt:
-.skip 4096
-.global boot_pd0
-boot_pd0:
-.skip 4096
-.global boot_pd0_pts
-boot_pd0_pts:
-.skip 4096 * (MAX_KERNEL_SIZE >> 21)
-.global boot_pd_kernel
-boot_pd_kernel:
-.skip 4096
-.global boot_pd_kernel_pt0
-boot_pd_kernel_pt0:
-.skip 4096
-.global boot_pd_kernel_image_pts
-boot_pd_kernel_image_pts:
-.skip 4096 * (MAX_KERNEL_SIZE >> 21)
-.global boot_pd_kernel_pt1023
-boot_pd_kernel_pt1023:
-.skip 4096
-
-.section .text
-
-.global start
-.type start, @function
-
-.extern init
-.type init, @function
-
-.global reload_cr3
-.type reload_cr3, @function
-
-.extern multiboot_info_ptr
-.type multiboot_info_ptr, @object
-
-/*
- construct the following (64-bit PML4T) page table layout:
- (the PML4T part is not used for 32-bit x86)
-
-pml4t:
-
- 0: pdpt (0-512GB)
-
-pdpt
-
- 0: boot_pd0 (0-1GB)
- 1: n/a (1-2GB)
- 2: n/a (2-3GB)
- 3: n/a (3-4GB)
-
-boot_pd0 : 512 PDEs
-
- boot_pd0_pts (0MB - MAX_KERNEL_SIZE) (id 512 4KB pages)
-
-the page tables each contain 512 PTEs that map individual 4KB pages
-
-*/
-
-#if ARCH(X86_64)
-gdt64:
- .quad 0
-gdt64code:
- .quad (1<<43) | (1<<44) | (1<<47) | (1<<53) /* executable, code segment, present, 64-bit */
-.global gdt64ptr
-gdt64ptr:
- .short . - gdt64 - 1
- .quad gdt64
-
-.set code64_sel_value, gdt64code - gdt64
-
-.global code64_sel
-code64_sel:
-.short code64_sel_value
-#endif
-
-start:
- jmp real_start
-
-/*
- this function assumes that paging is disabled (or everything is mapped 1:1)
- param 1: pointer to string ended with null terminator (C string)
-*/
-print_and_halt:
-
-/* from now on, we don't really care about booting because we are missing required CPU features such as PAE or long mode.
- the flow from now is like so:
- 1. Copy all necessary parts to low memory section in RAM
- 2. Jump to that section
- 3. In that section we do:
- a. exit protected mode to pure 16 bit real mode
- b. load the "<missing feature> is not supported" String, call the BIOS print to screen service
- c. halt
-*/
-
-.equ COPIED_STRING_LOCATION, 0x400
-.equ GDT_REAL_MODE_LOCATION, 0x45000
-.equ EXITING_PROTECTED_MODE_CODE_LOCATION, 0x10000
-.equ REAL_MODE_CODE, 0x500
-.equ PROTECTED_MODE_16_BIT_CODE, 0x600
- movl %esp, %ebp
- movl 4(%ebp), %edi
-
- /* Copy string to low memory section */
- movl %edi, %esi
- xor %ecx, %ecx
-
- pushl %eax
- pushl %edi
-check_string_length:
- movb (%edi), %ah
- cmp $0, %ah
- je check_string_length_exit
- inc %ecx
- inc %edi
- jmp check_string_length
-check_string_length_exit:
- popl %edi
- popl %eax
-
- /* source address of the code is ESI */
- movw %cx, (COPIED_STRING_LOCATION)
- mov $COPIED_STRING_LOCATION + 2, %edi /* destination address of the code */
- rep movsb
-
- /* Copy gdt_table_real_mode to low memory section */
- movl $gdt_table_real_mode, %eax
- movl $gdt_table_real_mode_end, %ebx
-
- movl %ebx, %ecx
- sub %eax, %ecx
- mov %eax, %esi /* source address of the code */
- mov $GDT_REAL_MODE_LOCATION, %edi /* destination address of the code */
- rep movsb
-
- /* Copy protected_mode_16_bit to real_mode to low memory section */
- movl $protected_mode_16_bit, %eax
- movl $real_mode, %ebx
-
- movl %ebx, %ecx
- sub %eax, %ecx
- mov %eax, %esi /* source address of the code */
- mov $PROTECTED_MODE_16_BIT_CODE, %edi /* destination address of the code */
- rep movsb
-
- /* Copy real_mode to end_of_print_and_halt_function to low memory section */
- movl $real_mode, %eax
- movl $end_of_print_and_halt_function, %ebx
-
- movl %ebx, %ecx
- sub %eax, %ecx
- mov %eax, %esi /* source address of the code */
- mov $REAL_MODE_CODE, %edi /* destination address of the code */
- rep movsb
-
-
- /* Copy all opcodes from exiting_real_mode label to protected_mode_16_bit label to low memory RAM */
- movl $exiting_real_mode, %eax
- movl $protected_mode_16_bit, %ebx
-
- movl %ebx, %ecx
- sub %eax, %ecx
- mov %eax, %esi /* source address of the code */
- mov $EXITING_PROTECTED_MODE_CODE_LOCATION, %edi /* destination address of the code */
- pushl %edi
- rep movsb
- popl %edi
- pushl %edi
- ret
-
-gdt_table_real_mode:
- .quad 0 /* Empty entry */
-
- .short 0xffff
- .short 0
- .byte 0
- .byte 0b10011010
- .byte 0b00001111
- .byte 0x0
-
- .short 0xffff
- .short 0
- .byte 0
- .byte 0b10010010
- .byte 0b00001111
- .byte 0x0
-gdt_table_real_mode_end:
-
-no_long_mode_string:
- .asciz "Your computer does not support long mode (64-bit mode). Halting!"
-
-no_pae_string:
- .asciz "Your computer does not support PAE. Halting!"
-
-kernel_image_too_big_string:
- .asciz "Error: Kernel Image too big for memory slot. Halting!"
-
-/*
- This part is completely standalone - it doesn't involve any location from this
- near code. It uses arbitrary locations in the low memory section of the RAM.
- We don't really worry about where are these locations, because we only want to quickly
- print a string and halt.
-*/
-.code32
-exiting_real_mode:
-
- /* Build IDT pointer and load it */
- mov $0x50000, %eax
- pushl %eax
- movl $0x3ff, 0(%eax)
- add $2, %eax
- movl $0, 0(%eax)
- popl %eax
- lidt (%eax)
-
- /* Build GDT pointer and load it */
- mov $0x40000, %eax
- pushl %eax
- movl $32, 0(%eax)
- add $2, %eax
- movl $GDT_REAL_MODE_LOCATION, 0(%eax)
- popl %eax
- lgdt (%eax)
-
- /* far jump to protected_mode_16_bit in 0x5000 */
- pushw $8
- push $PROTECTED_MODE_16_BIT_CODE
- lret
- hlt
-
-.code16
-protected_mode_16_bit:
- xor %eax, %eax
- movl $0x10, %eax
- movw %ax, %ds
- and $0xFE, %al /* switch to pure real mode */
- mov %eax, %cr0
- mov $0x10, %eax
- movl %eax, %cr0
-
- pushw $0
- push $REAL_MODE_CODE
- lret
- hlt
-
-real_mode:
- movw $0x7000, %ax
- movl $0x0000, %esp
- movw %ax, %ss
-
- xor %ax, %ax
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %fs
- movw %ax, %gs
-
- mov $0x3, %ax
- int $0x10
-
- movb $0x13, %ah
- movb $0x0, %bh
- movb $0xf, %bl
- movw (COPIED_STRING_LOCATION), %cx
- movw $0, %dx
- movw $COPIED_STRING_LOCATION + 2, %bp
- int $0x10
-
- movl $0xdeadcafe, %ebx
- cli
- hlt
-end_of_print_and_halt_function:
-
-.code32
-real_start:
- cli
- cld
- mov $end_of_prekernel_image, %esi
- cmp $MAX_KERNEL_SIZE, %esi
- jbe kernel_not_too_large
-
- movl $kernel_image_too_big_string, %esi
- pushl %esi
- call print_and_halt
- /* We should not return, but just in case, halt */
- hlt
-
-kernel_not_too_large:
- /* test for PAE presence, save the most important registers from corruption */
- pushl %eax
- pushl %edx
- pushl %ebx
-
- movl $0x1, %eax /* PAE presence is in CPUID input 0x1 */
- cpuid
- testl $(1 << 6), %edx /* Test if the PAE-bit, which is bit 6, is set in the edx register. */
- jnz pae_supported /* If the bit is not set, there is no PAE capability. */
-
- /* Since there is no PAE capability, halt with an error message */
- movl $no_pae_string, %esi
- pushl %esi
- call print_and_halt
- /* We should not return, but just in case, halt */
- hlt
-
-
-#if ARCH(X86_64)
-pae_supported:
- movl $0x80000001, %eax
- cpuid
- testl $(1 << 29), %edx /* Test if the LM-bit, which is bit 29, is set in the edx register. */
- jnz long_mode_supported /* If LM-bit is not enabled, there is no long mode. */
-
- /* Since there is no long mode, halt with an error message */
- movl $no_long_mode_string, %esi
- pushl %esi
- call print_and_halt
- /* We should not return, but just in case, halt */
- hlt
-
-
-/* If both PAE and long mode is supported, continue with booting the system */
-
-long_mode_supported:
- /* restore the pushed registers and continue with booting */
- popl %ebx
- popl %edx
- popl %eax
-#else
-/* If PAE is supported, continue with booting the system */
-
-pae_supported:
- /* restore the pushed registers and continue with booting */
- popl %ebx
- popl %edx
- popl %eax
-#endif
-
- /* We don't know where the bootloader might have put the command line.
- * It might be at an inconvenient location that we're not about to map,
- * so let's just copy it to a convenient location while we have the whole
- * memory space identity-mapped anyway. :^)
- */
-
- movl %ebx, %esi
- addl $16, %esi
- movl (%esi), %esi
- movl $1024, %ecx
- movl $kernel_cmdline, %edi
- rep movsl
-
-#if ARCH(X86_64)
- /* clear pml4t */
- movl $boot_pml4t, %edi
- movl $1024, %ecx
- xorl %eax, %eax
- rep stosl
-
- /* set up pml4t[0] */
- movl $boot_pml4t, %edi
- movl $boot_pdpt, 0(%edi)
- /* R/W + Present */
- orl $0x3, 0(%edi)
-#endif
-
- /* clear pdpt */
- movl $boot_pdpt, %edi
- movl $1024, %ecx
- xorl %eax, %eax
- rep stosl
-
- /* set up pdpt[0] and pdpt[3] */
- movl $boot_pdpt, %edi
-#if ARCH(X86_64)
- movl $(boot_pd0 + 3), 0(%edi)
-#else
- movl $(boot_pd0 + 1), 0(%edi)
-#endif
-
- /* clear pd0 */
- movl $boot_pd0, %edi
- movl $1024, %ecx
- xorl %eax, %eax
- rep stosl
-
- /* clear pd0's PTs */
- movl $boot_pd0_pts, %edi
- movl $(1024 * (MAX_KERNEL_SIZE >> 21)), %ecx
- xorl %eax, %eax
- rep stosl
-
- /* add boot_pd0_pts to boot_pd0 */
- movl $(MAX_KERNEL_SIZE >> 21), %ecx
- movl $boot_pd0, %edi
- movl $boot_pd0_pts, %eax
-
-1:
- movl %eax, 0(%edi)
- /* R/W + Present */
- orl $0x3, 0(%edi)
- addl $8, %edi
- addl $4096, %eax
- loop 1b
-
- /* identity map the 0MB to MAX_KERNEL_SIZE range */
- movl $(512 * (MAX_KERNEL_SIZE >> 21)), %ecx
- movl $boot_pd0_pts, %edi
- xorl %eax, %eax
-
-1:
- movl %eax, 0(%edi)
- /* R/W + Present */
- orl $0x3, 0(%edi)
- addl $8, %edi
- addl $4096, %eax
- loop 1b
-
-#if ARCH(X86_64)
- /* point CR3 to PML4T */
- movl $boot_pml4t, %eax
-#else
- /* point CR3 to PDPT */
- movl $boot_pdpt, %eax
-#endif
-
- movl %eax, %cr3
-
- /* enable PAE + PSE */
- movl %cr4, %eax
- orl $0x60, %eax
- movl %eax, %cr4
-
-#if ARCH(X86_64)
-1:
- /* Enter Long-mode! ref(https://wiki.osdev.org/Setting_Up_Long_Mode)*/
- mov $0xC0000080, %ecx /* Set the C-register to 0xC0000080, which is the EFER MSR.*/
- rdmsr /* Read from the model-specific register.*/
- or $(1 << 8), %eax /* Set the LM-bit which is the 9th bit (bit 8).*/
- wrmsr /* Write to the model-specific register.*/
-#endif
-
- /* enable PG */
- movl %cr0, %eax
- orl $0x80000000, %eax
- movl %eax, %cr0
-
- /* set up stack */
- mov $stack_top, %esp
- and $-16, %esp
-
-#if ARCH(X86_64)
- /* Now we are in 32-bit compatibility mode, We still need to load a 64-bit GDT */
- mov $gdt64ptr, %eax
- lgdt (%eax)
- ljmpl $code64_sel_value, $1f
-
-.code64
-1:
- movl %ebx, %ebx
- movq %rbx, multiboot_info_ptr
-
- mov $0, %ax
- mov %ax, %ss
- mov %ax, %ds
- mov %ax, %es
- mov %ax, %fs
- mov %ax, %gs
-#else
- movl %ebx, multiboot_info_ptr
-#endif
-
- call reload_cr3
- call init
-
- cli
-loop:
- hlt
- jmp loop
-
-reload_cr3:
-#if ARCH(X86_64)
- pushq %rax
- mov %cr3, %rax
- mov %rax, %cr3
- popq %rax
-#else
- pushl %eax
- movl %cr3, %eax
- movl %eax, %cr3
- popl %eax
-#endif
- ret