xref: /xv6-public/bootasm.S (revision 24118827)
121a88fd4Skaashoek#include "asm.h"
2a56c8d60SFrans Kaashoek#include "memlayout.h"
3a56c8d60SFrans Kaashoek#include "mmu.h"
455e95b16Srtm
55d1f4b8aSrsc# Start the first CPU: switch to 32-bit protected mode, jump into C.
65d1f4b8aSrsc# The BIOS loads this code from the first sector of the hard disk into
75d1f4b8aSrsc# memory at physical address 0x7c00 and starts executing in real mode
85d1f4b8aSrsc# with %cs=0 %ip=7c00.
955e95b16Srtm
10b7f653dcSrsc.code16                       # Assemble for 16-bit mode
112bc72bddSrsc.globl start
12a650c606Srscstart:
13faad047aSRobert Morris  cli                         # BIOS enabled interrupts; disable
1455e95b16Srtm
1590a81b32SRobert Morris  # Zero data segment registers DS, ES, and SS.
1690a81b32SRobert Morris  xorw    %ax,%ax             # Set %ax to zero
1755e95b16Srtm  movw    %ax,%ds             # -> Data Segment
1855e95b16Srtm  movw    %ax,%es             # -> Extra Segment
1955e95b16Srtm  movw    %ax,%ss             # -> Stack Segment
2055e95b16Srtm
21cf4b1ad9SRuss Cox  # Physical address line A20 is tied to zero so that the first PCs
22cf4b1ad9SRuss Cox  # with 2 MB would run software that assumed 1 MB.  Undo that.
23a650c606Srscseta20.1:
245d1f4b8aSrsc  inb     $0x64,%al               # Wait for not busy
255d1f4b8aSrsc  testb   $0x2,%al
265d1f4b8aSrsc  jnz     seta20.1
275d1f4b8aSrsc
285d1f4b8aSrsc  movb    $0xd1,%al               # 0xd1 -> port 0x64
295d1f4b8aSrsc  outb    %al,$0x64
30a650c606Srsc
31a650c606Srscseta20.2:
325d1f4b8aSrsc  inb     $0x64,%al               # Wait for not busy
335d1f4b8aSrsc  testb   $0x2,%al
345d1f4b8aSrsc  jnz     seta20.2
355d1f4b8aSrsc
365d1f4b8aSrsc  movb    $0xdf,%al               # 0xdf -> port 0x60
375d1f4b8aSrsc  outb    %al,$0x60
3855e95b16Srtm
39cf4b1ad9SRuss Cox  # Switch from real to protected mode.  Use a bootstrap GDT that makes
4090a81b32SRobert Morris  # virtual addresses map directly to physical addresses so that the
41cf4b1ad9SRuss Cox  # effective memory map doesn't change during the transition.
422bc72bddSrsc  lgdt    gdtdesc
432bc72bddSrsc  movl    %cr0, %eax
44b7f653dcSrsc  orl     $CR0_PE, %eax
452bc72bddSrsc  movl    %eax, %cr0
462bc72bddSrsc
47cf4b1ad9SRuss Cox//PAGEBREAK!
48*24118827SRobert Morris  # Complete the transition to 32-bit protected mode by using a long jmp
4941911afaSRobert Morris  # to reload %cs and %eip.  The segment descriptors are set up with no
50cf4b1ad9SRuss Cox  # translation, so that the mapping is still the identity mapping.
51e97519a6Srsc  ljmp    $(SEG_KCODE<<3), $start32
5255e95b16Srtm
53cf4b1ad9SRuss Cox.code32  # Tell assembler to generate 32-bit code now.
54b7f653dcSrscstart32:
5555e95b16Srtm  # Set up the protected-mode data segment registers
56e97519a6Srsc  movw    $(SEG_KDATA<<3), %ax    # Our data segment selector
5755e95b16Srtm  movw    %ax, %ds                # -> DS: Data Segment
5855e95b16Srtm  movw    %ax, %es                # -> ES: Extra Segment
59e97519a6Srsc  movw    %ax, %ss                # -> SS: Stack Segment
607b644318Srsc  movw    $0, %ax                 # Zero segments not ready for use
6155e95b16Srtm  movw    %ax, %fs                # -> FS
6255e95b16Srtm  movw    %ax, %gs                # -> GS
635d1f4b8aSrsc
642bc72bddSrsc  # Set up the stack pointer and call into C.
655d1f4b8aSrsc  movl    $start, %esp
66c35c064eSrsc  call    bootmain
675d1f4b8aSrsc
68b7f653dcSrsc  # If bootmain returns (it shouldn't), trigger a Bochs
69b7f653dcSrsc  # breakpoint if running under Bochs, then loop.
70b7f653dcSrsc  movw    $0x8a00, %ax            # 0x8a00 -> port 0x8a00
71b7f653dcSrsc  movw    %ax, %dx
72b7f653dcSrsc  outw    %ax, %dx
737d7465a8SFrans Kaashoek  movw    $0x8ae0, %ax            # 0x8ae0 -> port 0x8a00
74b7f653dcSrsc  outw    %ax, %dx
75a650c606Srscspin:
762bc72bddSrsc  jmp     spin
77a650c606Srsc
785d1f4b8aSrsc# Bootstrap GDT
7955e95b16Srtm.p2align 2                                # force 4 byte alignment
8055e95b16Srtmgdt:
817abf49d2Skaashoek  SEG_NULLASM                             # null seg
827abf49d2Skaashoek  SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)   # code seg
837abf49d2Skaashoek  SEG_ASM(STA_W, 0x0, 0xffffffff)         # data seg
845d1f4b8aSrsc
8555e95b16Srtmgdtdesc:
86887f1968SRuss Cox  .word   (gdtdesc - gdt - 1)             # sizeof(gdt) - 1
8755e95b16Srtm  .long   gdt                             # address gdt
88a56c8d60SFrans Kaashoek
89