IntelFsp2WrapperPkg BaseFspWrapperApiLib: Convert X64/Thunk64To32.asm to NASM

Manually convert X64/Thunk64To32.asm to X64/Thunk64To32.nasm

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Liming Gao <liming.gao@intel.com>
diff --git a/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
index 870c3fb..f2cef05 100644
--- a/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
+++ b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
@@ -47,6 +47,7 @@
   X64/DispatchExecute.c

   X64/Thunk64To32.asm

   X64/Thunk64To32.S

+  X64/Thunk64To32.nasm

 

 ################################################################################

 #

diff --git a/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.nasm b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.nasm
new file mode 100644
index 0000000..bcc6d70
--- /dev/null
+++ b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.nasm
@@ -0,0 +1,230 @@
+;

+; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>

+; This program and the accompanying materials

+; are licensed and made available under the terms and conditions of the BSD License

+; which accompanies this distribution.  The full text of the license may be found at

+; http://opensource.org/licenses/bsd-license.php.

+;

+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+;

+;

+; Module Name:

+;

+;    Thunk64To32.nasm

+;

+; Abstract:

+;

+;   This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then

+;   transit back to long mode.

+;

+;-------------------------------------------------------------------------------

+    DEFAULT REL

+    SECTION .text

+;----------------------------------------------------------------------------

+; Procedure:    AsmExecute32BitCode

+;

+; Input:        None

+;

+; Output:       None

+;

+; Prototype:    UINT32

+;               AsmExecute32BitCode (

+;                 IN UINT64           Function,

+;                 IN UINT64           Param1,

+;                 IN UINT64           Param2,

+;                 IN IA32_DESCRIPTOR  *InternalGdtr

+;                 );

+;

+;

+; Description:  A thunk function to execute 32-bit code in long mode.

+;

+;----------------------------------------------------------------------------

+global ASM_PFX(AsmExecute32BitCode)

+ASM_PFX(AsmExecute32BitCode):

+    ;

+    ; save IFLAG and disable it

+    ;

+    pushfq

+    cli

+

+    ;

+    ; save orignal GDTR and CS

+    ;

+    mov     rax, ds

+    push    rax

+    mov     rax, cs

+    push    rax

+    sub     rsp, 0x10

+    sgdt    [rsp]

+    ;

+    ; load internal GDT

+    ;

+    lgdt    [r9]

+    ;

+    ; Save general purpose register and rflag register

+    ;

+    pushfq

+    push    rdi

+    push    rsi

+    push    rbp

+    push    rbx

+

+    ;

+    ; save CR3

+    ;

+    mov     rax, cr3

+    mov     rbp, rax

+

+    ;

+    ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode

+    ;

+    mov     rax, dword 0x10              ; load long mode selector

+    shl     rax, 32

+    mov     r9,  ReloadCS          ;Assume the ReloadCS is under 4G

+    or      rax, r9

+    push    rax

+    ;

+    ; Save parameters for 32-bit function call

+    ;

+    mov     rax, r8

+    shl     rax, 32

+    or      rax, rdx

+    push    rax

+    ;

+    ; save the 32-bit function entry and the return address into stack which will be

+    ; retrieve in compatibility mode.

+    ;

+    mov     rax, ReturnBack   ;Assume the ReloadCS is under 4G

+    shl     rax, 32

+    or      rax, rcx

+    push    rax

+

+    ;

+    ; let rax save DS

+    ;

+    mov     rax, dword 0x18

+

+    ;

+    ; Change to Compatible Segment

+    ;

+    mov     rcx, dword 0x8               ; load compatible mode selector

+    shl     rcx, 32

+    mov     rdx, Compatible ; assume address < 4G

+    or      rcx, rdx

+    push    rcx

+    retf

+

+Compatible:

+    ; reload DS/ES/SS to make sure they are correct referred to current GDT

+    mov     ds, ax

+    mov     es, ax

+    mov     ss, ax

+

+    ;

+    ; Disable paging

+    ;

+    mov     rcx, cr0

+    btc     ecx, 31

+    mov     cr0, rcx

+    ;

+    ; Clear EFER.LME

+    ;

+    mov     ecx, 0xC0000080

+    rdmsr

+    btc     eax, 8

+    wrmsr

+

+; Now we are in protected mode

+    ;

+    ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G

+    ;

+    pop    rax                 ; Here is the function entry

+    ;

+    ; Now the parameter is at the bottom of the stack,  then call in to IA32 function.

+    ;

+    jmp   rax

+ReturnBack:

+    mov   ebx, eax             ; save return status

+    pop   rcx                  ; drop param1

+    pop   rcx                  ; drop param2

+

+    ;

+    ; restore CR4

+    ;

+    mov     rax, cr4

+    bts     eax, 5

+    mov     cr4, rax

+

+    ;

+    ; restore CR3

+    ;

+    mov     eax, ebp

+    mov     cr3, rax

+

+    ;

+    ; Set EFER.LME to re-enable ia32-e

+    ;

+    mov     ecx, 0xC0000080

+    rdmsr

+    bts     eax, 8

+    wrmsr

+    ;

+    ; Enable paging

+    ;

+    mov     rax, cr0

+    bts     eax, 31

+    mov     cr0, rax

+; Now we are in compatible mode

+

+    ;

+    ; Reload cs register

+    ;

+    retf

+ReloadCS:

+    ;

+    ; Now we're in Long Mode

+    ;

+    ;

+    ; Restore C register and eax hold the return status from 32-bit function.

+    ; Note: Do not touch rax from now which hold the return value from IA32 function

+    ;

+    mov     eax, ebx ; put return status to EAX

+    pop     rbx

+    pop     rbp

+    pop     rsi

+    pop     rdi

+    popfq

+    ;

+    ; Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor.

+    ;

+    lgdt    [rsp]

+    ;

+    ; drop GDT descriptor in stack

+    ;

+    add     rsp, 0x10

+    ;

+    ; switch to orignal CS and GDTR

+    ;

+    pop     r9                 ; get  CS

+    shl     r9,  32            ; rcx[32..47] <- Cs

+    mov     rcx, .0

+    or      rcx, r9

+    push    rcx

+    retf

+.0:

+    ;

+    ; Reload original DS/ES/SS

+    ;

+    pop     rcx

+    mov     ds, rcx

+    mov     es, rcx

+    mov     ss, rcx

+

+    ;

+    ; Restore IFLAG

+    ;

+    popfq

+

+    ret

+