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>
This commit is contained in:
Liming Gao 2016-06-08 17:51:15 +08:00
parent b295fbba8d
commit 24498828f7
2 changed files with 231 additions and 0 deletions

View File

@ -47,6 +47,7 @@
X64/DispatchExecute.c
X64/Thunk64To32.asm
X64/Thunk64To32.S
X64/Thunk64To32.nasm
################################################################################
#

View File

@ -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