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.
This commit is contained in:
parent
7d40987ab6
commit
8e8a5680d5
Notes:
sideshowbarker
2024-07-18 10:16:59 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/8e8a5680d58 Pull-request: https://github.com/SerenityOS/serenity/pull/8471 Reviewed-by: https://github.com/gunnarbeutner
1 changed files with 180 additions and 1 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue