Home | History | Annotate | Download | only in X64
      1 ;
      2 ; Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
      3 ; This program and the accompanying materials
      4 ; are licensed and made available under the terms and conditions of the BSD License
      5 ; which accompanies this distribution.  The full text of the license may be found at
      6 ; http://opensource.org/licenses/bsd-license.php
      7 ;
      8 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
      9 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     10 ;
     11 ;
     12 ; Module Name:
     13 ; 
     14 ;    AsmDispatchExecute.asm
     15 ;
     16 ; Abstract:
     17 ; 
     18 ;   This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then 
     19 ;   transit back to long mode.
     20 ;
     21 ;------------------------------------------------------------------------------- 
     22     .code
     23 ;----------------------------------------------------------------------------
     24 ; Procedure:    AsmExecute32BitCode
     25 ;
     26 ; Input:        None
     27 ;
     28 ; Output:       None
     29 ;
     30 ; Prototype:    EFI_STATUS
     31 ;               AsmExecute32BitCode (
     32 ;                 IN UINT64           Function,
     33 ;                 IN UINT64           Param1,
     34 ;                 IN UINT64           Param2,
     35 ;                 IN IA32_DESCRIPTOR  *InternalGdtr
     36 ;                 );
     37 ;
     38 ;
     39 ; Description:  A thunk function to execute 32-bit code in long mode. 
     40 ;
     41 ;----------------------------------------------------------------------------
     42 AsmExecute32BitCode    PROC    
     43     ;
     44     ; save orignal GDTR and CS
     45     ;
     46     mov     rax, ds
     47     push    rax
     48     mov     rax, cs
     49     push    rax
     50     sub     rsp, 10h
     51     sgdt    fword ptr [rsp]
     52     ;
     53     ; load internal GDT
     54     ;
     55     lgdt    fword ptr [r9]
     56     ;
     57     ; Save general purpose register and rflag register
     58     ;
     59     pushfq 
     60     push    rdi
     61     push    rsi
     62     push    rbp
     63     push    rbx
     64     
     65     ;
     66     ; save CR3
     67     ;
     68     mov     rax, cr3
     69     mov     rbp, rax
     70 
     71     ;
     72     ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode 
     73     ;        
     74     mov     rax, 10h              ; load long mode selector    
     75     shl     rax, 32
     76     mov     r9, OFFSET ReloadCS   ;Assume the ReloadCS is under 4G
     77     or      rax, r9
     78     push    rax
     79     ;
     80     ; Save parameters for 32-bit function call
     81     ;   
     82     mov     rax, r8
     83     shl     rax, 32
     84     or      rax, rdx
     85     push    rax
     86     ;
     87     ; save the 32-bit function entry and the return address into stack which will be 
     88     ; retrieve in compatibility mode.
     89     ;
     90     mov     rax, OFFSET ReturnBack   ;Assume the ReloadCS is under 4G 
     91     shl     rax, 32
     92     or      rax, rcx
     93     push    rax
     94     
     95     ;
     96     ; let rax save DS
     97     ;
     98     mov     rax, 018h
     99 
    100     ;
    101     ; Change to Compatible Segment
    102     ;
    103     mov     rcx, 08h               ; load compatible mode selector 
    104     shl     rcx, 32
    105     mov     rdx, OFFSET Compatible ; assume address < 4G
    106     or      rcx, rdx
    107     push    rcx
    108     retf
    109 
    110 Compatible:
    111     ; reload DS/ES/SS to make sure they are correct referred to current GDT
    112     mov     ds, ax
    113     mov     es, ax
    114     mov     ss, ax
    115 
    116     ;
    117     ; Disable paging
    118     ;
    119     mov     rcx, cr0
    120     btc     ecx, 31
    121     mov     cr0, rcx
    122     ;
    123     ; Clear EFER.LME
    124     ;
    125     mov     ecx, 0C0000080h
    126     rdmsr
    127     btc     eax, 8
    128     wrmsr
    129 
    130 ; Now we are in protected mode
    131     ;
    132     ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G
    133     ;    
    134     pop    rax                 ; Here is the function entry
    135     ;  
    136     ; Now the parameter is at the bottom of the stack,  then call in to IA32 function.
    137     ;
    138     jmp   rax
    139 ReturnBack:
    140     pop   rcx                  ; drop param1      
    141     pop   rcx                  ; drop param2      
    142 
    143     ;
    144     ; restore CR4
    145     ;
    146     mov     rax, cr4
    147     bts     eax, 5
    148     mov     cr4, rax
    149 
    150     ;
    151     ; restore CR3
    152     ;
    153     mov     eax, ebp
    154     mov     cr3, rax
    155 
    156     ;
    157     ; Set EFER.LME to re-enable ia32-e
    158     ;
    159     mov     ecx, 0C0000080h
    160     rdmsr
    161     bts     eax, 8
    162     wrmsr
    163     ;
    164     ; Enable paging
    165     ;
    166     mov     rax, cr0
    167     bts     eax, 31
    168     mov     cr0, rax
    169 ; Now we are in compatible mode
    170 
    171     ;
    172     ; Reload cs register 
    173     ;   
    174     retf
    175 ReloadCS:   
    176     ;
    177     ; Now we're in Long Mode
    178     ;
    179     ;
    180     ; Restore C register and eax hold the return status from 32-bit function.
    181     ; Note: Do not touch rax from now which hold the return value from IA32 function
    182     ;
    183     pop     rbx
    184     pop     rbp
    185     pop     rsi
    186     pop     rdi
    187     popfq
    188     ;
    189     ; Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor.
    190     ;
    191     lgdt    fword ptr[rsp]
    192     ;
    193     ; drop GDT descriptor in stack
    194     ;
    195     add     rsp, 10h 
    196     ;
    197     ; switch to orignal CS and GDTR
    198     ;
    199     pop     r9                 ; get  CS
    200     shl     r9,  32            ; rcx[32..47] <- Cs       
    201     mov     rcx, OFFSET @F          
    202     or      rcx, r9
    203     push    rcx
    204     retf
    205 @@:        
    206     ;
    207     ; Reload original DS/ES/SS
    208     ;
    209     pop     rcx
    210     mov     ds, rcx
    211     mov     es, rcx
    212     mov     ss, rcx
    213     ret
    214 AsmExecute32BitCode   ENDP
    215 
    216     END
    217