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

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

rename ia32_cboot() to arch_pre_main() and move it to ia32.c (to be in line with other platforms)

  • Property mode set to 100644
File size: 8.9 KB
RevLine 
[f761f1eb]1#
[df4ed85]2# Copyright (c) 2001-2004 Jakub Jermar
3# Copyright (c) 2005-2006 Martin Decky
[f761f1eb]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
[f9447155]30#include <arch/boot/boot.h>
[aa72859]31#include <arch/boot/memmap.h>
[8f2153b]32#include <arch/mm/page.h>
33#include <arch/pm.h>
[f9447155]34
[66def8d]35#define START_STACK (BOOT_OFFSET - BOOT_STACK_SIZE)
36
[874e312a]37.section K_TEXT_START, "ax"
[f761f1eb]38
[b0bf501]39.code32
[f9447155]40.align 4
[66def8d]41.global multiboot_image_start
[f9447155]42multiboot_header:
43 .long MULTIBOOT_HEADER_MAGIC
44 .long MULTIBOOT_HEADER_FLAGS
45 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) # checksum
[66def8d]46 .long multiboot_header
47 .long unmapped_ktext_start
[f9447155]48 .long 0
49 .long 0
[66def8d]50 .long multiboot_image_start
[5dce48b9]51
[f9447155]52multiboot_image_start:
[e13daa5d]53 cld
[66def8d]54 movl $START_STACK, %esp # initialize stack pointer
55 lgdt KA2PA(bootstrap_gdtr) # initialize Global Descriptor Table register
[b0bf501]56
[f476e76]57 movw $selector(KDATA_DES), %cx
[5eb1379]58 movw %cx, %es
59 movw %cx, %fs
[ff133e2]60 movw %cx, %gs
[66def8d]61 movw %cx, %ds # kernel data + stack
[5eb1379]62 movw %cx, %ss
[5dce48b9]63
[f476e76]64 jmpl $selector(KTEXT_DES), $multiboot_meeting_point
[4533601]65 multiboot_meeting_point:
66
[7cb567cd]67 movl %eax, grub_eax # save parameters from GRUB
68 movl %ebx, grub_ebx
[ff133e2]69
[eaf6cd6]70 xorl %eax, %eax
71 cpuid
72 cmp $0x0, %eax # any function > 0?
73 jbe pse_unsupported
[328f324b]74 movl $0x1, %eax # Basic function code 1
[eaf6cd6]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
[22cf454d]85#ifdef CONFIG_FB
[ff133e2]86 mov $vesa_init, %esi
87 mov $VESA_INIT_SEGMENT << 4, %edi
88 mov $e_vesa_init - vesa_init, %ecx
89 rep movsb
[22cf454d]90
[ff133e2]91 mov $VESA_INIT_SEGMENT << 4, %edi
[b3f8fb7]92 jmpl *%edi
[ff133e2]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)
[22cf454d]103#endif
[4b241f3]104
[b0edf3b2]105 call map_kernel # map kernel and turn paging on
[4b241f3]106
[deca67b]107 # arch_pre_main(grub_eax, grub_ebx)
[bf25efb]108 pushl grub_ebx
109 pushl grub_eax
[deca67b]110 call arch_pre_main
111
112 call main_bsp
113
[4b241f3]114 # Not reached.
[deca67b]115
[d47f0e1]116 cli
117 hlt
118
119.global map_kernel
120map_kernel:
[dcbc8be]121 #
122 # Here we setup mapping for both the unmapped and mapped sections of the kernel.
[cf27a6cb]123 # For simplicity, we map the entire 4G space.
[dcbc8be]124 #
125 movl %cr4, %ecx
[eaf6cd6]126 orl $(1 << 4), %ecx # turn PSE on
127 andl $(~(1 << 5)), %ecx # turn PAE off
128 movl %ecx, %cr4
[dcbc8be]129
[eaf6cd6]130 movl $(page_directory + 0), %esi
131 movl $(page_directory + 2048), %edi
[cf27a6cb]132 xorl %ecx, %ecx
133 xorl %ebx, %ebx
1340:
[eaf6cd6]135 movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax
[cf27a6cb]136 orl %ebx, %eax
[eaf6cd6]137 movl %eax, (%esi, %ecx, 4) # mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M
138 movl %eax, (%edi, %ecx, 4) # mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M
139 addl $(4 * 1024 * 1024), %ebx
[dcbc8be]140
[cf27a6cb]141 incl %ecx
142 cmpl $512, %ecx
143 jl 0b
[dcbc8be]144
[cf27a6cb]145 movl %esi, %cr3
[f761f1eb]146
[dcbc8be]147 movl %cr0, %ebx
[eaf6cd6]148 orl $(1 << 31), %ebx # turn paging on
[dcbc8be]149 movl %ebx, %cr0
[d47f0e1]150 ret
[dcbc8be]151
[eaf6cd6]152# Print string from %esi to EGA display (in red) and halt
153error_halt:
154 movl $0xb8000, %edi # base of EGA text mode memory
155 xorl %eax, %eax
156
157 movw $0x3d4, %dx # read bits 8 - 15 of the cursor address
158 movb $0xe, %al
159 outb %al, %dx
160
161 movw $0x3d5, %dx
162 inb %dx, %al
163 shl $8, %ax
164
165 movw $0x3d4, %dx # read bits 0 - 7 of the cursor address
166 movb $0xf, %al
167 outb %al, %dx
168
169 movw $0x3d5, %dx
170 inb %dx, %al
171
172 cmp $1920, %ax
173 jbe cursor_ok
174 movw $1920, %ax # sanity check for the cursor on the last line
175 cursor_ok:
176
177 movw %ax, %bx
178 shl $1, %eax
179 addl %eax, %edi
180
181 movw $0x0c00, %ax # black background, light red foreground
182
183 ploop:
184 lodsb
185 cmp $0, %al
186 je ploop_end
187 stosw
188 inc %bx
189 jmp ploop
190 ploop_end:
191
192 movw $0x3d4, %dx # write bits 8 - 15 of the cursor address
193 movb $0xe, %al
194 outb %al, %dx
195
196 movw $0x3d5, %dx
197 movb %bh, %al
198 outb %al, %dx
199
200 movw $0x3d4, %dx # write bits 0 - 7 of the cursor address
201 movb $0xf, %al
202 outb %al, %dx
203
204 movw $0x3d5, %dx
205 movb %bl, %al
206 outb %al, %dx
207
208 cli
209 hlt
210
[22cf454d]211#ifdef CONFIG_FB
212vesa_init:
[ff133e2]213 jmp $selector(VESA_INIT_DES), $vesa_init_real - vesa_init
214
[22cf454d]215.code16
[ff133e2]216vesa_init_real:
217
218 mov %cr0, %eax
219 and $~1, %eax
220 mov %eax, %cr0
221
222 jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init
223
224vesa_init_real2:
225
226 mov $VESA_INIT_SEGMENT, %bx
227
228 mov %bx, %es
229 mov %bx, %fs
230 mov %bx, %gs
231 mov %bx, %ds
232 mov %bx, %ss
233
234 movl %esp, %eax
235 movl $0x0000fffc, %esp
236 movl $0x0000fffc, %ebp
237 pushl %eax
[22cf454d]238
239#define VESA_INFO_SIZE 1024
240
[4f42d52]241#define VESA_MODE_ATTRIBUTES_OFFSET 0
[ff133e2]242#define VESA_MODE_LIST_PTR_OFFSET 14
[4f42d52]243#define VESA_MODE_SCANLINE_OFFSET 16
[22cf454d]244#define VESA_MODE_WIDTH_OFFSET 18
245#define VESA_MODE_HEIGHT_OFFSET 20
246#define VESA_MODE_BPP_OFFSET 25
247#define VESA_MODE_PHADDR_OFFSET 40
248
[ff133e2]249#define VESA_END_OF_MODES 0xffff
[22cf454d]250
[ff133e2]251#define VESA_OK 0x4f
[22cf454d]252
[ff133e2]253#define VESA_GET_INFO 0x4f00
[22cf454d]254#define VESA_GET_MODE_INFO 0x4f01
255#define VESA_SET_MODE 0x4f02
[4f42d52]256#define VESA_SET_PALETTE 0x4f09
[22cf454d]257
[ff133e2]258#if CONFIG_VESA_BPP == 24
[4f42d52]259#define CONFIG_VESA_BPP_VARIANT 32
[22cf454d]260#endif
261
[ff133e2]262 mov $VESA_GET_INFO, %ax
263 mov $e_vesa_init - vesa_init, %di
264 push %di
265 int $0x10
266
267 pop %di
268 cmp $VESA_OK, %al
269 jnz 0f
270
271 mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
272 mov %si, %gs
273 mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
274
275 add $VESA_INFO_SIZE, %di
[22cf454d]276
2771:# Try next mode
[ff133e2]278 mov %gs:(%si), %cx
279 cmp $VESA_END_OF_MODES, %cx
280 jz 0f
281
282 inc %si
283 inc %si
284 push %cx
285 push %di
286 push %si
287 mov $VESA_GET_MODE_INFO, %ax
288 int $0x10
289
290 pop %si
291 pop %di
292 pop %cx
293 cmp $VESA_OK, %al
294 jnz 0f
295
296 mov $CONFIG_VESA_WIDTH, %ax
297 cmp VESA_MODE_WIDTH_OFFSET(%di), %ax
298 jnz 1b
299
[4f42d52]300 mov $CONFIG_VESA_HEIGHT, %ax
[ff133e2]301 cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax
302 jnz 1b
303
304 mov $CONFIG_VESA_BPP, %al
305 cmp VESA_MODE_BPP_OFFSET(%di), %al
[4f42d52]306
307#ifdef CONFIG_VESA_BPP_VARIANT
[ff133e2]308 jz 2f
309
[4f42d52]310 mov $CONFIG_VESA_BPP_VARIANT, %al
[ff133e2]311 cmp VESA_MODE_BPP_OFFSET(%di), %al
[4f42d52]312#endif
[ff133e2]313 jnz 1b
[4f42d52]314
[22cf454d]3152:
316
[ff133e2]317 mov %cx, %bx
318 or $0xc000, %bx
319 push %di
320 mov $VESA_SET_MODE, %ax
321 int $0x10
322
323 pop %di
324 cmp $VESA_OK, %al
325 jnz 0f
[4f42d52]326
327#if CONFIG_VESA_BPP == 8
328
329 # Set 3:2:3 VGA palette
330
331 mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
332 push %di
333 mov $vga323 - vesa_init, %di
334 mov $0x100, %ecx
335
336 bt $5, %ax # Test if VGA compatible registers are present
337 jnc vga_compat
338
339 # Try VESA routine to set palette
340
341 mov $VESA_SET_PALETTE, %ax
342 xor %bl, %bl
343 xor %dx, %dx
344 int $0x10
345
[b1747a5]346 cmp $0x00, %ah
347 je vga_not_compat
[4f42d52]348
349 vga_compat:
350
351 # Try VGA registers to set palette
352
353 movw $0x3c6, %dx # Set palette mask
354 movb $0xff, %al
355 outb %al, %dx
356
357 movw $0x3c8, %dx # First index to set
358 xor %al, %al
359 outb %al, %dx
360
361 movw $0x3c9, %dx # Data port
362 vga_loop:
363 movb %es:2(%di), %al
364 outb %al, %dx
365
366 movb %es:1(%di), %al
367 outb %al, %dx
368
369 movb %es:(%di), %al
370 outb %al, %dx
371
372 addw $4, %di
373 loop vga_loop
374
375 vga_not_compat:
376
377 pop %di
378
379#endif
[ff133e2]380
381 mov VESA_MODE_PHADDR_OFFSET(%di), %esi
382 mov VESA_MODE_WIDTH_OFFSET(%di), %ax
383 shl $16, %eax
384 mov VESA_MODE_HEIGHT_OFFSET(%di), %ax
385 mov VESA_MODE_BPP_OFFSET(%di), %bl
386 xor %bh, %bh
387 shl $16, %ebx
388 mov VESA_MODE_SCANLINE_OFFSET(%di), %bx
389 mov %eax, %edi
[22cf454d]390
3918:
[ff133e2]392
393 mov %cr0, %eax
394 or $1, %eax
[8778271]395 mov %eax, %cr0
[ff133e2]396
397 jmp 9f
[22cf454d]3989:
[ff133e2]399
[f476e76]400 ljmpl $selector(KTEXT_DES), $(vesa_init_protect - vesa_init + VESA_INIT_SEGMENT << 4)
[ff133e2]401
4020:# No prefered mode found
403 mov $0x111, %cx
404 push %di
405 push %cx
406 mov $VESA_GET_MODE_INFO, %ax
407 int $0x10
408
409 pop %cx
410 pop %di
411 cmp $VESA_OK, %al
412 jnz 1f
413 jz 2b # Force relative jump
414
4151:
416 mov $0x0003, %ax
417 int $0x10
418 mov $0xffffffff, %edi # EGA text mode used, because of problems with VESA
419 xor %ax, %ax
420 jz 8b # Force relative jump
[4f42d52]421
422vga323:
423#include "vga323.pal"
[22cf454d]424
[203dcd45]425.code32
[ff133e2]426vesa_init_protect:
[f476e76]427 movw $selector(KDATA_DES), %cx
[ff133e2]428 movw %cx, %es
429 movw %cx, %fs
430 movw %cx, %gs
431 movw %cx, %ds # kernel data + stack
432 movw %cx, %ss
433
[7cb567cd]434 movl $START_STACK, %esp # initialize stack pointer
435
[f476e76]436 jmpl $selector(KTEXT_DES), $vesa_meeting_point
[22cf454d]437
438.align 4
439e_vesa_init:
440#endif
441
[874e312a]442.section K_DATA_START, "aw", @progbits
[dcbc8be]443
444.align 4096
445page_directory:
446 .space 4096, 0
[eaf6cd6]447
[7cb567cd]448grub_eax:
449 .long 0
450
451grub_ebx:
452 .long 0
453
[eaf6cd6]454pse_msg:
[4f42d52]455 .asciz "Page Size Extension not supported. System halted."
Note: See TracBrowser for help on using the repository browser.