Fix A20 by copying others' implementation
The implementation of the A20 wraparound check was off in some way, which is why the new implementation was copied from osdev.org, just using minor modifications to the label naming.
This commit is contained in:
parent
5ba30e5f8b
commit
65db388f00
|
@ -1,95 +1,48 @@
|
|||
|
||||
; A20 Wraparound check as gotten from osdev.org
|
||||
check_a20_wraparound:
|
||||
.prolog:
|
||||
push dword esi
|
||||
sub esp, 64
|
||||
mov esi, esp
|
||||
pushf
|
||||
push ds
|
||||
push es
|
||||
push di
|
||||
push si
|
||||
|
||||
; EAX is used for the return value,
|
||||
; so it doesn't have to be preserved.
|
||||
mov [esi + (64 - 8)], ebx
|
||||
mov [esi + (64 - 12)], edi
|
||||
xor ax, ax ; ax = 0
|
||||
mov es, ax
|
||||
|
||||
.test_a20:
|
||||
; Save the values which are going to be overwritten
|
||||
mov edi, 0x0800
|
||||
mov eax, [edi]
|
||||
mov edi, 0x00100800
|
||||
mov ebx, [edi]
|
||||
not ax ; ax = 0xFFFF
|
||||
mov ds, ax
|
||||
|
||||
; Write to two locations which, if A20 wraps around,
|
||||
; will both be written to by the second statement.
|
||||
; Write 0 to 0x08000 to avoid the unlikely case that
|
||||
; those bytes are there coincidentally and A20 is on.
|
||||
mov edi, 0x0800
|
||||
mov [edi], dword 0x00000000
|
||||
mov edi, 0x00100800
|
||||
mov [edi], dword 0xffaa00dd
|
||||
mov di, 0x0500
|
||||
mov si, 0x0510
|
||||
|
||||
; Check the lower address (which should NOT contain)
|
||||
; this value for the value. If it does contain it, the
|
||||
; memory space wraps around to 0 every 2^19 bytes.
|
||||
cmp [0x0800], dword 0xffaa00dd
|
||||
je .return_a20_not_enabled ; If the value at 0x0800
|
||||
; was written to instead
|
||||
; (or at the same time) of
|
||||
; writing to 0x100800,
|
||||
; the A20 wasn't enabled.
|
||||
; Reset the values at the addresses to which the test
|
||||
; values were written znd return that A20 is enabled.
|
||||
mov edi, 0x0800
|
||||
mov [edi], eax
|
||||
mov edi, 0x00100800
|
||||
mov [edi], ebx
|
||||
mov al, byte [es:di]
|
||||
push ax
|
||||
|
||||
.return_a20_enabled:
|
||||
mov al, byte [ds:si]
|
||||
push ax
|
||||
|
||||
mov eax, 1
|
||||
mov byte [es:di], 0x00
|
||||
mov byte [ds:si], 0xFF
|
||||
|
||||
; Restore the one used register which
|
||||
; doesn't contain the return value.
|
||||
mov ebx, [esi + (64 - 8)]
|
||||
cmp byte [es:di], 0xFF
|
||||
|
||||
pop ax
|
||||
mov byte [ds:si], al
|
||||
|
||||
pop ax
|
||||
mov byte [es:di], al
|
||||
|
||||
mov ax, 0
|
||||
je .exit
|
||||
|
||||
mov ax, 1
|
||||
|
||||
.exit:
|
||||
pop si
|
||||
pop di
|
||||
pop es
|
||||
pop ds
|
||||
popf
|
||||
|
||||
add esp, 64
|
||||
pop dword esi
|
||||
ret
|
||||
|
||||
.return_a20_not_enabled:
|
||||
; It's only necessary to write to one of the addresses
|
||||
; as both of them are equal either way.
|
||||
mov edi, 0x0800
|
||||
mov [edi], eax
|
||||
|
||||
mov eax, 0
|
||||
|
||||
; Restore the one used register which
|
||||
; doesn't contain the return value.
|
||||
mov ebx, [esi + (64 - 12)]
|
||||
mov edi, [esi + (64 - 8)]
|
||||
|
||||
add esp, 64
|
||||
pop dword esi
|
||||
ret
|
||||
|
||||
|
||||
|
||||
enable_a20_through_keyboard_controller:
|
||||
.prolog:
|
||||
push dword esi
|
||||
sub esp, 64
|
||||
mov esi, esp
|
||||
|
||||
mov [esi + (64 - 8)], ebx
|
||||
mov [esi + (64 - 12)], ecx
|
||||
mov [esi + (64 - 16)], edx
|
||||
mov [esi + (64 - 20)], edi
|
||||
|
||||
.epilog:
|
||||
mov ebx, [esi + (64 - 8)]
|
||||
mov ecx, [esi + (64 - 12)]
|
||||
mov edx, [esi + (64 - 16)]
|
||||
mov edi, [esi + (64 - 20)]
|
||||
|
||||
add esp, 64
|
||||
pop dword esi
|
||||
ret
|
||||
|
|
Loading…
Reference in New Issue