Home | History | Annotate | Download | only in Ia32
      1 
      2 #include "BaseLibInternals.h"
      3 
      4 ;------------------------------------------------------------------------------
      5 ;
      6 ; Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
      7 ; This program and the accompanying materials
      8 ; are licensed and made available under the terms and conditions of the BSD License
      9 ; which accompanies this distribution.  The full text of the license may be found at
     10 ; http://opensource.org/licenses/bsd-license.php.
     11 ;
     12 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 ;
     15 ; Module Name:
     16 ;
     17 ;   Thunk.asm
     18 ;
     19 ; Abstract:
     20 ;
     21 ;   Real mode thunk
     22 ;
     23 ;------------------------------------------------------------------------------
     24 
     25 global ASM_PFX(m16Size)
     26 global ASM_PFX(mThunk16Attr)
     27 global ASM_PFX(m16Gdt)
     28 global ASM_PFX(m16GdtrBase)
     29 global ASM_PFX(mTransition)
     30 global ASM_PFX(m16Start)
     31 
     32 struc IA32_REGS
     33 
     34   ._EDI:       resd      1
     35   ._ESI:       resd      1
     36   ._EBP:       resd      1
     37   ._ESP:       resd      1
     38   ._EBX:       resd      1
     39   ._EDX:       resd      1
     40   ._ECX:       resd      1
     41   ._EAX:       resd      1
     42   ._DS:        resw      1
     43   ._ES:        resw      1
     44   ._FS:        resw      1
     45   ._GS:        resw      1
     46   ._EFLAGS:    resd      1
     47   ._EIP:       resd      1
     48   ._CS:        resw      1
     49   ._SS:        resw      1
     50   .size:
     51 
     52 endstruc
     53 
     54 ;; .const
     55 
     56 SECTION .data
     57 
     58 ;
     59 ; These are global constant to convey information to C code.
     60 ;
     61 ASM_PFX(m16Size)         DW      ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start)
     62 ASM_PFX(mThunk16Attr)    DW      _BackFromUserCode.ThunkAttrEnd - 4 - ASM_PFX(m16Start)
     63 ASM_PFX(m16Gdt)          DW      _NullSegDesc - ASM_PFX(m16Start)
     64 ASM_PFX(m16GdtrBase)     DW      _16GdtrBase - ASM_PFX(m16Start)
     65 ASM_PFX(mTransition)     DW      _EntryPoint - ASM_PFX(m16Start)
     66 
     67 SECTION .text
     68 
     69 ASM_PFX(m16Start):
     70 
     71 SavedGdt:
     72             dw  0
     73             dd  0
     74 
     75 ;------------------------------------------------------------------------------
     76 ; _BackFromUserCode() takes control in real mode after 'retf' has been executed
     77 ; by user code. It will be shadowed to somewhere in memory below 1MB.
     78 ;------------------------------------------------------------------------------
     79 _BackFromUserCode:
     80     ;
     81     ; The order of saved registers on the stack matches the order they appears
     82     ; in IA32_REGS structure. This facilitates wrapper function to extract them
     83     ; into that structure.
     84     ;
     85 BITS    16
     86     push    ss
     87     push    cs
     88     ;
     89     ; Note: We can't use o32 on the next instruction because of a bug
     90     ; in NASM 2.09.04 through 2.10rc1.
     91     ;
     92     call    dword .Base                 ; push eip
     93 .Base:
     94     pushfd
     95     cli                                 ; disable interrupts
     96     push    gs
     97     push    fs
     98     push    es
     99     push    ds
    100     pushad
    101     mov     edx, strict dword 0
    102 .ThunkAttrEnd:
    103     test    dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15
    104     jz      .1
    105     mov     ax, 2401h
    106     int     15h
    107     cli                                 ; disable interrupts
    108     jnc     .2
    109 .1:
    110     test    dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL
    111     jz      .2
    112     in      al, 92h
    113     or      al, 2
    114     out     92h, al                     ; deactivate A20M#
    115 .2:
    116     xor     eax, eax
    117     mov     ax, ss
    118     lea     ebp, [esp + IA32_REGS.size]
    119     mov     [bp - IA32_REGS.size + IA32_REGS._ESP], ebp
    120     mov     bx, [bp - IA32_REGS.size + IA32_REGS._EIP]
    121     shl     eax, 4                      ; shl eax, 4
    122     add     ebp, eax                    ; add ebp, eax
    123     mov     eax, strict dword 0
    124 .SavedCr4End:
    125     mov     cr4, eax
    126 o32 lgdt [cs:bx + (SavedGdt - .Base)]
    127     mov     eax, strict dword 0
    128 .SavedCr0End:
    129     mov     cr0, eax
    130     mov     ax, strict word 0
    131 .SavedSsEnd:
    132     mov     ss, eax
    133     mov     esp, strict dword 0
    134 .SavedEspEnd:
    135 o32 retf                                ; return to protected mode
    136 
    137 _EntryPoint:
    138         DD      _ToUserCode - ASM_PFX(m16Start)
    139         DW      8h
    140 _16Idtr:
    141         DW      (1 << 10) - 1
    142         DD      0
    143 _16Gdtr:
    144         DW      GdtEnd - _NullSegDesc - 1
    145 _16GdtrBase:
    146         DD      0
    147 
    148 ;------------------------------------------------------------------------------
    149 ; _ToUserCode() takes control in real mode before passing control to user code.
    150 ; It will be shadowed to somewhere in memory below 1MB.
    151 ;------------------------------------------------------------------------------
    152 _ToUserCode:
    153 BITS    16
    154     mov     dx, ss
    155     mov     ss, cx                      ; set new segment selectors
    156     mov     ds, cx
    157     mov     es, cx
    158     mov     fs, cx
    159     mov     gs, cx
    160     mov     cr0, eax                    ; real mode starts at next instruction
    161                                         ;  which (per SDM) *must* be a far JMP.
    162     jmp     0:strict word 0
    163 .RealAddrEnd:
    164     mov     cr4, ebp
    165     mov     ss, si                      ; set up 16-bit stack segment
    166     xchg    esp, ebx                    ; set up 16-bit stack pointer
    167     mov     bp, [esp + IA32_REGS.size]
    168     mov     [cs:bp + (_BackFromUserCode.SavedSsEnd - 2 - _BackFromUserCode)], dx
    169     mov     [cs:bp + (_BackFromUserCode.SavedEspEnd - 4 - _BackFromUserCode)], ebx
    170     lidt    [cs:bp + (_16Idtr - _BackFromUserCode)]
    171 
    172     popad
    173     pop     ds
    174     pop     es
    175     pop     fs
    176     pop     gs
    177     popfd
    178 
    179 o32 retf                                ; transfer control to user code
    180 
    181 ALIGN   16
    182 _NullSegDesc    DQ      0
    183 _16CsDesc:
    184                 DW      -1
    185                 DW      0
    186                 DB      0
    187                 DB      9bh
    188                 DB      8fh             ; 16-bit segment, 4GB limit
    189                 DB      0
    190 _16DsDesc:
    191                 DW      -1
    192                 DW      0
    193                 DB      0
    194                 DB      93h
    195                 DB      8fh             ; 16-bit segment, 4GB limit
    196                 DB      0
    197 GdtEnd:
    198 
    199 ;------------------------------------------------------------------------------
    200 ; IA32_REGISTER_SET *
    201 ; EFIAPI
    202 ; InternalAsmThunk16 (
    203 ;   IN      IA32_REGISTER_SET         *RegisterSet,
    204 ;   IN OUT  VOID                      *Transition
    205 ;   );
    206 ;------------------------------------------------------------------------------
    207 global ASM_PFX(InternalAsmThunk16)
    208 ASM_PFX(InternalAsmThunk16):
    209 BITS    32
    210     push    ebp
    211     push    ebx
    212     push    esi
    213     push    edi
    214     push    ds
    215     push    es
    216     push    fs
    217     push    gs
    218     mov     esi, [esp + 36]             ; esi <- RegSet, the 1st parameter
    219     movzx   edx, word [esi + IA32_REGS._SS]
    220     mov     edi, [esi + IA32_REGS._ESP]
    221     add     edi, - (IA32_REGS.size + 4) ; reserve stack space
    222     mov     ebx, edi                    ; ebx <- stack offset
    223     imul    eax, edx, 16                ; eax <- edx * 16
    224     push    IA32_REGS.size / 4
    225     add     edi, eax                    ; edi <- linear address of 16-bit stack
    226     pop     ecx
    227     rep     movsd                       ; copy RegSet
    228     mov     eax, [esp + 40]             ; eax <- address of transition code
    229     mov     esi, edx                    ; esi <- 16-bit stack segment
    230     lea     edx, [eax + (_BackFromUserCode.SavedCr0End - ASM_PFX(m16Start))]
    231     mov     ecx, eax
    232     and     ecx, 0fh
    233     shl     eax, 12
    234     lea     ecx, [ecx + (_BackFromUserCode - ASM_PFX(m16Start))]
    235     mov     ax, cx
    236     stosd                               ; [edi] <- return address of user code
    237     add     eax, _ToUserCode.RealAddrEnd - _BackFromUserCode
    238     mov     [edx + (_ToUserCode.RealAddrEnd - 4 - _BackFromUserCode.SavedCr0End)], eax
    239     sgdt    [edx + (SavedGdt - _BackFromUserCode.SavedCr0End)]
    240     sidt    [esp + 36]        ; save IDT stack in argument space
    241     mov     eax, cr0
    242     mov     [edx - 4], eax                  ; save CR0 in _BackFromUserCode.SavedCr0End - 4
    243     and     eax, 7ffffffeh              ; clear PE, PG bits
    244     mov     ebp, cr4
    245     mov     [edx + (_BackFromUserCode.SavedCr4End - 4 - _BackFromUserCode.SavedCr0End)], ebp
    246     and     ebp, ~30h                ; clear PAE, PSE bits
    247     push    10h
    248     pop     ecx                         ; ecx <- selector for data segments
    249     lgdt    [edx + (_16Gdtr - _BackFromUserCode.SavedCr0End)]
    250     pushfd                              ; Save df/if indeed
    251     call    dword far [edx + (_EntryPoint - _BackFromUserCode.SavedCr0End)]
    252     popfd
    253     lidt    [esp + 36]        ; restore protected mode IDTR
    254     lea     eax, [ebp - IA32_REGS.size] ; eax <- the address of IA32_REGS
    255     pop     gs
    256     pop     fs
    257     pop     es
    258     pop     ds
    259     pop     edi
    260     pop     esi
    261     pop     ebx
    262     pop     ebp
    263     ret
    264