/*
* C-os V 0.0.6 (C) wzt 2007
*
* This is my simple kernel,it takes my much time to run it successfully in ring3,
* and i like it very much,haha.It has two tasks change with the contrl of time interrupt.
* When the kernel runs task-A,the task display a message"__bill gates like windows__",
* while the task-B display a message"__linus like linux__".
*
*/
.text
.global startup_32
startup_32:
movl $0x10,%eax
mov %ax,%ds
# mov %ax,%es
lss init_stack,%esp
call init8259A
/* setup idt table and gdt table */
call setup_idt
call setup_gdt
movl $0x10,%eax
mov %ax,%ds
mov %ax,%es
mov %ax,%fs
mov %ax,%gs
lss init_stack,%esp
/* set 8253 chip */
movb $0x36, %al
movl $0x43, %edx
outb %al, %dx
movl $119300, %eax # timer frequency 100 HZ
movl $0x40, %edx
outb %al, %dx
movb %ah, %al
outb %al, %dx
/* set timer interrupt */
movl $0x00080000, %eax
movw $timer_interrupt, %ax
movw $0x8E00, %dx
movl $0x20, %ecx # The PC default timer int.
lea idt(,%ecx,8), %esi
movl %eax,(%esi)
movl %edx,4(%esi)
/* set system call interrupt */
movw $system_interrupt, %ax
movw $0xef00, %dx
movl $0x85, %ecx
lea idt(,%ecx,8), %esi
movl %eax,(%esi)
movl %edx,4(%esi)
pm_mode_test:
movl $(80 * 1 + 0 ) * 2,%edi
movl $ring0_msg,%esi
call write_string
movl $(80 * 6 + 0 ) * 2,scr_loc
/* move to ring3.*/
pushfl
andl $0xffffbfff, (%esp)
popfl
movl $0x20,%eax
ltr %ax
movl $0x28,%eax
lldt %ax
movl $0,current
sti
pushl $0x17
pushl $init_stack
pushfl
pushl $0x0f
pushl $ring3_task0
iret
/* ignore interrupt,only display a message.*/
.align 2
ignore_int:
push %ds
pushl %eax
pushl %edi
movl $0x10,%eax
mov %ax,%ds
movl $ignore_msg,%esi
# movl $(80 * 3 + 0 ) * 2,%edi
movl scr_loc,%edi
call write_string
popl %edi
popl %eax
pop %ds
iret
/* like schedule,change tasks.*/
.align 2
timer_interrupt:
push %ds
pushl %eax
movl $0x10,%eax
mov %ax,%ds
movb $0x20,%al
outb %al, $0x20
movl $1,%eax
cmpl %eax,current
je 13f
movl %eax,current
ljmp $0x30,$0
jmp 14f
13:
movl $0,current
ljmp $0x20,$0
14:
popl %eax
pop %ds
iret
/* system interrupt,only display a message.*/
.align 2
system_interrupt:
push %ds
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
movl $0x10, %edx
mov %dx, %ds
movw $0x18,%bx
movw %bx,%gs
movb $0x0c,%ah
cld
2:
movl scr_loc,%ebx
shl $1,%ebx
lodsb
testb %al,%al
jz 5f
movw %ax,%gs:(%ebx)
1:
shr $1,%ebx
incl %ebx
cmpl $2000,%ebx
jb 4f
movl $0,%ebx
movl $(80 * 6 + 0 ) * 2,scr_loc
incb %ah
jmp 2b
4:
movl %ebx,scr_loc
jmp 2b
5:
popl %eax
popl %ebx
popl %ecx
popl %edx
pop %ds
iret
io_delay:
nop
nop
nop
nop
ret
init8259A:
movb $0x11,%al
outb %al,$0x20
call io_delay
outb %al,$0xa0
call io_delay
movb $0x20,%al
outb %al,$0x21
call io_delay
movb $0x28,%al
outb %al,$0xa1
call io_delay
movb $0x04,%al
outb %al,$0x21
call io_delay
movb $0x02,%al
outb %al,$0xa1
call io_delay
movb $0x01,%al
outb %al,$0x21
call io_delay
outb %al,$0xa1
call io_delay
movb $0xfe,%al
outb %al,$0x21
call io_delay
movb $0xff,%al
outb %al,$0xa1
call io_delay
ret
write_string:
push %gs
push %bx
push %ax
movw $0x18,%bx
movw %bx,%gs
movb $0x0c,%ah
cld
7:
lodsb
testb %al,%al
jz 8f
movw %ax,%gs:(%edi)
addl $2,%edi
jmp 7b
8:
pop %ax
pop %bx
pop %gs
ret
current:
.long 0
scr_loc:
.long 0
setup_gdt:
lgdt gdt_48
ret
setup_idt:
lea ignore_int,%edx
movl $0x00080000,%eax
movw %dx,%ax
movw $0x8e00,%dx
lea idt,%edi
movl $256,%ecx
loop_idt:
movl %eax,(%edi)
movl %edx,4(%edi)
addl $8,%edi
dec %ecx
jne loop_idt
lidt idt_48
ret
.align 2
idt_48:
.word 256*8-1
.long idt
gdt_48:
.word (end_gdt - gdt) - 1
.long gdt
.align 8
idt:
.fill 256,8,0
gdt:
desc_null:
.quad 0x0000000000000000 #0x0
desc_code:
.word 0x07ff #0x08
.word 0x0000
.word 0x9a00
.word 0x00c0
desc_data:
.quad 0x00c09200000007ff #0x10
desc_video:
.quad 0x00c0f20b80000002 #0x18,DPL=3
desc_tss0: #0x20
.word 0x0068
.word tss0
.word 0xe900
.word 0x0000
desc_ldt0: #0x28
.word 0x0040
.word ldt0 #base addr
.word 0xe200 #DPL=3,data
.word 0x0000
desc_tss1: #0x30
.word 0x0068
.word tss1
.word 0xe900
.word 0x0000
desc_ldt1: #0x38
.word 0x0040
.word ldt1 #base addr
.word 0xe200 #DPL=3,data
.word 0x0000
end_gdt:
.fill 128,4,0
init_stack: #aslo can be used with ring0 stack
.long init_stack
.word 0x10
.align 8
ldt0:
.quad 0x000000000000000 #0x4
code0:
.word 0x03ff #0x0f
.word 0x0000
.word 0xfa00
.word 0x00c0
data0:
.word 0x03ff #0x17
.word 0x0000
.word 0xf200
.word 0x00c0
tss0:
.long 0
.long ring3_stack, 0x10
.long 0, 0, 0, 0, 0
.long 0, 0, 0, 0, 0
.long 0, 0, 0, 0, 0
.long 0, 0, 0, 0, 0, 0
.long 0x28,0x8000000
.fill 128,4,0
ring3_stack:
.align 8
ldt1:
.quad 0x000000000000000 #0x4
code1:
.word 0x03ff #0x0f
.word 0x0000
.word 0xfa00
.word 0x00c0
data1:
.word 0x03ff #0x17
.word 0x0000
.word 0xf200
.word 0x00c0
tss1:
.long 0
.long ring3_stack1, 0x10
.long 0, 0, 0, 0, 0
.long ring3_task1,0x200
.long 0, 0, 0, 0
.long usr_stk1,0,0,0
.long 0x17,0x0f,0x17,0x17,0x17,0x17
.long 0x38,0x8000000
.fill 128,4,0
ring3_stack1:
pm_msg:
.asciz "move to protect mode."
ring3_msg:
.asciz "moved to Ring3."
ring3_msga:
.asciz "moved to ring3,starting task-A."
ring3_msgb:
.asciz "moved to ring3,starting task-B."
ring0_msg:
.asciz "moved to Ring0."
ignore_msg:
.asciz "ignore interrupt."
timer_msg:
.asciz "time interrupt."
task_a:
.asciz "__bill gates like windows__"
task_b:
.asciz "__linus like linux__"
ring3_task0:
movl $0x17,%eax
movw %ax,%ds
movl $(80 * 2 + 0 ) * 2,%edi
movl $ring3_msga,%esi
call write_string
movl $task_a,%esi
int $0x85
movl $0xff,%ecx
11:
loop 11b
jmp ring3_task0
ring3_task1:
movl $(80 * 2 + 0 ) * 2,%edi
movl $ring3_msgb,%esi
call write_string
movl $task_b,%esi
int $0x85
movl $0xff,%ecx
12:
loop 12b
jmp ring3_task1
.fill 128,4,0
usr_stk1:
|