diff options
author | Nico Weber <thakis@chromium.org> | 2021-08-28 13:39:34 -0400 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-08-28 21:51:30 +0100 |
commit | da785bd4bd6e63624954c6ebb90e017c6fe61099 (patch) | |
tree | 16bfe26b2c12ff375ef728076bc0e03d5bb10064 /Kernel/Prekernel/boot.S | |
parent | ce98aa567c5a2b67ca62ae2ba1fd450bb479943e (diff) | |
download | serenity-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.S | 512 |
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 |