global gdt global idt global kboot global register_isr global tss extern kmain extern paging_init extern syscall_init extern timer_init extern traps_init ; Multiboot header section .mboothdr mboot_hdr: align 4 dd 0x1BADB002 dd 0x00 dd - (0x1BADB002 + 0x00) section .text kboot: cli ; put the stack pointer near the end of conventional memory mov esp, 0x80000 ; setup descriptor tables call flush_gdt call paging_init call flush_idt ; last minute setup, then transfer to kmain call timer_init call kmain ; if kmain decides to return (which it shouldn't), ; disable interrupts and halt the system. cli hlt tss: dd 0 dd 0 ; kernel stack pointer dd 0x10 ; kernel stack segment times 60 db 0 dd 0x13 ; ES segment dd 0x0B ; CS segment dd 0x13 ; SS segment dd 0x13 ; DS segment dd 0x13 ; FS segment dd 0x13 ; GS segment times 8 db 0 .end: gdt: ; null descriptor dq 0 ; kernel code segment dw 0xFFFF ; limit (bits 0-15) dw 0x0000 ; base (bits 0-15) db 0x00 ; base (bits 16-23) db 0x9A ; access byte db 0xCF ; flags / limit (bits 16-19) db 0x00 ; base (bits 24-31) ; kernel data segment dw 0xFFFF dw 0x0000 db 0x00 db 0x92 db 0xCF db 0x00 ; userspace code segment dw 0xFFFF dw 0x0000 db 0x00 db 0xFA db 0xCF db 0x00 ; userspace data segment dw 0xFFFF dw 0x0000 db 0x00 db 0xF2 db 0xCF db 0x00 ; task state segment .tss: dq 0 ; we initialize this later .end: gdtp: dw (gdt.end-gdt-1) dd gdt flush_gdt: push ebp mov ebp, esp ; initialize the TSS entry mov eax, tss mov [gdt.tss+2], ax shr eax, 16 mov [gdt.tss+4], al mov [gdt.tss+7], ah mov eax, (tss.end-tss-1) mov [gdt.tss], ax shr eax, 16 and al, 0x0F mov [gdt.tss+6], al mov al, 0xE9 mov [gdt.tss+5], al ; now, load the GDT lgdt [gdtp] mov ax, 0x10 mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax jmp 0x08:.end .end: ; initialize the task state register mov ax, 0x002B ltr ax pop ebp ret idt: times (256*8) db 0 .end: idtp: dw (idt.end-idt-1) dd idt int_handler: iret flush_idt: push ebp mov ebp, esp ; install the exception handlers (vectors 0-31) call traps_init ; install the default handlers (vectors 32-255) mov ecx, 0 lea edx, [idt+(32*8)] .loop: mov eax, int_handler mov [edx], ax shr eax, 16 mov [edx+6], ax mov word [edx+2], 0x08 mov byte [edx+4], 0x00 mov byte [edx+5], 0x8E inc ecx cmp ecx, (256-32) je .end add edx, 8 jmp .loop .end: ; install the system call handler call syscall_init ; load the IDT, initialize the PIC's, and enable interrupts lidt [idtp] call pic_init sti pop ebp ret ; void register_isr(uint8_t n, uint8_t dpl, void *handler); register_isr: push ebp mov ebp, esp mov edx, [ebp+8] shl edx, 3 add edx, idt mov eax, [ebp+16] mov [edx], ax shr eax, 16 mov [edx+6], ax mov eax, [ebp+12] and al, 3 shl al, 5 mov cl, [edx+5] and cl, 0x9F or cl, al mov [edx+5], cl pop ebp ret pic_init: push ebp mov ebp, esp mov al, 0x11 out 0x20, al out 0xA0, al mov al, 0x20 out 0x21, al out 0xA1, al mov al, 0x04 out 0x21, al mov al, 0x02 out 0xA1, al mov al, 0x01 out 0x21, al out 0xA1, al mov al, 0xFF out 0x21, al out 0xA1, al pop ebp ret