* same with xv6
[mascara-docs.git] / i386 / standford / 2004 / src / lab5 / boot / boot.S
blobdc97e10b20b2a1a61c310ed77400bc6dcdf46ca6
1 #include <inc/asm.h>
2 #include <inc/mmu.h>
3         
4 .set PROT_MODE_CSEG,0x8         # code segment selector
5 .set PROT_MODE_DSEG,0x10        # data segment selector
6 .set CR0_PE_ON,0x1              # protected mode enable flag
7         
8 ###################################################################################
9 # ENTRY POINT   
10 #   This code should be stored in the first sector of the hard disk.
11 #   After the BIOS initializes the hardware on startup or system reset,
12 #   it loads this code at physical address 0x7c00 - 0x7d00 (512 bytes).
13 #   Then the BIOS jumps to the beginning of it, address 0x7c00,
14 #   while running in 16-bit real-mode (8086 compatibility mode).
15 #   The Code Segment register (CS) is initially zero on entry.
16 #       
17 # This code switches into 32-bit protected mode so that all of
18 # memory can accessed, then calls into C.
19 ###################################################################################
20         
21 .globl start                                    # Entry point   
22 start:          .code16                         # This runs in real mode
23                 cli                             # Disable interrupts
24                 cld                             # String operations increment
26                 # Set up the important data segment registers (DS, ES, SS).
27                 xorw    %ax,%ax                 # Segment number zero
28                 movw    %ax,%ds                 # -> Data Segment
29                 movw    %ax,%es                 # -> Extra Segment
30                 movw    %ax,%ss                 # -> Stack Segment
32                 # Set up the stack pointer, growing downward from 0x7c00.
33                 movw    $start,%sp              # Stack Pointer
34         
35 #### Enable A20:
36 ####   For fascinating historical reasons (related to the fact that
37 ####   the earliest 8086-based PCs could only address 1MB of physical memory
38 ####   and subsequent 80286-based PCs wanted to retain maximum compatibility),
39 ####   physical address line 20 is tied to low when the machine boots.
40 ####   Obviously this a bit of a drag for us, especially when trying to
41 ####   address memory above 1MB.  This code undoes this.
42         
43 seta20.1:       inb     $0x64,%al               # Get status
44                 testb   $0x2,%al                # Busy?
45                 jnz     seta20.1                # Yes
46                 movb    $0xd1,%al               # Command: Write
47                 outb    %al,$0x64               #  output port
48 seta20.2:       inb     $0x64,%al               # Get status
49                 testb   $0x2,%al                # Busy?
50                 jnz     seta20.2                # Yes
51                 movb    $0xdf,%al               # Enable
52                 outb    %al,$0x60               #  A20
54 #### Switch from real to protected mode 
55 ####     The descriptors in our GDT allow all physical memory to be accessed.
56 ####     Furthermore, the descriptors have base addresses of 0, so that the
57 ####     segment translation is a NOP, ie. virtual addresses are identical to
58 ####     their physical addresses.  With this setup, immediately after
59 ####     enabling protected mode it will still appear to this code
60 ####     that it is running directly on physical memory with no translation.
61 ####     This initial NOP-translation setup is required by the processor
62 ####     to ensure that the transition to protected mode occurs smoothly.
63         
64 real_to_prot:   cli                             # Mandatory since we dont set up an IDT
65                 lgdt    gdtdesc                 # load GDT -- mandatory in protected mode
66                 movl    %cr0, %eax              # turn on protected mode
67                 orl     $CR0_PE_ON, %eax        # 
68                 movl    %eax, %cr0              # 
69                 ### CPU magic: jump to relocation, flush prefetch queue, and reload %cs
70                 ### Has the effect of just jmp to the next instruction, but simultaneous
71                 ### loads CS with $PROT_MODE_CSEG.
72                 ljmp    $PROT_MODE_CSEG, $protcseg
73         
74 #### we are in 32-bit protected mode (hence the .code32)
75 .code32
76 protcseg:       
77                 # Set up the protected-mode data segment registers
78                 movw    $PROT_MODE_DSEG, %ax    # Our data segment selector
79                 movw    %ax, %ds                # -> DS: Data Segment
80                 movw    %ax, %es                # -> ES: Extra Segment
81                 movw    %ax, %fs                # -> FS
82                 movw    %ax, %gs                # -> GS
83                 movw    %ax, %ss                # -> SS: Stack Segment
84         
85                 call cmain                      # finish the boot load from C.
86                                                 # cmain() should not return
87 spin:           jmp spin                        # ..but in case it does, spin
88         
89 .p2align 2                                      # force 4 byte alignment
90 gdt:
91         SEG_NULL                                # null seg
92         SEG(STA_X|STA_R, 0x0, 0xffffffff)       # code seg
93         SEG(STA_W, 0x0, 0xffffffff)             # data seg
94         
95 gdtdesc:
96         .word   0x17                    # sizeof(gdt) - 1
97         .long   gdt                     # address gdt