/
core.asm
263 lines (219 loc) · 7.21 KB
/
core.asm
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
; Простановка редиректов
; ----------------------------------------------------------------------
irq_init:
; Отключение APIC
mov ecx, 0x1b
rdmsr
and eax, 0xfffff7ff
wrmsr
; Выполнение запросов
mov ecx, 10
xor edx, edx
mov esi, .data
@@: lodsw
mov dl, al
mov al, ah
out dx, al
jcxz $+2
jcxz $+2
loop @b
ret
.data: ; Данные для отправки команд
db PIC1_COMMAND, ICW1_INIT + ICW1_ICW4
db PIC2_COMMAND, ICW1_INIT + ICW1_ICW4
db PIC1_DATA, 0x20
db PIC2_DATA, 0x28
db PIC1_DATA, 0x04
db PIC2_DATA, 0x02
db PIC1_DATA, ICW4_8086
db PIC2_DATA, ICW4_8086
db PIC1_DATA, 0xFF xor (IRQ_TIMER or IRQ_KEYB or IRQ_FDC or IRQ_CASCADE)
db PIC2_DATA, 0xFF xor (IRQ_PS2)
; Инициализация IVT
; Для IRQ используются "обертки" - устанавливаются ссылки в .irq_X
; ----------------------------------------------------------------------
ivt_init:
; Очистка IVT
mov eax, .null
xor edi, edi
mov ecx, 256
@@: call .make
loop @b
; Установка ссылок на обработчики IRQ #n
mov cx, 16
mov eax, .it0
mov edi, $20 shl 3
@@: call .make
add eax, .it1 - .it0
loop @b
ret
.make: ; eax - адрес прерывания, edi - адрес ivt
mov [edi+0], eax
mov [edi+4], eax
mov [edi+2], dword $8E000010
add edi, 8
ret
; Ошибка вызова несуществующего прерывания. Ничегошеньки не делать.
.null: iretd
; Обработчики IRQ #n
.it0: IRQ_master .irq_0
.it1: IRQ_master .irq_1
IRQ_master .irq_2
IRQ_master .irq_3
IRQ_master .irq_4
IRQ_master .irq_5
IRQ_master .irq_6
IRQ_master .irq_7
IRQ_slave .irq_8
IRQ_slave .irq_9
IRQ_slave .irq_A
IRQ_slave .irq_B
IRQ_slave .irq_C
IRQ_slave .irq_D
IRQ_slave .irq_E
IRQ_slave .irq_F
; Ссылки на обработчики IRQ
; ----------------------------------------------------------------------
.irq_0: dd irq.timer
.irq_1: dd irq.keyb
.irq_2: dd irq.nil
.irq_3: dd irq.nil
.irq_4: dd irq.nil
.irq_5: dd irq.nil
.irq_6: dd fdc_irq
.irq_7: dd irq.nil
.irq_8: dd irq.nil
.irq_9: dd irq.nil
.irq_A: dd irq.nil
.irq_B: dd irq.nil
.irq_C: dd irq.ps2
.irq_D: dd irq.nil
.irq_E: dd irq.nil
.irq_F: dd irq.nil
; ----------------------------------------------------------------------
; Таймер
; ----------------------------------------------------------------------
irq:
.timer:
inc [irq_timer]
call fdc_timeout
ret
; Клавиатура
; ----------------------------------------------------------------------
.keyb:
in al, $60
ret
; Мышь
; ----------------------------------------------------------------------
.ps2: call ps2_handler
ret
; ----------------------------------------------------------------------
.nil: ret
; Два типа общих обработчиков
.master: IRQ_handler 0
.slave: IRQ_handler 1
; Инициализация главной TSS
; ----------------------------------------------------------------------
tss_init:
mov [tss.iobp], word 104
mov ax, 18h
ltr ax
ret
; Инициализация важных устройств
; ----------------------------------------------------------------------
tik_init:
mov [irq_timer], 0
; Часы на 100 мгц
mov al, $34
out $43, al
mov al, $9b
out $40, al
mov al, $2e
out $40, al
ret
; Поиск размера памяти и установка страниц -> TSS.cr3
; ----------------------------------------------------------------------
mem_init:
; Размер памяти
mov ecx, 32 ; Бинарный поиск на 2^32
mov esi, LOW_MEMORY
mov edi, $bfffffff ; $c0000000 hardware
.rept: mov ebx, esi ; ebx = (esi + edi) >> 1
add ebx, edi
rcr ebx, 1
mov al, [ebx] ; Тест изменений
xor [ebx], byte $55
cmp [ebx], al
cmove edi, ebx ; Уменьшить верхнюю
cmovne esi, ebx ; Увеличить нижнюю
mov [ebx], al
.next: loop .rept
mov [mem_size], edi ; Тут будет верхняя граница
; Разметка PDBR
mov ecx, edi
shr ecx, 22 ; Кол-во 4-мб страниц
mov edi, LOW_MEMORY ; Очистить PDBR
push edi ecx
mov ecx, 1024
xor eax, eax
rep stosd
pop ecx edi
mov eax, LOW_MEMORY + $1003 ; Каталоги c правами R/W=1, P=1
@@: stosd
add eax, $1000
loop @b
; Разметка каталогов
mov ecx, [mem_size]
shr ecx, 12
mov ecx, ecx
mov ecx, $8000
mov edi, LOW_MEMORY + $1000
mov eax, $000003
@@: stosd
add eax, $1000
loop @b
; Добавление региона UMMP (битовая маска занятости)
mov [ummp], edi
mov ecx, [mem_size]
shr ecx, (12 + 3) ; 1 байт описывает 2^15 памяти
push edi ecx
shr ecx, 2
xor eax, eax
rep stosd
pop ecx edi
add edi, ecx
; Локальная память для задач ядра
mov [appsmem], START_MEM
mov [dynamic], edi
; Включение страничной организации
mov eax, LOW_MEMORY
mov cr3, eax
mov [tss.cr3], eax
; Переключить на страницы
mov eax, cr0
bts eax, 31
mov cr0, eax
ret
; Перенос GDT в другое место
; ----------------------------------------------------------------------
gdt_init:
mov esi, GDT
mov edi, [dynamic]
add [dynamic], dword $10000 ; Выделить 64 кб
push edi edi
xor eax, eax
mov ecx, $4000
rep stosd
pop edi
mov cx, 4*2
rep movsd
pop edi
; Новый GDT. Сохранить размер
mov [GDTR + 2], edi
lgdt [GDTR]
; Перезагрузка сегментов
mov ax, $0008
mov ds, ax
mov es, ax
mov ss, ax
ret