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
|
global gdt
global idt
global kboot
global register_isr
extern con_init
extern hd_init
extern kmain
extern paging_init
extern printk
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
; WARNING: don't change this without changing the corresponding
; entries in the TSS constructor in sched.c
mov esp, 0x80000
; setup descriptor tables and enable paging
call flush_gdt
call paging_init
call flush_idt
; initialize the console
call con_init
; add this point, we can display *some* output
push .msg
call printk
add esp, 4
; initialize the disk interface
call hd_init
; 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
.msg: db "Kernel booting...", 10, 0
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
; empty TSS slots for our C scheduler
times 64 dq 0
.end:
gdtp:
dw (gdt.end-gdt-1)
dd gdt
flush_gdt:
push ebp
mov ebp, esp
; 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:
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
|