1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
;; boot.stage2.a20.asm
_enable_a20:
call _check_a20
test ax, ax
jnz .end
call _enable_a20_bios
call _check_a20
test ax, ax
jnz .end
call _enable_a20_keyb
call _check_a20
test ax, ax
jnz .end
call _enable_a20_io92
call _check_a20
test ax, ax
jnz .end
.halt: hlt
jmp .halt
.end:
ret
_check_a20:
pushf
push ds
push es
push di
push si
cli ; Clear Interrupts
xor ax, ax
mov es, ax
not ax
mov ds, ax
;; 0500 and 0510 are guaranteed to be free
mov di, 0x0500
mov si, 0x0510
;; Save the original values
mov dl, byte [es:di]
push dx
mov dl, byte [ds:si]
push dx
mov byte [es:di], 0x00
mov byte [ds:si], 0xFF
cmp byte [es:di], 0xFF
mov ax, 0 ; The A20 is disabled
je .a20_disabled
mov ax, 1 ; The A20 is enabled
.a20_disabled:
pop dx
mov byte [ds:si], dl
pop dx
mov byte [es:di], dl
pop si
pop di
pop es
pop ds
popf
sti ; Enable interrupts again
ret
_enable_a20_bios:
mov ax, 0x2401
int 0x15
jc .fast_gate
test ah, ah
jnz .failed
call _check_a20
test ax, ax
jnz .done
.fast_gate:
in al, 0x92
test al, 2
jnz .done
or al, 2
and al, 0xfe
out 0x92, al
call _check_a20
test ax, ax
jnz .done
.done:
mov ax, 1
ret
.failed:
mov ax, 0
ret
_enable_a20_keyb:
cli
call .wait_io1
mov al, 0xad
out 0x64, al
call .wait_io1
mov al, 0x0d0
out 0x64, al
call .wait_io2
in al, 0x60
push eax
call .wait_io1
mov al, 0xd1
out 0x64, al
call .wait_io1
mov al, 0xae
out 0x64, al
sti
ret
.wait_io1:
in al, 0x64
test al, 2
jnz .wait_io1
ret
.wait_io2:
in al, 0x64
test al, 1
jz .wait_io2
ret
_enable_a20_io92:
in al, 0x92 ; Read from port 0x92
test al, 2 ; Check if bit 1
jnz .end
or al, 2
and al, 0xfe
out 0x92, al
.end:
ret
|