source: mainline/kernel/arch/ia32/src/boot/multiboot.S@ 06ae793

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 06ae793 was e02bfb4, checked in by jzr <zarevucky.jiri@…>, 8 years ago

Remove duplicated label.

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