Home | History | Annotate | Download | only in Ia32
      1 #------------------------------------------------------------------------------
      2 #
      3 # Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
      4 # This program and the accompanying materials
      5 # are licensed and made available under the terms and conditions of the BSD License
      6 # which accompanies this distribution.  The full text of the license may be found at
      7 # http://opensource.org/licenses/bsd-license.php
      8 #
      9 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 #
     12 # Module Name:
     13 #
     14 #   Thunk16.S
     15 #
     16 # Abstract:
     17 #
     18 #   Real mode thunk
     19 #
     20 #------------------------------------------------------------------------------
     21 
     22 #include <EdkIIGlueBase.h>
     23 
     24 .globl ASM_PFX(m16Start), ASM_PFX(m16Size), ASM_PFX(mThunk16Attr), ASM_PFX(m16Gdt), ASM_PFX(m16GdtrBase), ASM_PFX(mTransition)
     25 .globl ASM_PFX(InternalAsmThunk16)
     26 
     27 ASM_PFX(m16Start):
     28 
     29 SavedGdt:     .space  6
     30 
     31 ASM_PFX(BackFromUserCode):
     32     push    %ss
     33     push    %cs
     34     .byte   0x66
     35     call    L_Base1                     # push eip
     36 L_Base1:
     37     pushfw                              # pushfd actually
     38     cli                                 # disable interrupts
     39     push    %gs
     40     push    %fs
     41     push    %es
     42     push    %ds
     43     pushaw                              # pushad actually
     44     .byte   0x66, 0xba                  # mov edx, imm32
     45 ASM_PFX(ThunkAttr): .space  4
     46     testb   $THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15, %dl
     47     jz      1f
     48     movl    $0x15cd2401, %eax           # mov ax, 2401h & int 15h
     49     cli                                 # disable interrupts
     50     jnc     2f
     51 1:
     52     testb   $THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL, %dl
     53     jz      2f
     54     inb     $0x92, %al
     55     orb     $2, %al
     56     outb    %al, $0x92                  # deactivate A20M#
     57 2:
     58     xorw    %ax, %ax                    # xor eax, eax
     59     movl    %ss, %eax                   # mov ax, ss
     60     .byte   0x67, 0x66, 0x8d, 0x6c, 0x24, 0x34, 0x66
     61     mov     %ebp, 0xffffffd8(%esi)
     62     mov     0xfffffff8(%esi), %ebx
     63     shlw    $4, %ax                     # shl eax, 4
     64     addw    %ax, %bp                    # add ebp, eax
     65     .byte   0x66, 0xb8                   # mov eax, imm32
     66 SavedCr4:   .space  4
     67     movl    %eax, %cr4
     68     lgdtw   %cs:0xfffffff2(%edi)
     69     .byte   0x66, 0xb8                   # mov eax, imm32
     70 SavedCr0:   .space  4
     71     movl    %eax, %cr0
     72     .byte   0xb8                        # mov ax, imm16
     73 SavedSs:    .space  2
     74     movl    %eax, %ss
     75     .byte   0x66, 0xbc                   # mov esp, imm32
     76 SavedEsp:   .space  4
     77     .byte   0x66
     78     lret                                # return to protected mode
     79 
     80 _EntryPoint:    .long      ASM_PFX(ToUserCode) - ASM_PFX(m16Start)
     81                 .word      0x8
     82 _16Idtr:        .word      0x3ff
     83                 .long      0
     84 _16Gdtr:        .word      GdtEnd - _NullSegDesc - 1
     85 _16GdtrBase:    .long      _NullSegDesc
     86 
     87 ASM_PFX(ToUserCode):
     88     movl    %ss, %edx
     89     movl    %ecx, %ss                   # set new segment selectors
     90     movl    %ecx, %ds
     91     movl    %ecx, %es
     92     movl    %ecx, %fs
     93     movl    %ecx, %gs
     94     movl    %eax, %cr0
     95     movl    %ebp, %cr4                  # real mode starts at next instruction
     96     movl    %esi, %ss                   # set up 16-bit stack segment
     97     xchgw   %bx, %sp                    # set up 16-bit stack pointer
     98     .byte   0x66
     99     call    L_Base                      # push eip
    100 L_Base:
    101     popw    %bp                         # ebp <- offset L_Base
    102     .byte   0x67;                       # address size override
    103     push    54(%esp)
    104     lea     0xc(%esi), %eax
    105     push    %eax
    106     lret
    107 
    108 L_RealMode:
    109     mov     %edx, %cs:0xffffffc5(%esi)
    110     mov     %bx, %cs:0xffffffcb(%esi)
    111     lidtw   %cs:0xffffffd7(%esi)
    112     popaw                               # popad actually
    113     pop     %ds
    114     pop     %es
    115     pop     %fs
    116     pop     %gs
    117     popfw                               # popfd
    118     lretw                               # transfer control to user code
    119 
    120 _NullSegDesc:   .quad   0
    121 _16CsDesc:
    122                 .word   -1
    123                 .word   0
    124                 .byte   0
    125                 .byte   0x9b
    126                 .byte   0x8f            # 16-bit segment, 4GB limit
    127                 .byte   0
    128 _16DsDesc:
    129                 .word   -1
    130                 .word   0
    131                 .byte   0
    132                 .byte   0x93
    133                 .byte   0x8f            # 16-bit segment, 4GB limit
    134                 .byte   0
    135 GdtEnd:
    136 
    137 #
    138 #   @param  RegSet  The pointer to a IA32_DWORD_REGS structure
    139 #   @param  Transition  The pointer to the transition code
    140 #   @return The address of the 16-bit stack after returning from user code
    141 #
    142 ASM_PFX(InternalAsmThunk16):
    143     push    %ebp
    144     push    %ebx
    145     push    %esi
    146     push    %edi
    147     push    %ds
    148     push    %es
    149     push    %fs
    150     push    %gs
    151     movl    36(%esp), %esi              # esi <- RegSet
    152     movzwl  0x32(%esi), %edx
    153     mov     0xc(%esi), %edi
    154     add     $0xffffffc8, %edi
    155     movl    %edi, %ebx                  # ebx <- stack offset
    156     imul    $0x10, %edx, %eax
    157     push    $0xd
    158     addl    %eax, %edi                  # edi <- linear address of 16-bit stack
    159     pop     %ecx
    160     rep
    161     movsl                               # copy RegSet
    162     movl    40(%esp), %eax              # eax <- address of transition code
    163     movl    %edx, %esi                  # esi <- 16-bit stack segment
    164     lea     0x61(%eax), %edx
    165     movl    %eax, %ecx
    166     andl    $0xf, %ecx
    167     shll    $12, %eax
    168     lea     0x6(%ecx), %ecx
    169     movw    %cx, %ax
    170     stosl                               # [edi] <- return address of user code
    171     sgdtl   0xffffff9f(%edx)
    172     sidtl   0x24(%esp)
    173     movl    %cr0, %eax
    174     movl    %eax, (%edx)                # save CR0 in SavedCr0
    175     andl    $0x7ffffffe, %eax           # clear PE, PG bits
    176     movl    %cr4, %ebp
    177     mov     %ebp, 0xfffffff1(%edx)
    178     andl    $0x300, %ebp                # clear all but PCE and OSFXSR bits
    179     pushl   $0x10
    180     pop     %ecx                        # ecx <- selector for data segments
    181     lgdtl   0x20(%edx)
    182     pushfl
    183     lcall   *0x14(%edx)
    184     popfl
    185     lidtl   0x24(%esp)
    186     lea     0xffffffcc(%ebp), %eax
    187     pop     %gs
    188     pop     %fs
    189     pop     %es
    190     pop     %ds
    191     pop     %edi
    192     pop     %esi
    193     pop     %ebx
    194     pop     %ebp
    195     ret
    196 
    197     .const:
    198 
    199 ASM_PFX(m16Size):        .word      ASM_PFX(InternalAsmThunk16)  - ASM_PFX(m16Start)
    200 ASM_PFX(mThunk16Attr):   .word      ASM_PFX(ThunkAttr)          - ASM_PFX(m16Start)
    201 ASM_PFX(m16Gdt):         .word      _NullSegDesc        - ASM_PFX(m16Start)
    202 ASM_PFX(m16GdtrBase):    .word      _16GdtrBase         - ASM_PFX(m16Start)
    203 ASM_PFX(mTransition):    .word      _EntryPoint         - ASM_PFX(m16Start)
    204