diff options
author | Liav A <liavalb@gmail.com> | 2021-07-05 21:49:24 +0300 |
---|---|---|
committer | Gunnar Beutner <gunnar@beutner.name> | 2021-07-06 19:01:27 +0200 |
commit | 8e8a5680d581d34fd6de8d15b63a924277c28a82 (patch) | |
tree | 8fd54aaf0b64b890ba05362c55737bc0bc83d0d7 /Kernel | |
parent | 7d40987ab62e2d4d52317683060df0a7f05d5d08 (diff) | |
download | serenity-8e8a5680d581d34fd6de8d15b63a924277c28a82.zip |
Kernel/x86_64: Print if machine doesn't support x86_64 mode
We drop to real mode and use two BIOS calls to do this.
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Arch/x86/common/Boot/boot.S | 181 |
1 files changed, 180 insertions, 1 deletions
diff --git a/Kernel/Arch/x86/common/Boot/boot.S b/Kernel/Arch/x86/common/Boot/boot.S index 1d383bf920..51ed1b0273 100644 --- a/Kernel/Arch/x86/common/Boot/boot.S +++ b/Kernel/Arch/x86/common/Boot/boot.S @@ -123,10 +123,189 @@ start: cpuid testl $(1 << 29), %edx /* Test if the LM-bit, which is bit 29, is set in the edx register. */ jnz continue /* If LM-bit is not enabled, there is no long mode. */ + + /* from now on, we don't really care about booting because we don't have long mode supported. + 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 "Long mode is not supported" String, call the BIOS print to screen service + c. halt + */ + +.equ NO_LONG_MODE_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 + + /* Copy no_long_mode_string to low memory section */ + lea no_long_mode_string, %eax + lea exiting_real_mode, %ebx + sub $0xc0000000, %ebx + sub $0xc0000000, %eax + + movl %ebx, %ecx + sub %eax, %ecx + mov %eax, %esi /* source address of the code */ + movw %cx, (NO_LONG_MODE_STRING_LOCATION) + mov $NO_LONG_MODE_STRING_LOCATION+2, %edi /* destination address of the code */ + rep movsb + + /* Copy gdt_table_real_mode to low memory section */ + lea gdt_table_real_mode, %eax + lea gdt_table_real_mode_end, %ebx + sub $0xc0000000, %ebx + sub $0xc0000000, %eax + + 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 */ + lea protected_mode_16_bit, %eax + lea real_mode, %ebx + sub $0xc0000000, %ebx + sub $0xc0000000, %eax + + 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 continue to low memory section */ + lea real_mode, %eax + lea continue, %ebx + sub $0xc0000000, %ebx + sub $0xc0000000, %eax + + 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 */ + lea exiting_real_mode, %eax + lea protected_mode_16_bit, %ebx + sub $0xc0000000, %ebx + sub $0xc0000000, %eax + + 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!" + +/* + 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 + retf + 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 + retf 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 (NO_LONG_MODE_STRING_LOCATION), %cx + movw $0, %dx + movw $NO_LONG_MODE_STRING_LOCATION + 2, %bp + int $0x10 + + movl $0xdeadcafe, %ebx + cli + hlt + +/* If long mode is supported, continue with booting the system */ + +.code32 continue: - /* restore the pushed registers */ + /* restore the pushed registers and continue with booting */ popl %ebx popl %edx popl %eax |