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

Last change on this file was 8be3230, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Revert "Remove realmode VESA code" - needs more work

This reverts commit 8781e9d05ac3f6aeaa3ad709c5af9efa3209b87a.

  • Property mode set to 100644
File size: 14.2 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_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(kdata_end), %edi
288 movl %edi, kernel_end
289 ret
290
291/** Find free 2M (+4k for alignment) region where to store page tables */
292find_mem_for_pt:
293 /* Check if multiboot info is present */
294 cmpl $MULTIBOOT_LOADER_MAGIC, multiboot_eax
295 je check_multiboot_map
296
297 ret
298
299 check_multiboot_map:
300
301 /* Copy address of the multiboot info to ebx */
302 movl multiboot_ebx, %ebx
303
304 /* Check if memory map flag is present */
305 movl (%ebx), %edx
306 andl $MULTIBOOT_INFO_FLAGS_MMAP, %edx
307 jnz use_multiboot_map
308
309 ret
310
311 use_multiboot_map:
312
313 /* Copy address of the memory map to edx */
314 movl MULTIBOOT_INFO_OFFSET_MMAP_ADDR(%ebx), %edx
315 movl %edx, %ecx
316
317 addl MULTIBOOT_INFO_OFFSET_MMAP_LENGTH(%ebx), %ecx
318
319 /* Find a free region at least 2M in size */
320 check_memmap_loop:
321
322 /* Is this a free region? */
323 cmpl $MEMMAP_MEMORY_AVAILABLE, MULTIBOOT_MEMMAP_OFFSET_MM_INFO + E820MEMMAP_OFFSET_TYPE(%edx)
324 jnz next_region
325
326 /* Check size */
327 cmpl $0, MULTIBOOT_MEMMAP_OFFSET_MM_INFO + E820MEMMAP_OFFSET_SIZE + 4(%edx)
328 jnz next_region
329 cmpl $(2 * 1024 * 1024 + PAGE_SIZE), MULTIBOOT_MEMMAP_OFFSET_MM_INFO + E820MEMMAP_OFFSET_SIZE(%edx)
330 jbe next_region
331
332 cmpl $0, MULTIBOOT_MEMMAP_OFFSET_MM_INFO + E820MEMMAP_OFFSET_BASE_ADDRESS + 4(%edx)
333 jz found_region
334
335 next_region:
336
337 cmp %ecx, %edx
338 jbe next_region_do
339
340 ret
341
342 next_region_do:
343
344 addl MULTIBOOT_MEMMAP_OFFSET_SIZE(%edx), %edx
345 addl $MULTIBOOT_MEMMAP_SIZE_SIZE, %edx
346 jmp check_memmap_loop
347
348 found_region:
349
350 /* Use end of the found region */
351 mov MULTIBOOT_MEMMAP_OFFSET_MM_INFO + E820MEMMAP_OFFSET_BASE_ADDRESS(%edx), %ecx
352 add MULTIBOOT_MEMMAP_OFFSET_MM_INFO + E820MEMMAP_OFFSET_SIZE(%edx), %ecx
353 sub $(2 * 1024 * 1024), %ecx
354 mov %ecx, free_area
355
356 ret
357
358/** Print string to EGA display (in light red) and halt.
359 *
360 * Should be executed from 32 bit protected mode with paging
361 * turned off. Stack is not required. This routine is used even
362 * if CONFIG_EGA is not enabled. Since we are going to halt the
363 * CPU anyway, it is always better to at least try to print
364 * some hints.
365 *
366 * @param %esi NULL-terminated string to print.
367 *
368 */
369pm_error_halt:
370 movl $0xb8000, %edi /* base of EGA text mode memory */
371 xorl %eax, %eax
372
373 /* Read bits 8 - 15 of the cursor address */
374 movw $0x3d4, %dx
375 movb $0xe, %al
376 outb %al, %dx
377
378 movw $0x3d5, %dx
379 inb %dx, %al
380 shl $8, %ax
381
382 /* Read bits 0 - 7 of the cursor address */
383 movw $0x3d4, %dx
384 movb $0xf, %al
385 outb %al, %dx
386
387 movw $0x3d5, %dx
388 inb %dx, %al
389
390 /* Sanity check for the cursor on screen */
391 cmp $2000, %ax
392 jb err_cursor_ok
393
394 movw $1998, %ax
395
396 err_cursor_ok:
397
398 movw %ax, %bx
399 shl $1, %eax
400 addl %eax, %edi
401
402 err_ploop:
403 lodsb
404
405 cmp $0, %al
406 je err_ploop_end
407
408 movb $0x0c, %ah /* black background, light red foreground */
409 stosw
410
411 /* Sanity check for the cursor on the last line */
412 inc %bx
413 cmp $2000, %bx
414 jb err_ploop
415
416 /* Scroll the screen (24 rows) */
417 movl %esi, %edx
418 movl $0xb80a0, %esi
419 movl $0xb8000, %edi
420 movl $960, %ecx
421 rep movsl
422
423 /* Clear the 24th row */
424 xorl %eax, %eax
425 movl $40, %ecx
426 rep stosl
427
428 /* Go to row 24 */
429 movl %edx, %esi
430 movl $0xb8f00, %edi
431 movw $1920, %bx
432
433 jmp err_ploop
434 err_ploop_end:
435
436 /* Write bits 8 - 15 of the cursor address */
437 movw $0x3d4, %dx
438 movb $0xe, %al
439 outb %al, %dx
440
441 movw $0x3d5, %dx
442 movb %bh, %al
443 outb %al, %dx
444
445 /* Write bits 0 - 7 of the cursor address */
446 movw $0x3d4, %dx
447 movb $0xf, %al
448 outb %al, %dx
449
450 movw $0x3d5, %dx
451 movb %bl, %al
452 outb %al, %dx
453
454 cli
455 hlt1:
456 hlt
457 jmp hlt1
458
459/** Print string to EGA display (in light green).
460 *
461 * Should be called from 32 bit protected mode with paging
462 * turned off. A stack space of at least 24 bytes is required,
463 * but the function does not establish a stack frame.
464 *
465 * Macros such as pm_status take care that this function
466 * is used only when CONFIG_EGA is enabled.
467 *
468 * @param %esi NULL-terminated string to print.
469 *
470 */
471pm_early_puts:
472 pushl %eax
473 pushl %ebx
474 pushl %ecx
475 pushl %edx
476 pushl %edi
477
478 movl $0xb8000, %edi /* base of EGA text mode memory */
479 xorl %eax, %eax
480
481 /* Read bits 8 - 15 of the cursor address */
482 movw $0x3d4, %dx
483 movb $0xe, %al
484 outb %al, %dx
485
486 movw $0x3d5, %dx
487 inb %dx, %al
488 shl $8, %ax
489
490 /* Read bits 0 - 7 of the cursor address */
491 movw $0x3d4, %dx
492 movb $0xf, %al
493 outb %al, %dx
494
495 movw $0x3d5, %dx
496 inb %dx, %al
497
498 /* Sanity check for the cursor on screen */
499 cmp $2000, %ax
500 jb pm_puts_cursor_ok
501
502 movw $1998, %ax
503
504 pm_puts_cursor_ok:
505
506 movw %ax, %bx
507 shl $1, %eax
508 addl %eax, %edi
509
510 pm_puts_ploop:
511 lodsb
512
513 cmp $0, %al
514 je pm_puts_ploop_end
515
516 movb $0x0a, %ah /* black background, light green foreground */
517 stosw
518
519 /* Sanity check for the cursor on the last line */
520 inc %bx
521 cmp $2000, %bx
522 jb pm_puts_ploop
523
524 /* Scroll the screen (24 rows) */
525 movl %esi, %edx
526 movl $0xb80a0, %esi
527 movl $0xb8000, %edi
528 movl $960, %ecx
529 rep movsl
530
531 /* Clear the 24th row */
532 xorl %eax, %eax
533 movl $40, %ecx
534 rep stosl
535
536 /* Go to row 24 */
537 movl %edx, %esi
538 movl $0xb8f00, %edi
539 movw $1920, %bx
540
541 jmp pm_puts_ploop
542 pm_puts_ploop_end:
543
544 /* Write bits 8 - 15 of the cursor address */
545 movw $0x3d4, %dx
546 movb $0xe, %al
547 outb %al, %dx
548
549 movw $0x3d5, %dx
550 movb %bh, %al
551 outb %al, %dx
552
553 /* Write bits 0 - 7 of the cursor address */
554 movw $0x3d4, %dx
555 movb $0xf, %al
556 outb %al, %dx
557
558 movw $0x3d5, %dx
559 movb %bl, %al
560 outb %al, %dx
561
562 popl %edi
563 popl %edx
564 popl %ecx
565 popl %ebx
566 popl %eax
567
568 ret
569
570/** Print string to EGA display.
571 *
572 * Should be called from 32 bit protected mode (with paging
573 * enabled and stack established). This function is ABI compliant.
574 *
575 * If CONFIG_EGA is undefined or CONFIG_FB is defined
576 * then this function does nothing.
577 *
578 * @param %ebp+0x08 NULL-terminated string to print.
579 *
580 */
581early_puts:
582
583#if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))
584
585 /* Prologue, save preserved registers */
586 pushl %ebp
587 movl %esp, %ebp
588 pushl %ebx
589 pushl %esi
590 pushl %edi
591
592 movl 0x08(%ebp), %esi
593 movl $(PA2KA(0xb8000)), %edi /* base of EGA text mode memory */
594 xorl %eax, %eax
595
596 /* Read bits 8 - 15 of the cursor address */
597 movw $0x3d4, %dx
598 movb $0xe, %al
599 outb %al, %dx
600
601 movw $0x3d5, %dx
602 inb %dx, %al
603 shl $8, %ax
604
605 /* Read bits 0 - 7 of the cursor address */
606 movw $0x3d4, %dx
607 movb $0xf, %al
608 outb %al, %dx
609
610 movw $0x3d5, %dx
611 inb %dx, %al
612
613 /* Sanity check for the cursor on screen */
614 cmp $2000, %ax
615 jb early_puts_cursor_ok
616
617 movw $1998, %ax
618
619 early_puts_cursor_ok:
620
621 movw %ax, %bx
622 shl $1, %eax
623 addl %eax, %edi
624
625 early_puts_ploop:
626 lodsb
627
628 cmp $0, %al
629 je early_puts_ploop_end
630
631 movb $0x0e, %ah /* black background, yellow foreground */
632 stosw
633
634 /* Sanity check for the cursor on the last line */
635 inc %bx
636 cmp $2000, %bx
637 jb early_puts_ploop
638
639 /* Scroll the screen (24 rows) */
640 movl %esi, %edx
641 movl $(PA2KA(0xb80a0)), %esi
642 movl $(PA2KA(0xb8000)), %edi
643 movl $960, %ecx
644 rep movsl
645
646 /* Clear the 24th row */
647 xorl %eax, %eax
648 movl $40, %ecx
649 rep stosl
650
651 /* Go to row 24 */
652 movl %edx, %esi
653 movl $(PA2KA(0xb8f00)), %edi
654 movw $1920, %bx
655
656 jmp early_puts_ploop
657 early_puts_ploop_end:
658
659 /* Write bits 8 - 15 of the cursor address */
660 movw $0x3d4, %dx
661 movb $0xe, %al
662 outb %al, %dx
663
664 movw $0x3d5, %dx
665 movb %bh, %al
666 outb %al, %dx
667
668 /* Write bits 0 - 7 of the cursor address */
669 movw $0x3d4, %dx
670 movb $0xf, %al
671 outb %al, %dx
672
673 movw $0x3d5, %dx
674 movb %bl, %al
675 outb %al, %dx
676
677 /* Epilogue, restore preserved registers */
678 popl %edi
679 popl %esi
680 popl %ebx
681 leave
682
683#endif
684
685 ret
686
687#include "vesa_real.inc"
688
689.section K_DATA_START, "aw", @progbits
690
691.align 4096
692page_directory:
693 .space 4096, 0
694
695SYMBOL(bootstrap_idtr)
696 .word 0
697 .long 0
698
699SYMBOL(bootstrap_gdtr)
700 .word GDT_SELECTOR(GDT_ITEMS)
701 .long KA2PA(gdt)
702
703SYMBOL(multiboot_eax)
704 .long 0
705
706SYMBOL(multiboot_ebx)
707 .long 0
708
709pt_loc:
710 .long 0
711kernel_end:
712 .long 0
713free_area:
714 .long 0
715
716status_prot:
717 .asciz "[prot] "
718status_pse:
719 .asciz "[pse] "
720status_non_pse:
721 .asciz "[non_pse] "
722status_vesa_copy:
723 .asciz "[vesa_copy] "
724status_multiboot_cmdline:
725 .asciz "[multiboot_cmdline] "
726status_vesa_real:
727 .asciz "[vesa_real] "
728status_prot2:
729 .asciz "[prot2] "
730status_prot3:
731 .asciz "[prot3] "
732status_main:
733 .asciz "[main] "
Note: See TracBrowser for help on using the repository browser.