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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8781e9d was 8781e9d, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

Remove realmode VESA code

This simply enables framebuffer setup via multiboot1
(multiboot2 already did it), and removes the obsolete code.

  • Property mode set to 100644
File size: 14.3 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// TODO: most of this file can be rewritten in C
41
42#define START_STACK (BOOT_OFFSET - BOOT_STACK_SIZE)
43
44.section K_TEXT_START, "ax"
45
46.code32
47
48.macro pm_error msg
49 movl \msg, %esi
50 jmp pm_error_halt
51.endm
52
53.macro pm_status msg
54#if defined(CONFIG_EGA) && !defined(CONFIG_FB)
55 pushl %esi
56 movl \msg, %esi
57 call pm_early_puts
58 popl %esi
59#endif
60.endm
61
62.macro pm2_status msg
63 pushl \msg
64 call early_puts
65.endm
66
67.align 4
68multiboot_header:
69 .long MULTIBOOT_HEADER_MAGIC
70#ifdef CONFIG_FB
71 .long MULTIBOOT_HEADER_FLAGS
72 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) /* checksum */
73#else
74 .long MULTIBOOT_HEADER_FLAGS_NOFB
75 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS_NOFB) /* checksum */
76#endif
77 .long multiboot_header
78 .long unmapped_start
79 .long 0
80 .long 0
81 .long multiboot_image_start
82#ifdef CONFIG_FB
83 .long 0
84 .long CONFIG_BFB_WIDTH
85 .long CONFIG_BFB_HEIGHT
86 .long CONFIG_BFB_BPP
87#endif
88
89SYMBOL(multiboot_image_start)
90 cli
91 cld
92
93 /* Initialize stack pointer */
94 movl $START_STACK, %esp
95
96 /*
97 * Initialize Global Descriptor Table and
98 * Interrupt Descriptor Table registers
99 */
100 lgdtl bootstrap_gdtr
101 lidtl bootstrap_idtr
102
103 /* Kernel data + stack */
104 movw $GDT_SELECTOR(KDATA_DES), %cx
105 movw %cx, %es
106 movw %cx, %fs
107 movw %cx, %gs
108 movw %cx, %ds
109 movw %cx, %ss
110
111 jmpl $GDT_SELECTOR(KTEXT_DES), $multiboot_meeting_point
112 multiboot_meeting_point:
113
114 /* Save multiboot arguments */
115 movl %eax, multiboot_eax
116 movl %ebx, multiboot_ebx
117
118 pm_status $status_prot
119
120#ifndef PROCESSOR_i486
121
122 pm_status $status_prot2
123
124 movl $(INTEL_CPUID_LEVEL), %eax
125 cpuid
126 cmp $0x0, %eax /* any function > 0? */
127 jbe pse_unsupported
128
129 movl $(INTEL_CPUID_STANDARD), %eax
130 cpuid
131 bt $(INTEL_PSE), %edx
132 jnc pse_unsupported
133
134 /* Map kernel and turn paging on */
135 pm_status $status_pse
136 call map_kernel_pse
137 jmp stack_init
138
139#endif /* PROCESSOR_i486 */
140
141 pse_unsupported:
142
143 /* Map kernel and turn paging on */
144 pm_status $status_non_pse
145 call map_kernel_non_pse
146
147 stack_init:
148
149 /* Create the first stack frame */
150 pushl $0
151 movl %esp, %ebp
152
153 pm2_status $status_prot3
154
155 /* Call ia32_pre_main(multiboot_eax, multiboot_ebx) */
156 pushl multiboot_ebx
157 pushl multiboot_eax
158 call ia32_pre_main
159
160 pm2_status $status_main
161
162 /* Call main_bsp() */
163 call main_bsp
164
165 /* Not reached */
166 cli
167 hlt0:
168 hlt
169 jmp hlt0
170
171/** Setup mapping for the kernel (PSE variant)
172 *
173 * Setup mapping for both the unmapped and mapped sections
174 * of the kernel. For simplicity, we map the entire 4G space.
175 *
176 */
177FUNCTION_BEGIN(map_kernel_pse)
178 /* Paging features */
179 movl %cr4, %ecx
180 orl $CR4_PSE, %ecx /* PSE on */
181 andl $~CR4_PAE, %ecx /* PAE off */
182 movl %ecx, %cr4
183
184 movl $(page_directory + 0), %esi
185 movl $(page_directory + 2048), %edi
186 xorl %ecx, %ecx
187 xorl %ebx, %ebx
188
189 floop_pse:
190 movl $(PDE_4M | PDE_RW | PDE_P), %eax
191 orl %ebx, %eax
192 /* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
193 movl %eax, (%esi, %ecx, 4)
194 /* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
195 movl %eax, (%edi, %ecx, 4)
196 addl $(4 * 1024 * 1024), %ebx
197
198 incl %ecx
199 cmpl $512, %ecx
200 jl floop_pse
201
202 movl %esi, %cr3
203
204 movl %cr0, %ebx
205 orl $CR0_PG, %ebx /* paging on */
206 movl %ebx, %cr0
207 ret
208FUNCTION_END(map_kernel_pse)
209
210/** Setup mapping for the kernel (non-PSE variant).
211 *
212 * Setup mapping for both the unmapped and mapped sections
213 * of the kernel. For simplicity, we map the entire 4G space.
214 *
215 */
216FUNCTION_BEGIN(map_kernel_non_pse)
217 /* Paging features */
218 movl %cr4, %ecx
219 andl $~CR4_PAE, %ecx /* PAE off */
220 movl %ecx, %cr4
221
222 call calc_kernel_end
223 call find_mem_for_pt
224
225 mov kernel_end, %esi
226 mov free_area, %ecx
227
228 cmpl %esi, %ecx
229 jbe use_kernel_end
230
231 mov %ecx, %esi
232
233 /* Align address down to 4k */
234 andl $(~(PAGE_SIZE - 1)), %esi
235
236 use_kernel_end:
237
238 /* Align address to 4k */
239 addl $(PAGE_SIZE - 1), %esi
240 andl $(~(PAGE_SIZE - 1)), %esi
241
242 /* Allocate space for page tables */
243 movl %esi, pt_loc
244 movl $KA2PA(ballocs), %edi
245
246 movl %esi, (%edi)
247 addl $4, %edi
248 movl $(2 * 1024 * 1024), (%edi)
249
250 /* Fill page tables */
251 xorl %ecx, %ecx
252 xorl %ebx, %ebx
253
254 floop_pt:
255 movl $(PTE_RW | PTE_P), %eax
256 orl %ebx, %eax
257 movl %eax, (%esi, %ecx, 4)
258 addl $PAGE_SIZE, %ebx
259
260 incl %ecx
261 cmpl $(512 * 1024), %ecx
262
263 jl floop_pt
264
265 /* Fill page directory */
266 movl $(page_directory + 0), %esi
267 movl $(page_directory + 2048), %edi
268 xorl %ecx, %ecx
269 movl pt_loc, %ebx
270
271 floop:
272 movl $(PDE_RW | PDE_P), %eax
273 orl %ebx, %eax
274
275 /* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
276 movl %eax, (%esi, %ecx, 4)
277
278 /* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
279 movl %eax, (%edi, %ecx, 4)
280 addl $PAGE_SIZE, %ebx
281
282 incl %ecx
283 cmpl $512, %ecx
284
285 jl floop
286
287 movl %esi, %cr3
288
289 movl %cr0, %ebx
290 orl $CR0_PG, %ebx /* paging on */
291 movl %ebx, %cr0
292
293 ret
294FUNCTION_END(map_kernel_non_pse)
295
296/** Calculate unmapped address of the end of the kernel. */
297calc_kernel_end:
298 movl $KA2PA(kdata_end), %edi
299 movl %edi, kernel_end
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.section K_DATA_START, "aw", @progbits
699
700.align 4096
701page_directory:
702 .space 4096, 0
703
704SYMBOL(bootstrap_idtr)
705 .word 0
706 .long 0
707
708SYMBOL(bootstrap_gdtr)
709 .word GDT_SELECTOR(GDT_ITEMS)
710 .long KA2PA(gdt)
711
712SYMBOL(multiboot_eax)
713 .long 0
714
715SYMBOL(multiboot_ebx)
716 .long 0
717
718pt_loc:
719 .long 0
720kernel_end:
721 .long 0
722free_area:
723 .long 0
724
725status_prot:
726 .asciz "[prot] "
727status_pse:
728 .asciz "[pse] "
729status_non_pse:
730 .asciz "[non_pse] "
731status_multiboot_cmdline:
732 .asciz "[multiboot_cmdline] "
733status_prot2:
734 .asciz "[prot2] "
735status_prot3:
736 .asciz "[prot3] "
737status_main:
738 .asciz "[main] "
Note: See TracBrowser for help on using the repository browser.