* same with xv6
[mascara-docs.git] / i386 / MIT / src.xv6 / bootasm.S
blob91a595e5cff45d19a25be177c9f8960a7d235454
1 #include "asm.h"
2 #include "memlayout.h"
3 #include "mmu.h"
5 # Start the first CPU: switch to 32-bit protected mode, jump into C.
6 # The BIOS loads this code from the first sector of the hard disk into
7 # memory at physical address 0x7c00 and starts executing in real mode
8 # with %cs=0 %ip=7c00.
10 .code16                       # Assemble for 16-bit mode
11 .globl start
12 start:
13   cli                         # BIOS enabled interrupts; disable
15   # Zero data segment registers DS, ES, and SS.
16   xorw    %ax,%ax             # Set %ax to zero
17   movw    %ax,%ds             # -> Data Segment
18   movw    %ax,%es             # -> Extra Segment
19   movw    %ax,%ss             # -> Stack Segment
21   # Physical address line A20 is tied to zero so that the first PCs 
22   # with 2 MB would run software that assumed 1 MB.  Undo that.
23 seta20.1:
24   inb     $0x64,%al               # Wait for not busy
25   testb   $0x2,%al
26   jnz     seta20.1
28   movb    $0xd1,%al               # 0xd1 -> port 0x64
29   outb    %al,$0x64
31 seta20.2:
32   inb     $0x64,%al               # Wait for not busy
33   testb   $0x2,%al
34   jnz     seta20.2
36   movb    $0xdf,%al               # 0xdf -> port 0x60
37   outb    %al,$0x60
39   # Switch from real to protected mode.  Use a bootstrap GDT that makes
40   # virtual addresses map directly to physical addresses so that the
41   # effective memory map doesn't change during the transition.
42   lgdt    gdtdesc
43   movl    %cr0, %eax
44   orl     $CR0_PE, %eax
45   movl    %eax, %cr0
47 //PAGEBREAK!
48   # Complete transition to 32-bit protected mode by using long jmp
49   # to reload %cs and %eip.  The segment descriptors are set up with no
50   # translation, so that the mapping is still the identity mapping.
51   ljmp    $(SEG_KCODE<<3), $start32
53 .code32  # Tell assembler to generate 32-bit code now.
54 start32:
55   # Set up the protected-mode data segment registers
56   movw    $(SEG_KDATA<<3), %ax    # Our data segment selector
57   movw    %ax, %ds                # -> DS: Data Segment
58   movw    %ax, %es                # -> ES: Extra Segment
59   movw    %ax, %ss                # -> SS: Stack Segment
60   movw    $0, %ax                 # Zero segments not ready for use
61   movw    %ax, %fs                # -> FS
62   movw    %ax, %gs                # -> GS
64   # Set up the stack pointer and call into C.
65   movl    $start, %esp
66   call    bootmain
68   # If bootmain returns (it shouldn't), trigger a Bochs
69   # breakpoint if running under Bochs, then loop.
70   movw    $0x8a00, %ax            # 0x8a00 -> port 0x8a00
71   movw    %ax, %dx
72   outw    %ax, %dx
73   movw    $0x8ae0, %ax            # 0x8ae0 -> port 0x8a00
74   outw    %ax, %dx
75 spin:
76   jmp     spin
78 # Bootstrap GDT
79 .p2align 2                                # force 4 byte alignment
80 gdt:
81   SEG_NULLASM                             # null seg
82   SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)   # code seg
83   SEG_ASM(STA_W, 0x0, 0xffffffff)         # data seg
85 gdtdesc:
86   .word   (gdtdesc - gdt - 1)             # sizeof(gdt) - 1
87   .long   gdt                             # address gdt