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

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

fallback to VGA registers if VESA routine fails

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