Enable A20 line and enter 'unreal mode' in the bootsect
This commit is contained in:
parent
3c4c1a878a
commit
563825e44d
126
bootsect/a20_enabler.inc
Normal file
126
bootsect/a20_enabler.inc
Normal 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
|
@ -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
59
bootsect/gdt.inc
Normal 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:
|
Loading…
Reference in New Issue
Block a user