Blob


1 [cpu 286]
2 [bits 16]
4 %include "macros.inc"
6 struc TSS
7 .link: resw 1 ; +0x00
8 .sp0: resw 1 ; +0x02
9 .ss0: resw 1 ; +0x04
10 .sp1: resw 1 ; +0x06
11 .ss1: resw 1 ; +0x08
12 .sp2: resw 1 ; +0x0a
13 .ss2: resw 1 ; +0x0c
14 .ip: resw 1 ; +0x0e
15 .flags: resw 1 ; +0x10
16 .ax: resw 1 ; +0x12
17 .cx: resw 1 ; +0x14
18 .dx: resw 1 ; +0x16
19 .bx: resw 1 ; +0x18
20 .sp: resw 1 ; +0x1a
21 .bp: resw 1 ; +0x1c
22 .si: resw 1 ; +0x1e
23 .di: resw 1 ; +0x20
24 .es: resw 1 ; +0x22
25 .cs: resw 1 ; +0x24
26 .ss: resw 1 ; +0x26
27 .ds: resw 1 ; +0x28
28 .ldtr: resw 1 ; +0x2a
29 .size: ; +0x2c
30 endstruc
32 section .text
33 extern floppy_init
34 global _entry
35 global putchar
36 global puts
37 global puthexb
38 global puthexw
39 global panic
40 _entry:
41 pop dx
42 mov byte [bootdrv], dl
44 ; copy user task into 0x2000:0
45 mov ax, 0x2000
46 mov es, ax
47 xor di, di
48 lea si, [user]
49 lea cx, [user.end - user]
50 rep movsb
52 ; clear screen
53 mov bx, 0xb800
54 mov es, bx
55 xor di, di
56 mov ax, (' ' | (0x07 << 8))
57 mov cx, (80 * 25 * 2)
58 rep stosw
60 ; get size of conventional memory (below 640K)
61 int 0x12
62 mov word [convmem], ax
64 ; get size of extended memory (above 1M)
65 mov ah, 0x88
66 int 0x15
67 jc .noxm
68 mov word [highmem], ax
70 .noxm:
71 ; NOTE: BIOS cannot be accessed from here
72 cli
74 ; disable keyboard
75 call .wait
76 mov al, 0xAD
77 out 0x64, al
79 ; read from input
80 call .wait
81 mov al, 0xD0
82 out 0x64, al
83 call .wait2
84 in al, 0x60
85 mov bl, al
87 ; write to output
88 call .wait
89 mov al,0xD1
90 out 0x64,al
91 call .wait
92 mov al, bl
93 or al, 2 ; enable A20 line
94 out 0x60, al
96 ; enable keyboard
97 call .wait
98 mov al, 0xAE
99 out 0x64, al
100 call .wait
101 jmp .setup
103 .wait:
104 in al,0x64
105 test al, 2
106 jnz .wait
107 ret
110 .wait2:
111 in al,0x64
112 test al,1
113 jz .wait2
114 ret
116 .setup:
117 lidt [idtr]
118 lgdt [gdtr]
119 smsw ax
120 or ax, 1
121 lmsw ax
122 jmp (gdt.text - gdt):.reloadcs
124 .reloadcs:
125 lea sp, [stack]
126 lea ax, [gdt.data - gdt]
127 mov ds, ax
128 mov es, ax
129 mov ss, ax
131 ; initialize PIC
132 outb_slow 0x20, 0x11 ; Start the initialization routine (in cascae mode)
133 outb_slow 0xA0, 0x11
134 outb_slow 0x21, 0x20 ; Master PIC IRQ offset
135 outb_slow 0xA1, 0x28 ; Slave PIC IRQ offset
136 outb_slow 0x21, 4 ; Tell the master PIC that there is a slave PIC at IRQ2
137 outb_slow 0xA1, 2 ; Tell the slave PIC it's cascade identity
138 outb_slow 0x21, 1 ; Use the 8086-mode (and not the 8088 mode)
139 outb_slow 0xA1, 1
140 outb_slow 0x21, 0xfe ; Set the IRQ masks
141 outb_slow 0xA1, 0xff
143 ; initialize IDT
144 mov al, 0x20
145 mov ah, 0x86
146 lea dx, [i_timer]
147 call set_irq
148 mov al, 0x80
149 mov ah, 0xe6
150 lea dx, [i_sys]
151 call set_irq
153 lea bp, [convmsg]
154 call puts
155 mov ax, word [convmem]
156 call puthexw
157 lea bp, [kbmsg]
158 call puts
160 lea bp, [xmmsg]
161 call puts
162 mov ax, word [highmem]
163 call puthexw
164 lea bp, [kbmsg]
165 call puts
167 call floppy_init
169 ; set up TSS
170 mov word [tss + TSS.link], 0
171 mov word [tss + TSS.sp0], stack
172 mov word [tss + TSS.ss0], (gdt.data - gdt)
174 ; load TSS into TR
175 lea ax, [gdt.tss - gdt]
176 ltr ax
178 ; load LDT
179 lea ax, [gdt.ldt - gdt]
180 lldt ax
182 ; enter userspace, TODO: enter ring 3
183 mov ax, 0x0f ; LDT .data
184 mov ds, ax
185 mov es, ax
186 push 0x17 ; ss (LDT .stack)
187 push 0xfffe ; sp
188 push 0x202 ; flags (EI | 0x02)
189 push 0x07 ; cs (LDT .text)
190 push 0 ; ip
191 iret
193 i_timer:
194 pusha
195 push ds
196 push es
198 mov ax, (gdt.data - gdt)
199 mov ds, ax
200 mov es, ax
202 mov al, '.'
203 call putchar
205 outb 0x20, 0x20
206 pop es
207 pop ds
208 popa
209 iret
211 ; ds:si - from
212 ; es:di - to
213 ; cx - count
214 copy_from_user:
215 rep movsb
216 ret
218 i_sys: ; syscall interrupt (0x80)
219 push ds
220 push es
222 ; load kernel .data into es
223 push ax
224 mov ax, (gdt.data - gdt)
225 mov es, ax
226 pop ax
228 test ax, ax
229 jz .print
231 ; invalid interrupt
232 mov ax, -1
233 jmp .ret
236 .print:
237 push cx
238 mov si, bx
239 lea di, [ubuf]
240 ; TODO: check that cx < sizeof(ubuf)
241 call copy_from_user
242 pop bx
243 mov byte [ubuf + bx], 0
245 ; load kernel .data into ds & es
246 lea ax, [gdt.data - gdt]
247 mov ds, ax
248 mov es, ax
250 lea bp, [ubuf]
251 call puts
252 xor ax, ax
253 jmp .ret
255 .ret:
256 pop es
257 pop ds
258 iret
260 ; al - num
261 ; ah - attr
262 ; dx - offset
263 set_irq:
264 xor bh, bh
265 mov bl, al
266 shl bx, 3
267 lea bx, [idt + bx]
268 mov word [bx + 0], dx
269 mov word [bx + 2], (gdt.text - gdt)
270 mov byte [bx + 4], 0x00
271 mov byte [bx + 5], ah
272 mov word [bx + 6], 0
273 ret
275 error:
276 cli
277 lea bp, [errstr]
278 call puts
279 hlt
280 jmp $
282 ; ax - value
283 puthexw:
284 push ax
285 mov al, ah
286 call puthexb
287 pop ax
288 jmp puthexb
290 ; al - value
291 puthexb:
292 push ax
293 shr al, 4
294 call puthexch
295 pop ax
296 and al, 0xf
297 jmp puthexch
299 ; al - hex digit
300 puthexch:
301 cmp al, 10
302 jae .hex
303 add al, '0'
304 jmp putchar
306 .hex:
307 add al, 'a' - 10
308 jmp putchar
310 ; al - char
311 writech:
312 lea bx, [gdt.vid - gdt]
313 mov es, bx
315 xor ch, ch
316 xor dh, dh
317 mov cl, byte [posx]
318 mov dl, byte [posy]
320 cmp al, 10 ; '\n'
321 je .nl
323 imul bx, dx, 80
324 add bx, cx
325 shl bx, 1
326 mov byte [es:bx], al
328 inc cl
329 cmp cl, 80
330 je .nl
331 mov byte [posx], cl
332 ret
334 .nl:
335 mov byte [posx], 0
336 inc dl
338 cmp dl, 25
339 je .scroll
340 mov byte [posy], dl
341 ret
343 .scroll:
344 push ds
345 mov ax, 0x18
346 mov ds, ax
348 cld
349 xor di, di
350 mov si, 160
351 mov cx, 80 * 24
352 rep movsw
354 pop ds
356 mov di, 80 * 24 * 2
357 mov cx, 80
358 mov ax, (' ' | (0x07 << 8))
359 rep stosw
360 mov byte [posy], 24
361 ret
363 ; al - ch
364 putchar:
365 call writech
366 jmp update_cursor
368 ; bp - str
369 puts:
370 mov al, byte [ds:bp]
371 inc bp
372 test al, al
373 jz update_cursor
375 call writech
376 jmp puts
378 update_cursor:
379 mov dx, 0x3D4
380 mov al, 0x0f
381 out dx, al
383 mov bx, word [posy]
384 imul bx, 80
385 add bx, word [posx]
387 inc dx ; 0x3D5
388 mov al, bl
389 out dx, al
391 dec dx ; 0x3D4
392 mov al, 0x0E
393 out dx, al
395 inc dx ; 0x3D5
396 mov al, bh
397 out dx, al
398 ret
400 ; bp - str
401 panic:
402 call puts
404 .halt:
405 cli
406 hlt
407 jmp .halt
409 section .rodata
410 user:
411 incbin "user.bin"
412 .end:
413 hello:
414 db "Hello World", 10, 0
415 errstr:
416 db "Error", 10, 0
417 convmsg:
418 db "Conventional memory: 0x", 0
419 xmmsg:
420 db "Extended memory: 0x", 0
421 kbmsg:
422 db " KB", 10, 0
424 align 2
425 idtr:
426 dw idt.end - idt - 1
427 dd idt + 0x10000
429 align 2
430 gdtr:
431 dw gdt.end - gdt - 1
432 dd gdt + 0x10000
435 section .data
436 gdt:
437 dq 0
439 .text: ; 0x08 - kernel code
440 dw 0xffff
441 dw 0x0000
442 db 0x01
443 db 0x9A
444 dw 0x0000
446 .data: ; 0x10 - kernel data
447 dw 0xffff
448 dw 0x0000
449 db 0x01
450 db 0x92
451 dw 0x0000
453 .vid: ; 0x18 - video memory
454 dw 4000
455 dw 0x8000
456 db 0x0b
457 db 0x92
458 dw 0x0000
460 .tss: ; 0x20 - TSS
461 dw TSS.size
462 dw tss
463 db 0x01
464 db 0x81
465 dw 0x0000
467 .ldt: ; 0x28 - LDT
468 dw (ldt.end - ldt)
469 dw ldt
470 db 0x01
471 db 0x82
472 dw 0x0000
473 .end:
475 ldt:
476 .text: ; 0x07 - user code
477 dw 0xffff
478 dw 0x0000
479 db 0x02
480 db 0xfa
481 dw 0x0000
483 .data: ; 0x0f - user data
484 dw 0xffff
485 dw 0x0000
486 db 0x02
487 db 0xf2
488 dw 0x0000
490 .stack: ; 0x17 - user stack
491 dw 0xffff
492 dw 0x0000
493 db 0x03
494 db 0xf2
495 dw 0x0000
496 .end:
498 section .bss
499 ubuf:
500 resb 256
501 posx:
502 resw 1
503 posy:
504 resw 1
505 bootdrv:
506 resb 1
507 convmem:
508 resw 1 ; in kilobytes
509 highmem:
510 resw 1 ; in kilobytes
511 idt:
512 resq 256
513 .end:
514 resb 512
515 stack:
516 tss:
517 resb TSS.size