[MBR] Add A20 line
This commit is contained in:
parent
1f88f01c33
commit
e14c9e8b53
1 changed files with 125 additions and 10 deletions
135
mbr/mbr.asm
135
mbr/mbr.asm
|
|
@ -93,11 +93,106 @@ print_loop:
|
|||
RET ; return
|
||||
|
||||
|
||||
; function check_a20: get status of address line 20 (21st bit of any address)
|
||||
; Returns:
|
||||
; AX=0 if A20 off, AX=1 if A20 on
|
||||
check_a20:
|
||||
PUSHF ; save FLAGS
|
||||
PUSH DS ; save DS
|
||||
PUSH ES ; save ES
|
||||
PUSH DI ; save DI
|
||||
PUSH SI ; save SI
|
||||
|
||||
CLI ; disable interrupts
|
||||
|
||||
XOR AX, AX ; AX = 0
|
||||
MOV ES, AX ; ES = 0
|
||||
|
||||
NOT AX ; AX = 0xFFFF
|
||||
MOV DS, AX ; DS = 0xFFFF
|
||||
|
||||
MOV DI, 0x0500 ; DI = 0x0500
|
||||
MOV SI, 0x0510 ; SI = 0x0510
|
||||
|
||||
MOV AL, [ES:DI] ; AL = Memory[0x0500]
|
||||
PUSH AX ; save original value at Memory[0x500]
|
||||
|
||||
MOV AL, [DS:SI] ; AL = Memory[0xFFFF:0x0510]
|
||||
PUSH AX ; save original value at Memory[0xFFFF:0x0510]
|
||||
|
||||
MOV BYTE [ES:DI], 0x00 ; Memory[0x0500] = 0x00
|
||||
MOV BYTE [DS:SI], 0xFF ; Memory[0xFFFF:0x0510] = 0xFF
|
||||
|
||||
CMP BYTE [ES:DI], 0xFF ; Compare Memory[0x0500] to 0xFF
|
||||
; if the bytes match, the memory is wrapping around
|
||||
; therefore, the A20 line is disabled
|
||||
|
||||
POP AX ; Restore memory at [0xFFFF:0x0510]
|
||||
MOV [DS:SI], AL ; ^^^^
|
||||
|
||||
POP AX ; Restore memory at [0x0500]
|
||||
MOV [ES:DI], AL ; ^^^^
|
||||
|
||||
MOV AX, 0 ; AX (return value) = 0 (A20 disabled)
|
||||
|
||||
JE check_a20_exit ; If the last CMP was equal (A20 disabled), exit
|
||||
|
||||
MOV AX, 1 ; AX (return value) = 1 (A20 enabled)
|
||||
|
||||
check_a20_exit:
|
||||
POP SI ; restore SI
|
||||
POP DI ; restore DI
|
||||
POP ES ; restore ES
|
||||
POP DS ; restore DS
|
||||
POPF ; restore FLAGS
|
||||
|
||||
RET ; return
|
||||
|
||||
enable_a20:
|
||||
CALL a20_wait ; wait for keyboard controller
|
||||
MOV AL, 0xAD ; 0xAD = disable keyboard
|
||||
OUT 0x64, AL ; send command 0xAD to keyboard controller
|
||||
|
||||
CALL a20_wait ; wait for keyboard controller
|
||||
MOV AL, 0xD0 ; 0xD0 = read from input
|
||||
OUT 0x64, AL ; send command 0xD0
|
||||
|
||||
CALL a20_wait2 ; wait for keyboard input
|
||||
IN AL, 0x60 ; read input from keyboard controller
|
||||
PUSH AX ; save input
|
||||
|
||||
CALL a20_wait ; wait for keybaord controller
|
||||
MOV AL, 0xD1 ; 0xD1 = write to output
|
||||
OUT 0x64, AL ; send command 0xD1
|
||||
|
||||
CALL a20_wait ; wait for keyboard controller
|
||||
POP AX ; restore input value
|
||||
OR AL, 2 ; enable bit 1
|
||||
OUT 0x60, AL ; send output to keyboard
|
||||
|
||||
CALL a20_wait ; wait for keyboard controller
|
||||
MOV AL, 0xAE ; 0xAE = enable keyboard
|
||||
OUT 0x64, AL ; send command 0xAE
|
||||
RET
|
||||
|
||||
|
||||
a20_wait:
|
||||
IN AL, 0x64 ; read status of keyboard controller
|
||||
TEST AL, 2 ; read bit 1 of status
|
||||
JNZ a20_wait ; if not zero, keyboard controller isn't ready. Retry
|
||||
RET ; return
|
||||
|
||||
a20_wait2:
|
||||
IN AL, 0x64 ; read status of keyboard controller
|
||||
TEST AL, 1 ; read bit 0 of status
|
||||
JZ a20_wait2 ; if zero, input isn't ready
|
||||
RET ; return
|
||||
|
||||
entry:
|
||||
; Set up stack and segments
|
||||
MOV AX, 0 ; set up stack segment
|
||||
MOV SS, AX ; ^^^
|
||||
MOV SP, 0x7C00 ; set up stack pointer (0x6c00-x7BFF)
|
||||
MOV SP, 0x7C00 ; set up stack pointer (0x6c00-0x7BFF)
|
||||
; Sp HAS TO be set in the instruction after settings SS
|
||||
; as setting SS disables interrupts for the next instruction
|
||||
; Not doing this may cause an interrupt to use an old SP and new SS
|
||||
|
|
@ -106,8 +201,13 @@ entry:
|
|||
MOV FS, AX ; ^^^
|
||||
MOV GS, AX ; ^^^
|
||||
|
||||
PUSH DX ; save drive number (DL)
|
||||
|
||||
; Load drive parameters
|
||||
MOV AX, 4800h ; load AH=48h, AL=0h
|
||||
MOV SI, disk_info_packet ; load address of Disk_Info_Packet
|
||||
INT 13H ; INT 14h AH=48h: get drive parameters
|
||||
|
||||
PUSH DX ; save drive number (DL)
|
||||
|
||||
; Print message
|
||||
MOV AX, msg ; load address of msg
|
||||
|
|
@ -116,17 +216,31 @@ entry:
|
|||
PUSH AX ; push parameter 'size of string'
|
||||
CALL print ; call function 'print'
|
||||
|
||||
over:
|
||||
JMP over ; loop forever
|
||||
SUB SP, 4 ; clear previous call parameters
|
||||
|
||||
CALL check_a20 ; call check_a20. Result in Ax
|
||||
CMP AX, 0 ; compare AX to 0 (0 = A20 disabled)
|
||||
JNE after_a20 ; if AX != 0, a20 is enabled, skip enabling it
|
||||
|
||||
CALL enable_a20 ; enable A20 line via keyboard controller
|
||||
|
||||
CALL check_a20 ; check status of A20 line (again)
|
||||
CMP AX, 0 ; compare AX to 0 (0 = A20 disabled)
|
||||
JNE after_a20 ; if AX != 0, a20 is enabled
|
||||
|
||||
MOV AX, a20_msg ; load address of 'a20_msg'
|
||||
PUSH AX ; push parameter 'address of string'
|
||||
MOV AX, 6 ; load size of 'a20_msg'
|
||||
PUSH AX ; push parameter 'size of string'
|
||||
CALL print ; print 'a20_msg'
|
||||
JMP endless_loop ; loop endlessly
|
||||
|
||||
|
||||
; Load drive parameters
|
||||
MOV AX, 4800h ; load AH=48h, AL=0h
|
||||
MOV SI, disk_info_packet ; load address of Disk_Info_Packet
|
||||
INT 13H ; INT 14h AH=48h: get drive parameters
|
||||
|
||||
after_a20:
|
||||
|
||||
|
||||
endless_loop:
|
||||
JMP endless_loop ; loop endlessly
|
||||
|
||||
section .data
|
||||
disk_info_packet:
|
||||
|
|
@ -150,4 +264,5 @@ build_settings_magic_0 dd 0x49494949
|
|||
build_settings_bytes dw 0x0
|
||||
build_settings_magic_1 dd 0x49494949
|
||||
|
||||
msg db "OS3_BOOT_OK!"
|
||||
msg db "OS3_BOOT_OK!"
|
||||
a20_msg db "NO_A20"
|
||||
Loading…
Add table
Reference in a new issue