source: mainline/kernel/arch/ia32/src/boot/multiboot.S@ 0fb70e1

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

explicitly load default BIOS IDT for real-mode VESA BIOS access (GRUB 2.00 setups an empty IDT for bootstrap)
always use an empty IDT during bootstrap (for consistency)
make sure the interrupts are disabled during bootstrap
make sure correct GDT is set after returning from VESA BIOS

  • Property mode set to 100644
File size: 14.1 KB
Line 
1/*
2 * Copyright (c) 2001 Jakub Jermar
3 * Copyright (c) 2005 Martin Decky
4 * Copyright (c) 2011 Martin Sucha
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * - The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <arch/boot/boot.h>
32#include <arch/mm/page.h>
33#include <arch/pm.h>
34#include <genarch/multiboot/multiboot.h>
35#include <arch/cpuid.h>
36
37#define START_STACK (BOOT_OFFSET - BOOT_STACK_SIZE)
38
39.section K_TEXT_START, "ax"
40
41.code32
42
43.macro pm_error msg
44 movl \msg, %esi
45 jmp pm_error_halt
46.endm
47
48.macro pm_status msg
49#ifdef CONFIG_EGA
50 pushl %esi
51 movl \msg, %esi
52 call pm_early_puts
53 popl %esi
54#endif
55.endm
56
57.macro pm2_status msg
58 pushl \msg
59 call early_puts
60.endm
61
62.align 4
63.global multiboot_image_start
64multiboot_header:
65 .long MULTIBOOT_HEADER_MAGIC
66 .long MULTIBOOT_HEADER_FLAGS
67 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) /* checksum */
68 .long multiboot_header
69 .long unmapped_ktext_start
70 .long 0
71 .long 0
72 .long multiboot_image_start
73
74multiboot_image_start:
75 cli
76 cld
77
78 /* Initialize stack pointer */
79 movl $START_STACK, %esp
80
81 /*
82 * Initialize Global Descriptor Table and
83 * Interrupt Descriptor Table registers
84 */
85 lgdtl bootstrap_gdtr
86 lidtl bootstrap_idtr
87
88 /* Kernel data + stack */
89 movw $GDT_SELECTOR(KDATA_DES), %cx
90 movw %cx, %es
91 movw %cx, %fs
92 movw %cx, %gs
93 movw %cx, %ds
94 movw %cx, %ss
95
96 jmpl $GDT_SELECTOR(KTEXT_DES), $multiboot_meeting_point
97 multiboot_meeting_point:
98
99 /* Save multiboot arguments */
100 movl %eax, multiboot_eax
101 movl %ebx, multiboot_ebx
102
103 pm_status $status_prot
104
105#include "vesa_prot.inc"
106
107#ifndef PROCESSOR_i486
108
109 pm_status $status_prot2
110
111 movl $(INTEL_CPUID_LEVEL), %eax
112 cpuid
113 cmp $0x0, %eax /* any function > 0? */
114 jbe pse_unsupported
115
116 movl $(INTEL_CPUID_STANDARD), %eax
117 cpuid
118 bt $(INTEL_PSE), %edx
119 jnc pse_unsupported
120
121 /* Map kernel and turn paging on */
122 pm_status $status_pse
123 call map_kernel_pse
124 jmp stack_init
125
126#endif /* PROCESSOR_i486 */
127
128 pse_unsupported:
129
130 /* Map kernel and turn paging on */
131 pm_status $status_non_pse
132 call map_kernel_non_pse
133
134 stack_init:
135
136 /* Create the first stack frame */
137 pushl $0
138 movl %esp, %ebp
139
140 pm2_status $status_prot3
141
142 /* Call arch_pre_main(multiboot_eax, multiboot_ebx) */
143 pushl multiboot_ebx
144 pushl multiboot_eax
145 call arch_pre_main
146
147 pm2_status $status_main
148
149 /* Call main_bsp() */
150 call main_bsp
151
152 /* Not reached */
153 cli
154 hlt0:
155 hlt
156 jmp hlt0
157
158/** Setup mapping for the kernel (PSE variant)
159 *
160 * Setup mapping for both the unmapped and mapped sections
161 * of the kernel. For simplicity, we map the entire 4G space.
162 *
163 */
164.global map_kernel_pse
165map_kernel_pse:
166 /* Paging features */
167 movl %cr4, %ecx
168 orl $(1 << 4), %ecx /* PSE on */
169 andl $(~(1 << 5)), %ecx /* PAE off */
170 movl %ecx, %cr4
171
172 movl $(page_directory + 0), %esi
173 movl $(page_directory + 2048), %edi
174 xorl %ecx, %ecx
175 xorl %ebx, %ebx
176
177 floop_pse:
178 movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax
179 orl %ebx, %eax
180 /* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
181 movl %eax, (%esi, %ecx, 4)
182 /* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
183 movl %eax, (%edi, %ecx, 4)
184 addl $(4 * 1024 * 1024), %ebx
185
186 incl %ecx
187 cmpl $512, %ecx
188 jl floop_pse
189
190 movl %esi, %cr3
191
192 movl %cr0, %ebx
193 orl $(1 << 31), %ebx /* paging on */
194 movl %ebx, %cr0
195 ret
196
197/** Setup mapping for the kernel (non-PSE variant).
198 *
199 * Setup mapping for both the unmapped and mapped sections
200 * of the kernel. For simplicity, we map the entire 4G space.
201 *
202 */
203.global map_kernel_non_pse
204map_kernel_non_pse:
205 /* Paging features */
206 movl %cr4, %ecx
207 andl $(~(1 << 5)), %ecx /* PAE off */
208 movl %ecx, %cr4
209
210 call calc_kernel_end
211 call find_mem_for_pt
212
213 mov kernel_end, %esi
214 mov free_area, %ecx
215
216 cmpl %esi, %ecx
217 jbe use_kernel_end
218
219 mov %ecx, %esi
220
221 /* Align address down to 4k */
222 andl $(~4095), %esi
223
224 use_kernel_end:
225
226 /* Align address to 4k */
227 addl $4095, %esi
228 andl $(~4095), %esi
229
230 /* Allocate space for page tables */
231 movl %esi, pt_loc
232 movl $ballocs, %edi
233 andl $0x7fffffff, %edi
234
235 movl %esi, (%edi)
236 addl $4, %edi
237 movl $(2 * 1024 * 1024), (%edi)
238
239 /* Fill page tables */
240 xorl %ecx, %ecx
241 xorl %ebx, %ebx
242
243 floop_pt:
244 movl $((1 << 1) | (1 << 0)), %eax
245 orl %ebx, %eax
246 movl %eax, (%esi, %ecx, 4)
247 addl $(4 * 1024), %ebx
248
249 incl %ecx
250 cmpl $(512 * 1024), %ecx
251
252 jl floop_pt
253
254 /* Fill page directory */
255 movl $(page_directory + 0), %esi
256 movl $(page_directory + 2048), %edi
257 xorl %ecx, %ecx
258 movl pt_loc, %ebx
259
260 floop:
261 movl $((1 << 1) | (1 << 0)), %eax
262 orl %ebx, %eax
263
264 /* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
265 movl %eax, (%esi, %ecx, 4)
266
267 /* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
268 movl %eax, (%edi, %ecx, 4)
269 addl $(4 * 1024), %ebx
270
271 incl %ecx
272 cmpl $512, %ecx
273
274 jl floop
275
276 movl %esi, %cr3
277
278 movl %cr0, %ebx
279 orl $(1 << 31), %ebx /* paging on */
280 movl %ebx, %cr0
281
282 ret
283
284/** Calculate unmapped address of the end of the kernel. */
285calc_kernel_end:
286 movl $hardcoded_load_address, %edi
287 andl $0x7fffffff, %edi
288 movl (%edi), %esi
289 andl $0x7fffffff, %esi
290
291 movl $hardcoded_ktext_size, %edi
292 andl $0x7fffffff, %edi
293 addl (%edi), %esi
294 andl $0x7fffffff, %esi
295
296 movl $hardcoded_kdata_size, %edi
297 andl $0x7fffffff, %edi
298 addl (%edi), %esi
299 andl $0x7fffffff, %esi
300 movl %esi, kernel_end
301
302 ret
303
304/** Find free 2M (+4k for alignment) region where to store page tables */
305find_mem_for_pt:
306 /* Check if multiboot info is present */
307 cmpl $MULTIBOOT_LOADER_MAGIC, multiboot_eax
308 je check_multiboot_map
309
310 ret
311
312 check_multiboot_map:
313
314 /* Copy address of the multiboot info to ebx */
315 movl multiboot_ebx, %ebx
316
317 /* Check if memory map flag is present */
318 movl (%ebx), %edx
319 andl $(1 << 6), %edx
320 jnz use_multiboot_map
321
322 ret
323
324 use_multiboot_map:
325
326 /* Copy address of the memory map to edx */
327 movl 48(%ebx), %edx
328 movl %edx, %ecx
329
330 addl 44(%ebx), %ecx
331
332 /* Find a free region at least 2M in size */
333 check_memmap_loop:
334
335 /* Is this a free region? */
336 cmp $1, 20(%edx)
337 jnz next_region
338
339 /* Check size */
340 cmp $0, 16(%edx)
341 jnz next_region
342
343 cmpl $(2 * 1024 * 1024 + 4 * 1024), 12(%edx)
344 jbe next_region
345
346 cmp $0, 8(%edx)
347 jz found_region
348
349 next_region:
350
351 cmp %ecx, %edx
352 jbe next_region_do
353
354 ret
355
356 next_region_do:
357
358 addl (%edx), %edx
359 addl $4, %edx
360 jmp check_memmap_loop
361
362 found_region:
363
364 /* Use end of the found region */
365 mov 4(%edx), %ecx
366 add 12(%edx), %ecx
367 sub $(2 * 1024 * 1024), %ecx
368 mov %ecx, free_area
369
370 ret
371
372/** Print string to EGA display (in light red) and halt.
373 *
374 * Should be executed from 32 bit protected mode with paging
375 * turned off. Stack is not required. This routine is used even
376 * if CONFIG_EGA is not enabled. Since we are going to halt the
377 * CPU anyway, it is always better to at least try to print
378 * some hints.
379 *
380 * @param %esi NULL-terminated string to print.
381 *
382 */
383pm_error_halt:
384 movl $0xb8000, %edi /* base of EGA text mode memory */
385 xorl %eax, %eax
386
387 /* Read bits 8 - 15 of the cursor address */
388 movw $0x3d4, %dx
389 movb $0xe, %al
390 outb %al, %dx
391
392 movw $0x3d5, %dx
393 inb %dx, %al
394 shl $8, %ax
395
396 /* Read bits 0 - 7 of the cursor address */
397 movw $0x3d4, %dx
398 movb $0xf, %al
399 outb %al, %dx
400
401 movw $0x3d5, %dx
402 inb %dx, %al
403
404 /* Sanity check for the cursor on screen */
405 cmp $2000, %ax
406 jb err_cursor_ok
407
408 movw $1998, %ax
409
410 err_cursor_ok:
411
412 movw %ax, %bx
413 shl $1, %eax
414 addl %eax, %edi
415
416 err_ploop:
417 lodsb
418
419 cmp $0, %al
420 je err_ploop_end
421
422 movb $0x0c, %ah /* black background, light red foreground */
423 stosw
424
425 /* Sanity check for the cursor on the last line */
426 inc %bx
427 cmp $2000, %bx
428 jb err_ploop
429
430 /* Scroll the screen (24 rows) */
431 movl %esi, %edx
432 movl $0xb80a0, %esi
433 movl $0xb8000, %edi
434 movl $960, %ecx
435 rep movsl
436
437 /* Clear the 24th row */
438 xorl %eax, %eax
439 movl $40, %ecx
440 rep stosl
441
442 /* Go to row 24 */
443 movl %edx, %esi
444 movl $0xb8f00, %edi
445 movw $1920, %bx
446
447 jmp err_ploop
448 err_ploop_end:
449
450 /* Write bits 8 - 15 of the cursor address */
451 movw $0x3d4, %dx
452 movb $0xe, %al
453 outb %al, %dx
454
455 movw $0x3d5, %dx
456 movb %bh, %al
457 outb %al, %dx
458
459 /* Write bits 0 - 7 of the cursor address */
460 movw $0x3d4, %dx
461 movb $0xf, %al
462 outb %al, %dx
463
464 movw $0x3d5, %dx
465 movb %bl, %al
466 outb %al, %dx
467
468 cli
469 hlt1:
470 hlt
471 jmp hlt1
472
473/** Print string to EGA display (in light green).
474 *
475 * Should be called from 32 bit protected mode with paging
476 * turned off. A stack space of at least 24 bytes is required,
477 * but the function does not establish a stack frame.
478 *
479 * Macros such as pm_status take care that this function
480 * is used only when CONFIG_EGA is enabled.
481 *
482 * @param %esi NULL-terminated string to print.
483 *
484 */
485pm_early_puts:
486 pushl %eax
487 pushl %ebx
488 pushl %ecx
489 pushl %edx
490 pushl %edi
491
492 movl $0xb8000, %edi /* base of EGA text mode memory */
493 xorl %eax, %eax
494
495 /* Read bits 8 - 15 of the cursor address */
496 movw $0x3d4, %dx
497 movb $0xe, %al
498 outb %al, %dx
499
500 movw $0x3d5, %dx
501 inb %dx, %al
502 shl $8, %ax
503
504 /* Read bits 0 - 7 of the cursor address */
505 movw $0x3d4, %dx
506 movb $0xf, %al
507 outb %al, %dx
508
509 movw $0x3d5, %dx
510 inb %dx, %al
511
512 /* Sanity check for the cursor on screen */
513 cmp $2000, %ax
514 jb pm_puts_cursor_ok
515
516 movw $1998, %ax
517
518 pm_puts_cursor_ok:
519
520 movw %ax, %bx
521 shl $1, %eax
522 addl %eax, %edi
523
524 pm_puts_ploop:
525 lodsb
526
527 cmp $0, %al
528 je pm_puts_ploop_end
529
530 movb $0x0a, %ah /* black background, light green foreground */
531 stosw
532
533 /* Sanity check for the cursor on the last line */
534 inc %bx
535 cmp $2000, %bx
536 jb pm_puts_ploop
537
538 /* Scroll the screen (24 rows) */
539 movl %esi, %edx
540 movl $0xb80a0, %esi
541 movl $0xb8000, %edi
542 movl $960, %ecx
543 rep movsl
544
545 /* Clear the 24th row */
546 xorl %eax, %eax
547 movl $40, %ecx
548 rep stosl
549
550 /* Go to row 24 */
551 movl %edx, %esi
552 movl $0xb8f00, %edi
553 movw $1920, %bx
554
555 jmp pm_puts_ploop
556 pm_puts_ploop_end:
557
558 /* Write bits 8 - 15 of the cursor address */
559 movw $0x3d4, %dx
560 movb $0xe, %al
561 outb %al, %dx
562
563 movw $0x3d5, %dx
564 movb %bh, %al
565 outb %al, %dx
566
567 /* Write bits 0 - 7 of the cursor address */
568 movw $0x3d4, %dx
569 movb $0xf, %al
570 outb %al, %dx
571
572 movw $0x3d5, %dx
573 movb %bl, %al
574 outb %al, %dx
575
576 popl %edi
577 popl %edx
578 popl %ecx
579 popl %ebx
580 popl %eax
581
582 ret
583
584/** Print string to EGA display.
585 *
586 * Should be called from 32 bit protected mode (with paging
587 * enabled and stack established). This function is ABI compliant.
588 *
589 * If CONFIG_EGA is undefined or CONFIG_FB is defined
590 * then this function does nothing.
591 *
592 * @param %ebp+0x08 NULL-terminated string to print.
593 *
594 */
595early_puts:
596
597#if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))
598
599 /* Prologue, save preserved registers */
600 pushl %ebp
601 movl %esp, %ebp
602 pushl %ebx
603 pushl %esi
604 pushl %edi
605
606 movl 0x08(%ebp), %esi
607 movl $(PA2KA(0xb8000)), %edi /* base of EGA text mode memory */
608 xorl %eax, %eax
609
610 /* Read bits 8 - 15 of the cursor address */
611 movw $0x3d4, %dx
612 movb $0xe, %al
613 outb %al, %dx
614
615 movw $0x3d5, %dx
616 inb %dx, %al
617 shl $8, %ax
618
619 /* Read bits 0 - 7 of the cursor address */
620 movw $0x3d4, %dx
621 movb $0xf, %al
622 outb %al, %dx
623
624 movw $0x3d5, %dx
625 inb %dx, %al
626
627 /* Sanity check for the cursor on screen */
628 cmp $2000, %ax
629 jb early_puts_cursor_ok
630
631 movw $1998, %ax
632
633 early_puts_cursor_ok:
634
635 movw %ax, %bx
636 shl $1, %eax
637 addl %eax, %edi
638
639 early_puts_ploop:
640 lodsb
641
642 cmp $0, %al
643 je early_puts_ploop_end
644
645 movb $0x0e, %ah /* black background, yellow foreground */
646 stosw
647
648 /* Sanity check for the cursor on the last line */
649 inc %bx
650 cmp $2000, %bx
651 jb early_puts_ploop
652
653 /* Scroll the screen (24 rows) */
654 movl %esi, %edx
655 movl $(PA2KA(0xb80a0)), %esi
656 movl $(PA2KA(0xb8000)), %edi
657 movl $960, %ecx
658 rep movsl
659
660 /* Clear the 24th row */
661 xorl %eax, %eax
662 movl $40, %ecx
663 rep stosl
664
665 /* Go to row 24 */
666 movl %edx, %esi
667 movl $(PA2KA(0xb8f00)), %edi
668 movw $1920, %bx
669
670 jmp early_puts_ploop
671 early_puts_ploop_end:
672
673 /* Write bits 8 - 15 of the cursor address */
674 movw $0x3d4, %dx
675 movb $0xe, %al
676 outb %al, %dx
677
678 movw $0x3d5, %dx
679 movb %bh, %al
680 outb %al, %dx
681
682 /* Write bits 0 - 7 of the cursor address */
683 movw $0x3d4, %dx
684 movb $0xf, %al
685 outb %al, %dx
686
687 movw $0x3d5, %dx
688 movb %bl, %al
689 outb %al, %dx
690
691 /* Epilogue, restore preserved registers */
692 popl %edi
693 popl %esi
694 popl %ebx
695 leave
696
697#endif
698
699 ret
700
701#include "vesa_real.inc"
702
703.section K_DATA_START, "aw", @progbits
704
705.align 4096
706page_directory:
707 .space 4096, 0
708
709.global bootstrap_idtr
710bootstrap_idtr:
711 .word 0
712 .long 0
713
714.global bootstrap_gdtr
715bootstrap_gdtr:
716 .word GDT_SELECTOR(GDT_ITEMS)
717 .long KA2PA(gdt)
718
719.global multiboot_eax
720multiboot_eax:
721 .long 0
722
723.global multiboot_ebx
724multiboot_ebx:
725 .long 0
726
727pt_loc:
728 .long 0
729kernel_end:
730 .long 0
731free_area:
732 .long 0
733
734status_prot:
735 .asciz "[prot] "
736status_pse:
737 .asciz "[pse] "
738status_non_pse:
739 .asciz "[non_pse] "
740status_vesa_copy:
741 .asciz "[vesa_copy] "
742status_multiboot_cmdline:
743 .asciz "[multiboot_cmdline] "
744status_vesa_real:
745 .asciz "[vesa_real] "
746status_prot2:
747 .asciz "[prot2] "
748status_prot3:
749 .asciz "[prot3] "
750status_main:
751 .asciz "[main] "
Note: See TracBrowser for help on using the repository browser.