Enable A20 line and enter 'unreal mode' in the bootsect

This commit is contained in:
mintsuki 2019-05-30 16:25:23 +02:00
parent 3c4c1a878a
commit 563825e44d
4 changed files with 255 additions and 13 deletions

126
bootsect/a20_enabler.inc Normal file
View File

@ -0,0 +1,126 @@
a20_check:
; *************************************************
; Checks if the A20 address line is enabled
; *************************************************
; OUT:
; Carry if disabled, cleared if enabled
push ax ; Save registers
push bx
push es
push fs
xor ax, ax ; Set ES segment to zero
mov es, ax
not ax ; Set FS segment to 0xFFFF
mov fs, ax
mov ax, word [es:0x7DFE] ; Check using boot signature
cmp word [fs:0x7E0E], ax ; If A20 is disabled, this should be the
; same address as the boot signature
je .change_values ; If they are equal, check again with another value
.enabled:
clc ; A20 is enabled, clear carry flag
jmp .done
.change_values:
mov word [es:0x7DFE], 0x1234 ; Change the value of 0000:7DFE to 0x1234
cmp word [fs:0x7E0E], 0x1234 ; Is FFFF:7E0E changed as well?
jne .enabled ; If it is, A20 is enabled
stc ; Otherwise set carry
.done:
mov word [es:0x7DFE], ax ; Restore boot signature
pop fs ; Restore registers
pop es
pop bx
pop ax
ret ; Exit routine
enable_a20:
; ********************************************
; Tries to enable the A20 address line
; ********************************************
; OUT:
; Carry cleared if success, set if fail
push eax ; Save registers
call a20_check ; Check if a20 is already enabled
jnc .done ; If it is, we are done
mov ax, 0x2401 ; Use BIOS to try to enable a20
int 0x15
call a20_check ; Check again to see if BIOS succeeded
jnc .done ; If it has, we are done
.keyboard_method:
cli ; Disable interrupts
call .a20wait ; Use the keyboard controller to try and
mov al, 0xAD ; open the A20 gate
out 0x64, al
call .a20wait
mov al, 0xD0
out 0x64, al
call .a20wait2
in al, 0x60
push eax
call .a20wait
mov al, 0xD1
out 0x64, al
call .a20wait
pop eax
or al, 2
out 0x60, al
call .a20wait
mov al, 0xAE
out 0x64, al
call .a20wait
sti ; Enable interrupts back
jmp .keyboard_done
.a20wait:
in al, 0x64
test al, 2
jnz .a20wait
ret
.a20wait2:
in al, 0x64
test al, 1
jz .a20wait2
ret
.keyboard_done:
call a20_check ; Check for success
; Now just quit the routine, forwarding the carry flag to the caller
.done:
pop eax
ret

View File

@ -15,8 +15,6 @@ mov ss, ax
mov sp, 0x7c00
sti
mov byte [drive_number], dl
mov si, LoadingMsg
call simple_print
@ -27,7 +25,7 @@ call simple_print
mov ax, 1
mov ebx, 0x7e00
mov cx, 7
mov cx, 1
call read_sectors
jc err
@ -45,23 +43,82 @@ halt:
hlt
jmp halt
;Data
; Data
LoadingMsg db 0x0D, 0x0A, '<qLoader 2>', 0x0D, 0x0A, 0x0A, 0x00
Stage2Msg db 'stage1: Loading stage2...', 0x00
ErrMsg db 0x0D, 0x0A, 'Error, system halted.', 0x00
DoneMsg db ' DONE', 0x0D, 0x0A, 0x00
LoadingMsg db 0x0D, 0x0A, '<qLoader 2>', 0x0D, 0x0A, 0x0A, 0x00
Stage2Msg db 'stage1: Loading stage2...', 0x00
ErrMsg db 0x0D, 0x0A, 'Error, system halted.', 0x00
DoneMsg db ' DONE', 0x0D, 0x0A, 0x00
times 0xda-($-$$) db 0
times 6 db 0
;Includes
; Includes
%include 'simple_print.inc'
%include 'disk.inc'
drive_number db 0
times 0x1b8-($-$$) db 0
times 510-($-$$) db 0
dw 0xaa55
; ********************* Stage 2 *********************
; ***** A20 *****
call enable_a20
jc err
; Enable 4GiB limits
lgdt [GDT] ; Load the GDT
cli
mov eax, cr0
or eax, 00000001b
mov cr0, eax
jmp 0x08:.pmodeu
.pmodeu:
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov eax, cr0
and eax, 11111110b
mov cr0, eax
jmp 0x0000:.unreal_mode
.unreal_mode:
xor ax, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
sti
; Load stage 3
mov ax, 2
mov ebx, 0x8000
mov cx, 6
call read_sectors
jc err
jmp 0x8000
%include 'a20_enabler.inc'
%include 'gdt.inc'
times 1024-($-$$) db 0

59
bootsect/gdt.inc Normal file
View File

@ -0,0 +1,59 @@
GDT:
dw .GDTEnd - .GDTStart - 1 ; GDT size
dd .GDTStart ; GDT start
.GDTStart:
; Null descriptor (required)
.NullDescriptor:
dw 0x0000 ; Limit
dw 0x0000 ; Base (low 16 bits)
db 0x00 ; Base (mid 8 bits)
db 00000000b ; Access
db 00000000b ; Granularity
db 0x00 ; Base (high 8 bits)
; Unreal mode
.UnrealCode:
dw 0xFFFF ; Limit
dw 0x0000 ; Base (low 16 bits)
db 0x00 ; Base (mid 8 bits)
db 10011010b ; Access
db 10001111b ; Granularity
db 0x00 ; Base (high 8 bits)
.UnrealData:
dw 0xFFFF ; Limit
dw 0x0000 ; Base (low 16 bits)
db 0x00 ; Base (mid 8 bits)
db 10010010b ; Access
db 10001111b ; Granularity
db 0x00 ; Base (high 8 bits)
; Protected mode
.PmodeCode:
dw 0xFFFF ; Limit
dw 0x0000 ; Base (low 16 bits)
db 0x00 ; Base (mid 8 bits)
db 10011010b ; Access
db 11001111b ; Granularity
db 0x00 ; Base (high 8 bits)
.PmodeData:
dw 0xFFFF ; Limit
dw 0x0000 ; Base (low 16 bits)
db 0x00 ; Base (mid 8 bits)
db 10010010b ; Access
db 11001111b ; Granularity
db 0x00 ; Base (high 8 bits)
.GDTEnd:

View File

@ -3,7 +3,7 @@ ENTRY(main)
SECTIONS
{
. = 0x7e00;
. = 0x8000;
.text : {
bootsect_begin = .;
@ -14,7 +14,7 @@ SECTIONS
.data : {
KEEP(*(.data*))
KEEP(*(.bss*))
. += 3584 - (. - bootsect_begin);
. += 3072 - (. - bootsect_begin);
}
}