xref: /xv6-public/bootasm.S (revision 24118827)
1#include "asm.h"
2#include "memlayout.h"
3#include "mmu.h"
4
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.
9
10.code16                       # Assemble for 16-bit mode
11.globl start
12start:
13  cli                         # BIOS enabled interrupts; disable
14
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
20
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.
23seta20.1:
24  inb     $0x64,%al               # Wait for not busy
25  testb   $0x2,%al
26  jnz     seta20.1
27
28  movb    $0xd1,%al               # 0xd1 -> port 0x64
29  outb    %al,$0x64
30
31seta20.2:
32  inb     $0x64,%al               # Wait for not busy
33  testb   $0x2,%al
34  jnz     seta20.2
35
36  movb    $0xdf,%al               # 0xdf -> port 0x60
37  outb    %al,$0x60
38
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
46
47//PAGEBREAK!
48  # Complete the transition to 32-bit protected mode by using a 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
52
53.code32  # Tell assembler to generate 32-bit code now.
54start32:
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
63
64  # Set up the stack pointer and call into C.
65  movl    $start, %esp
66  call    bootmain
67
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
75spin:
76  jmp     spin
77
78# Bootstrap GDT
79.p2align 2                                # force 4 byte alignment
80gdt:
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
84
85gdtdesc:
86  .word   (gdtdesc - gdt - 1)             # sizeof(gdt) - 1
87  .long   gdt                             # address gdt
88
89