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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4f42d52 was 4f42d52, checked in by Martin Decky <martin@…>, 18 years ago

force VGA palette to 3:2:3 palette on 8 bpp modes
(this fixes ticket #33)

  • Property mode set to 100644
File size: 11.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 movl $START_STACK, %esp # initialize stack pointer
54 lgdt KA2PA(bootstrap_gdtr) # initialize Global Descriptor Table register
55
56 movw $selector(KDATA_DES), %cx
57 movw %cx, %es
58 movw %cx, %fs
59 movw %cx, %gs
60 movw %cx, %ds # kernel data + stack
61 movw %cx, %ss
62
63 jmpl $selector(KTEXT_DES), $multiboot_meeting_point
64 multiboot_meeting_point:
65
66 movl %eax, grub_eax # save parameters from GRUB
67 movl %ebx, grub_ebx
68
69 xorl %eax, %eax
70 cpuid
71 cmp $0x0, %eax # any function > 0?
72 jbe pse_unsupported
73 movl $0x1, %eax # Basic function code 1
74 cpuid
75 bt $3, %edx # Test if PSE is supported
76 jc pse_supported
77
78 pse_unsupported:
79 movl $pse_msg, %esi
80 jmp error_halt
81
82 pse_supported:
83
84#ifdef CONFIG_FB
85 mov $vesa_init, %esi
86 mov $VESA_INIT_SEGMENT << 4, %edi
87 mov $e_vesa_init - vesa_init, %ecx
88 cld
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 size or map available
113 movl %ecx, e801memorysize
114 movl %ecx, e820counter
115
116 jmp invalid_boot
117
118 valid_boot:
119
120 movl (%ebx), %eax # ebx = physical address of struct multiboot_info
121
122 bt $0, %eax # mbi->flags[0] (mem_lower, mem_upper valid)
123 jc mem_valid
124
125 xorl %ecx, %ecx
126 jmp mem_invalid
127
128 mem_valid:
129 movl 4(%ebx), %ecx # mbi->mem_lower
130 addl 8(%ebx), %ecx # mbi->mem_upper
131
132 mem_invalid:
133 movl %ecx, e801memorysize
134
135 bt $3, %eax # mbi->flags[3] (mods_count, mods_addr valid)
136 jc mods_valid
137
138 xorl %ecx, %ecx
139 movl %ecx, init
140 jmp mods_end
141
142 mods_valid:
143
144 movl 20(%ebx), %ecx # mbi->mods_count
145 movl %ecx, init
146
147 cmpl $0, %ecx
148 je mods_end
149
150 movl 24(%ebx), %esi # mbi->mods_addr
151 movl $init, %edi
152
153 mods_loop:
154
155 movl 0(%esi), %edx # mods->mod_start
156 addl $0x80000000, %edx
157 movl %edx, 4(%edi)
158
159 movl 4(%esi), %edx
160 subl 0(%esi), %edx # mods->mod_end - mods->mod_start
161 movl %edx, 8(%edi)
162
163 addl $16, %esi
164 addl $8 , %edi
165
166 loop mods_loop
167
168 mods_end:
169
170 bt $6, %eax # mbi->flags[6] (mmap_length, mmap_addr valid)
171 jc mmap_valid
172
173 xorl %edx, %edx
174 jmp mmap_invalid
175
176 mmap_valid:
177 movl 44(%ebx), %ecx # mbi->mmap_length
178 movl 48(%ebx), %esi # mbi->mmap_addr
179 movl $e820table, %edi
180 xorl %edx, %edx
181
182 mmap_loop:
183 cmpl $0, %ecx
184 jle mmap_end
185
186 movl 4(%esi), %eax # mmap->base_addr_low
187 movl %eax, (%edi)
188
189 movl 8(%esi), %eax # mmap->base_addr_high
190 movl %eax, 4(%edi)
191
192 movl 12(%esi), %eax # mmap->length_low
193 movl %eax, 8(%edi)
194
195 movl 16(%esi), %eax # mmap->length_high
196 movl %eax, 12(%edi)
197
198 movl 20(%esi), %eax # mmap->type
199 movl %eax, 16(%edi)
200
201 movl (%esi), %eax # mmap->size
202 addl $0x4, %eax
203 addl %eax, %esi
204 subl %eax, %ecx
205 addl $MEMMAP_E820_RECORD_SIZE, %edi
206 incl %edx
207 jmp mmap_loop
208
209 mmap_end:
210
211 mmap_invalid:
212 movl %edx, e820counter
213
214 invalid_boot:
215
216#ifdef CONFIG_SMP
217
218 # copy AP bootstrap routines below 1 MB
219
220 movl $BOOT_OFFSET, %esi
221 movl $AP_BOOT_OFFSET, %edi
222 movl $_hardcoded_unmapped_size, %ecx
223 cld
224 rep movsb
225
226#endif
227
228 call main_bsp # never returns
229
230 cli
231 hlt
232
233.global map_kernel
234map_kernel:
235 #
236 # Here we setup mapping for both the unmapped and mapped sections of the kernel.
237 # For simplicity, we map the entire 4G space.
238 #
239 movl %cr4, %ecx
240 orl $(1 << 4), %ecx # turn PSE on
241 andl $(~(1 << 5)), %ecx # turn PAE off
242 movl %ecx, %cr4
243
244 movl $(page_directory + 0), %esi
245 movl $(page_directory + 2048), %edi
246 xorl %ecx, %ecx
247 xorl %ebx, %ebx
2480:
249 movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax
250 orl %ebx, %eax
251 movl %eax, (%esi, %ecx, 4) # mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M
252 movl %eax, (%edi, %ecx, 4) # mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M
253 addl $(4 * 1024 * 1024), %ebx
254
255 incl %ecx
256 cmpl $512, %ecx
257 jl 0b
258
259 movl %esi, %cr3
260
261 movl %cr0, %ebx
262 orl $(1 << 31), %ebx # turn paging on
263 movl %ebx, %cr0
264 ret
265
266# Print string from %esi to EGA display (in red) and halt
267error_halt:
268 movl $0xb8000, %edi # base of EGA text mode memory
269 xorl %eax, %eax
270
271 movw $0x3d4, %dx # read bits 8 - 15 of the cursor address
272 movb $0xe, %al
273 outb %al, %dx
274
275 movw $0x3d5, %dx
276 inb %dx, %al
277 shl $8, %ax
278
279 movw $0x3d4, %dx # read bits 0 - 7 of the cursor address
280 movb $0xf, %al
281 outb %al, %dx
282
283 movw $0x3d5, %dx
284 inb %dx, %al
285
286 cmp $1920, %ax
287 jbe cursor_ok
288 movw $1920, %ax # sanity check for the cursor on the last line
289 cursor_ok:
290
291 movw %ax, %bx
292 shl $1, %eax
293 addl %eax, %edi
294
295 movw $0x0c00, %ax # black background, light red foreground
296 cld
297
298 ploop:
299 lodsb
300 cmp $0, %al
301 je ploop_end
302 stosw
303 inc %bx
304 jmp ploop
305 ploop_end:
306
307 movw $0x3d4, %dx # write bits 8 - 15 of the cursor address
308 movb $0xe, %al
309 outb %al, %dx
310
311 movw $0x3d5, %dx
312 movb %bh, %al
313 outb %al, %dx
314
315 movw $0x3d4, %dx # write bits 0 - 7 of the cursor address
316 movb $0xf, %al
317 outb %al, %dx
318
319 movw $0x3d5, %dx
320 movb %bl, %al
321 outb %al, %dx
322
323 cli
324 hlt
325
326#ifdef CONFIG_FB
327vesa_init:
328 jmp $selector(VESA_INIT_DES), $vesa_init_real - vesa_init
329
330.code16
331vesa_init_real:
332
333 mov %cr0, %eax
334 and $~1, %eax
335 mov %eax, %cr0
336
337 jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init
338
339vesa_init_real2:
340
341 mov $VESA_INIT_SEGMENT, %bx
342
343 mov %bx, %es
344 mov %bx, %fs
345 mov %bx, %gs
346 mov %bx, %ds
347 mov %bx, %ss
348
349 movl %esp, %eax
350 movl $0x0000fffc, %esp
351 movl $0x0000fffc, %ebp
352 pushl %eax
353
354#define VESA_INFO_SIZE 1024
355
356#define VESA_MODE_ATTRIBUTES_OFFSET 0
357#define VESA_MODE_LIST_PTR_OFFSET 14
358#define VESA_MODE_SCANLINE_OFFSET 16
359#define VESA_MODE_WIDTH_OFFSET 18
360#define VESA_MODE_HEIGHT_OFFSET 20
361#define VESA_MODE_BPP_OFFSET 25
362#define VESA_MODE_PHADDR_OFFSET 40
363
364#define VESA_END_OF_MODES 0xffff
365
366#define VESA_OK 0x4f
367
368#define VESA_GET_INFO 0x4f00
369#define VESA_GET_MODE_INFO 0x4f01
370#define VESA_SET_MODE 0x4f02
371#define VESA_SET_PALETTE 0x4f09
372
373#if CONFIG_VESA_BPP == 24
374#define CONFIG_VESA_BPP_VARIANT 32
375#endif
376
377 mov $VESA_GET_INFO, %ax
378 mov $e_vesa_init - vesa_init, %di
379 push %di
380 int $0x10
381
382 pop %di
383 cmp $VESA_OK, %al
384 jnz 0f
385
386 mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
387 mov %si, %gs
388 mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
389
390 add $VESA_INFO_SIZE, %di
391
3921:# Try next mode
393 mov %gs:(%si), %cx
394 cmp $VESA_END_OF_MODES, %cx
395 jz 0f
396
397 inc %si
398 inc %si
399 push %cx
400 push %di
401 push %si
402 mov $VESA_GET_MODE_INFO, %ax
403 int $0x10
404
405 pop %si
406 pop %di
407 pop %cx
408 cmp $VESA_OK, %al
409 jnz 0f
410
411 mov $CONFIG_VESA_WIDTH, %ax
412 cmp VESA_MODE_WIDTH_OFFSET(%di), %ax
413 jnz 1b
414
415 mov $CONFIG_VESA_HEIGHT, %ax
416 cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax
417 jnz 1b
418
419 mov $CONFIG_VESA_BPP, %al
420 cmp VESA_MODE_BPP_OFFSET(%di), %al
421
422#ifdef CONFIG_VESA_BPP_VARIANT
423 jz 2f
424
425 mov $CONFIG_VESA_BPP_VARIANT, %al
426 cmp VESA_MODE_BPP_OFFSET(%di), %al
427#endif
428 jnz 1b
429
4302:
431
432 mov %cx, %bx
433 or $0xc000, %bx
434 push %di
435 mov $VESA_SET_MODE, %ax
436 int $0x10
437
438 pop %di
439 cmp $VESA_OK, %al
440 jnz 0f
441
442#if CONFIG_VESA_BPP == 8
443
444 # Set 3:2:3 VGA palette
445
446 mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
447 push %di
448 mov $vga323 - vesa_init, %di
449 mov $0x100, %ecx
450
451 bt $5, %ax # Test if VGA compatible registers are present
452 jnc vga_compat
453
454 # Try VESA routine to set palette
455
456 mov $VESA_SET_PALETTE, %ax
457 xor %bl, %bl
458 xor %dx, %dx
459 int $0x10
460
461 jmp vga_not_compat
462
463 vga_compat:
464
465 # Try VGA registers to set palette
466
467 movw $0x3c6, %dx # Set palette mask
468 movb $0xff, %al
469 outb %al, %dx
470
471 movw $0x3c8, %dx # First index to set
472 xor %al, %al
473 outb %al, %dx
474
475 movw $0x3c9, %dx # Data port
476 vga_loop:
477 movb %es:2(%di), %al
478 outb %al, %dx
479
480 movb %es:1(%di), %al
481 outb %al, %dx
482
483 movb %es:(%di), %al
484 outb %al, %dx
485
486 addw $4, %di
487 loop vga_loop
488
489 vga_not_compat:
490
491 pop %di
492
493#endif
494
495 mov VESA_MODE_PHADDR_OFFSET(%di), %esi
496 mov VESA_MODE_WIDTH_OFFSET(%di), %ax
497 shl $16, %eax
498 mov VESA_MODE_HEIGHT_OFFSET(%di), %ax
499 mov VESA_MODE_BPP_OFFSET(%di), %bl
500 xor %bh, %bh
501 shl $16, %ebx
502 mov VESA_MODE_SCANLINE_OFFSET(%di), %bx
503 mov %eax, %edi
504
5058:
506
507 mov %cr0, %eax
508 or $1, %eax
509 mov %eax, %cr0
510
511 jmp 9f
5129:
513
514 ljmpl $selector(KTEXT_DES), $(vesa_init_protect - vesa_init + VESA_INIT_SEGMENT << 4)
515
5160:# No prefered mode found
517 mov $0x111, %cx
518 push %di
519 push %cx
520 mov $VESA_GET_MODE_INFO, %ax
521 int $0x10
522
523 pop %cx
524 pop %di
525 cmp $VESA_OK, %al
526 jnz 1f
527 jz 2b # Force relative jump
528
5291:
530 mov $0x0003, %ax
531 int $0x10
532 mov $0xffffffff, %edi # EGA text mode used, because of problems with VESA
533 xor %ax, %ax
534 jz 8b # Force relative jump
535
536vga323:
537#include "vga323.pal"
538
539.code32
540vesa_init_protect:
541 movw $selector(KDATA_DES), %cx
542 movw %cx, %es
543 movw %cx, %fs
544 movw %cx, %gs
545 movw %cx, %ds # kernel data + stack
546 movw %cx, %ss
547
548 movl $START_STACK, %esp # initialize stack pointer
549
550 jmpl $selector(KTEXT_DES), $vesa_meeting_point
551
552.align 4
553e_vesa_init:
554#endif
555
556.section K_DATA_START, "aw", @progbits
557
558.align 4096
559page_directory:
560 .space 4096, 0
561
562grub_eax:
563 .long 0
564
565grub_ebx:
566 .long 0
567
568pse_msg:
569 .asciz "Page Size Extension not supported. System halted."
Note: See TracBrowser for help on using the repository browser.