source: mainline/kernel/arch/ia32/src/boot/boot.S@ 4b241f3

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4b241f3 was 4b241f3, checked in by Jiri Svoboda <jirik.svoboda@…>, 16 years ago

The ia32-specific boot code is written completely in assembly for no reason. Start fixing this. For now rewrite the copying of multiboot info to C.

  • Property mode set to 100644
File size: 9.2 KB
Line 
1#
2# Copyright (c) 2001-2004 Jakub Jermar
3# Copyright (c) 2005-2006 Martin Decky
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9#
10# - Redistributions of source code must retain the above copyright
11# notice, this list of conditions and the following disclaimer.
12# - Redistributions in binary form must reproduce the above copyright
13# notice, this list of conditions and the following disclaimer in the
14# documentation and/or other materials provided with the distribution.
15# - The name of the author may not be used to endorse or promote products
16# derived from this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28#
29
30#include <arch/boot/boot.h>
31#include <arch/boot/memmap.h>
32#include <arch/mm/page.h>
33#include <arch/pm.h>
34
35#define START_STACK (BOOT_OFFSET - BOOT_STACK_SIZE)
36
37.section K_TEXT_START, "ax"
38
39.code32
40.align 4
41.global multiboot_image_start
42multiboot_header:
43 .long MULTIBOOT_HEADER_MAGIC
44 .long MULTIBOOT_HEADER_FLAGS
45 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) # checksum
46 .long multiboot_header
47 .long unmapped_ktext_start
48 .long 0
49 .long 0
50 .long multiboot_image_start
51
52multiboot_image_start:
53 cld
54 movl $START_STACK, %esp # initialize stack pointer
55 lgdt KA2PA(bootstrap_gdtr) # initialize Global Descriptor Table register
56
57 movw $selector(KDATA_DES), %cx
58 movw %cx, %es
59 movw %cx, %fs
60 movw %cx, %gs
61 movw %cx, %ds # kernel data + stack
62 movw %cx, %ss
63
64 jmpl $selector(KTEXT_DES), $multiboot_meeting_point
65 multiboot_meeting_point:
66
67 movl %eax, grub_eax # save parameters from GRUB
68 movl %ebx, grub_ebx
69
70 xorl %eax, %eax
71 cpuid
72 cmp $0x0, %eax # any function > 0?
73 jbe pse_unsupported
74 movl $0x1, %eax # Basic function code 1
75 cpuid
76 bt $3, %edx # Test if PSE is supported
77 jc pse_supported
78
79 pse_unsupported:
80 movl $pse_msg, %esi
81 jmp error_halt
82
83 pse_supported:
84
85#ifdef CONFIG_FB
86 mov $vesa_init, %esi
87 mov $VESA_INIT_SEGMENT << 4, %edi
88 mov $e_vesa_init - vesa_init, %ecx
89 rep movsb
90
91 mov $VESA_INIT_SEGMENT << 4, %edi
92 jmpl *%edi
93
94 vesa_meeting_point:
95
96 mov %esi, KA2PA(vesa_ph_addr)
97 mov %di, KA2PA(vesa_height)
98 shr $16, %edi
99 mov %di, KA2PA(vesa_width)
100 mov %bx, KA2PA(vesa_scanline)
101 shr $16, %ebx
102 mov %bx, KA2PA(vesa_bpp)
103#endif
104
105 call map_kernel # map kernel and turn paging on
106
107 movl grub_eax, %eax
108 movl grub_ebx, %ebx
109 cmpl $MULTIBOOT_LOADER_MAGIC, %eax # compare GRUB signature
110 je valid_boot
111
112 xorl %ecx, %ecx # no memory map available
113 movl %ecx, e820counter
114
115 jmp invalid_boot
116
117 valid_boot:
118
119 movl grub_eax, %eax
120 movl grub_ebx, %ebx
121
122 # ia32_boot(grub_eax, grub_ebx)
123 pushl %ebx
124 pushl %eax
125 call ia32_cboot # Does not return.
126
127 # Not reached.
128
129 invalid_boot:
130
131 cli
132 hlt
133
134.global map_kernel
135map_kernel:
136 #
137 # Here we setup mapping for both the unmapped and mapped sections of the kernel.
138 # For simplicity, we map the entire 4G space.
139 #
140 movl %cr4, %ecx
141 orl $(1 << 4), %ecx # turn PSE on
142 andl $(~(1 << 5)), %ecx # turn PAE off
143 movl %ecx, %cr4
144
145 movl $(page_directory + 0), %esi
146 movl $(page_directory + 2048), %edi
147 xorl %ecx, %ecx
148 xorl %ebx, %ebx
1490:
150 movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax
151 orl %ebx, %eax
152 movl %eax, (%esi, %ecx, 4) # mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M
153 movl %eax, (%edi, %ecx, 4) # mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M
154 addl $(4 * 1024 * 1024), %ebx
155
156 incl %ecx
157 cmpl $512, %ecx
158 jl 0b
159
160 movl %esi, %cr3
161
162 movl %cr0, %ebx
163 orl $(1 << 31), %ebx # turn paging on
164 movl %ebx, %cr0
165 ret
166
167# Print string from %esi to EGA display (in red) and halt
168error_halt:
169 movl $0xb8000, %edi # base of EGA text mode memory
170 xorl %eax, %eax
171
172 movw $0x3d4, %dx # read bits 8 - 15 of the cursor address
173 movb $0xe, %al
174 outb %al, %dx
175
176 movw $0x3d5, %dx
177 inb %dx, %al
178 shl $8, %ax
179
180 movw $0x3d4, %dx # read bits 0 - 7 of the cursor address
181 movb $0xf, %al
182 outb %al, %dx
183
184 movw $0x3d5, %dx
185 inb %dx, %al
186
187 cmp $1920, %ax
188 jbe cursor_ok
189 movw $1920, %ax # sanity check for the cursor on the last line
190 cursor_ok:
191
192 movw %ax, %bx
193 shl $1, %eax
194 addl %eax, %edi
195
196 movw $0x0c00, %ax # black background, light red foreground
197
198 ploop:
199 lodsb
200 cmp $0, %al
201 je ploop_end
202 stosw
203 inc %bx
204 jmp ploop
205 ploop_end:
206
207 movw $0x3d4, %dx # write bits 8 - 15 of the cursor address
208 movb $0xe, %al
209 outb %al, %dx
210
211 movw $0x3d5, %dx
212 movb %bh, %al
213 outb %al, %dx
214
215 movw $0x3d4, %dx # write bits 0 - 7 of the cursor address
216 movb $0xf, %al
217 outb %al, %dx
218
219 movw $0x3d5, %dx
220 movb %bl, %al
221 outb %al, %dx
222
223 cli
224 hlt
225
226#ifdef CONFIG_FB
227vesa_init:
228 jmp $selector(VESA_INIT_DES), $vesa_init_real - vesa_init
229
230.code16
231vesa_init_real:
232
233 mov %cr0, %eax
234 and $~1, %eax
235 mov %eax, %cr0
236
237 jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init
238
239vesa_init_real2:
240
241 mov $VESA_INIT_SEGMENT, %bx
242
243 mov %bx, %es
244 mov %bx, %fs
245 mov %bx, %gs
246 mov %bx, %ds
247 mov %bx, %ss
248
249 movl %esp, %eax
250 movl $0x0000fffc, %esp
251 movl $0x0000fffc, %ebp
252 pushl %eax
253
254#define VESA_INFO_SIZE 1024
255
256#define VESA_MODE_ATTRIBUTES_OFFSET 0
257#define VESA_MODE_LIST_PTR_OFFSET 14
258#define VESA_MODE_SCANLINE_OFFSET 16
259#define VESA_MODE_WIDTH_OFFSET 18
260#define VESA_MODE_HEIGHT_OFFSET 20
261#define VESA_MODE_BPP_OFFSET 25
262#define VESA_MODE_PHADDR_OFFSET 40
263
264#define VESA_END_OF_MODES 0xffff
265
266#define VESA_OK 0x4f
267
268#define VESA_GET_INFO 0x4f00
269#define VESA_GET_MODE_INFO 0x4f01
270#define VESA_SET_MODE 0x4f02
271#define VESA_SET_PALETTE 0x4f09
272
273#if CONFIG_VESA_BPP == 24
274#define CONFIG_VESA_BPP_VARIANT 32
275#endif
276
277 mov $VESA_GET_INFO, %ax
278 mov $e_vesa_init - vesa_init, %di
279 push %di
280 int $0x10
281
282 pop %di
283 cmp $VESA_OK, %al
284 jnz 0f
285
286 mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
287 mov %si, %gs
288 mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
289
290 add $VESA_INFO_SIZE, %di
291
2921:# Try next mode
293 mov %gs:(%si), %cx
294 cmp $VESA_END_OF_MODES, %cx
295 jz 0f
296
297 inc %si
298 inc %si
299 push %cx
300 push %di
301 push %si
302 mov $VESA_GET_MODE_INFO, %ax
303 int $0x10
304
305 pop %si
306 pop %di
307 pop %cx
308 cmp $VESA_OK, %al
309 jnz 0f
310
311 mov $CONFIG_VESA_WIDTH, %ax
312 cmp VESA_MODE_WIDTH_OFFSET(%di), %ax
313 jnz 1b
314
315 mov $CONFIG_VESA_HEIGHT, %ax
316 cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax
317 jnz 1b
318
319 mov $CONFIG_VESA_BPP, %al
320 cmp VESA_MODE_BPP_OFFSET(%di), %al
321
322#ifdef CONFIG_VESA_BPP_VARIANT
323 jz 2f
324
325 mov $CONFIG_VESA_BPP_VARIANT, %al
326 cmp VESA_MODE_BPP_OFFSET(%di), %al
327#endif
328 jnz 1b
329
3302:
331
332 mov %cx, %bx
333 or $0xc000, %bx
334 push %di
335 mov $VESA_SET_MODE, %ax
336 int $0x10
337
338 pop %di
339 cmp $VESA_OK, %al
340 jnz 0f
341
342#if CONFIG_VESA_BPP == 8
343
344 # Set 3:2:3 VGA palette
345
346 mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
347 push %di
348 mov $vga323 - vesa_init, %di
349 mov $0x100, %ecx
350
351 bt $5, %ax # Test if VGA compatible registers are present
352 jnc vga_compat
353
354 # Try VESA routine to set palette
355
356 mov $VESA_SET_PALETTE, %ax
357 xor %bl, %bl
358 xor %dx, %dx
359 int $0x10
360
361 cmp $0x00, %ah
362 je vga_not_compat
363
364 vga_compat:
365
366 # Try VGA registers to set palette
367
368 movw $0x3c6, %dx # Set palette mask
369 movb $0xff, %al
370 outb %al, %dx
371
372 movw $0x3c8, %dx # First index to set
373 xor %al, %al
374 outb %al, %dx
375
376 movw $0x3c9, %dx # Data port
377 vga_loop:
378 movb %es:2(%di), %al
379 outb %al, %dx
380
381 movb %es:1(%di), %al
382 outb %al, %dx
383
384 movb %es:(%di), %al
385 outb %al, %dx
386
387 addw $4, %di
388 loop vga_loop
389
390 vga_not_compat:
391
392 pop %di
393
394#endif
395
396 mov VESA_MODE_PHADDR_OFFSET(%di), %esi
397 mov VESA_MODE_WIDTH_OFFSET(%di), %ax
398 shl $16, %eax
399 mov VESA_MODE_HEIGHT_OFFSET(%di), %ax
400 mov VESA_MODE_BPP_OFFSET(%di), %bl
401 xor %bh, %bh
402 shl $16, %ebx
403 mov VESA_MODE_SCANLINE_OFFSET(%di), %bx
404 mov %eax, %edi
405
4068:
407
408 mov %cr0, %eax
409 or $1, %eax
410 mov %eax, %cr0
411
412 jmp 9f
4139:
414
415 ljmpl $selector(KTEXT_DES), $(vesa_init_protect - vesa_init + VESA_INIT_SEGMENT << 4)
416
4170:# No prefered mode found
418 mov $0x111, %cx
419 push %di
420 push %cx
421 mov $VESA_GET_MODE_INFO, %ax
422 int $0x10
423
424 pop %cx
425 pop %di
426 cmp $VESA_OK, %al
427 jnz 1f
428 jz 2b # Force relative jump
429
4301:
431 mov $0x0003, %ax
432 int $0x10
433 mov $0xffffffff, %edi # EGA text mode used, because of problems with VESA
434 xor %ax, %ax
435 jz 8b # Force relative jump
436
437vga323:
438#include "vga323.pal"
439
440.code32
441vesa_init_protect:
442 movw $selector(KDATA_DES), %cx
443 movw %cx, %es
444 movw %cx, %fs
445 movw %cx, %gs
446 movw %cx, %ds # kernel data + stack
447 movw %cx, %ss
448
449 movl $START_STACK, %esp # initialize stack pointer
450
451 jmpl $selector(KTEXT_DES), $vesa_meeting_point
452
453.align 4
454e_vesa_init:
455#endif
456
457.section K_DATA_START, "aw", @progbits
458
459.align 4096
460page_directory:
461 .space 4096, 0
462
463grub_eax:
464 .long 0
465
466grub_ebx:
467 .long 0
468
469pse_msg:
470 .asciz "Page Size Extension not supported. System halted."
Note: See TracBrowser for help on using the repository browser.