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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 82b71ef1 was e13daa5d, checked in by Jakub Jermar <jakub@…>, 17 years ago

Fortify ia32 and amd64 kernels against mallicious uspace applications that set
DF prior to entering the kernel. For AMD64 syscalls, we don't use the CLD
instruction, but make use of the SFMASK MSR instead. Simics works fine with
it, but QEMU seems to have a problem.

  • Property mode set to 100644
File size: 10.8 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 jmp vga_not_compat
446
447 vga_compat:
448
449 # Try VGA registers to set palette
450
451 movw $0x3c6, %dx # Set palette mask
452 movb $0xff, %al
453 outb %al, %dx
454
455 movw $0x3c8, %dx # First index to set
456 xor %al, %al
457 outb %al, %dx
458
459 movw $0x3c9, %dx # Data port
460 vga_loop:
461 movb %es:2(%di), %al
462 outb %al, %dx
463
464 movb %es:1(%di), %al
465 outb %al, %dx
466
467 movb %es:(%di), %al
468 outb %al, %dx
469
470 addw $4, %di
471 loop vga_loop
472
473 vga_not_compat:
474
475 pop %di
476
477#endif
478
479 mov VESA_MODE_PHADDR_OFFSET(%di), %esi
480 mov VESA_MODE_WIDTH_OFFSET(%di), %ax
481 shl $16, %eax
482 mov VESA_MODE_HEIGHT_OFFSET(%di), %ax
483 mov VESA_MODE_BPP_OFFSET(%di), %bl
484 xor %bh, %bh
485 shl $16, %ebx
486 mov VESA_MODE_SCANLINE_OFFSET(%di), %bx
487 mov %eax, %edi
488
4898:
490
491 mov %cr0, %eax
492 or $1, %eax
493 mov %eax, %cr0
494
495 jmp 9f
4969:
497
498 ljmpl $selector(KTEXT_DES), $(vesa_init_protect - vesa_init + VESA_INIT_SEGMENT << 4)
499
5000:# No prefered mode found
501 mov $0x111, %cx
502 push %di
503 push %cx
504 mov $VESA_GET_MODE_INFO, %ax
505 int $0x10
506
507 pop %cx
508 pop %di
509 cmp $VESA_OK, %al
510 jnz 1f
511 jz 2b # Force relative jump
512
5131:
514 mov $0x0003, %ax
515 int $0x10
516 mov $0xffffffff, %edi # EGA text mode used, because of problems with VESA
517 xor %ax, %ax
518 jz 8b # Force relative jump
519
520vga323:
521#include "vga323.pal"
522
523.code32
524vesa_init_protect:
525 movw $selector(KDATA_DES), %cx
526 movw %cx, %es
527 movw %cx, %fs
528 movw %cx, %gs
529 movw %cx, %ds # kernel data + stack
530 movw %cx, %ss
531
532 movl $START_STACK, %esp # initialize stack pointer
533
534 jmpl $selector(KTEXT_DES), $vesa_meeting_point
535
536.align 4
537e_vesa_init:
538#endif
539
540.section K_DATA_START, "aw", @progbits
541
542.align 4096
543page_directory:
544 .space 4096, 0
545
546grub_eax:
547 .long 0
548
549grub_ebx:
550 .long 0
551
552pse_msg:
553 .asciz "Page Size Extension not supported. System halted."
Note: See TracBrowser for help on using the repository browser.