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