Use free Windows DDK and compile with latest MinGW releases.
[reactos.git] / reactos / ntoskrnl / ke / i386 / multiboot.S
1
2 #include <ntoskrnl.h>
3
4 #define KERNEL_BASE (0xc0000000)
5
6 #define MULTIBOOT_HEADER_MAGIC (0x1BADB002)
7
8 #define MULTIBOOT_HEADER_FLAGS (0x00010003)
9
10 #define V2P(x) (x - 0xc0000000 + 0x200000)
11
12 #ifdef MP
13
14 #define AP_MAGIC (0x12481020)
15
16 #endif /* MP */
17
18 .globl _NtProcessStartup
19 .globl _start
20 .globl _init_stack
21 .globl _init_stack_top
22 .globl _trap_stack
23 .globl _trap_stack_top
24 .globl _unmap_me
25 .globl _unmap_me2
26 .globl _unmap_me3
27 .globl _unmap_me4
28
29 /*
30 * This is called by the realmode loader, with protected mode
31 * enabled, paging disabled and the segment registers pointing
32 * a 4Gb, 32-bit segment starting at zero.
33 *
34 * EAX = Multiboot magic or application processor magic
35 *
36 * EBX = Points to a structure in lowmem with data from the
37 * loader
38 */
39
40 _NtProcessStartup:
41 _start:
42 jmp _multiboot_entry
43
44 /* Align 32 bits boundary */
45 .align 4
46
47 /* Multiboot header */
48 multiboot_header:
49 /* magic */
50 .long MULTIBOOT_HEADER_MAGIC
51 /* flags */
52 .long MULTIBOOT_HEADER_FLAGS
53 /* checksum */
54 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
55 /* header_addr */
56 .long (0x200000 + multiboot_header - KERNEL_BASE)
57 /* load_addr */
58 .long 0x200000
59 /* load_end_addr */
60 .long (__bss_start__ + 0x200000 - KERNEL_BASE)
61 /* bss_end_addr */
62 .long (__bss_end__ + 0x200000 - KERNEL_BASE)
63 /* entry_addr */
64 .long (0x200000 + _start - KERNEL_BASE)
65
66 _multiboot_entry:
67 /*
68 * This must be PIC because we haven't set up paging yet
69 */
70
71 /*
72 * Gcc expects this at all times
73 */
74 cld
75
76 #ifdef MP
77
78 /*
79 * Save the multiboot or application processor magic
80 */
81 movl %eax, %edx
82
83 cmpl $AP_MAGIC, %edx
84 je .m1
85
86 #endif /* MP */
87
88 /*
89 * Zero the BSS
90 */
91 movl %eax, %edx
92 movl $0, %eax
93 movl $__bss_end__, %ecx
94 subl $__bss_start__, %ecx
95 shr $2, %ecx
96 movl $__bss_start__, %edi
97 subl $0xc0000000, %edi
98 addl $0x200000, %edi
99 rep
100 stosl
101
102 /*
103 * Initialize the page directory
104 */
105 movl $V2P(startup_pagedirectory), %esi
106 movl $(V2P(lowmem_pagetable) + 0x7), 0x0(%esi)
107 movl $(V2P(kernel_pagetable) + 0x7), 0xC00(%esi)
108 movl $(V2P(kernel_pagetable+4096) + 0x7), 0xC04(%esi)
109 movl $(V2P(kernel_pagetable+2*4096) + 0x7), 0xC08(%esi)
110 movl $(V2P(kernel_pagetable+3*4096) + 0x7), 0xC0c(%esi)
111 movl $(V2P(kernel_pagetable+4*4096) + 0x7), 0xC10(%esi)
112 movl $(V2P(kernel_pagetable+5*4096) + 0x7), 0xC14(%esi)
113 movl $(V2P(kernel_pagetable+6*4096) + 0x7), 0xC18(%esi)
114 movl $(V2P(kernel_pagetable+7*4096) + 0x7), 0xC1c(%esi)
115 movl $(V2P(kernel_pagetable+8*4096) + 0x7), 0xC20(%esi)
116 movl $(V2P(kernel_pagetable+9*4096) + 0x7), 0xC24(%esi)
117 movl $(V2P(kernel_pagetable+10*4096) + 0x7), 0xC28(%esi)
118 movl $(V2P(kernel_pagetable+11*4096) + 0x7), 0xC2c(%esi)
119 movl $(V2P(kernel_pagetable+12*4096) + 0x7), 0xC30(%esi)
120 movl $(V2P(kernel_pagetable+13*4096) + 0x7), 0xC34(%esi)
121 movl $(V2P(kernel_pagetable+14*4096) + 0x7), 0xC38(%esi)
122 movl $(V2P(kernel_pagetable+15*4096) + 0x7), 0xC3c(%esi)
123 movl $(V2P(kernel_pagetable+16*4096) + 0x7), 0xC40(%esi)
124 movl $(V2P(kernel_pagetable+17*4096) + 0x7), 0xC44(%esi)
125 movl $(V2P(kernel_pagetable+18*4096) + 0x7), 0xC48(%esi)
126 movl $(V2P(kernel_pagetable+19*4096) + 0x7), 0xC4c(%esi)
127 movl $(V2P(kernel_pagetable+20*4096) + 0x7), 0xC50(%esi)
128 movl $(V2P(kernel_pagetable+21*4096) + 0x7), 0xC54(%esi)
129 movl $(V2P(kernel_pagetable+22*4096) + 0x7), 0xC58(%esi)
130 movl $(V2P(kernel_pagetable+23*4096) + 0x7), 0xC5c(%esi)
131 movl $(V2P(kernel_pagetable+24*4096) + 0x7), 0xC60(%esi)
132 movl $(V2P(kernel_pagetable+25*4096) + 0x7), 0xC64(%esi)
133 movl $(V2P(kernel_pagetable+26*4096) + 0x7), 0xC68(%esi)
134 movl $(V2P(kernel_pagetable+27*4096) + 0x7), 0xC6c(%esi)
135 movl $(V2P(kernel_pagetable+28*4096) + 0x7), 0xC70(%esi)
136 movl $(V2P(kernel_pagetable+29*4096) + 0x7), 0xC74(%esi)
137 movl $(V2P(kernel_pagetable+30*4096) + 0x7), 0xC78(%esi)
138 movl $(V2P(kernel_pagetable+31*4096) + 0x7), 0xC7c(%esi)
139
140 movl $(V2P(lowmem_pagetable) + 0x7), 0xD00(%esi)
141 movl $(V2P(startup_pagedirectory) + 0x7), 0xF00(%esi)
142 #ifdef MP
143 movl $(V2P(apic_pagetable) + 0x7), 0xFEC(%esi)
144 #endif /* MP */
145 movl $(V2P(kpcr_pagetable) + 0x7), 0xFF0(%esi)
146
147 /*
148 * Initialize the page table that maps low memory
149 */
150 movl $V2P(lowmem_pagetable), %esi
151 movl $0x7, %eax
152 movl $0, %edi
153 .l3:
154 movl %eax, (%esi, %edi)
155 addl $0x1000, %eax
156 addl $4, %edi
157 cmpl $4096, %edi
158 jl .l3
159
160 /*
161 * Initialize the page table that maps kernel memory
162 */
163 movl $V2P(kernel_pagetable), %esi
164 movl $0x200007, %eax
165 movl $0, %edi
166 .l4:
167 movl %eax, (%esi, %edi)
168 addl $0x1000, %eax
169 addl $4, %edi
170 cmpl $8192, %edi
171 jl .l4
172
173 #ifdef MP
174
175 /*
176 * Initialize the page table that maps the APIC register address space
177 */
178
179 /*
180 * FIXME: APIC register address space can be non-standard so do the
181 * mapping later
182 */
183 movl $V2P(apic_pagetable), %esi
184 movl $0, %edi
185 movl $0xFEC0001B, %eax
186 movl %eax, (%esi, %edi)
187 movl $0x800, %edi
188 movl $0xFEE0001B, %eax
189 movl %eax, (%esi, %edi)
190
191 #endif /* MP */
192
193 /*
194 * Initialize the page table that maps the initial KPCR (at FF000000)
195 */
196 movl $V2P(kpcr_pagetable), %esi
197 movl $0, %edi
198 movl $0x1007, %eax
199 movl %eax, (%esi, %edi)
200
201 #ifdef MP
202
203 .m1:
204
205 #endif /* MP */
206
207 /*
208 * Set up the PDBR
209 */
210 movl $(V2P(startup_pagedirectory)), %eax
211 movl %eax, %cr3
212
213 /*
214 * Enable paging and set write protect
215 */
216 movl %cr0, %eax
217 orl $0x80010000, %eax
218 movl %eax, %cr0
219
220 /*
221 * Do an absolute jump because we now want to execute above 0xc0000000
222 */
223 movl $.l2, %eax
224 jmp *%eax
225 .l2:
226
227 /*
228 * Load the GDTR and IDTR with new tables located above
229 * 0xc0000000
230 */
231
232 /* FIXME: Application processors should have their own GDT/IDT */
233 lgdt _KiGdtDescriptor
234 lidt _KiIdtDescriptor
235
236 /*
237 * Reload the data segment registers
238 */
239 movl $KERNEL_DS, %eax
240 movl %eax, %ds
241 movl %eax, %es
242 movl %eax, %gs
243 movl %eax, %ss
244 movl $0, %eax
245 movl %eax, %fs
246
247 #ifdef MP
248
249 cmpl $AP_MAGIC, %edx
250 jne .m2
251
252 /*
253 * This is an application processor executing
254 */
255
256 /*
257 * Initialize EFLAGS
258 */
259 pushl $0
260 popfl
261
262 /*
263 * Call the application processor initialization code
264 */
265 pushl $0
266 pushl $.l7
267 pushl $KERNEL_CS
268 pushl $_KiSystemStartup
269 lret
270
271 /*
272 * Catch illegal returns from KiSystemStartup
273 */
274 .l7:
275 popl %eax
276 pushl $0
277 call _KeBugCheck@4
278 popl %eax
279 .l8:
280 jmp .l8
281
282
283 .m2:
284
285 #endif /* MP */
286
287 /*
288 * Load the PCR selector
289 */
290 movl $PCR_SELECTOR, %eax
291 movl %eax, %fs
292
293 /*
294 * Load the initial kernel stack
295 */
296 movl $_init_stack_top, %esp
297
298 /*
299 * Initialize EFLAGS
300 */
301 pushl $0
302 popfl
303
304 /*
305 * Call the main kernel initialization
306 */
307 movl $0, %ebp
308 pushl %ebx
309 pushl %edx
310 pushl $.l5
311 pushl $KERNEL_CS
312 pushl $__main
313 lret
314
315 /*
316 * Catch illegal returns from main, try bug checking the system,
317 * if that fails then loop forever.
318 */
319 .l5:
320 popl %eax
321 popl %eax
322 pushl $0
323 call _KeBugCheck@4
324 popl %eax
325 .l6:
326 jmp .l6
327
328
329 /*
330 * This needs to be page aligned so put it at the beginning of the bss
331 * segment
332 */
333 .bss
334 startup_pagedirectory:
335 .fill 4096, 1, 0
336
337 lowmem_pagetable:
338 .fill 4096, 1, 0
339
340 kernel_pagetable:
341 .fill 32*4096, 1, 0
342
343 #ifdef MP
344 apic_pagetable:
345 .fill 4096, 1, 0
346 #endif /* MP */
347
348 kpcr_pagetable:
349 .fill 4096, 1, 0
350
351 _unmap_me:
352 .fill 4096, 1, 0
353
354 _init_stack:
355 .fill 3*4096, 1, 0
356 _init_stack_top:
357
358 _unmap_me2:
359 .fill 4096, 1, 0
360
361 _trap_stack:
362 .fill 3*4096, 1, 0
363 _trap_stack_top:
364
365 _unmap_me3:
366 .fill 4096, 1, 0