IntelFsp2WrapperPkg BaseFspWrapperApiLib: Convert X64/Thunk64To32.asm to NASM
authorLiming Gao <liming.gao@intel.com>
Wed, 8 Jun 2016 09:51:15 +0000 (17:51 +0800)
committerLiming Gao <liming.gao@intel.com>
Tue, 28 Jun 2016 01:52:04 +0000 (09:52 +0800)
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>
IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.nasm [new file with mode: 0644]

index 870c3fb..f2cef05 100644 (file)
@@ -47,6 +47,7 @@
   X64/DispatchExecute.c\r
   X64/Thunk64To32.asm\r
   X64/Thunk64To32.S\r
+  X64/Thunk64To32.nasm\r
 \r
 ################################################################################\r
 #\r
diff --git a/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.nasm b/IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.nasm
new file mode 100644 (file)
index 0000000..bcc6d70
--- /dev/null
@@ -0,0 +1,230 @@
+;\r
+; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+; This program and the accompanying materials\r
+; are licensed and made available under the terms and conditions of the BSD License\r
+; which accompanies this distribution.  The full text of the license may be found at\r
+; http://opensource.org/licenses/bsd-license.php.\r
+;\r
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+;\r
+;\r
+; Module Name:\r
+;\r
+;    Thunk64To32.nasm\r
+;\r
+; Abstract:\r
+;\r
+;   This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then\r
+;   transit back to long mode.\r
+;\r
+;-------------------------------------------------------------------------------\r
+    DEFAULT REL\r
+    SECTION .text\r
+;----------------------------------------------------------------------------\r
+; Procedure:    AsmExecute32BitCode\r
+;\r
+; Input:        None\r
+;\r
+; Output:       None\r
+;\r
+; Prototype:    UINT32\r
+;               AsmExecute32BitCode (\r
+;                 IN UINT64           Function,\r
+;                 IN UINT64           Param1,\r
+;                 IN UINT64           Param2,\r
+;                 IN IA32_DESCRIPTOR  *InternalGdtr\r
+;                 );\r
+;\r
+;\r
+; Description:  A thunk function to execute 32-bit code in long mode.\r
+;\r
+;----------------------------------------------------------------------------\r
+global ASM_PFX(AsmExecute32BitCode)\r
+ASM_PFX(AsmExecute32BitCode):\r
+    ;\r
+    ; save IFLAG and disable it\r
+    ;\r
+    pushfq\r
+    cli\r
+\r
+    ;\r
+    ; save orignal GDTR and CS\r
+    ;\r
+    mov     rax, ds\r
+    push    rax\r
+    mov     rax, cs\r
+    push    rax\r
+    sub     rsp, 0x10\r
+    sgdt    [rsp]\r
+    ;\r
+    ; load internal GDT\r
+    ;\r
+    lgdt    [r9]\r
+    ;\r
+    ; Save general purpose register and rflag register\r
+    ;\r
+    pushfq\r
+    push    rdi\r
+    push    rsi\r
+    push    rbp\r
+    push    rbx\r
+\r
+    ;\r
+    ; save CR3\r
+    ;\r
+    mov     rax, cr3\r
+    mov     rbp, rax\r
+\r
+    ;\r
+    ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode\r
+    ;\r
+    mov     rax, dword 0x10              ; load long mode selector\r
+    shl     rax, 32\r
+    mov     r9,  ReloadCS          ;Assume the ReloadCS is under 4G\r
+    or      rax, r9\r
+    push    rax\r
+    ;\r
+    ; Save parameters for 32-bit function call\r
+    ;\r
+    mov     rax, r8\r
+    shl     rax, 32\r
+    or      rax, rdx\r
+    push    rax\r
+    ;\r
+    ; save the 32-bit function entry and the return address into stack which will be\r
+    ; retrieve in compatibility mode.\r
+    ;\r
+    mov     rax, ReturnBack   ;Assume the ReloadCS is under 4G\r
+    shl     rax, 32\r
+    or      rax, rcx\r
+    push    rax\r
+\r
+    ;\r
+    ; let rax save DS\r
+    ;\r
+    mov     rax, dword 0x18\r
+\r
+    ;\r
+    ; Change to Compatible Segment\r
+    ;\r
+    mov     rcx, dword 0x8               ; load compatible mode selector\r
+    shl     rcx, 32\r
+    mov     rdx, Compatible ; assume address < 4G\r
+    or      rcx, rdx\r
+    push    rcx\r
+    retf\r
+\r
+Compatible:\r
+    ; reload DS/ES/SS to make sure they are correct referred to current GDT\r
+    mov     ds, ax\r
+    mov     es, ax\r
+    mov     ss, ax\r
+\r
+    ;\r
+    ; Disable paging\r
+    ;\r
+    mov     rcx, cr0\r
+    btc     ecx, 31\r
+    mov     cr0, rcx\r
+    ;\r
+    ; Clear EFER.LME\r
+    ;\r
+    mov     ecx, 0xC0000080\r
+    rdmsr\r
+    btc     eax, 8\r
+    wrmsr\r
+\r
+; Now we are in protected mode\r
+    ;\r
+    ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G\r
+    ;\r
+    pop    rax                 ; Here is the function entry\r
+    ;\r
+    ; Now the parameter is at the bottom of the stack,  then call in to IA32 function.\r
+    ;\r
+    jmp   rax\r
+ReturnBack:\r
+    mov   ebx, eax             ; save return status\r
+    pop   rcx                  ; drop param1\r
+    pop   rcx                  ; drop param2\r
+\r
+    ;\r
+    ; restore CR4\r
+    ;\r
+    mov     rax, cr4\r
+    bts     eax, 5\r
+    mov     cr4, rax\r
+\r
+    ;\r
+    ; restore CR3\r
+    ;\r
+    mov     eax, ebp\r
+    mov     cr3, rax\r
+\r
+    ;\r
+    ; Set EFER.LME to re-enable ia32-e\r
+    ;\r
+    mov     ecx, 0xC0000080\r
+    rdmsr\r
+    bts     eax, 8\r
+    wrmsr\r
+    ;\r
+    ; Enable paging\r
+    ;\r
+    mov     rax, cr0\r
+    bts     eax, 31\r
+    mov     cr0, rax\r
+; Now we are in compatible mode\r
+\r
+    ;\r
+    ; Reload cs register\r
+    ;\r
+    retf\r
+ReloadCS:\r
+    ;\r
+    ; Now we're in Long Mode\r
+    ;\r
+    ;\r
+    ; Restore C register and eax hold the return status from 32-bit function.\r
+    ; Note: Do not touch rax from now which hold the return value from IA32 function\r
+    ;\r
+    mov     eax, ebx ; put return status to EAX\r
+    pop     rbx\r
+    pop     rbp\r
+    pop     rsi\r
+    pop     rdi\r
+    popfq\r
+    ;\r
+    ; Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor.\r
+    ;\r
+    lgdt    [rsp]\r
+    ;\r
+    ; drop GDT descriptor in stack\r
+    ;\r
+    add     rsp, 0x10\r
+    ;\r
+    ; switch to orignal CS and GDTR\r
+    ;\r
+    pop     r9                 ; get  CS\r
+    shl     r9,  32            ; rcx[32..47] <- Cs\r
+    mov     rcx, .0\r
+    or      rcx, r9\r
+    push    rcx\r
+    retf\r
+.0:\r
+    ;\r
+    ; Reload original DS/ES/SS\r
+    ;\r
+    pop     rcx\r
+    mov     ds, rcx\r
+    mov     es, rcx\r
+    mov     ss, rcx\r
+\r
+    ;\r
+    ; Restore IFLAG\r
+    ;\r
+    popfq\r
+\r
+    ret\r
+\r