root/bootasm.S

/* [<][>][^][v][top][bottom][index][help] */
   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
  12 start:
  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.
  23 seta20.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 
  31 seta20.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 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
  52 
  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
  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
  75 spin:
  76   jmp     spin
  77 
  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
  84 
  85 gdtdesc:
  86   .word   (gdtdesc - gdt - 1)             # sizeof(gdt) - 1
  87   .long   gdt                             # address gdt
  88 

/* [<][>][^][v][top][bottom][index][help] */