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

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

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 14.4 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.