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